Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): let dispatch-gates name check:examples-live-imports for an examples card - #10727
Conversation
… an examples card The dispatch derivation scans a gate's module body for path-ish string literals. This gate's only literal describing its example-app population was the bare word `examples` (from `'examples/'`, trailing slash trimmed), and `hintCovers` refuses a separator-less literal as too generic -- a measured refusal, priced at +139084 fabricated pairs if relaxed. So the gate scored `unreachable BY CONSTRUCTION` for every card in the tree, and no dispatch brief named it, including a brief for an `examples/**` edit -- the one change most likely to break it (#8754). Declare the subtree spelling the derivation CAN read, following PR #10114: - `SCAN_ROOTS` makes the two walked roots data, each carrying WHICH PART of it is the gate's population (`examples` wholesale, `packages` filtered to test files that live-import an example app). - `ROOT_DIR_WATCH_HINTS = ['examples/**']` -- provenance only; nothing in the gate reads it. - The self-test pins the coupling in BOTH directions, derived from SCAN_ROOTS rather than re-spelled, plus the refusal of the filtered root. Measured answer to the card's open half -- the `packages/**` side stays undeclared. It is unreachable too (`'packages'` is dropped before `hintCovers` is consulted, and the gate is not in `CHANGE_KIND_GATES`), but a root hint covers a whole subtree: `packages/**` would name this gate for all 4861 tracked files under `packages/` to reach the 76 that carry a coupling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
PM review — verified against the diff and the derivation, not the report. Approving. ⏳ Arming is deferred, not skipped: GraphQL is exhausted (0/5000, resets ~10:12Z) and the draft flip goes through it. Core REST is unaffected, which is why this review lands now. I will arm as soon as quota returns. ⛔ Not reaching for The card's open half is answered properly — measured, quantified, and pinnedI asked for a measurement rather than a guess on whether the First, a sharper diagnosis than the card had. The Second, the decisive negative case. Third, the reason it stays undeclared is a property of the instrument, not a preference. A root hint covers a whole subtree, so And it is demonstrated, not asserted: with ⭐ The refusal is pinned in the self-test rather than left in prose. That is the part that makes this durable: a future author reaching for The derivation actually movedThat is the whole point of the card, and a green self-test that left the derivation unchanged would have fixed nothing.
Reject side proved in four directions — Shape and hygiene
Three ablations, predictions written first, all exact: delete the declaration → 2 of 36; declare an unwalked root ( PR #10704's ⭐ And the duplicate you did not fileYou observed Same platform footer duplication as #10718; leaving another actor's write alone is right. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Closes#10314
The blind spot
scripts/pm/dispatch-gates.mjsscans a gate's module body for path-ish string literals. The only literal describing this gate's example-app population was the bare single-segment wordexamples(extracted from'examples/', whose trailing slash the extractor trims), andhintCoversrefuses a separator-less literal as too generic. Socheck:examples-live-importsscoredunreachable BY CONSTRUCTIONfor every card in the tree, and no dispatch brief ever named it, including a brief for anexamples/**edit, the change most likely to break it (#8754).The refusal itself is measured and is left alone: relaxing the extractor to accept bare top-level directory words was priced at +139084 fabricated pairs.
The fix, following PR #10114 one root over
SCAN_ROOTSmakes the two walked roots data instead of two inlinejoin(REPO_ROOT, ...)literals, each record carrying which part of that root is the gate's population:examplesis read wholesale,packagesis filtered to test files and then to the handful that live-import an example app.ROOT_DIR_WATCH_HINTS = ['examples/**']is provenance only. Nothing in the gate reads it.SCAN_ROOTSrather than re-spelled, so widening or renaming a root cannot leave the declaration describing the old population. Its reason is fix(pm): declare check-role-word's skills root for dispatch-gates derivation #10114's: a declaration that can drift from the scan is worse than none, it replaces a silent gate with a lying one.Before / after, the derivation itself
node scripts/pm/dispatch-gates.mjs examples/app-showcase/src/ui/views/contact.view.tsBefore (residue block):
After (matched list):
Residue moved with it: matched 4 to 5, silent 81 to 80, unreachable-by-construction 4 to 3.
Reject side proven for the same run:
packages/cli/test/i18n-section-coverage.test.ts,packages/spec/src/index.ts,content/docs/index.mdxandturbo.jsonall derive this gate not at all.scripts/check-examples-live-imports.mjsdoes derive it, viagate scriptidentity rather than the new hint, which is pre-existing and correct.The card's open half, answered with a measurement
The
packages/**test-inventory side stays undeclared.It is unreachable too, and by a wider margin than the examples side:
'packages'carries no separator, soextractWatchHintsdrops it beforehintCoversis ever consulted. It is not even a dead hint, which is why the residue block never mentioned it. It is also not reached by the test-file convention trigger, since this gate is not inCHANGE_KIND_GATES. Measured: a derivation forpackages/cli/test/i18n-section-coverage.test.ts, the very file #8754 went red on, names this gate nowhere.It stays undeclared because the instrument cannot express this side's population. A root hint covers a whole subtree, so
packages/**would name this gate for all 4861 tracked files underpackages/in order to reach the 76 that actually carry a coupling (@objectstack/dogfood72,@objectstack/cli2,@objectstack/lint2, from the gate's own--jsoninventory). That is 1.6% precision pasted into everypackages/**dispatch prompt, a worse ratio than the wholesale admissionhintCoversalready refuses.Demonstrated rather than asserted: with
packages/**temporarily declared,packages/spec/src/index.tsandpackages/objectql/src/engine.tsboth derive this gate, andtestFiles()never reads either one.By contrast
examples/has 239 tracked files and effectively all of them are in the population, sincecouplingTarget()resolves to arbitrary paths beneath it.The refusal is pinned in the self-test, not left in prose, so a later author who adds
packages/**meets a failing assertion.Ablations, predicted before each run
Each mutation was confirmed on disk by counting the injected and the removed text, not by the editor's exit code, and restored from the commit with a re-count. This gate runs from source, so no build or
dist/leg is involved.examples/**pin)skills/**)packages/**)Self-test grew 31 to 36 cases, all passing.
Gates
Run at
fa77e513bf, the final commit, after a clean working tree. Exit codes captured before any pipe; each gate's own verdict line quoted.pnpm check:examples-live-imports:examples/** live-import inventory OK -- 0 invisible (declared), 6 inputs-declared, 70 graph-visible.(self-testAll 36 self-test cases passed.)pnpm check:pm-dispatch-gates:dispatch-gates self-test: 463 cases pass.pnpm check:cross-package-test-inputs:OK: 13 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.pnpm check:nul-bytes:check-nul-bytes: OK (scanned 6226 text file(s) ...)pnpm check:parse-guard:check:parse-guard: 124 scripts/ file(s)(not named by the derivation, it is the same escapable species; run because this edit is ascripts/file)pnpm check:entry-guard:check:entry-guard: 125 scripts/ file(s)(PR fix(scripts): burn 25 of the 35 KNOWN_IMPORT_UNSAFE entry-guard debts down #10704'sisEntrypointguard untouched; the file stays off the SHRINK-ONLY ledger, verified: 10 entries, none of them this file)The union was re-derived with
node scripts/pm/dispatch-gates.mjsand no paths at that same commit; it namescheck:cross-package-test-inputsandcheck:examples-live-imports, both above.Changeset
None. Gate tooling publishes nothing, so this carries the
skip-changesetlabel.Generated by Claude Code
Generated by Claude Code