Uh oh!
There was an error while loading. Please reload this page.
fix(pm): declare the runtime-enumerated gate populations dispatch-gates could never name (#10542) - #11189
Merged
Conversation
…es could never name (#10542) Seven of the discovered gate families compute their population at RUNTIME by parsing pnpm-workspace.yaml, so they spell no path literal and the dispatch derivation named them for no card in the tree. Re-measured on current main the class is 8 unrescued families across 137 discovered, not the 5 of 119 the card recorded — the instrument moved when the tree did. Read each one against its source rather than declaring a blanket population, and the readings disagree with the card in one place that matters: check:published-files DECLARES the workspace globs. It walks and judges every non-build file of every publishable member — 4803 of the 5263 files the declaration names, 91.3%. Reconciled against the live parse in its self-test, so a workspace root that moves fails here. check:published-readme-exports REFUSES the same declaration, against the card's own triage. It narrows the same walk to published markdown and manifests: 149 of 5263, 2.8% — the `filtered` shape check-examples-live-imports refuses by name at 1.6%. Recorded with the measurement and pinned, so a later author meets an assertion. check:pnpm-filter-targets DECLARES scripts/** (228 of 235, 97.0%); the per-member manifest half has no truthful spelling and stays a documented blind spot. check:cross-package-test-inputs moves to CHANGE_KIND_GATES instead: its judged population IS the test-file kind, and a subtree declaration would name it at 49.6%. check:release-body declares no path population, with a reason. check:prerelease-pins likewise — its population is one repo-root file its own workflow already names in `paths:`, so the CI-trigger key reaches it. check:dev-prereqs needs nothing: its one hint is honest. The instrument grows the half that made the count unreadable: a gate may carry `dispatch-gates: no-path-population -- <reason>` in its own source, mirroring the workflow-level marker one level down, and the residue reports those apart from the families nobody has examined. A declaration is not an escape from having a population, and the self-test holds that line against the live tree. The shared workspace-enumerator consolidation the card proposed is NOT done, and the reason is now an assertion rather than a paragraph: resolveCheckToFiles reads the script paths out of the npm script's COMMAND STRING, so a module a gate imports is never opened. Moving a population declaration into a shared enumerator would DELETE it from every gate that imports it — undoing #10540's declarations and this card's. The consolidation is blocked on teaching the derivation to follow first-party imports, not on the gates. Co-Authored-By: Claude <noreply@anthropic.com>
os-zhuang
commented
Aug 23, 2026
ContributorAuthor
ACCEPT — session 逐文件读完全量 diff(7 文件,+522/−22,head
按普通队列落地:flip ready + auto-merge(SQUASH)。 Generated by Claude Code |
os-zhuang
marked this pull request as ready for review
August 23, 2026 02:00
os-zhuang
enabled auto-merge
August 23, 2026 02:00
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 23, 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#10542
scripts/pm/dispatch-gates.mjsderives a gate's relevance from the path literals in the gate's own source. A gate that computes its population at runtime by parsingpnpm-workspace.yamlnames no literal at all, so the derivation could name it for no card in the tree. This closes that class per-gate, with the reading the card itself asked for first — and one of those readings disagrees with the card.The measurement, before and after
Reproduced the way #10542 specifies: build the family table the way
derive()does, then askcoveringKey(entry, specimen)for each of the four layout specimens —packages/cli/src/index.ts(flat),packages/services/service-cache/src/index.ts(nested),apps/docs/package.json,examples/showcase/package.json.The tree moved under the card, in both directions: the class grew from 5 unrescued to 8, and the discovered farm from 119 to 137.
check:test-source-aliasandcheck:type-source-resolutionstill name all four (PR #10540), so the instrument tracks the tree rather than reporting a constant.Of the 8, two moved out and four are now recorded as correct-by-reading rather than unexamined:
pnpm check:published-filesgate source 'packages/*'/'apps/*'/'examples/*'pnpm check:pnpm-filter-targetsscripts/**cards (e.g.scripts/check-nul-bytes.mjs) — not the four specimens, deliberatelypnpm check:cross-package-test-inputsCHANGE_KIND_GATESPer-gate classification — which refusal each is actually under
Verified against current source, not the card. The decision rule is the one
check-examples-live-imports.mjsalready sets and pins: declare a root the gate walks wholesale, refuse one it merely traverses to reach a narrow subset — with the precision measured, not asserted.check:published-filespackages,apps,examples) refused as too genericworkspaceGlobs()parse in its self-testcheck:published-readme-exports.md+ manifests + thedisttype entrycheck:pnpm-filter-targetsscripts/and.github/workflows/whole; reads onepackage.jsonper memberscriptsspelledjoin(root, 'scripts')— a bare word, dropped beforehintCoversis consultedcheck:cross-package-test-inputs(×2 invocations)packages/apps/examplesfor tests reading outside their own packageCHANGE_KIND_GATESunder "adds or edits a test file", which is the granularity it actually judgescheck:release-body--self-testalone; the workspace/CHANGELOG reads belong to the release runisNonPathNamespacemedia-type refusal the card namesno-path-populationmarker with a reasoncheck:prerelease-pinspnpm-workspace.yamloverridesand npm, nothing elseprerelease-pin-watch.ymldeclarespnpm-workspace.yamlinpaths:, so the CI-trigger key (#9171) reaches itcheck:dev-prereqs--self-testonly (the step name says so); the scan is apnpm devpreflightpackages/spec, is honest — the freshness half really reads that distsilentelsewhere is the right verdictThe card said of the published-files pair that "their population genuinely is the workspace and the #10114 escape applies directly". It applies to one of them.
check-published-readme-exports.mjswalks the same members and then keeps only the markdown, so the same declaration would paste it into every prompt whose surface brushes any package source file with 97 of every 100 leads naming a gate that never opens the file — the shapecheck-examples-live-imports.mjsalready refuses by name at 1.6%.The instrument change: documented non-coverage
undeterminedis the honest verdict and was an unreadable report — the bucket holds gates the derivation cannot place, gates it need not place, and gates it already places through a trigger, and nothing told them apart. #10542 was filed against a count of that pile.A gate may now carry, in its own source, a whole-line
mirroring the workflow-level
no-check-familiesmarker one level down, and for the same reason: a roster indispatch-gates.mjswould be a second copy of a fact that belongs on the thing it describes. The residue reports those apart from the unexamined remainder and prints each reason against its family under--residue. A reason is required; the marker is not an escape from having a population, and the self-test asserts against the live tree that no family both declares one and names paths anyway.The shared enumerator refactor — deferred, with the reason pinned
The card called the twelve private
pnpm-workspace.yamlparsers "the same refactor as the fix rather than a separate one". Under the current derivation it is the opposite, and this is now an assertion rather than a paragraph:So moving a population declaration into a shared enumerator would delete it from every gate that imports it — silently undoing #10540's declarations and the ones this PR adds. The consolidation is blocked on teaching the derivation to follow first-party imports, not on the gates, and is filed separately. The new self-test case pins the import opacity so a later author measures it instead of trusting this paragraph.
Gates run — all green at
5f8e2b4e67Derived with
node scripts/pm/dispatch-gates.mjson the real change set (no hand-written path list), re-derived after the final commit — same 12 families, no additions. Exit codes captured before any pipe.pnpm check:pm-dispatch-gates✓ dispatch-gates self-test: 557 cases pass.pnpm check:published-files✓ check:published-files — 69 publishable package(s) of 78 workspace member(s) …+✓ … 21 pattern case(s), 12 classification case(s) and 4 population-declaration case(s) over 11 live workspace glob(s).pnpm check:published-readme-exports✓ check:published-readme-exports --self-test — …, full scan green on a built tree (319 documented symbols checked)pnpm check:pnpm-filter-targets✓ check-pnpm-filter-targets --self-test: 40 assertions …+✓ check:pnpm-filter-targets: 121/149 --filter occurrence(s) … 0 deadpnpm check:release-bodypnpm check:cross-package-test-inputs/node scripts/check-cross-package-test-inputs.mjspnpm check:entry-guard,pnpm check:parse-guard,pnpm check:nul-bytesnode scripts/check-ci-filter-parity.mjsnode scripts/check-dev-prereqs.mjs --self-test,node scripts/check-prerelease-pin-watch.mjs --self-testcheck:published-readme-exportsandcheck:published-fileswere re-run afterturbo run build— the first refuses an unbuilt tree by design and every finding said so.Lint, narrowed with its evidence.
eslint --no-inline-configover the 7 changed files: 7 files linted, 0 errors, 0 warnings (count read from--format json, not from the console). The narrowing is a measurement rather than a skip because the population is read from the config itself, which states it enables "noparserOptions.project, no typed@typescript-eslintrules) for ANY file" — with type-aware linting off, this diff cannot move the verdict on any untouched file.Reverse-verified. The new refusal assertion in
check-published-readme-exports.mjswas ablated under a restoringtrap: injecting a workspace glob into the declaration (mutation confirmed on disk by grepping both the removed and the injected spelling — old 1→0, new 0→1) turned the self-test red with the intended message, and the restore leg was confirmed by the same grep. Direction as predicted.Landing class.
node scripts/pm/check-governed-merges.mjs --test $(git diff --name-only)on the final file list:Changeset. Scripts-only, CI-internal — the textbook
skip-changesetcase by lint.yml's own prescription ("this PR edits a CI-internal script is the textbookskip-changesetcase — such a PR releases nothing"). Label applied and read back; the changeset-family self-tests in lint.yml are unconditional and unaffected.Files
scripts/pm/dispatch-gates.mjs— theno-path-populationmarker, its residue accounting, theCHANGE_KIND_GATESentry, and the pinning cases for all of itscripts/check-published-files.mjs— population declaration, reconciled against the live parsescripts/check-pnpm-filter-targets.mjs— the scripts-subtree declaration + the workspace-globs refusal, both pinnedscripts/check-published-readme-exports.mjs— the measured refusal, pinnedscripts/check-prerelease-pin-watch.mjs,scripts/release-github-releases.mjs— markersscripts/check-dev-prereqs.mjs— header note recording why it needs neitherGenerated by Claude Code
Generated by Claude Code
Generated by Claude Code