Uh oh!
There was an error while loading. Please reload this page.
fix(devx): dispatch-gates drift banner scopes its quiet line to the visible range and refuses the unqualified all-clear - #13418
Merged
os-project-manager merged 1 commit intoAug 30, 2026
Conversation
… range and refuses the unqualified all-clear The quiet branch printed 'nothing this answer derives from changed across that range' from a reading whose range ends at the last-fetched snapshot of the base ref. Measured on a production incident: the snapshot was at most ~13 minutes old, the visible reading exact, and upstream landed four derivation-surface commits between derivation and the CI run that consumed the answer — one carrying the very family whose absence turned CI red. The sentence is not earnable by any local instrument, so it now states what it measured (the VISIBLE commits are surface-clear), states the unseen half as untellable, and hands over the fetch. A second unearned-reassurance door closed with it: a failed three-dot diff read collapsed into changed: [] and rendered the same quiet clear sentence from no reading at all. A shallow clone plus one shallow fetch reaches it (measured: the count reads 1, the diff dies with no merge base). changed is now null when unread, unmeasuredDrift gains the third door, and the self-test pins both doors from literals and from a real depth-1 fixture. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
os-project-manager
marked this pull request as ready for review
August 30, 2026 11:21
os-project-manager
enabled auto-merge
August 30, 2026 11:21
Uh oh!
There was an error while loading. Please reload this page.
os-project-manager
deleted the
claude/issue-13392-stale-tree-honest-refusal
branch
August 30, 2026 11:54
This was referenced Aug 30, 2026
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 freeto 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.
Fixes#13392
Per the dispatch ruling, this lands the corrected card's option D — fix the determination itself — and deliberately does NOT layer a non-zero exit or a stdout incompleteness marker on top of it (the exit-code question once the determination is trustworthy is a follow-up card). The loud STALE TREE branch, the three-dot diff direction, and the silence at zero are untouched; no existing refusal is weakened. Everything below strictly adds refusals.
What changed
1. The quiet line no longer asserts what it did not measure. The old spelling —
At least N commit(s) behind origin/main, but nothing this answer derives from changed across that range— was a claim about a range the instrument cannot see the end of: the diff runs against the LOCALorigin/mainsnapshot, which only a fetch moves, while a reader takes "that range" to reach upstream. The new spelling states exactly the reading taken and refuses the rest, in two lines:...and none of the commit(s) this tree can SEE touched what this answer derives from...followed byWhether UNSEEN upstream work did, this run cannot tell: the range above ends at origin/main, a LOCAL snapshot only a fetch moves — not at upstream, plus the fetch remedy. A true "I cannot tell" replaces a sometimes-false "nothing changed".2. A second unearned-reassurance door is closed. When the three-dot diff READ failed, the old producer collapsed it into an empty changed-set (
names ? split : []), and the render printed the same reassurance from no reading at all.changedis nownullwhen unread and an array only when read;unmeasuredDriftgains a third door that refuses in the register the other two already use (STALENESS NOT MEASURED ... The changed set is UNKNOWN. Not empty: no reading was taken.), naming the step that failed and the diff command as its remedy. This state is one command away in production, not hypothetical: a depth-1 clone — which is how this fleet's containers arrive — plus one shallow fetch counts a distance fine (rev-list --countanswered 1, exit 0) while the three-dot diff dies withno merge base(exit 128). Measured in a sandbox and re-measured by the new self-test fixture.The measured mechanism (Zone 2 verification)
The PM's hypothesis was "the #13369 worktree had an unfetched base". Measured, the mechanism is sharper and worse:
check:doc-authoringcross-package prose-id leg) touched exactly 4 files, all underscripts/— insideDERIVATION_SURFACE. Alternatives (a) surface-misses-the-path and (b) family-derives-off-surface are dead: after merging main, re-derivation on test(qa): census the authz-conformance probe table's reach across all 11 probe files #13369 gained exactly that family, so the surface and the matcher see it whenever it is on disk.behind ? read : emptyshort-circuit, was not the emitter: the quoted first-run line saysAt least 1 commit(s) behind, which requires a truthybehind, so the diff ran — and the visible diff genuinely was empty. (The adjacent failed-read door is real anyway and is closed by change 2.)3ec8646f(landed 06:08:09Z). Its final pre-fix commit is 06:41:04Z; the PR opened 07:07:13Z with the union results already in its body, and the union includes an 85-second repo lint plus 24 families — so the derivation ran in the window 06:41 to roughly 07:00. The reading it printed — behind 1, changed empty — is exactly what a snapshot at56c5b1db(PR 13316, landed 06:32:24Z, plugin-email only, off-surface) yields. That snapshot was AT MOST ~13 minutes old at derivation, possibly minutes. The falsifying landings came after the snapshot and mostly after the derivation:54cc1555(scripts, 06:45:04Z), then four more, then Rule 3 root extension: a ledgered cross-package prose-id leg on check-doc-authoring, sized by its own AST census #13355 itself at 07:05:43Z — about 20 minutes after the derivation and 11 minutes before the CI run (07:16:21Z) that consumed the answer and reddened on the missing family.Self-tests (ruling obligation 4)
New cases pin both doors from literals and from a real depth-1 fixture, with the required red demonstrated by ablation:
can SEE), states the unseen half as untellable (cannot tell), hands over the fetch, and a departure pin with a length-and-content conjunct asserts the retired spelling is gone — it cannot pass vacuously against an empty render.Not empty), names the base and the count so the reader can tell WHICH step failed, and its remedy is the diff, not the fetch or the count; the three unmeasured doors render distinctly.null, render refuses, and no line reassures while a surface commit sits in the unreadable range.Ablation, both legs predicted before running, mutations and restores proven on disk (anchored grep counts, then blob hash against the HEAD blob; restores byte-identical,
git diff HEADempty; the subject runs from source, so no build sits between the edit and the run):Verification
Union derived on the final head — the derivation's own stderr names
objectstack-ai/objectstack at commit a1d5df1d, change set 1 path vs merge base090f2302e— 14 matched families, all run at that head:check:pm-dispatch-gates("919 cases pass"),check:self-test-wired("every one of the 151 script(s) ... has that self-test run by CI"),check:agent-test-spelling,check:bash32-floor,check:cli-command-ids,check:entry-guard,check:parse-guard,check:pnpm-filter-targets,check:watch-hint-literal,check:cross-package-test-inputs("OK: 24 package(s) read outside themselves, all declared"),check-ci-filter-parity("OK: all 123 declared cross-package glob(s)"),check-cross-package-test-inputs,check-shard-attestation("2 aggregate gate(s) count 3 declared leg(s)").check-test-completenessexits 3 with "PREREQUISITE NOT MET — this gate grades a saved turbo run test log ... the local reading for this gate is NOT MEASURED. It is not a red."node scripts/pm/bare-root-worklist.mjs --self-testOK ("51 live row(s) ... none stale, none missing, none contradicted");check:nul-bytesOK (7433 files, no raw control bytes).scripts/pm/dispatch-gates.mjs, from the derivation stderr);--format jsoncounted 1 file linted, 0 errors 0 warnings, exit 0; and the config is not type-aware (no project service for these files — stated at eslint.config.mjs line 328), so this diff cannot move any untouched file's verdict.No changeset: the diff publishes nothing — it is entirely
scripts/pm/(PM tooling), which is the skip-changeset class; the label is applied with this PR's opening.The report with the full measurement record is on the card as an
os-dev-reportcomment.Generated by Claude Code
Generated by Claude Code