Repository navigation
Conversation
…o annotations The "external job 'workspace-test': not completed within 12000s" error on x86-main never came from a wait. x86-main runs no --external-job. The line, and "section a: failure" / "section a: cancelled" beside it, are ::error:: workflow commands printed by planted rows of `fat_driver.py self-test`, which passed 60/60 about a minute into the job. GitHub turned them into job error annotations. When the job went red later on another section (#4813 pr-review-sign, #4913 guard-tree at its 3600 s budget), the annotation was read as the cause. scripts/ci/fence_workflow_commands.sh runs a case table between `::stop-commands::<token>` and `::<token>::` (fresh token, never exported, stderr merged into the one ordered pipe). The step's verdict is the table's rc, and a failing table gets one live ::error:: naming it. Both fat_driver self-test steps (x86-main, workspace-test-shard) go through it. `fat_driver.py run`/`wait` stay unfenced, so a real deadline still annotates. The script's wiring check is RED on an unfenced self-test step and on a fenced real run. It runs, with its 19-row case table, in x86-main's cheap-checks step. No gate loosened: same commands, same exit codes, one guard added. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ad is cut Shard, determinism and x86-main sections died on one git fetch: "curl 92 HTTP/2 stream was not closed cleanly: CANCEL" or "curl 56 Recv failure: Connection reset by peer", on every host alike. The tier step's depth-1 fetch of main ran 376 s and died although main's objects were already in the section clone: the read did not answer, it was not too big. Every section fetch was a single read. scripts/ci/fetch_p6.sh replaces `git fetch` at all 11 call sites in ci/sections.yml. P6: a read that did not answer is read at most 3 times; an answer (missing ref, not found, 401/403/404) is never re-read; each re-read is one status line. Every read runs under http.lowSpeedLimit 1000 B/s for 60 s, so a stall ends in a re-read, not a hung section. A failure on all 3 reads still fails the step, and the `|| true` fallback at the tier step is unchanged. Case table: 23 rows (planted git + real file:// remote); 6 mutants each lose rows (1 read, 4 reads, answers re-read, no stall cut, no wait, wiring that read nothing). --check-wiring is RED on any bare git fetch in ci/sections.yml (12 FAIL lines before this change). Both run in x86-main Cheap checks. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stacked merge_group entry deepens its depth-1 checkout by one commit in scripts/lib/resolve_base.sh, which the section guards source. It was one read with no stall cutoff. It now goes through scripts/ci/fetch_p6.sh, located next to the library (REPO_ROOT may be a repo without scripts/). The helper's status lines go to stderr, never into a caller's $(...); git's own stderr is still dropped, and `|| true` is unchanged. check_roadmap_diff_additive row 20 does that deepen for real: 25/25. Mutant (helper path broken): row 20 FAILs. Six other resolve_base users and check_sourced_libs_option_neutral: rc 0. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two non-author reviews of 2481ab6 approved with findings. Each one that changes behaviour now has a planted row and a mutant that turns it red. - fence: the resume line starts its own line. A child whose last line had no newline glued it on, the fence never closed and the failure ::error:: was swallowed. New rows: partial last line, fence closes, rc 3, 1 live. - fetch_p6: git runs under LC_ALL=C, so the answered() texts are git's own. rc 129 (usage), "could not read Username" and "not a git repository" are answers and are never re-read. The wiring regex now sees git's global options between git and fetch (-C, -c, --git-dir, --no-pager, quoted words, any blank run); 9 must-match and 5 must-not-match forms. - fetch_p6: the backoff row records each planted sleep (7 14 at SLEEP_S=7) instead of passing with sleep stubbed out. - resolve_base: the helper path is absolute before the cd into REPO_ROOT. A caller that sourced the library by a relative path from another tree lost the deepen and was refused; the probe is red on 2481ab6, green here. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ource time (#4936) Second review round on 656bf90 (both APPROVE, non-blocking findings): - fence: the "stderr is fenced too" row sent only stdout to its file, so it passed with the 2>&1 merge removed. stdout and stderr now go to two files, as they are two pipes on the runner; the merge mutant fails the row. - fence: live_commands now errs on the high side only. An indented command and a property value with a colon count; an indented stop line does not start a region. A new row fails on the old counter. - fetch_p6: the LC_ALL=C row passed with the helper's own LC_ALL=C removed whenever the caller already exported LC_ALL=C. The table's caller now runs under LC_ALL=POSIX; the mutant fails the row under an exported LC_ALL=C too. - resolve_base: the helper path was resolved at CALL time from a possibly relative BASH_SOURCE, so a caller that cds after sourcing, or a CDPATH with a decoy scripts/lib, was refused on a stacked merge_group entry that the base deepened fine. It is found once at source time, with CDPATH cleared. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…acts on (#4936) live_commands is the oracle for every "0 live" row, and it claimed to err on the high side only. It did not: it matched error/warning/notice in one case, trimmed only space and tab, ignored the legacy ##[error] form and a line the runner splits on \r, and ended a region only on an exact resume line. Now an annotation counts anywhere in a line and in any case, a region starts only at the fence's own stop line, and it ends at the first line holding ::<token> in any case, which is counted too. Three rows pin it (7 forms, 2 region ends, 2 region starts); each of the 7 counter mutants fails one. The fence itself is unchanged. On mawk, gawk and busybox awk: 24/24. An upper bound can say only "at most 1" live, so the failing-table row now also wants the exact resume line just before the failure annotation. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wiring check (#4936) Review of b7544ba found two ways the fence's proof could pass while the runner saw something else. 1. The live counter read one \n-line as one command. The runner splits on \r too, so `::error::a\r::error::b\r::error::c` is 3 commands, and the counter said 1: "a 1 is at most 1" was false. The counter now splits on \r and counts each piece. Two more under-counts were closed on the way: - A region ends at ##[<token> as well as ::<token> (the legacy form resumes the runner too). - After an odd stop line (one the fence never prints) or an odd end (a ::<token> line other than the exact resume), the runner may be stopped on another token or still be stopped. No region starts again after either, so every later annotation counts. 2. check_wiring took any line holding the fenced command as wired, so `... self-test || true`, `; true`, `| tee x` and `|| :` passed and could mask the case table's rc. A self-test line must now be exactly `bash scripts/ci/fence_workflow_commands.sh -- python3 scripts/ci/fat_driver.py self-test`, after indentation, an optional `- ` and `run: `, and before trailing blanks. Any whitespace run between fat_driver.py and self-test is found, so two spaces is RED, not missed. Self-test now 27 rows, all green under gawk, mawk and busybox awk. The new rows: an 8th counter form (3 commands on one \r-joined line, want 3), a ##[<token> region end, two doubt rows, 5 masked or re-spaced wiring lines, and the fenced command alone in a run block. Each of 16 literal mutants and both earlier counters (967b7ea, b7544ba) turns at least one row RED. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two conflicts, both resolved to main's side: - ci/sections.yml: guard-tree's guard-setup and guard-cargo's comparand step. Main replaced the origin/main tip fetch there with scripts/ci/pin_build_base.sh (#4861, #4983), so the fetch_p6 lines this branch had put in those steps are gone with them. The next commit puts pin_build_base.sh's own fetches under P6. - docs/roadmaps/roadmap.yaml: regenerated with make roadmap-aggregate (main's entries plus PMAT-4936). Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… caller The merge of main moved the sections' comparand fetches into scripts/ci/pin_build_base.sh, so the P6 re-reads (operator C343 #9) those fetches had on this branch went with them. The pin's three fetches (the tip, the push deepen, the build base) now go through fetch_p6.sh: a read that did not answer is read again, up to 3 reads in all; a read that answered is never read again. fetch_p6.sh takes a leading `-C <dir>` and hands it to git, so neither caller cds (bashrs SEC010 on both `cd -- "$dir"` subshells). Case tables, each new row RED under a planted mutant: - pin_build_base: 6 P6 rows (a planted git kills the named reads), floor 22 -> 28. 10 mutants, 10 killed: fetch() bypassing P6, -C dropped, fetch_p6 losing -C, each site bare, P6_READS=2, answered() never true, helper missing, a P6 row dropped (the floor). - fetch_p6: 5 -C rows (a cwd that is no repo, every re-read keeps -C, -C with no dir is a usage answer). - roadmap diff: the stacked merge_group deepen with its first read dead must read the deepen twice. A bare deepen, and both reads bare, are killed; dropping -C there is equivalent (callers run from REPO_ROOT). - ratchet C16: its mutant runs from a copy, so fetch_p6.sh is placed beside it, and a new row asserts the mutant ran its fall-through to the tip. Without the copy the old C16 row stayed green on a crashed mutant; the new row is RED. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A fetch that loses its -C runs in the caller's cwd. Run from a checkout, a depth fetch there writes .git/shallow into the shared common dir and every worktree of that clone stops working. A mutant that dropped -C did exactly that. pin_build_base.sh --self-test now cds into its own temp dir and sets git's ceiling to that dir's parent (git never stops at the dir it starts in). fetch_p6.sh's table ceilings at its temp dir, and its -C rows start from a dir under it. A fetch without -C then reads "not a git repository" instead of reaching a checkout. New rows, each failable: - pin: the table's cwd is no repository; the ceiling is TD's parent. Floor 28 -> 30. - fetch_p6: the cwd the -C reads start from is no repository. Mutants, run with cwd in a planted empty repo and TMPDIR inside it, so the ceilings are load-bearing: 16 killed, 0 survived, both controls green (pin 30 ok; fetch_p6 PASS). New ones: cd dropped, ceiling dropped, ceiling at TD, cwd row dropped, fetch_p6 ceiling dropped. The planted repo held no ref, no remote and no shallow file after each run. bashrs: no finding code rises in either file vs the previous commit. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dmap P6 row could not see a lost -C (#4936) - fetch_p6.sh: `-C` with an empty dir is now a usage error (rc 129), the same as `-C` with no dir. `git -C ""` keeps the cwd, so a caller whose dir variable was empty would have fetched into whatever repo the cwd is. A new row covers it. The planted git now exits 99 on an unknown SHIM_MODE (it exited 0), and a row proves that. - check_roadmap_diff_additive.sh: the P6 stacked-entry row now runs from a cwd outside REPO_ROOT, under a ceiling, and checks that cwd is no repo. check_ont_ratchet.sh calls resolve_base without a cd. A resolve_base read that lost its -C "$REPO_ROOT" is now RED; on the previous head the row passed, so that mutant was not equivalent. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A non-author review of 36e691c measured that no self-test row reached the by-sha read in resolve_base.sh's stacked merge_group path. The P6 row answers on its second deepen read, so the `||` fallback never runs. A by-sha read that lost its -C "$REPO_ROOT", or that skipped P6, stayed green. New row: the same stacked entry with all 3 deepen reads dead and the by-sha read dead once. It starts from a cwd that is no repo (the planted git's own dir, under a ceiling at the table's temp dir), in the same way as the row above. It needs 3 deepen reads, then 2 by-sha reads, and the previous entry's squash as the base: - a by-sha read without -C runs in no repo, so the base does not resolve: RED; - a by-sha read that skips P6 is never read again: RED. The comment on the row above is narrowed: it covers the deepen read only. Self-test: 26 -> 27 rows. Mutants of resolve_base.sh under the self-test (13, each did what it names): the by-sha read's -C dropped, and the by-sha read made a bare fetch, are now killed by the new row. Refs #4936 Agent: aprender-4936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
noahgift
enabled auto-merge
October 10, 2026 11:43
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 10, 2026
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #4936
keep-open: B cuts section-fetch drops but cannot clear them; the stalls on the egress path continue until the network is fixed, and #4936 closes only after a post-merge x86-main log shows both mechanisms engaged.
Head ca7d665: what changed since 36e691c
A non-author review of 36e691c measured one gap. No self-test row reached the by-sha read in
resolve_base.sh's stacked merge_group path. The P6 row answers on its second deepen read, so the||fallback never ran, and a by-sha read that lost its-C "$REPO_ROOT"stayed green. One file changes:scripts/check_roadmap_diff_additive.sh(+22, -1).-Cruns in no repo, so the base does not resolve. A by-sha read that skips P6 is never read again. Either way the row is RED.check_roadmap_diff_additive.sh --self-testREPO_ROOT.fetch_p6.sh --self-testpin_build_base.sh --self-testMutants, built from the head's tree (the same harness as below: a planted empty repo, re-checked after every run).
resolve_base.shand the two P6 rows: 12 mutants and a control, and each did what it names. The control is green.resolve_base.sh:-Cpointed at a missing dir;-C "$REPO_ROOT"dropped from both reads, from the deepen read only, or from the by-sha read only (that one survived on 36e691c);REPO_ROOTwith its cwd check kept; either row's ceiling dropped.-Cdropped and the first P6 row put back as it was at 7b77d51. The new row cannot see this one, because its deepen reads all die in the planted git whatever their-C.bashrs 7.4.1, the pinned version, reports 0 errors, and its gate form (
--no-ignore --level error) finds 0 SEC, DET or IDEM findings at both heads. Oncheck_roadmap_diff_additive.sh, warnings go 88 → 101 and infos 108 → 125. Two non-author reviews measured those counts independently with 7.4.1. Unpinned 7.4.2 builds disagree with each other on warning counts, so no 7.4.2 count is given here. Every new finding is on the new row's lines. SC2143 (info), on the planted git's count of by-sha reads, is the one code new to the file; the new SEC010, SEC014 and SEC020 findings are warnings. CI's bashrs gate counts only error-severity SEC, DET and IDEM findings, and the shell-lint ratchet counts only errors.ci.yml,ci/sections.yml,fetch_p6.shandresolve_base.share unchanged since 36e691c.Not changed here:
sleepand thechmodthat the row above leaves in its dir, so the two rows must stay together. This cannot turn the row falsely green. Without the plantedsleep, the row really sleeps (about 40 s) and still checks the same reads. Without thechmod, the real git answers the first read and the row is RED.Head 36e691c: what changed since 7b77d51
A non-author review of 7b77d51 found two holes, and the sign-off round raised one nit. All three are fixed here. Two files change:
scripts/ci/fetch_p6.shandscripts/check_roadmap_diff_additive.sh.fetch_p6.sh -C ""fetched in the cwd's repo.git -C ""keeps the cwd, so a caller whose dir variable was empty would read and write whatever repo the cwd is. The review measured it: the ref landed in the cwd repo. Now-Cwith an empty dir is a usage error (rc 129), the same as-Cwith no dir. A usage error is an answer, so it is never read again.-C "$REPO_ROOT". Its P6 row ran from insideREPO_ROOT, so a deepen read without-Cstill landed in the right repo. This body called that mutant "equivalent" because every caller cds first. That was wrong:check_ont_ratchet.shcallsresolve_basewithout a cd.REPO_ROOT(the planted git's own dir), under a ceiling at the table's temp dir.SHIM_MODE. It now exits 99, and a row proves it.fetch_p6.sh --self-test-C '': rc 129, and git never runs. A mistypedSHIM_MODE: rc 99, never 0.check_roadmap_diff_additive.sh --self-testpin_build_base.sh --self-testMutants, built from the head's tree. Each self-test ran with its cwd in a planted empty repo and
TMPDIRinside it. After every run:FETCH_HEADwas unchanged.The results:
resolve_base.shand the roadmap row: 7 mutants, and each did what it names.resolve_base.sh:-Cpointed at a missing dir;-C "$REPO_ROOT"dropped from both reads (it survived on 7b77d51; the by-sha read alone was not reached until ca7d665); the deepen made a bare fetch; both reads made bare fetches.REPO_ROOTwith its cwd check kept (the check turns it RED); row 8's ceiling dropped (from the planted repo, git finds that repo above the cwd).-Cdropped and row 8 put back as it was at 7b77d51. This is why the old table could not see a lost-C.bashrs reports 0 errors (a local bashrs 7.4.2; the gate form also finds 0 SEC, DET or IDEM errors with the pinned 7.4.1).
check_roadmap_diff_additive.sh, every finding code's count equals 7b77d51's (7.4.2, both heads).fetch_p6.sh, two codes fall (SC2249, SC2297) and none rises.ci.ymlandci/sections.ymlare unchanged since 7b77d51.fetch_p6.sh --check-wiringpasses: 7 fetches, each through the helper.Not changed here:
--check-wiringscansci/sections.ymlonly. Todayci.ymlruns nogit fetch. Extending the scan is a separate change, with its own mutants in the new scope.Head 7b77d51: what changed since a5e3f09
The sections from "Planted falsifiers" down describe a5e3f09 and the review rounds before it. This section is the delta.
ci/sections.ymlintoscripts/ci/pin_build_base.sh. Soci/sections.ymlnow holds 7 fetches (it held 11), and the pin holds 3. All 10 read under P6, as does theresolve_base.shdeepen.fetch_p6.sh -C <dir> <args...>stands in forgit -C <dir> fetch <args...>. A-Cwith no dir is a usage error (rc 129). That counts as an answer, so it is never re-read.cdin either P6 caller.pin_build_base.shandresolve_base.shpass-C <dir>to the helper. bashrs SEC010 flags acdinto a variable path, so neither caller cds.-Cruns in the caller's cwd. Run from a checkout, a depth fetch there writes.git/shallowinto the shared git dir, and every worktree of that clone breaks. A mutant that dropped-Cdid exactly that. Sopin_build_base.sh --self-testcds into its temp dir and sets git's ceiling to that dir's parent (git never stops at the dir it starts in).fetch_p6.sh --self-testsets its ceiling at its temp dir, and its-Crows start from a dir under it. A fetch without-Cnow reads "not a git repository".New rows, each able to fail:
pin_build_base.sh --self-testfetch_p6.sh --self-test-C <dir>, from a cwd that is no repo: rc 0, 1 read, and the ref lands in<dir>. curl 92 twice under-C: rc 0 after 3 reads, and every read keeps-C <dir>and the stall cut.-Cwith no dir: rc 129, git never runs. That cwd is no repo.check_roadmap_diff_additive.sh --self-testratchet_semantics_test.shC16Mutants, built from the head's tree. Each self-test ran with its cwd in a planted empty repo and
TMPDIRinside it, so its own ceiling carried weight. After every run the planted repo still had no ref, no remote and no shallow file.-Cdropped at the pin;-Clost inside the helper (under both tables);git fetch;P6_READS=2; answers re-read; helper path wrong; a P6 row dropped (caught by the floor);cddropped; the ceiling dropped; the ceiling set at TD; the cwd row dropped; fetch_p6's ceiling dropped.resolve_base.sh(under the roadmap-diff table): 3 killed. They are-Cpointed at a missing dir, the deepen made a baregit fetch, and both reads made bare fetches. One survived, and this body called it equivalent: dropping-C "$REPO_ROOT". That was wrong, becausecheck_ont_ratchet.shcallsresolve_basewithout a cd. On 36e691c it is killed (see that section).bashrs reports 0 errors on all four changed scripts. On
pin_build_base.shandfetch_p6.sh, no finding code rises against the previous head. actionlint's 2 findings are the same on main and on the head.Two halves, each with a planted falsifier:
::error::lines. Unfenced it raises 3 live annotations; fenced, 0. The same table planted to fail (exit 3) still fails the step with rc 3 and one live::error::. Removing the fence's stop line brings all 3 annotations back.giton PATH:P6_READS=1, 8 of the 40 self-test rows fail (a5e3f09).B reduces section-fetch drops and does not clear them. See "What this does not fix" under B.
Planted falsifiers, against the real scripts as CI calls them (a5e3f09)
These sit outside both case tables. The fence wrapper runs a planted table.
fetch_p6.shruns with a plantedgiton PATH against a realfile://remote, with the real 10 s backoff.resolve_base.shis sourced by a relative path from this tree, withREPO_ROOTpointing at a fresh depth-1 clone of a stacked merge-queue entry for each row.The A rows count live annotations with two fixed counters in the falsifier script. They never use the tree's own
--live, so a mutant cannot grade itself:\ras well as\n, as the runner does, and counts each piece once. It counts an annotation anywhere in a piece, in any case, and the legacy##[errorform too. A region starts only at the exact fence stop line, and ends at the first piece holding::<token>or##[<token>. After an odd stop line or an odd end, no region starts again.stop-commandsopens a region, and only the exact::<token>::line closes it.A row that wants 0 reads hi. A row that wants exactly 1 wants
lo/hi = 1/1, because hi alone can only say "at most 1".Three mutant copies run the same 21 rows:
P6_READS=1.resolve_basecalling the helper by its repo-relative path fromREPO_ROOT, as 2481ab6 did.Every mutation was checked with
cmpbefore the run.\r, unfenced: live annotations, lo/hiresolve_basesourced by a relative path,REPO_ROOTanother tree: the stacked entry is deepenedCDPATHholding a decoyscripts/libAll 21 rows hold on the head. M-off fails 9 rows: 4 in the fence half and 5 in the P6 half. M-review fails 5: A7, B9, and all three
resolve_baserows, because the repo-relative call fails in any other tree. On M-review, A7 is red on lo only. The glued resume line ends the region for hi, but not on the runner, which then swallows the failure annotation. That is why A7 reads both counters. M-review2 fails B11 and B12, the two shapes the second round found. Before #4936,resolve_baserangit -C "$REPO_ROOT" fetchwith no script path at all, so neither shape could fail it; 656bf90 had brought that failure in, and 967b7ea takes it out. A8 is a control: it shows the hi oracle sees all 3 commands on a\r-joined line, where lo, which reads only column 0 of a\n-line, sees 1.Main at f0bc7d9 (#4934) merges into a5e3f09 with 0 conflicts and no file overlap. On the merged tree these are all green:
check_guard_steps_run_all.sh,check_ci_push_reuse.shandcheck_guards_are_wired.sh.guard_tree_parallel_test.sh(9/9) andcheck_sourced_libs_option_neutral.sh(12 libraries).Review findings on b7544ba (fourth round), and what was done
Two more non-author reviews (Sonnet 5.5) read b7544ba. The P6 and
resolve_basereview approved it. The fence review held it on two blocking findings. I reproduced both, and a5e3f09 fixes both. Both reviews then re-read a5e3f09 and approve it. The fence review built its own mutant for each new row, and each went red.\r, soprintf '::error::a\r::error::b\r::error::c\n'is 3 commands, and--livecounted 1. The falsifier script's hi oracle had the same defect.\ras well as\n, and count each piece once. A new 8th counter form wants 3 for that line. A8 plants it unfenced (lo/hi 1/3) and A9 fenced (0). Fixing it closed two more under-counts. A region now also ends at##[<token>, because the legacy form resumes the runner too. After an odd stop line or an odd end, no region starts again, because the runner may be stopped on another token or still be stopped. New rows and a mutant pin each one (tables above).$*holding a newline could put a second live::error::after the fence.python3 scripts/ci/fat_driver.py self-test), and the wiring check now requires exactly that line.self-test, and a run block that splits a command over lines.self-testline is not the whole fenced command, so it is RED. Still line-based, and not seen: a fencedrunorwaitsplit over lines with\, a foldedrun: >scalar, and a step-levelcontinue-on-error:,if:orshell:. Neither self-test step has any of these today, and C324 already banscontinue-on-erroron this path.resolve_base's worst case is 6 reads and about 60 s of backoff, across its two chained helper calls. This body said 3 reads.return 0turns B4 red, and no answer check makes B8 read 3 times. So the rows can fail. No script change.answered()searches all of git's stderr.Since b7544ba the only changed file is
fence_workflow_commands.sh.Review findings on 967b7ea (third round), and what was done
Two more non-author reviews (Sonnet 5.5) read 967b7ea: one deep on the fence and
resolve_base, one on P6 and its 11 sites. The P6 review approved it. The fence review held it on two findings. Both are fixed here. The first one was mine: I had not refreshed the copy of this body that it read.live_commandsclaimed to err on the high side only, and it did not. It matched in one case only, trimmed only space and tab, missed the legacy##[error]form and a command after a\r(the runner splits lines on it too), and ended a region only on an exact resume line. Every "0 live" row reads this counter, so a 0 could be a miss.##[form included. A region starts only at the fence's own stop line (column 0, lower case, a 32-hex token, nothing after it). It ends at the first line holding::<token>in any case, and that line counts too. Three new rows pin it (7 forms, 2 region ends, 2 region starts). Each of the 7 counter mutants below fails one of them, and the 967b7ea counter fails 3.::WARNING file=a.rs:1,line=2::, and the case and anchoring mutants fail it.check_roadmap_diff_additive.sh's self-test stagesresolve_base.shinto a temp tree withoutscripts/ci/fetch_p6.sh.Since 967b7ea the only changed file is
fence_workflow_commands.sh.fetch_p6.sh,resolve_base.sh,ci.ymlandci/sections.ymlare byte-identical.Review findings on 656bf90 (second round), and what was done
Two more non-author reviews (Sonnet 5.5), one deep on each half, approved 656bf90 with no blocking finding. Two rows they found could not fail, which is a defect in a gate, so those were fixed with the rest.
2>&1merge removed (0 rows lost).2>&1fails it (1 0 0).LC_ALL=C" read the locale the plantedgitsaw. A caller that already exportedLC_ALL=Cpassed it with the helper's ownLC_ALL=Cremoved.LC_ALL=POSIX. Thenolcmutant fails the row, and also fails it withLC_ALL=Cexported around the whole self-test.resolve_baseresolved the helper path at call time fromBASH_SOURCE. A caller that sourced it by a relative path and then cd'd, or aCDPATHwith a matchingscripts/lib, broke the path. The stacked entry was then refused (fails closed).CDPATHcleared, and the cd intoREPO_ROOTclears it too. Rows B11 and B12 are red on 656bf90 and green here. All 6 caller self-tests pass again (25, 16, 16, 56, 14 and 14 rows), and so doescheck_sourced_libs_option_neutral(12 libraries).live_commandscounted no indented command and no property value with a colon, so a log could hold more live annotations than it counted.( … ) >&2 2>/dev/nullinresolve_baseas dropping the helper's status lines.>&2points stdout at stderr first, then2>/dev/nulldrops git's own stderr. The other review read it that way too. The comment now says so.invalid refspec,--deepen and --depth are mutually exclusive,cannot lock ref) are not answers, so they cost 3 reads and 30 s of backoff before the same red.git --git-dir "$d" fetch(an option value after a blank),'git' fetch, and agit \line continuation. It flags a message such asecho "git fetch failed".ci/sections.ymltoday. A false flag is red on a clean file, never green on a bare fetch. They join$GIT fetchas known blind spots.binary-release.yml(5),guards-nightly.yml,pr-review-quorum.ymlandrc-cut.yml.ci/sections.ymlonly. Those sites need their own ticket.ci.ymlonly. A self-test step added to another workflow would not be checked.fat_driver.py self-teststeps are inci.yml.provable-ladder-nightly.ymlrunsfat_driver.py run, a real run that stays unfenced by design.bashrs reports 0 errors on all three files. The only new warnings are 2 × SC2030 on the scoped
CDPATH='' cdinside a subshell, and that scoping is the intent.Review findings on 2481ab6, and what was done
Two non-author reviews (Sonnet 5.5) approved 2481ab6 with findings. Every finding that changed behaviour got a planted row and a mutant that turns it red.
::error::was swallowed with it.resolve_base.shbuilt the helper path relative to the caller's cwd, then ran it aftercd "$REPO_ROOT". A caller in another tree lost the deepen and was refused.resolve_basecallers pass:check_roadmap_diff_additive(25/25, its row 20 deepens for real),check_hardcoded_paths,check_row_pr_write_set(14/14),check_ont_ratchet(56),check_mutants_debt_ratchet(16) andcheck_roadmap_fragment_required(14/14).gitandfetch(-c k=v,--no-pager,--git-dir=), quoted words and runs of blanks.answered()matched git's English text in whatever locale the runner had. It also re-read three answers: a usage error (rc 129), a 401 with no credentials, and "not a git repository".LC_ALL=C, and those three are answers, read once. Each rule has its own row and a mutant that fails it.sleepstubbed out, so it could not fail.sleeprecords its argument. The row wants7 14atSLEEP_S=7, and a separate row pinsSLEEP_S=10. With the sleep call removed, the row fails.lowSpeedLimit=1000for 60 s) could cut a slow but healthy fetch. One case is a server that computes a pack for over 60 s while sending only keepalives.maininto an empty repo, three times, the largest at 71 MB; depth 1 ofmainover a clone holdingmain~300; and--deepen=1. The pack request was answered in 0.72 s. No phase below 1000 B/s can last 60 s inside a 7.9 s fetch. The residual risk: a server phase over 60 s would be cut and read again, and after 3 reads the step goes red. That is the same red as today, about 3.5 minutes later.$GIT fetch(git named by a variable) is not seen by the wiring regex.ci/sections.ymlorci.ymltoday. It is listed here as a known blind spot.A. What it was
No wait was involved. x86-main runs no
--external-job, so it never waits onworkspace-test. The three early errors on #4813 (13:31:46Z) and #4913 (13:06:42Z) were:All three come from the step
fat_driver case table must still turn RED(fat_driver.py self-test), which passed 60/60 at that point. Its planted rows drive real code paths that print real::error::workflow commands: the verdict rows on fixture sectiona, and the past-deadline external-need row. GitHub turned each one into a job error annotation. The jobs went red later for other reasons:pr-review-signat 14:06:51Z.guard-tree, at its 3600 s budget, at 14:06:46Z (guard_tree.sh: name each guard, per-guard timeout, keep fixture ##[error] out of the live log #4919).The annotation list showed the 12000s line first, so it was read as the cause. The same three lines are printed in every
workspace-test-shardjob too.A. Fix
scripts/ci/fence_workflow_commands.sh -- <cmd>runs a case table between::stop-commands::<token>and::<token>::, GitHub's own mechanism for printing text without acting on it:/dev/urandom, fresh per call, and never exported, so the child cannot end the fence.::error::case table failed (rc=N): <cmd>after the fence.Both
fat_driver.py self-teststeps (x86-main and workspace-test-shard) go through it.fat_driver.py runandwaitstay unfenced, so a real deadline still annotates. The script's wiring check (no arguments) is RED on an unfenced self-test step, on a fenced real run, and on a self-test line that is anything but the fenced command (so|| true,; trueor a pipe cannot mask its rc). Its 27-row case table and the wiring check run in x86-main's cheap-checks step. The table passes 27/27 under gawk 5.1.0, mawk 1.3.4 and busybox awk.The fence stops workflow commands only. Problem matchers still act inside a stop region, and no workflow or
ci/file here registers one (noadd-matcher, nomatcher:, no toolchain action that adds one).No gate is loosened: the commands and exit codes are the same, and one guard is added. There is no report-only and no continue-on-error, and no Python is added or changed.
A. Red/green case table (measured locally)
external need: past the deadline and still absent -> failureok, and the row still prints its::error::(inside the fence)fat_driver.py runstays unfenced, so its deadline annotation stays live (wiring check on this head)PASS: 2 fat_driver self-test step(s), each fenced; no real run fenced.fat_driver.py self-testunfenced (main)if time.time() >= self.external_deadline:→if False:)BAD external need: past the deadline and still absent -> failure got=None; 1 live annotation naming the failed tablesuccess)job not listed yet -> pending,job in progress -> pending,another job's success does not count::stop-commands::line from the fence--self-testrc=1, 10 FAIL rows; real table back to 3 livefat_driver.py runfenceda last line with no newline: the fence still closes on its own line)"Live annotations" means the annotation commands outside every stop..resume region.
fence_workflow_commands.sh --live <log>counts them, and the case table uses it. It splits lines on\ras well as\n, as the runner does, and each of its rules errs on the high side, so a 0 from it is a 0 on the runner and a 1 is at most 1. Its control row counts the #4813 lines unfenced as 3. The rows that need exactly 1 also check the structure: the exact resume line on its own line, then the failure line last.Every fence mutant was built from a5e3f09 by a literal first-occurrence replacement (no regex to get wrong), checked to apply, and run against the 27-row table. No mutant failed on an awk syntax error:
2>&1mergestderr is fenced too, got1 0 0)\r\r)##[form##[<token>::stop-commands::linefat_driver.pyandself-testis foundrun:prefix is not stripped##[end, the doubt rows)One mutant survives: counting the line that ends a region (
stop = ""; returnbecomesstop = ""). It can only raise the count, so it cannot turn a check green, and no row pins it. The runner never acts on that line as an annotation: it is the resume itself, or the runner is still stopped on it.Also run on a5e3f09. All rc 0, except one test that fails the same way on main:
check_guards_are_wired,check_ci_push_reuse,check_determinism_wait,check_fat_secrets_passed,check_ci_fat_secrets_plumbedandcheck_no_timing_in_required.check_pr_review_wiring,check_explicit_test_commands,check_ci_reusable_workflow_pinned,check_coverage_has_producers,check_bin_cli_tests_wiredandcheck_model_tests_wired.check_tree_reader_tests,check_receipt_gate_base_owned,check_hardcoded_paths,check_guard_steps_run_allandcheck_sourced_libs_option_neutral.guard_tree_test(52/52) andguard_tree_parallel_test(6/6).guard_tree_job_testfails 1 of 8 here, and on main at ad8fafc the same way: its mutant sed expectsdeterminismlast in the gate'sneeds:list, so the mutant equals ci.yml. No workflow runs that test, and this PR does not touch that line. Filed as guard_tree_job_test row 5: the x86-main-dropped mutant no longer applies (sed expects determinism last) #4940.actionlint reports nothing on the changed lines; its two info findings are on a step this PR does not touch. bashrs reports 0 errors. On the fence script it gives 18 warnings: the same 18 as on b7544ba, and 3 more than the 15 on 967b7ea. Those 3 are SC2086 on
$iand$t3, both inside double quotes (false findings), and PERF002 on a 7-iteration loop in the self-test.B. Section fetches get 3 reads. This reduces fetch drops; it does not clear them
Sections died on
RPC failed; curl 92 HTTP/2 stream N was not closed cleanly: CANCEL (err 8)orcurl 56 Recv failure: Connection reset by peer. This happened on every runner host alike, on the x86-main and shard reds of PRs 4931-4935 and 4923. The depth-1 fetch ofmainin the step "Decide the test tier (BSE-17)" ran 376 s and died, although main's objects were already in the section clone. In a test clone that already holds main's tip, the same fetch moves 0 objects in 2 s. So the read stalled; it was not too big.What this does not fix. The stalls come from the egress path, so they continue until infra acts on the network.
actions/checkoutalready reads 3 times, and on #4927 all 3 reads failed. More reads can turn a dropped section fetch into a green one when one read gets through. They cannot help when every read stalls. Checkout drops are untouched here and need the same network act.Change (operator C343 #9, P6).
scripts/ci/fetch_p6.sh <git fetch args>replacesgit fetchat all 7 call sites inci/sections.ymland the 3 inscripts/ci/pin_build_base.sh(as-C <dir>). It also replaces the merge_group deepen inscripts/lib/resolve_base.sh, which section guards source.resolve_basethe deepen is two chained helper calls (--deepen=1, then the parent by sha). Its worst case is 6 reads and about 60 s of backoff (10 + 20 per call) before the entry is refused.LC_ALL=C, so those texts are git's own whatever the runner's locale.resolve_baseit goes to stderr, so no caller's$(...)captures it.http.lowSpeedLimit=1000andhttp.lowSpeedTime=60, so a stalled read ends and is read again instead of hanging the section.|| truebest-effort sites keep|| true. There is nocontinue-on-errorand no report-only.B. Red/green case table (
fetch_p6.sh --self-test, 40 rows, measured locally on a5e3f09; the 6 rows added since are listed at the top)A planted
giton PATH counts its reads and answers as each row says. A plantedsleeprecords each wait. The real-git rows use afile://remote in a temp dir.LC_ALL=C(the caller runs underLC_ALL=POSIX)-c http.lowSpeedLimit=1000 -c http.lowSpeedTime=60 fetch …, locale C7 14atSLEEP_S=7(n × SLEEP_S before re-read n+1, none after);SLEEP_S=10outside the tablegit fetch …,git -C "$ws" fetch,git -C "$a b" fetch,git -c http.version=HTTP/1.1 fetch,git --no-pager fetch,git --git-dir=.git fetch,git fetch(two blanks),cd "$ws" && git fetch; echo done,"git" fetchgit log --grep fetch,git status && echo fetch,echo "the git fetched it",legit fetchfetch_p6.shis byte-identical here; checked withcmp)P6_READS=1)P6_READS=4)answereddropped)-c http.lowSpeed*dropped)LC_ALL=CLC_ALL=Cexported by the callerresolve_basepointed at a missing helpercheck_roadmap_diff_additiverow 20 (stacked merge_group deepen, done for real) FAILsfetch_p6.sh --check-wiringon main 5a8e4b5'sci/sections.yml: rc 1, 8 FAIL lines (7 bare fetches, plus no helper call). On this head:PASS: 7 fetch call(s) in ci/sections.yml, each through the helper.The wiring check readsci/sections.ymlonly. The pin's 3 fetches are held by its P6 rows and by the three "bare fetch" mutants killed above. Both--self-testand--check-wiringrun in x86-main's cheap-checks step.Still a single read, and not changed here:
actions/checkout@v7, which already retries its fetch 3 times itself.fat_driver.py's own checkout fetch. It is Python, and a hook refuses edits to it.fetch-depth: 0checkout on a runner with no warm cache. It pulls the whole pack over the stalling path. That is host and egress work, outside this PR.Pre-push on the head ca7d665:
cargo fmt --all -- --checkand the cargo checks were not re-run. The head changes no Rust file, noCargo.toml, noCargo.lockand nothing undercontracts/:git diff --name-only 5a8e4b5f89lists 10 files (+770, -14), all workflow, YAML, roadmap and shell. So every Rust, Cargo andcontracts/file is byte-identical to main 5a8e4b5, which passed the merge queue's required checks. Earlier, on a5e3f09:cargo fmt --all -- --checkrc 0 (0 diffs) andcargo deny check advisoriesok.cargo test -p aprender-contracts --libran on 967b7ea: rc 0, 2290 passed, 0 failed, 5 ignored. It ran in a separate clone checked out at that sha. Since then onlyfence_workflow_commands.shchanged. The whole PR touches no Rust and nothing undercontracts/.Post-push proof (mechanism engaged):
::error::…text in the self-test step, between::stop-commands::and its resume line. No##[error]external jobmay appear before the first real section verdict.bash scripts/ci/fetch_p6.shwheregit fetchwas. Afetch_p6: read n/3line appears only when a read did not answer.🤖 Generated with Claude Code