fix(pm): dispatch-gates names every CI-run gate — whole-tree census gates join the declared bucket, residue measured - #15344
Merged
Conversation
…he repo root `check:driver-memory-census` counts a `vi.mock` of a frozen driver package as a module binding wherever in the tree it is written, and names no path literal in its source — so the dispatch derivation scored it `undetermined` for every card and no `--commands` harvest could contain it. A seat derived its family, ran 57 of them with 53 green, and CI's lint job then failed on the one gate the derivation could not offer. The gate's truthful population is the whole repository, so it now says so with the `whole-tree-population` marker the bucket already uses, vouched by the liveness predicate that reads its `git ls-files` enumeration. Fixing one gate is not the fix. `ROOT_WALK_RESIDUE_LEDGER` and its live `--self-test` case make the class computed: every family whose own source carries a recognised repo-root walk must declare whole-tree, declare path-less, be derivable by path, or hold a justified exclusion row. The next unnamed census gate reds in `check:pm-dispatch-gates` instead of in CI a cycle later. The wider residue was measured rather than guessed: of the 186 gate scripts CI runs, 44 are named by no derivation. The remainder are subtree walkers whose remedy is the ordinary ROOT_DIR_WATCH_HINTS declaration, one per-gate judgement each; that class is filed separately rather than swallowed by a forty-row table nobody would revisit. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
This was referenced Sep 4, 2026
baozhoutao
marked this pull request as ready for review
September 4, 2026 12:47
baozhoutao
enabled auto-merge
September 4, 2026 12:47
This was referenced Sep 4, 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 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 #15312
The defect, and the shape of the fix
check:driver-memory-censuscounts avi.mockof the frozen@objectstack/driver-memorypackage as a module binding wherever in the tree it is written, and names no path literal anywhere in its source.scripts/pm/dispatch-gates.mjstherefore scored itundeterminedfor every card in the repo, so no--commandsharvest could contain it. The seat on PR #15282 derived its family, ran 57 of them with 53 green, and CI'sLint & Repo Gatesfailed on the one gate the derivation could not offer.The card's⚠️ is binding and is honoured: nothing here widens what a seat is told to run by hand. Every change below is computed from the tree at runtime.
1. MEASUREMENT — which gates does CI run that no derivation can name
Measured mechanically at
cd1f8ee96, not recalled. Column A is every gate script CI runs, taken fromcheck-self-test-wired.mjs's owncollectInvocations(an independent parser, deliberately notdispatch-gates' discovery, so a discovery gap surfaces as residue too). Column B is the union of whatdispatch-gatescan ever name: the matched derivation over the whole tracked tree as one maximal card, plus the convention block, plus the whole-tree bucket, plus the artifact-roster block.The probe card for Column B is the whole tracked tree minus each family's own file closure. That subtraction is load-bearing: every family matches the card that edits the gate itself through the identity key, and counting that as "the derivation can name it" scores the entire population green on a card nobody files. Without it the residue measures 14; with it, 44.
check:driver-memory-censusis in the pre-fix residue — the card's positive control, confirmed rather than assumed.A. CI runs it, but it is not a
check:*family — 13scripts/assert-console-spec-injection.mjscheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/build-console.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/collect-release-notes.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/console-spec-probes.mjscheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/downstream-smoke.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/gen-sdui-manifest.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/pm/os-regen-merge.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/pm/os-verify-lock.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/publish-smoke.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/release-publish.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/release-spec-changes.shcheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/sync-protocol-version.mjscheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionscripts/vitest-worker-cap.mjscheck:script or anode scripts/check-*.mjsstep — outside the derivation's population by constructionB. declared no-path-population (examined; the derivation prints the reason) — 3
check:objectui-bumpcheck:pm-clause2-carrierscheck:release-bodyC. carries a repo-root walk — the ledgered class — 4
scripts/check-console-intercept-disarm.mjs --self-test · scripts/check-console-intercept-disarm.mjscheck:org-identifiergit ls-filesenumeration of the tracked corpus; ROOT_WALK_RESIDUE_LEDGER rowscripts/check-skill-frame-freshness.mjs --self-testscripts/symbol-anchors.mjs --self-testgit ls-filesenumeration of the tracked corpus; ROOT_WALK_RESIDUE_LEDGER rowD.
--self-test-only family of a shared library — 6scripts/import-prerequisite.mjs --self-testscripts/invoked-as.mjs --self-testscripts/js-comment-mask.mjs --self-testscripts/partition-test-shards.mjs --self-testscripts/pm/git-history.mjs --self-testscripts/ts-parse.mjs --self-testE. Column-A parser artifact — 1
scripts/check-reference-carrier-shape.mjsscripts/, so it keys lint.yml'snode packages/lint/scripts/check-reference-carrier-shape.mjsto a root path that does not exist. dispatch-gates does not discover the real invocation either — its DIRECT_CHECK_INVOCATION is anchored the same way.F. names no path literal and carries no repo-root walk — the FOLLOW-UP class — 16
scripts/check-declaration-mirrors.mjs --self-test · scripts/check-declaration-mirrors.mjsreaddirSync), seeded from runtime literal(s) this scan could not read — remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:init-service-contractreaddirSync), seeded from runtime literal(s)packages— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:live-db-isolationreaddirSync), seeded from runtime literal(s)packages,apps,examples— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:meta-type-normalizedreaddirSync), seeded from runtime literal(s)packages— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:optional-error-sinkreaddirSync), seeded from runtime literal(s)packages— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:resume-authority-declaredreaddirSync), seeded from runtime literal(s)packages,examples— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:runner-env-posturereaddirSync), seeded from runtime literal(s)packages,apps,examples— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationscripts/check-sdui-manifest.mjs --self-test · scripts/check-sdui-manifest.mjscheck:settings-bind-windowreaddirSync), seeded from runtime literal(s)packages— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:startup-registry-verdictreaddirSync), seeded from runtime literal(s)packages— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:tenant-chokepointcheck:verify-stand-inreaddirSync), seeded from runtime literal(s)packages,examples— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:wildcard-fallthroughreaddirSync), seeded from runtime literal(s)packages— remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:publish-smoke-pincheck:stall-guardreaddirSync), seeded from runtime literal(s) this scan could not read — remedy is the ordinary ROOT_DIR_WATCH_HINTS subtree declarationcheck:docs-image-tag-syncTOTAL RESIDUE: 43
2. THE FIX for the class the card names
scripts/check-driver-memory-census.mjsjoins the existing "declared WHOLE-TREE and named on every card" bucket, in the shape the bucket already uses — thedispatch-gates: whole-tree-populationmarker, with a required reason, backed by the published liveness predicate reading itsgit ls-filesenumeration.The declaration is truthful and was read rather than assumed:
candidateFiles()enumerates every tracked*.ts,*.tsx,*.mts,*.ctsand everypackage.jsonin the repository, with a repo-root walk as the non-git fallback. No subtree narrows it. This is the same shape as two families already in the bucket (check:watch-hint-literalandcheck-comment-mask-corpusare type-filtered whole-tree walks, not literally every byte).The always-runs bucket goes 6 to 7, and its liveness row prints beside it:
Residue gates that are NOT whole-tree are not widened into the bucket. Four carry a recognised repo-root walk and are still not whole-tree; each gets a justified
ROOT_WALK_RESIDUE_LEDGERrow saying what it reads instead (group C above). The 16 in group F need a per-gate reading the card did not make, and are filed as a follow-up rather than guessed at.3. THE REGRESSION GUARD, computed
ROOT_WALK_RESIDUE_LEDGERplus a live--self-testcase, following theCOMPOUND_ANCHOR_LEDGERconvention in the same file (a literal table, a maintenance docblock, and a live case that reds on both an unlisted member and a stale row).The case asserts: every family whose own source carries a recognised repo-root walk must declare whole-tree, declare path-less, be derivable by path, or hold a justified exclusion row. Two controls make it an instrument rather than a sweep that quietly finds nothing — the population must be non-empty, and the card's own specimen must be seen to have left it through the bucket and not through the ledger.
RED on the pre-fix residue, proven by ablation (mutation confirmed on disk, restore proven by matching blob hash and an empty
git diff HEAD):GREEN after:
✓ dispatch-gates self-test: 1392 cases pass.No existing case is weakened or deleted — the diff is additive only (0 deletions indispatch-gates.mjs), and the ablated run registered the same 1392 cases with 2 failing.The card's scenario, reproduced as a clean A/B
A test file under
packages/**carryingvi.mock('@objectstack/driver-memory', …), derived on both trees with the identical single-path card so the gate's own identity key cannot contaminate either side:Exactly one row moves. On the base tree the same file as a scratch commit under
--changed --commandsderives 36 commands with the census gate absent.Verification
Union run at
c1c5f96bb, the final commit.node scripts/pm/dispatch-gates.mjs --self-test—✓ dispatch-gates self-test: 1392 cases pass.(exit 0, foreground underscripts/pm/os-verify-lock.sh)--changed --commands --repo objectstack-ai/objectstack— 23 commands, every one run, all exit 0.✓ dispatch-gates --ran: 23 derived famil(ies) accounted for — 23 run, 0 NOT-MEASURED.✓ check:declared-population-live — 201 of 252 famil(ies) declare a path population, and every one of them reaches this tree's 7442 tracked file(s).check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states "#6664 census: 2 ruled consumers".✓ check-self-test-workflow-commands: no self-test CI runs prints a line the Actions runner would parse as a workflow command.plus its--self-test(23 cases, every battery at or above its pinned floor)check:nul-bytes,check:watch-hint-literal,check:ratchet-remedy-authority,check-self-test-wired.mjs(+--self-test) — exit 0pnpm lint(eslint . --no-inline-config) — exit 0, no findings. Not narrowed.skip-changeset:scripts/**only, nothing published from any released package.Follow-ups filed
The residue beyond the card's class is filed rather than swallowed, so the boundary is a card and not an omission. Neither is addressed here; both stay open.
silent/ artifact-roster class); remedy is the ordinaryROOT_DIR_WATCH_HINTSidiom, one per-gate reading each. Landingcheck:org-identifierthere should also clear itsROOT_WALK_RESIDUE_LEDGERrow — the ledger's live case reds on a stale row, so the two moves are coupled by construction.scripts/, so lint.yml's package-local check-reference-carrier-shape gate is invisible to one and mis-keyed by the other #15342 — group E.lint.ymlrunsnode packages/lint/scripts/check-reference-carrier-shape.mjs, and bothdispatch-gates'DIRECT_CHECK_INVOCATIONandcheck-self-test-wired'sINVOCATION_REare anchored onscripts/: the first never discovers it at all, the second keys it to a root path with no file behind it. Strictly worse than this card's shape — there is nothing in--residuefor a seat to read and decline.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code