fix(pm): derive the always-runs tail dispatch-gates could never name - #13501
Merged
os-project-manager merged 2 commits intoAug 30, 2026
Merged
Conversation
…13333) Report the unconditional CI steps the family derivation names NOTHING for, instead of widening a matcher for the one gate that reddened. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
…spatch-gates-always-runs-tail
os-project-manager
marked this pull request as ready for review
August 30, 2026 15:17
os-project-manager
enabled auto-merge
August 30, 2026 15:17
os-project-manager
deleted the
claude/issue-13333-dispatch-gates-always-runs-tail
branch
August 30, 2026 15:41
This was referenced Aug 30, 2026
Closed
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.
Fixes #13333
Triage adjudicated option (b) on this card — have
dispatch-gatesenumerate theunconditional
Lint & Repo Gatessteps as an "always runs" tail — and explicitlyrefused option (a), adding
check-reference-carrier-shapeto the derivation. Thisimplements (b), derived rather than hand-listed.
What was measured first
Reproduced on current
origin/main, with positive controls, because the card's ownfigures had drifted:
reference-carrierindispatch-gates.mjswhere-matcher, same filecheck-reference-carrier-shapeinlint.yml:3281-3284:3338-3339--residueuniverse of 187 familiesturbo-task-graph1,where-matcher2So the gate is not in the
silentbucket and not inundetermined— it is in nobucket at all, the one output shape this file's contract forbids.
H1 as stated is FALSIFIED, and the falsification changes the fix
The sharpened mechanism on the card is "every package-local script invoked by path
inside a multi-line
run: |block". Measured over all 26 workflows:run: |half is already handled —runCommandTextshas read block-scalarbodies since [finding] dispatch-gates.mjs does not derive pr-automation.yml's Check Changeset for
.changeset/paths — a breaking changeset shipped locally-green and went red only in CI #8410, and 3 of the 5 invisible gates are plain one-linerun:steps.It is not a reason today at all.
(
packages/cli/bin/run.jsis the other package-localnodeinvocation and is a CLIsmoke run, not a gate.)
A fix built on that mechanism would therefore have been option (a) with extra steps.
The population that is real is the one triage named — unconditional steps — and
it is invisible for at least three unrelated reasons: a package-local path, an
interpreter that is not
node, and a root script not namedcheck:*. That is why nofourth widening of the three matchers was going to be the last one.
The coverage measurement triage asked for
Derived live, on the merge commit of this branch:
with no
paths:filter, in jobs and steps with noif:(11 conditional jobs and 12conditional steps excluded, and both counts printed rather than dropped);
Proof that it reaches the CLASS, not the instance
The tail names the card's gate and members invisible for different reasons:
pnpm lintand the twobash … --self-teststeps are real verification that nowidening of the
node scripts/…matchers would ever have reached.That claim is a self-test case, derived live, not a sentence here: the tail must contain
a member whose interpreter is not
nodeand that member must not be the card's owngate. Reverse verification (ablation, run against the committed implementation, the
mutation confirmed on disk by object hash
8e8d9489->ac39a3dfbefore any reading,restored and re-proved byte-identical to the
HEADblob afterwards):The instance case (
a package-local gate invoked by path IS in the tail) stayed greenthrough that ablation — which is exactly the discriminator between (a) and (b).
Why this is not "22 leads is the same as none"
The header's refusal stands: 166 of 189 discovered families sit outside both path
declarations CI obeys, and naming them per card would say nothing. This tail is the
complement of that set, not a slice of it — a step leaves the list the moment the
derivation names any family for it, so it is bounded by the derivation's own blind spot
and shrinks as discovery improves. It carries no per-card claim and says so.
What it deliberately does NOT do
check-reference-carrier-shape, or extend discovery to reach it.pnpm installandpnpm lintareboth in the tail; every rule separating them is a guess about a step's intent.
about derivation on a stale tree ([finding]
dispatch-gates.mjsEXITS 0 on a STALE TREE — a green-looking answer that silently omits newly-landed gate families; cost one CI cycle today, and was caught by luck on a second PR the same hour #13392), fabricated leads ([finding]dispatch-gates --residueprints THREE fabricated leads for check:query-options-erasure — literals naming files that have never existed, unannotated because one live sibling keeps the family reachable #13312, [finding]check:doc-anchorsdeclares a fabricated watch hintscripts/scripts/check-doc-anchors.mjs— a remedy string meant to run from the repo root is resolved module-relative, doubling the prefix #13449) ordownstream truncation (A
pnpm check:harvest ofdispatch-gates.mjsoutput silently drops a third of the gate list #13462), and a gate unreachable for the [finding] dispatch-gates never names a family for an edit to a first-party module its gate script IMPORTS — 228 (family, module) pairs unreached, measured #13126 reason isdiscovered, so the tail does not name it either. The header states this so a green tail
is not read as the class being closed. [finding] an
.objectui-shadiff derives NO pin-critical gate — the gates a pin bump most needs are the ones structurally excluded from path derivation, and one of them shipped a red on PR #12955 #12956 is not folded in and is not touched.Verification
All on
263b4923, exit codes captured before any pipe.check:pm-dispatch-gates— EXIT=0,✓ dispatch-gates self-test: 976 cases pass.(944 -> 976, +32 cases: the walk's fixtures, the renderer's refusals, and the live
class pins.)
bare-root-worklist.mjs --self-test— EXIT=0,OK self-test: 51 live row(s), 43 unreachable as spelled, 43 recorded verdict(s) — none stale, none missing, none contradicted.dispatch-gatesderives for this diff — all EXIT=0, includingcheck:watch-hint-literal,check:entry-guard,check:parse-guard,check:self-test-wired(✓ every one of the 152 script(s) CI runs that ship a --self-test has that self-test run by CI)and
check:nul-bytes.check-test-completeness.mjs— EXIT=3 = NOT MEASURED, neither red nor green, perits own printed refusal.
eslint scripts/pm/dispatch-gates.mjs --no-inline-config --format json-> EXIT=0, 1 file, 0 errors, 0 warnings, 0 suppressed. The narrowing issound because (i) the linted population and the rules are read from ESLint's own
--print-configfor this path, not guessed — 2 rules apply,comment-swallow/no-code-inside-block-commentandno-restricted-imports; (ii) the filecount is ESLint's own
--format jsonoutput; (iii)eslint.config.mjsstates, with arecorded positive-control measurement, that this repo never enables type-aware linting
for any file (
no parserOptions.project, no typed @typescript-eslint rules), confirmedlive here (
parserOptions.project present: false), so a one-file diff cannot move anyuntouched file's verdict. The repo-wide
eslint .is CI's run.scripts/pm/**only and publishes from no package, soskip-changesetis applied on this PR.Generated by Claude Code
Generated by Claude Code