From 292a626a35611012687d451e4cfa8a7a90229115 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 4 Sep 2026 16:05:25 +0000 Subject: [PATCH 1/2] fix(scripts): the subtree-walking gates declare their watch hints (#15341) Sixteen gate families CI runs declared no path literal at all and walked a subtree seeded from a runtime constant, so dispatch-gates scored them `undetermined` for every card: absent from every dispatch brief and every `--commands` harvest while CI ran them on each pull request. Each gate now declares the population its own source really reads, under the rostered watch-hint idiom, with the coupling held in that gate's own self-test. Three families whose CI invocation is a fixture-only `--self-test` carry the `no-path-population` marker instead. `check:org-identifier` gains hints and its now-stale ROOT_WALK_RESIDUE_LEDGER row is deleted in the same commit. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk --- scripts/check-declaration-mirrors.mjs | 38 +++++++++++ scripts/check-init-service-contract.mjs | 50 +++++++++++++- scripts/check-live-db-isolation.mjs | 49 +++++++++++++- scripts/check-meta-type-normalized.mjs | 49 +++++++++++++- .../check-optional-error-sink-contract.mjs | 54 ++++++++++++++- scripts/check-org-identifier.mjs | 60 ++++++++++++++++- scripts/check-resume-authority-declared.mjs | 42 +++++++++++- scripts/check-runner-env-posture.mjs | 38 ++++++++++- scripts/check-sdui-manifest.mjs | 66 +++++++++++++++++-- scripts/check-settings-bind-window.mjs | 46 ++++++++++++- scripts/check-startup-registry-verdict.mjs | 38 ++++++++++- scripts/check-tenant-chokepoint.mjs | 52 ++++++++++++++- scripts/check-verify-stand-in-erasure.mjs | 39 ++++++++++- scripts/check-wildcard-fallthrough.mjs | 47 ++++++++++++- scripts/pm/dispatch-gates.mjs | 7 -- scripts/publish-smoke-pack.mjs | 12 ++++ scripts/run-with-stall-guard.mjs | 13 ++++ scripts/sync-docs-image-tags.mjs | 16 +++++ 18 files changed, 691 insertions(+), 25 deletions(-) diff --git a/scripts/check-declaration-mirrors.mjs b/scripts/check-declaration-mirrors.mjs index 016e2efd3d..288a98986d 100644 --- a/scripts/check-declaration-mirrors.mjs +++ b/scripts/check-declaration-mirrors.mjs @@ -118,6 +118,26 @@ const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, '..'); const SCRIPTS_DIR = join(REPO_ROOT, 'scripts'); +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `mirrorFiles()` walks `SCRIPTS_DIR` for every `*.d.mts` and opens the `.mjs` + * beside each one — one subtree, `scripts/`. The walk root is assembled with + * `join()`, so the derivation, which reads SOURCE TEXT, saw a bare word and no + * path at all: both of this gate's CI invocations (the scan and its + * `--self-test`) were scored `undetermined` for EVERY card, absent from every + * dispatch brief and every `--commands` harvest, while CI ran them on each pull + * request. `hintCovers` refuses a bare single-segment literal by design, so the + * subtree spelling is the escape the idiom exists to be. + * + * ⛔ Not a whole-tree marker: `scripts/**` is a subtree, and this gate reads + * nothing outside it. + * + * The self-test holds the declaration against the live walk rather than against + * a second spelling of the root, so a moved corpus reds here. + */ +const ROOT_DIR_WATCH_HINTS = ['scripts/**']; + /** * The export spellings this parser recognises, in the words a declaration * author would write them. Published for the same reason the cross-package @@ -603,6 +623,24 @@ async function selfTest() { mirrorFiles().every((f) => f.endsWith('.d.mts')), ); + // ── the dispatch-gates population declaration ── + ok( + 'the declared population is the subtree spelling of the walked root — a bare `scripts` literal is ' + + 'refused by hintCovers as too generic, which is how this gate came to declare nothing at all', + ROOT_DIR_WATCH_HINTS.length === 1 && ROOT_DIR_WATCH_HINTS[0] === 'scripts/**', + ); + ok( + 'and the live walk agrees with it — every discovered mirror sits under the declared root, so a ' + + 'moved corpus reds here instead of quietly re-emptying the declaration', + mirrorFiles().every((f) => relative(REPO_ROOT, f).split(sep).join('/') + .startsWith(`${ROOT_DIR_WATCH_HINTS[0].replace(/\/\*+$/, '')}/`)), + ); + ok( + 'the declared form is NOT the bare walk root — the glob form would send the walk at a directory ' + + 'the tree does not have', + !ROOT_DIR_WATCH_HINTS.includes(relative(REPO_ROOT, SCRIPTS_DIR).split(sep).join('/')), + ); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-init-service-contract.mjs b/scripts/check-init-service-contract.mjs index 70dd6f2716..bc97f8ddc7 100644 --- a/scripts/check-init-service-contract.mjs +++ b/scripts/check-init-service-contract.mjs @@ -121,11 +121,12 @@ const SELF_TEST_BATTERIES = Object.freeze({ '17. Every exemption is decided by WHEN the call runs, not by which accessor': 1, '18. `--list` and the problem text must quote the accessor actually called.': 1, '19. Nothing outside the vocabulary is invented: a lookup-shaped call on a': 1, + '20. The dispatch-gates population declaration.': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 19; +const SELF_TEST_BATTERY_FLOOR = 20; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -134,6 +135,27 @@ const UNATTRIBUTED_BATTERY = '(no battery open)'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); +/** The trees this gate walks. Plugin units live under `packages/`. */ +const SCAN_ROOTS = ['packages']; + +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * The walk root used to be an inline `'packages'` argument. The derivation reads + * SOURCE TEXT and `hintCovers` refuses a bare single-segment literal by design + * (admitting them was priced at +139084 fabricated (gate, file) pairs, because + * `packages` is a path COMPONENT in dozens of gates that never read that root), + * so this gate declared no path at all: scored `undetermined` for EVERY card, + * absent from every dispatch brief and every `--commands` harvest, while CI ran + * it on each pull request. The subtree spelling is the escape the idiom exists + * to be, and `SCAN_ROOTS` is the constant it is held against — the walk now + * reads the same constant, so a moved read reds in this file's own self-test. + * + * ⛔ Not a whole-tree marker: `packages/**` is a subtree, and a whole-tree row + * appears on every card in the repo whether or not the gate reads the file. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**']; + const DECLARATION_FIELDS = ['dependencies', 'optionalDependencies', 'requiresServices', 'providesServices']; // ── Discovery ──────────────────────────────────────────────────────────────── @@ -152,7 +174,7 @@ function discoverFiles() { out.push(relative(ROOT, full).split(sep).join('/')); } }; - walk(join(ROOT, 'packages')); + for (const root of SCAN_ROOTS) walk(join(ROOT, root)); return out.sort(); } @@ -924,6 +946,30 @@ function selfTest() { assert(problems.length === 0, 'hasService is not in the vocabulary (not plugin-reachable in packages/core)'); } + // 20. The dispatch-gates population declaration. + battery('20. The dispatch-gates population declaration.'); + assert( + SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), + 'every separator-less SCAN_ROOT is declared in the subtree spelling — a bare root is refused as ' + + 'too generic, so without the glob the hint extractor reads nothing and this gate goes back to ' + + 'scoring `undetermined` for every card', + ); + assert( + ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), + 'no root is declared that this gate does not walk — a declaration that has drifted from the scan ' + + 'replaces a silent gate with a lying one', + ); + assert( + !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), + 'the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a directory ' + + 'the tree does not have', + ); + assert( + discoverFiles().every((f) => ROOT_DIR_WATCH_HINTS.some((h) => f.startsWith(`${h.replace(/\/\*+$/, '')}/`))), + 'and the WALK agrees with the declaration on the live tree — this is the half the two assertions ' + + 'above cannot hold, since both read the constant rather than what discoverFiles() returns', + ); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ─── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-live-db-isolation.mjs b/scripts/check-live-db-isolation.mjs index 67a7a3a221..89352764ef 100644 --- a/scripts/check-live-db-isolation.mjs +++ b/scripts/check-live-db-isolation.mjs @@ -94,11 +94,12 @@ const SELF_TEST_BATTERIES = Object.freeze({ '7. comments are not source -- the reason codeOf exists': 1, '8. the live-file needle must MATCH a real read and not the cell form': 2, '9. `use strict` and friends are not live DDL': 1, + '10. the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 9; +const SELF_TEST_BATTERY_FLOOR = 10; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -174,6 +175,29 @@ function batteryFloorFailures() { const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const ROOTS = ['packages', 'apps', 'examples']; + +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `ROOTS` is a runtime constant, and the derivation reads SOURCE TEXT: three + * bare top-level words carry no separator, and `hintCovers` refuses a bare + * single-segment literal by design (accepting them was priced at +139084 + * fabricated (gate, file) pairs, because `packages`, `apps` and `examples` are + * path COMPONENTS in dozens of gates that never read those roots). So this gate + * declared no path at all and was scored `undetermined` for EVERY card: it + * appeared in no dispatch brief and in no `--commands` harvest, while CI ran it + * on every pull request. The subtree spelling is the escape the idiom exists to + * be — the same claim `ROOTS` makes, written where a text scanner can read it. + * + * ⛔ Not a whole-tree marker: this gate reads three subtrees, and the liveness + * predicate that vouches for a whole-tree declaration is documented as too weak + * to tell a seeded subtree walk apart from a repo-root one. + * + * The self-test derives the coupling from `ROOTS` on both sides rather than + * re-spelling it, so widening or renaming a root cannot leave this declaration + * describing the old population. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**', 'apps/**', 'examples/**']; const SKIP_DIRS = new Set(['node_modules', 'dist', '.turbo', 'coverage', '.next', 'build']); /** @@ -436,6 +460,29 @@ function selfTest() { battery('9. `use strict` and friends are not live DDL'); check('does not flag a non-identifier use', violationsIn(`'use strict';`).length === 0); + // 10. the dispatch-gates population declaration + battery('10. the dispatch-gates population declaration'); + check( + 'every separator-less ROOT is declared in the subtree spelling (a bare root is refused as too ' + + 'generic, so it needs the glob)', + ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), + ); + check( + 'and it declares no root this gate does not walk — a declaration that can drift from the scan ' + + 'replaces a silent gate with a lying one', + ROOT_DIR_WATCH_HINTS.every((h) => ROOTS.includes(h.replace(/\/\*+$/, ''))), + ); + check( + 'the declared form is NOT a ROOTS entry — the glob form would send the walk at a directory the ' + + 'tree does not have', + !ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), + ); + check( + 'the declaration is not empty — an empty hint list reads exactly like the undetermined verdict ' + + 'it exists to leave', + ROOT_DIR_WATCH_HINTS.length === ROOTS.length, + ); + // The floor runs BEFORE the verdict below, so a success line can only be // printed by a run in which every declared battery registered its cases. for (const message of batteryFloorFailures()) cases.push({ label: message, ok: false }); diff --git a/scripts/check-meta-type-normalized.mjs b/scripts/check-meta-type-normalized.mjs index 9fdee8a1ec..d781da5268 100644 --- a/scripts/check-meta-type-normalized.mjs +++ b/scripts/check-meta-type-normalized.mjs @@ -90,6 +90,30 @@ const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); /** Directories scanned. Route handlers that read `:type` live here. */ const SCAN_DIRS = [join('packages', 'rest', 'src')]; +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `SCAN_DIRS` is assembled with `join()`, one SEGMENT per literal, so the + * derivation — which reads SOURCE TEXT — sees three bare words and no path at + * all. This gate was therefore scored `undetermined` for EVERY card, absent from + * every dispatch brief and every `--commands` harvest, while CI ran it on each + * pull request. + * + * ⚠️ The hint is `packages/rest/src/**`, NOT `packages/**`. The scan is one + * package's source directory; the wider spelling would paste this gate onto + * every card under `packages/`, which is the costlier error — a lead that is + * wrong on thousands of files rather than a gate that is quiet. + * + * ⛔ And not a whole-tree marker for the same reason, one size up. + * + * The self-test derives the coupling from `SCAN_DIRS` on both sides rather than + * re-spelling it, so a moved or widened scan directory cannot leave this + * declaration describing the old population. The POSIX normalisation is + * load-bearing: `join()` yields a platform separator, and the declaration is + * read as text by a scanner that only knows `/`. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/rest/src/**']; + /** * Blessed raw comparisons: `'::'` -> reason. * Empty by design — see the header. @@ -218,11 +242,12 @@ const SELF_TEST_VERDICT = 'check-meta-type-normalized self-test reached its verd // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-meta-type-normalized self-test': 4, + 'the dispatch-gates population declaration': 3, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 1; +const SELF_TEST_BATTERY_FLOOR = 2; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -295,6 +320,28 @@ function selfTest() { if (hits.length !== 5) problems.push(`expected 5 findings total, saw ${hits.length} — a pass-through or a comment was flagged`); }); + // ── The dispatch-gates population declaration ──────────────────────── + battery('the dispatch-gates population declaration'); + const scannedPosix = SCAN_DIRS.map((d) => d.split(sep).join('/')); + check(() => { + if (!scannedPosix.every((d) => ROOT_DIR_WATCH_HINTS.includes(`${d}/**`))) { + problems.push('a SCAN_DIRS entry is not declared in the subtree spelling — the hint extractor ' + + 'reads source text, and a join()-assembled path is invisible to it'); + } + }); + check(() => { + if (!ROOT_DIR_WATCH_HINTS.every((h) => scannedPosix.includes(h.replace(/\/\*+$/, '')))) { + problems.push('ROOT_DIR_WATCH_HINTS declares a directory this gate does not walk — a declaration ' + + 'that has drifted from the scan replaces a silent gate with a lying one'); + } + }); + check(() => { + if (ROOT_DIR_WATCH_HINTS.some((h) => !h.startsWith('packages/rest/src'))) { + problems.push('the declaration widened past this gate\'s own package — `packages/**` would paste ' + + 'this gate onto every card under packages/, which is worse than the silence it replaces'); + } + }); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-optional-error-sink-contract.mjs b/scripts/check-optional-error-sink-contract.mjs index 1f7eac8713..80c86f0dbd 100644 --- a/scripts/check-optional-error-sink-contract.mjs +++ b/scripts/check-optional-error-sink-contract.mjs @@ -243,6 +243,27 @@ const BASELINE_PATH = join(HERE, 'optional-error-sink-contract.baseline.json'); /** Where the PUBLISHED contracts live. See "Scope" in the header. */ const SCAN_ROOTS = ['packages']; +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `SCAN_ROOTS` is a runtime constant and the derivation reads SOURCE TEXT, so + * the bare word `packages` contributes NOTHING: `hintCovers` refuses a + * single-segment literal by design, because `packages` is a path COMPONENT in + * dozens of gates that never read that root. This gate therefore declared no + * path at all, was scored `undetermined` for EVERY card, and appeared in no + * dispatch brief and no `--commands` harvest while CI ran it on every pull + * request. The subtree spelling is the escape the idiom exists to be. + * + * ⛔ Not a whole-tree marker: `packages/**` is a subtree, and a whole-tree + * declaration would put this gate on every card in the repo on a population it + * does not read. + * + * The self-test derives the coupling from `SCAN_ROOTS` on both sides rather + * than re-spelling it, so a widened or renamed root cannot leave this + * declaration describing the old population. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**']; + const SKIP_DIRS = new Set([ 'node_modules', 'dist', 'build', 'coverage', '.turbo', '.next', '.cache', 'json-schema', '.git', ]); @@ -826,11 +847,12 @@ let selfTestReachedVerdict = false; // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-optional-error-sink-contract self-test': 66, + 'the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 1; +const SELF_TEST_BATTERY_FLOOR = 2; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -1146,6 +1168,36 @@ check(() => { } } + // ── The dispatch-gates population declaration ─────────────────────────── + battery('the dispatch-gates population declaration'); + const declFail = (msg) => { failures++; console.error(` ✗ ${msg}`); }; +check(() => { + const separatorless = SCAN_ROOTS.filter((r) => !r.includes('/')); + if (!separatorless.every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))) { + declFail('a separator-less SCAN_ROOT is not declared in the subtree spelling — a bare root is ' + + 'refused as too generic, so the hint extractor sees nothing and this gate goes back to ' + + 'scoring `undetermined` for every card.'); + } +}); +check(() => { + if (!ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, '')))) { + declFail('ROOT_DIR_WATCH_HINTS declares a root this gate does not walk — a declaration that has ' + + 'drifted from the scan replaces a silent gate with a lying one.'); + } +}); +check(() => { + if (SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))) { + declFail('the declared form is a SCAN_ROOTS entry — the glob form would send the walk at a ' + + 'directory the tree does not have.'); + } +}); +check(() => { + if (ROOT_DIR_WATCH_HINTS.length !== SCAN_ROOTS.length) { + declFail('the declaration is not one hint per walked root — an empty or short hint list reads ' + + 'exactly like the undetermined verdict it exists to leave.'); + } +}); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-org-identifier.mjs b/scripts/check-org-identifier.mjs index 36df46c993..2c868bfb45 100644 --- a/scripts/check-org-identifier.mjs +++ b/scripts/check-org-identifier.mjs @@ -275,6 +275,34 @@ import { maskComments } from './js-comment-mask.mjs'; import { isEntrypoint } from './invoked-as.mjs'; const ROOTS = ['examples', 'apps', 'packages']; + +/** + * The population this gate enumerates, declared for + * `scripts/pm/dispatch-gates.mjs`. + * + * `sourceFiles` runs `git ls-files -- examples apps packages` — three SUBTREES, + * seeded from the `ROOTS` constant above. The derivation reads SOURCE TEXT and + * `hintCovers` refuses a bare single-segment literal by design (accepting them + * was priced at +139084 fabricated (gate, file) pairs, because these three words + * are path COMPONENTS in dozens of gates that never read those roots), so this + * gate declared nothing and was scored `undetermined` for EVERY card: it reached + * no dispatch brief and no `--commands` harvest while CI ran it on every pull + * request. + * + * ⛔ Not a whole-tree marker, and this gate is the reason that boundary is + * written down. It was held OUT of the whole-tree bucket with a + * `ROOT_WALK_RESIDUE_LEDGER` row precisely because the liveness predicate that + * vouches for a whole-tree declaration sees a `git ls-files` call and cannot + * tell a three-subtree enumeration apart from a repo-wide one — so a whole-tree + * marker here would be exactly the mis-declaration that predicate cannot catch. + * That ledger row named this declaration as the remedy; landing it clears the + * row, and the two moves are coupled by construction (a stale exclusion reds). + * + * The self-test derives the coupling from `ROOTS` on both sides rather than + * re-spelling it, so widening or renaming a root cannot leave this declaration + * describing the old population. + */ +const ROOT_DIR_WATCH_HINTS = ['examples/**', 'apps/**', 'packages/**']; const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.cts', '.mts']; const EXCLUDED = /(^|\/)(node_modules|dist|build|\.next|\.turbo)\//; // Dropped WHOLESALE: absence pins and fixtures that CONSTRUCT the removed @@ -614,11 +642,12 @@ let selfTestReachedVerdict = false; // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-org-identifier self-test': 31, + 'the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 1; +const SELF_TEST_BATTERY_FLOOR = 2; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -750,6 +779,35 @@ check(() => { } }); + // ── The dispatch-gates population declaration ──────────────────────────── + battery('the dispatch-gates population declaration'); + const declFail = (msg) => { console.error(` ✗ ${msg}`); failed++; }; +check(() => { + if (!ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))) { + declFail('a separator-less ROOT is not declared in the subtree spelling — a bare root is refused ' + + 'as too generic, so the hint extractor reads nothing and this gate returns to scoring ' + + '`undetermined` for every card.'); + } +}); +check(() => { + if (!ROOT_DIR_WATCH_HINTS.every((h) => ROOTS.includes(h.replace(/\/\*+$/, '')))) { + declFail('ROOT_DIR_WATCH_HINTS declares a root this gate does not enumerate — a declaration that ' + + 'has drifted from the scan replaces a silent gate with a lying one.'); + } +}); +check(() => { + if (ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))) { + declFail('the declared form is a ROOTS entry — the bare form is what `git ls-files` takes, and it ' + + 'is exactly what the hint extractor cannot read.'); + } +}); +check(() => { + if (ROOT_DIR_WATCH_HINTS.length !== ROOTS.length) { + declFail('the declaration is not one hint per enumerated root — a short list reads exactly like ' + + 'the undetermined verdict it exists to leave.'); + } +}); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-resume-authority-declared.mjs b/scripts/check-resume-authority-declared.mjs index 2f7959babd..744edf52a7 100644 --- a/scripts/check-resume-authority-declared.mjs +++ b/scripts/check-resume-authority-declared.mjs @@ -112,6 +112,29 @@ import { parseSourceFile } from './ts-parse.mjs'; const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const DEFAULT_SCAN_ROOTS = ['packages', 'examples']; +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `DEFAULT_SCAN_ROOTS` is a runtime constant and the derivation reads SOURCE + * TEXT, so two bare top-level words contribute NOTHING — `hintCovers` refuses a + * single-segment literal by design, because `packages` and `examples` are path + * COMPONENTS in dozens of gates that never read those roots. This gate declared + * no path at all, so it was scored `undetermined` for EVERY card and reached no + * dispatch brief and no `--commands` harvest while CI ran it on every pull + * request. The subtree spelling is the escape the idiom exists to be. + * + * ⛔ Not a whole-tree marker: these are two subtrees, and a whole-tree row + * appears on every card in the repo — a fabricated lead unless the gate really + * reads every file. + * + * The self-test derives the coupling from `DEFAULT_SCAN_ROOTS` on both sides + * rather than re-spelling it, so widening or renaming a root cannot leave this + * declaration describing the old population. `--dir` narrows the scan for a + * single manual run; the DEFAULT is what CI schedules and what a card can + * implicate, which is why the declaration is held against that constant. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**', 'examples/**']; + /** The factory whose argument IS an action descriptor (packages/spec). */ const FACTORY = 'defineActionDescriptor'; @@ -364,11 +387,12 @@ const SELF_TEST_BATTERIES = Object.freeze({ 'A dynamically assembled argument is recorded, never judged.': 2, 'A same-named local factory is not the spec\'s. Deliberately still counted:': 2, 'Wiring: discovery must reach the real tree, and specifically the four': 5, + 'The dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 7; +const SELF_TEST_BATTERY_FLOOR = 8; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -497,6 +521,22 @@ const b = defineActionDescriptor({ type: 'b', version: '1.0.0', name: 'B', suppo expect(`discovery reaches the '${t}' pausing built-in`, pausingTypes.has(t)); } + // ── The dispatch-gates population declaration + battery('The dispatch-gates population declaration'); + const separatorless = DEFAULT_SCAN_ROOTS.filter((r) => !r.includes('/')); + expect('every separator-less scan root is declared in the subtree spelling (a bare root is refused ' + + 'as too generic, so the extractor reads nothing without the glob)', + separatorless.every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))); + expect('and it declares no root this gate does not walk — a declaration that drifts from the scan ' + + 'replaces a silent gate with a lying one', + ROOT_DIR_WATCH_HINTS.every((h) => DEFAULT_SCAN_ROOTS.includes(h.replace(/\/\*+$/, '')))); + expect('the declared form is NOT a DEFAULT_SCAN_ROOTS entry — the glob form would send the walk at ' + + 'a directory the tree does not have', + !DEFAULT_SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))); + expect('one hint per walked root — a short list reads exactly like the undetermined verdict it ' + + 'exists to leave', + ROOT_DIR_WATCH_HINTS.length === DEFAULT_SCAN_ROOTS.length); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ─── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-runner-env-posture.mjs b/scripts/check-runner-env-posture.mjs index 28ed071a91..94783857a4 100644 --- a/scripts/check-runner-env-posture.mjs +++ b/scripts/check-runner-env-posture.mjs @@ -111,11 +111,12 @@ const SELF_TEST_BATTERIES = Object.freeze({ 'Population.': 7, 'Wiring. Unwiring the gate must redden HERE rather than go quiet.': 3, 'The corpus itself, as a case rather than as the run\'s only evidence.': 1, + 'The dispatch-gates population declaration.': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 8; +const SELF_TEST_BATTERY_FLOOR = 9; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -195,6 +196,31 @@ const ROOT = resolve(HERE, '..'); /** Trees that can hold product source. */ export const SCANNED_ROOTS = ['packages', 'apps', 'examples']; +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `SCANNED_ROOTS` is a runtime constant and the derivation reads SOURCE TEXT, + * so three bare top-level words contribute NOTHING: `hintCovers` refuses a + * single-segment literal by design, because `packages`, `apps` and `examples` + * are path COMPONENTS in dozens of gates that never read those roots. This gate + * therefore declared no path at all and was scored `undetermined` for EVERY + * card — absent from every dispatch brief and every `--commands` harvest, while + * CI ran it on every pull request. The subtree spelling is the escape the idiom + * exists to be. + * + * ⛔ Not a whole-tree marker: three subtrees are not the tree, and a whole-tree + * row appears on every card whether or not the gate reads the file. + * + * The hints name the WALKED roots, not the narrower `isProductSource` filter + * applied inside them. That is the honest claim for a lead: the filter decides + * what the gate REPORTS on, the roots decide what it READS, and a card under a + * walked root can move this gate's verdict by adding a `src/` file to it. + * + * The self-test derives the coupling from `SCANNED_ROOTS` on both sides rather + * than re-spelling it. + */ +export const ROOT_DIR_WATCH_HINTS = ['packages/**', 'apps/**', 'examples/**']; + /** Directory names never descended into. */ const SKIP_DIRS = new Set(['node_modules', 'dist', 'build', '.turbo', '.next', 'coverage', '.git']); @@ -421,6 +447,16 @@ export function selfTest() { battery('The corpus itself, as a case rather than as the run\'s only evidence.'); t('today\'s tree is clean', scanTree().length, 0); + // --- The dispatch-gates population declaration. + battery('The dispatch-gates population declaration.'); + t('every separator-less scanned root is declared in the subtree spelling', + SCANNED_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), true); + t('and no root is declared that this gate does not walk', + ROOT_DIR_WATCH_HINTS.every((h) => SCANNED_ROOTS.includes(h.replace(/\/\*+$/, ''))), true); + t('the declared form is NOT a SCANNED_ROOTS entry', + SCANNED_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), false); + t('one hint per walked root', ROOT_DIR_WATCH_HINTS.length, SCANNED_ROOTS.length); + // The floor runs BEFORE the verdict below, so a success line can only be // printed by a run in which every declared battery registered its cases. for (const message of batteryFloorFailures()) cases.push([message, false, true]); diff --git a/scripts/check-sdui-manifest.mjs b/scripts/check-sdui-manifest.mjs index a6dbac4d96..9e29c9d2c3 100644 --- a/scripts/check-sdui-manifest.mjs +++ b/scripts/check-sdui-manifest.mjs @@ -50,19 +50,57 @@ import { createHash } from 'node:crypto'; import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; -import { dirname, join } from 'node:path'; +import { dirname, join, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; import { isEntrypoint } from './invoked-as.mjs'; const DEFAULT_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); +/** The three files `checkTree` opens, repo-relative. */ +const READ_PATHS = { + artefact: 'sdui.manifest.json', + record: join('scripts', 'sdui-manifest.record.json'), + pin: '.objectui-sha', +}; + +/** + * The population this gate reads, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `checkTree` opens exactly three files. None of them was visible to the + * derivation: it reads SOURCE TEXT, and a literal with no separator is refused + * by `hintCovers` as too generic (`sdui.manifest.json`), while `.objectui-sha` + * is not one of the dot-prefixed names the extractor admits and the record path + * is assembled with `join()`. So both of this gate's CI invocations — the scan + * and its `--self-test` — were scored `undetermined` for EVERY card, absent from + * every dispatch brief and every `--commands` harvest, while CI ran them on each + * pull request. That cost is sharpest here: the cards that implicate this gate + * are exactly the ones that move the objectui pin or regenerate the manifest. + * + * `ROOT_WATCH_HINTS` is the mixed-roots spelling of the idiom, which is what + * this population is: two repo-ROOT files and one under `scripts/`. The + * repo-root pair carries the `/**` suffix because a bare single-segment literal + * is refused; the collapse reduces each one back to the single file it names and + * to nothing else. + * + * ⛔ Not a whole-tree marker, and not `scripts/**`: three files are three files. + * + * The self-test derives the coupling from `READ_PATHS` — the same object + * `checkTree` reads — so a moved or added read reds here rather than leaving the + * declaration describing the old population. + */ +const ROOT_WATCH_HINTS = [ + 'sdui.manifest.json/**', + 'scripts/sdui-manifest.record.json', + '.objectui-sha/**', +]; + /** Gate one tree. Returns a list of problems; empty = green. */ export function checkTree(root) { const problems = []; - const artefactPath = join(root, 'sdui.manifest.json'); - const recordPath = join(root, 'scripts', 'sdui-manifest.record.json'); - const pinPath = join(root, '.objectui-sha'); + const artefactPath = join(root, READ_PATHS.artefact); + const recordPath = join(root, READ_PATHS.record); + const pinPath = join(root, READ_PATHS.pin); if (!existsSync(artefactPath)) { problems.push( @@ -247,6 +285,26 @@ function selfTest() { for (const p of problems) console.error(` ${p}`); } } + // ── The dispatch-gates population declaration ────────────────────────── + // Filed outside the cases table, deliberately: each table ROW is a declared + // battery here, so an assertion added as a row would owe a roster entry for a + // case that gates nothing about `checkTree`'s verdicts. + const declFail = (message) => { console.error(`✗ self-test: ${message}`); failures++; }; + const readPosix = Object.values(READ_PATHS).map((f) => f.split(sep).join('/')); + const declared = ROOT_WATCH_HINTS.map((h) => h.replace(/\/\*+$/, '')); + if (!readPosix.every((f) => declared.includes(f))) { + declFail('a file checkTree reads is not declared for dispatch-gates — an unreadable literal is how ' + + 'this gate came to declare nothing at all, and it scores `undetermined` for every card again.'); + } + if (!declared.every((h) => readPosix.includes(h))) { + declFail('ROOT_WATCH_HINTS declares a path this gate does not read — a declaration that has drifted ' + + 'from the reads replaces a silent gate with a lying one.'); + } + if (!ROOT_WATCH_HINTS.filter((h) => !h.replace(/\/\*+$/, '').includes('/')).every((h) => h.endsWith('/**'))) { + declFail('a repo-ROOT file is declared without the subtree suffix — a bare single-segment literal is ' + + 'refused by hintCovers as too generic, so it would contribute no hint at all.'); + } + // ── The floor: every declared row RAN, and ran its case (#13489) ─────── // // Evaluated after every row has had its chance and BEFORE the verdict, so the diff --git a/scripts/check-settings-bind-window.mjs b/scripts/check-settings-bind-window.mjs index 74df37bf1e..dd3ef9766a 100644 --- a/scripts/check-settings-bind-window.mjs +++ b/scripts/check-settings-bind-window.mjs @@ -113,6 +113,27 @@ import { parseSourceFile } from './ts-parse.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); +/** The trees this gate walks. Plugin units live under `packages/`. */ +const SCAN_ROOTS = ['packages']; + +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * The walk root used to be an inline `'packages'` argument. The derivation reads + * SOURCE TEXT and `hintCovers` refuses a bare single-segment literal by design + * (admitting them was priced at +139084 fabricated (gate, file) pairs, because + * `packages` is a path COMPONENT in dozens of gates that never read that root), + * so this gate declared no path at all: scored `undetermined` for EVERY card, + * absent from every dispatch brief and every `--commands` harvest, while CI ran + * it on each pull request. The subtree spelling is the escape the idiom exists + * to be, and `SCAN_ROOTS` is the constant it is held against — the walk reads + * the same constant, so a moved read reds in this file's own self-test. + * + * ⛔ Not a whole-tree marker: `packages/**` is a subtree, and a whole-tree row + * lands on every card in the repo whether or not the gate reads the file. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**']; + const DECLARATION_FIELDS = ['dependencies', 'optionalDependencies', 'requiresServices', 'providesServices']; /** The service name whose provider late-binds its engine — see the header. */ @@ -177,7 +198,7 @@ function discoverFiles() { out.push(relative(ROOT, full).split(sep).join('/')); } }; - walk(join(ROOT, 'packages')); + for (const root of SCAN_ROOTS) walk(join(ROOT, root)); return out.sort(); } @@ -1038,6 +1059,29 @@ function selfTest() { assert(stale.length === 1, 'a ledger entry with no matching problem is stale'); } + // 17. The dispatch-gates population declaration: the subtree spelling names + // the roots the walk really reads, and only those. + assert( + SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), + 'every separator-less SCAN_ROOT is declared in the subtree spelling — a bare root is refused as ' + + 'too generic, so without the glob this gate scores `undetermined` for every card', + ); + assert( + ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), + 'no root is declared that this gate does not walk — a declaration that has drifted from the scan ' + + 'replaces a silent gate with a lying one', + ); + assert( + !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), + 'the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a directory ' + + 'the tree does not have', + ); + assert( + discoverFiles().every((f) => ROOT_DIR_WATCH_HINTS.some((h) => f.startsWith(`${h.replace(/\/\*+$/, '')}/`))), + 'and the WALK agrees with the declaration on the live tree — the half the assertions above cannot ' + + 'hold, since they read the constant rather than what discoverFiles() returns', + ); + console.log(`✓ settings bind-window guard self-test: all cases pass.`); } diff --git a/scripts/check-startup-registry-verdict.mjs b/scripts/check-startup-registry-verdict.mjs index 2422b4e2db..8935383f7c 100644 --- a/scripts/check-startup-registry-verdict.mjs +++ b/scripts/check-startup-registry-verdict.mjs @@ -154,6 +154,29 @@ import { parseSourceFile } from './ts-parse.mjs'; import { isEntrypoint } from './invoked-as.mjs'; const ROOT = fileURLToPath(new URL('..', import.meta.url)); + +/** The trees this gate walks by default. Plugin units live under `packages/`. */ +const SCAN_ROOTS = ['packages']; + +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * The default scan root used to be an inline `'packages'` argument. The + * derivation reads SOURCE TEXT and `hintCovers` refuses a bare single-segment + * literal by design (admitting them was priced at +139084 fabricated + * (gate, file) pairs, because `packages` is a path COMPONENT in dozens of gates + * that never read that root), so this gate declared no path at all: scored + * `undetermined` for EVERY card, absent from every dispatch brief and every + * `--commands` harvest, while CI ran it on each pull request. The subtree + * spelling is the escape the idiom exists to be. + * + * The declaration is held against the DEFAULT root, which is what CI schedules + * and what a card can implicate; `--packages-dir` retargets a single manual run + * and is not a population any card can predict. + * + * ⛔ Not a whole-tree marker: `packages/**` is a subtree. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**']; const BASELINE_PATH = join(ROOT, 'scripts', 'startup-registry-verdict.baseline.json'); // ── Vocabulary ─────────────────────────────────────────────────────────────── @@ -905,7 +928,7 @@ function baselineKey(f) { } function run({ list = false, packagesDir } = {}) { - const scanRoot = packagesDir ? resolve(packagesDir) : join(ROOT, 'packages'); + const scanRoot = packagesDir ? resolve(packagesDir) : join(ROOT, SCAN_ROOTS[0]); const relBase = packagesDir ? resolve(packagesDir, '..') : ROOT; // The scan root must resolve BEFORE anything is concluded from the scan. The // old guard was `existsSync`, which accepts a file: the run then fell through @@ -1506,6 +1529,19 @@ function selfTest() { rmSync(dir, { recursive: true, force: true }); } + // --- The dispatch-gates population declaration. --------------------------- + // Filed through `expectRoot` rather than as a battery, deliberately: the + // roster above is one row per CASE in the table, and the floor block + // cross-checks the two — a battery with no table row would red that + // cross-check for a case that ran. + expectRoot('every separator-less SCAN_ROOT is declared in the subtree spelling', + SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), true); + expectRoot('no root is declared that this gate does not walk', + ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), true); + expectRoot('the declared form is NOT a SCAN_ROOTS entry (the glob form would send the walk at a directory the tree does not have)', + SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), false); + expectRoot('one hint per walked root', ROOT_DIR_WATCH_HINTS.length, SCAN_ROOTS.length); + // ── The floor: every declared row RAN, and ran its case (#13489) ─────── // // Evaluated after every row has had its chance and BEFORE the verdict, so the diff --git a/scripts/check-tenant-chokepoint.mjs b/scripts/check-tenant-chokepoint.mjs index f74cedbfe7..b2448f4f49 100644 --- a/scripts/check-tenant-chokepoint.mjs +++ b/scripts/check-tenant-chokepoint.mjs @@ -108,7 +108,7 @@ */ import { readFileSync, existsSync } from 'node:fs'; -import { join, relative } from 'node:path'; +import { join, relative, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; import { requireDefaultExport } from './import-prerequisite.mjs'; const ts = await requireDefaultExport('typescript', () => import('typescript'), import.meta.url); @@ -124,6 +124,38 @@ const SCAN_FILES = [ join('packages', 'drivers', 'driver-turso', 'src', 'turso-driver.ts'), ]; +/** + * The population this gate reads, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `SCAN_FILES` is assembled with `join()`, one SEGMENT per literal, so the + * derivation — which reads SOURCE TEXT — saw a handful of bare words and no path + * at all. This gate was scored `undetermined` for EVERY card: absent from every + * dispatch brief and every `--commands` harvest, while CI ran it on each pull + * request. Worse than the usual cost, because this gate's population is THREE + * FILES: the cards that actually implicate it are rare and precisely nameable, + * and it was reaching none of them. + * + * The spelling is `DECLARED_WATCH_HINTS` rather than the directory idiom: this + * is an enumerated population, not a walked subtree, and each hint is a whole + * repo-relative FILE path — which carries a separator, so `hintCovers` reads it + * without a glob suffix. + * + * ⛔ Not `packages/drivers/**`, and not a whole-tree marker. Both would put this + * gate on cards it does not read a byte for; a lead that is wrong on thousands + * of files is worse than the silence it replaces. + * + * The self-test derives the coupling from `SCAN_FILES` on both sides rather than + * re-spelling it, so a driver added to or removed from the family cannot leave + * this declaration describing the old population. The POSIX normalisation is + * load-bearing: `join()` yields a platform separator, and the declaration is + * read as text by a scanner that only knows `/`. + */ +const DECLARED_WATCH_HINTS = [ + 'packages/drivers/driver-sql/src/sql-driver.ts', + 'packages/drivers/driver-sqlite-wasm/src/sqlite-wasm-driver.ts', + 'packages/drivers/driver-turso/src/turso-driver.ts', +]; + /** * The floor a real scan must clear. A scan that silently stops matching reports * "clean" while reading nothing (#4690), and this gate's whole value is that it @@ -522,6 +554,24 @@ function selfTest() { assert(builders.length === 0, 'the empty fixture must discover no builders'); } + // ── the dispatch-gates population declaration ──────────────────────────── + const scannedPosix = SCAN_FILES.map((f) => f.split(sep).join('/')); + assert( + scannedPosix.every((f) => DECLARED_WATCH_HINTS.includes(f)), + 'every SCAN_FILES entry is declared for dispatch-gates — a join()-assembled path is invisible to ' + + 'the hint extractor, which is how this gate came to declare nothing at all', + ); + assert( + DECLARED_WATCH_HINTS.every((h) => scannedPosix.includes(h)), + 'and nothing is declared that this gate does not read — a declaration that has drifted from the ' + + 'scan replaces a silent gate with a lying one', + ); + assert( + DECLARED_WATCH_HINTS.every((h) => !h.includes('*')), + 'the declaration stays file-exact — a `packages/drivers/**` widening would name this gate on ' + + 'cards it does not read a byte for', + ); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-verify-stand-in-erasure.mjs b/scripts/check-verify-stand-in-erasure.mjs index 116b814354..d5bdea0c65 100644 --- a/scripts/check-verify-stand-in-erasure.mjs +++ b/scripts/check-verify-stand-in-erasure.mjs @@ -81,6 +81,27 @@ const { VERIFY_STAND_IN_CHECKS } = await requireDependency('../eslint.config.mjs const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const VERIFY_SRC = join(REPO_ROOT, 'packages', 'verify', 'src'); const SCAN_ROOTS = ['packages', 'examples']; + +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * `SCAN_ROOTS` is a runtime constant and the derivation reads SOURCE TEXT, so + * two bare top-level words contribute NOTHING — `hintCovers` refuses a + * single-segment literal by design, because `packages` and `examples` are path + * COMPONENTS in dozens of gates that never read those roots. This gate declared + * no path at all and was scored `undetermined` for EVERY card: absent from every + * dispatch brief and every `--commands` harvest, while CI ran it on each pull + * request. The subtree spelling is the escape the idiom exists to be. + * + * ⛔ Not a whole-tree marker: two subtrees are not the tree. + * + * `VERIFY_SRC` is inside `packages/**` and needs no second hint — declaring it + * separately would name the same population twice and say nothing new. + * + * The self-test derives the coupling from `SCAN_ROOTS` on both sides rather + * than re-spelling it. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**', 'examples/**']; const SKIP_DIRS = new Set(['node_modules', 'dist', 'build', '.next', '.turbo', 'coverage']); const SOURCE_RE = /\.(ts|tsx|mts|cts)$/; @@ -414,11 +435,12 @@ const SELF_TEST_BATTERIES = Object.freeze({ 'CLEAN: the scan separates an asserted driver argument from a clean one.': 9, 'DISCOVERED: the shape test, on synthetic sources.': 2, 'Wiring: discovery must reach the REAL tree, and reach the two helpers': 13, + 'The dispatch-gates population declaration.': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 3; +const SELF_TEST_BATTERY_FLOOR = 4; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -595,6 +617,21 @@ function selfTest() { realSites.length >= 10, ); + // --- The dispatch-gates population declaration. + battery('The dispatch-gates population declaration.'); + expect('every separator-less scan root is declared in the subtree spelling (a bare root is refused ' + + 'as too generic, so the extractor reads nothing without the glob)', + SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))); + expect('and it declares no root this gate does not walk — a declaration that drifts from the scan ' + + 'replaces a silent gate with a lying one', + ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, '')))); + expect('the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a ' + + 'directory the tree does not have', + !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))); + expect('one hint per walked root — a short list reads exactly like the undetermined verdict it ' + + 'exists to leave', + ROOT_DIR_WATCH_HINTS.length === SCAN_ROOTS.length); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ─── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-wildcard-fallthrough.mjs b/scripts/check-wildcard-fallthrough.mjs index 59ca1b6909..a2ae326a98 100644 --- a/scripts/check-wildcard-fallthrough.mjs +++ b/scripts/check-wildcard-fallthrough.mjs @@ -83,6 +83,25 @@ import { parseSourceFile } from './ts-parse.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); +/** The trees this gate walks. Router mounts live under `packages/`. */ +const SCAN_ROOTS = ['packages']; + +/** + * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. + * + * The walk root used to be an inline `'packages'` argument, and every path-shaped + * literal this file DOES carry is a LEDGER KEY (`: `), + * which the extractor cannot read as a path. So the derivation saw no population + * at all: this gate was scored `undetermined` for EVERY card, absent from every + * dispatch brief and every `--commands` harvest, while CI ran it on each pull + * request. `hintCovers` refuses a bare single-segment literal by design, so the + * subtree spelling is the escape — held against `SCAN_ROOTS`, which the walk + * now reads, so a moved read reds in this file's own self-test. + * + * ⛔ Not a whole-tree marker: `packages/**` is a subtree. + */ +const ROOT_DIR_WATCH_HINTS = ['packages/**']; + /** * Every namespace-claiming wildcard mount in the repo. Keyed by * `: ` so two mounts in one file stay distinguishable. @@ -195,7 +214,7 @@ function discoverFiles() { out.push(relative(ROOT, full).split(sep).join('/')); } }; - walk(join(ROOT, 'packages')); + for (const root of SCAN_ROOTS) walk(join(ROOT, root)); return out.sort(); } @@ -480,11 +499,12 @@ const SELF_TEST_VERDICT = 'check-wildcard-fallthrough self-test reached its verd // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-wildcard-fallthrough self-test': 18, + 'the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 1; +const SELF_TEST_BATTERY_FLOOR = 2; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -574,6 +594,29 @@ function selfTest() { 'method is part of the key', ); + // ── The dispatch-gates population declaration ───────────────────────────── + battery('the dispatch-gates population declaration'); + assert( + SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), + 'every separator-less SCAN_ROOT is declared in the subtree spelling — a bare root is refused as ' + + 'too generic, so without the glob this gate scores `undetermined` for every card', + ); + assert( + ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), + 'no root is declared that this gate does not walk — a declaration that has drifted from the scan ' + + 'replaces a silent gate with a lying one', + ); + assert( + !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), + 'the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a directory ' + + 'the tree does not have', + ); + assert( + discoverFiles().every((f) => ROOT_DIR_WATCH_HINTS.some((h) => f.startsWith(`${h.replace(/\/\*+$/, '')}/`))), + 'and the WALK agrees with the declaration on the live tree — the half the assertions above cannot ' + + 'hold, since they read the constant rather than what discoverFiles() returns', + ); + // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/pm/dispatch-gates.mjs b/scripts/pm/dispatch-gates.mjs index 79b4a2e508..9f0667019b 100644 --- a/scripts/pm/dispatch-gates.mjs +++ b/scripts/pm/dispatch-gates.mjs @@ -2341,13 +2341,6 @@ export function wholeTreePopulationRefusal(entry) { * reds too: a stale exclusion is an exclusion nobody is measuring any more. */ export const ROOT_WALK_RESIDUE_LEDGER = [ - [ - 'check:org-identifier', - 'its enumeration is `git ls-files -- examples apps packages` (the ROOTS constant) — three SUBTREES, not the ' - + 'tree. The liveness predicate selects it on limb A and is documented as too weak to tell that apart, so a ' - + 'whole-tree marker here would be precisely the mis-declaration that predicate cannot catch. Its remedy is ' - + 'the ordinary ROOT_DIR_WATCH_HINTS declaration naming those three roots, after which it is MATCHED here.', - ], [ 'scripts/check-console-intercept-disarm.mjs', 'its `scan(REPO_ROOT)` walks `workspacePackageDirs(root)` — every workspace PACKAGE ROOT\'s package.json and ' diff --git a/scripts/publish-smoke-pack.mjs b/scripts/publish-smoke-pack.mjs index 15b1e76c21..c2a7c98883 100644 --- a/scripts/publish-smoke-pack.mjs +++ b/scripts/publish-smoke-pack.mjs @@ -40,6 +40,18 @@ * reading a copy that a gate keeps honest, rather than the thing itself. */ +// ## The dispatch-gates population +// +// `main()` shells out to `pnpm -r list` and `pnpm pack`; it opens no path this +// file names, and it runs only from `scripts/publish-smoke.sh` during a release. +// The family CI schedules on a pull request is `check:publish-smoke-pin`, which +// is this file's `--self-test`: pure fixtures, no workspace, no network, no +// tracked file. There is no path population for a card to implicate, so the +// marker is the honest declaration -- and `packages/**` would be the costly +// error, naming this family on thousands of cards for reads it never performs. +// +// dispatch-gates: no-path-population -- check:publish-smoke-pin runs this packer's --self-test against in-memory fixtures; the workspace enumeration and the pack itself belong to the release smoke, which no pull request schedules + import { execFile } from 'node:child_process'; import { mkdirSync, writeFileSync } from 'node:fs'; import { resolve } from 'node:path'; diff --git a/scripts/run-with-stall-guard.mjs b/scripts/run-with-stall-guard.mjs index 7ac9a686a9..52acfd5608 100644 --- a/scripts/run-with-stall-guard.mjs +++ b/scripts/run-with-stall-guard.mjs @@ -182,6 +182,19 @@ // Exit status: the child's own code when it finishes; 75 on a declared stall; // 1 when the child dies on a signal this guard did not send. +// ## The dispatch-gates population +// +// This is a RUNNER, not a scanner. Its reads are `/proc` (process state for the +// stall verdict) and, when CI passes `--report-dir`, a runner temp directory of +// diagnostic reports -- neither is in the repository, and no card can contain +// either. The family CI schedules on a pull request is `check:stall-guard`, +// which is this file's `--self-test`. So there is no path population to declare, +// and the marker says so rather than leaving the family in the unexamined pile. +// A card that edits THIS file is already led to `check:stall-guard-budget`, +// which declares this path as part of its own population. +// +// dispatch-gates: no-path-population -- this is a process runner: it reads /proc and, when given --report-dir, a runner temp dir, never a file in the repository; check:stall-guard is its --self-test + import { spawn } from 'node:child_process'; import { createWriteStream, diff --git a/scripts/sync-docs-image-tags.mjs b/scripts/sync-docs-image-tags.mjs index 9649967524..8a3edd694b 100644 --- a/scripts/sync-docs-image-tags.mjs +++ b/scripts/sync-docs-image-tags.mjs @@ -75,6 +75,22 @@ // historical facts across three files with nothing downstream to complain, so // --self-test asserts a clean corpus is left BYTE-IDENTICAL, with no write at all. +// ## The dispatch-gates population, read rather than assumed +// +// This file is a REWRITER, and in rewrite mode it opens the three doc surfaces +// plus `packages/cli/package.json` -- all of them inherited from +// `check-docs-image-tag.mjs`, which declares them and is judged on them. But the +// family CI schedules is `check:docs-image-tag-sync`, and both of its call sites +// (lint.yml and release.yml) run `--self-test`, which works entirely inside a +// `mkdtempSync` fixture tree and reads not one tracked file. So there is no +// population for a card to implicate, and the honest declaration is the marker +// rather than a hint set copied from the gate next door -- a hint here would +// name this family on every `content/docs/**` card for reads its CI invocation +// never performs. The SURFACES themselves are already declared where they are +// read: `check:docs-image-tag` carries them. +// +// dispatch-gates: no-path-population -- both CI call sites (lint.yml, release.yml) run this rewriter's --self-test, which works inside a mkdtemp fixture tree and reads no tracked file; the doc surfaces and the version source belong to check:docs-image-tag, which declares them + import { readFileSync, writeFileSync, mkdirSync, mkdtempSync, rmSync, statSync, existsSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; From 565db3e17983f53eb1136b6555a0b026774399e6 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 4 Sep 2026 16:52:23 +0000 Subject: [PATCH 2/2] fix(scripts): withdraw the wholesale-root hints refused by bare-root-worklist (#15341) `scripts/pm/bare-root-worklist.mjs` carries the recorded, measured triage for exactly this class, and its `--self-test` reds on a declaration that contradicts a recorded refusal. Eleven of the sixteen gates the card names are refused there by name: REFUSE-WIDE where the bare root is TRUE of the walk and refused for width, REFUSE-UNSPELLABLE where the population is a file-kind filter no subtree glob can spell. Two of those rows quote percentages for the exact spellings this branch had declared. Those eleven declarations are withdrawn and their gates left as they were. What stays is the half neither map refuses: two enumerated FILE populations at 100% precision, three families whose CI invocation is a fixture-only self-test and which now say so, and check:org-identifier, whose ROOT_WALK_RESIDUE_LEDGER row names this declaration as its remedy. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk --- scripts/check-declaration-mirrors.mjs | 38 ------------- scripts/check-init-service-contract.mjs | 50 +---------------- scripts/check-live-db-isolation.mjs | 49 +---------------- scripts/check-meta-type-normalized.mjs | 49 +---------------- .../check-optional-error-sink-contract.mjs | 54 +------------------ scripts/check-resume-authority-declared.mjs | 42 +-------------- scripts/check-runner-env-posture.mjs | 38 +------------ scripts/check-settings-bind-window.mjs | 46 +--------------- scripts/check-startup-registry-verdict.mjs | 38 +------------ scripts/check-verify-stand-in-erasure.mjs | 39 +------------- scripts/check-wildcard-fallthrough.mjs | 47 +--------------- 11 files changed, 12 insertions(+), 478 deletions(-) diff --git a/scripts/check-declaration-mirrors.mjs b/scripts/check-declaration-mirrors.mjs index 288a98986d..016e2efd3d 100644 --- a/scripts/check-declaration-mirrors.mjs +++ b/scripts/check-declaration-mirrors.mjs @@ -118,26 +118,6 @@ const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, '..'); const SCRIPTS_DIR = join(REPO_ROOT, 'scripts'); -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `mirrorFiles()` walks `SCRIPTS_DIR` for every `*.d.mts` and opens the `.mjs` - * beside each one — one subtree, `scripts/`. The walk root is assembled with - * `join()`, so the derivation, which reads SOURCE TEXT, saw a bare word and no - * path at all: both of this gate's CI invocations (the scan and its - * `--self-test`) were scored `undetermined` for EVERY card, absent from every - * dispatch brief and every `--commands` harvest, while CI ran them on each pull - * request. `hintCovers` refuses a bare single-segment literal by design, so the - * subtree spelling is the escape the idiom exists to be. - * - * ⛔ Not a whole-tree marker: `scripts/**` is a subtree, and this gate reads - * nothing outside it. - * - * The self-test holds the declaration against the live walk rather than against - * a second spelling of the root, so a moved corpus reds here. - */ -const ROOT_DIR_WATCH_HINTS = ['scripts/**']; - /** * The export spellings this parser recognises, in the words a declaration * author would write them. Published for the same reason the cross-package @@ -623,24 +603,6 @@ async function selfTest() { mirrorFiles().every((f) => f.endsWith('.d.mts')), ); - // ── the dispatch-gates population declaration ── - ok( - 'the declared population is the subtree spelling of the walked root — a bare `scripts` literal is ' - + 'refused by hintCovers as too generic, which is how this gate came to declare nothing at all', - ROOT_DIR_WATCH_HINTS.length === 1 && ROOT_DIR_WATCH_HINTS[0] === 'scripts/**', - ); - ok( - 'and the live walk agrees with it — every discovered mirror sits under the declared root, so a ' - + 'moved corpus reds here instead of quietly re-emptying the declaration', - mirrorFiles().every((f) => relative(REPO_ROOT, f).split(sep).join('/') - .startsWith(`${ROOT_DIR_WATCH_HINTS[0].replace(/\/\*+$/, '')}/`)), - ); - ok( - 'the declared form is NOT the bare walk root — the glob form would send the walk at a directory ' - + 'the tree does not have', - !ROOT_DIR_WATCH_HINTS.includes(relative(REPO_ROOT, SCRIPTS_DIR).split(sep).join('/')), - ); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-init-service-contract.mjs b/scripts/check-init-service-contract.mjs index bc97f8ddc7..70dd6f2716 100644 --- a/scripts/check-init-service-contract.mjs +++ b/scripts/check-init-service-contract.mjs @@ -121,12 +121,11 @@ const SELF_TEST_BATTERIES = Object.freeze({ '17. Every exemption is decided by WHEN the call runs, not by which accessor': 1, '18. `--list` and the problem text must quote the accessor actually called.': 1, '19. Nothing outside the vocabulary is invented: a lookup-shaped call on a': 1, - '20. The dispatch-gates population declaration.': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 20; +const SELF_TEST_BATTERY_FLOOR = 19; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -135,27 +134,6 @@ const UNATTRIBUTED_BATTERY = '(no battery open)'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); -/** The trees this gate walks. Plugin units live under `packages/`. */ -const SCAN_ROOTS = ['packages']; - -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * The walk root used to be an inline `'packages'` argument. The derivation reads - * SOURCE TEXT and `hintCovers` refuses a bare single-segment literal by design - * (admitting them was priced at +139084 fabricated (gate, file) pairs, because - * `packages` is a path COMPONENT in dozens of gates that never read that root), - * so this gate declared no path at all: scored `undetermined` for EVERY card, - * absent from every dispatch brief and every `--commands` harvest, while CI ran - * it on each pull request. The subtree spelling is the escape the idiom exists - * to be, and `SCAN_ROOTS` is the constant it is held against — the walk now - * reads the same constant, so a moved read reds in this file's own self-test. - * - * ⛔ Not a whole-tree marker: `packages/**` is a subtree, and a whole-tree row - * appears on every card in the repo whether or not the gate reads the file. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**']; - const DECLARATION_FIELDS = ['dependencies', 'optionalDependencies', 'requiresServices', 'providesServices']; // ── Discovery ──────────────────────────────────────────────────────────────── @@ -174,7 +152,7 @@ function discoverFiles() { out.push(relative(ROOT, full).split(sep).join('/')); } }; - for (const root of SCAN_ROOTS) walk(join(ROOT, root)); + walk(join(ROOT, 'packages')); return out.sort(); } @@ -946,30 +924,6 @@ function selfTest() { assert(problems.length === 0, 'hasService is not in the vocabulary (not plugin-reachable in packages/core)'); } - // 20. The dispatch-gates population declaration. - battery('20. The dispatch-gates population declaration.'); - assert( - SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), - 'every separator-less SCAN_ROOT is declared in the subtree spelling — a bare root is refused as ' - + 'too generic, so without the glob the hint extractor reads nothing and this gate goes back to ' - + 'scoring `undetermined` for every card', - ); - assert( - ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), - 'no root is declared that this gate does not walk — a declaration that has drifted from the scan ' - + 'replaces a silent gate with a lying one', - ); - assert( - !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), - 'the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a directory ' - + 'the tree does not have', - ); - assert( - discoverFiles().every((f) => ROOT_DIR_WATCH_HINTS.some((h) => f.startsWith(`${h.replace(/\/\*+$/, '')}/`))), - 'and the WALK agrees with the declaration on the live tree — this is the half the two assertions ' - + 'above cannot hold, since both read the constant rather than what discoverFiles() returns', - ); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ─── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-live-db-isolation.mjs b/scripts/check-live-db-isolation.mjs index 89352764ef..67a7a3a221 100644 --- a/scripts/check-live-db-isolation.mjs +++ b/scripts/check-live-db-isolation.mjs @@ -94,12 +94,11 @@ const SELF_TEST_BATTERIES = Object.freeze({ '7. comments are not source -- the reason codeOf exists': 1, '8. the live-file needle must MATCH a real read and not the cell form': 2, '9. `use strict` and friends are not live DDL': 1, - '10. the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 10; +const SELF_TEST_BATTERY_FLOOR = 9; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -175,29 +174,6 @@ function batteryFloorFailures() { const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const ROOTS = ['packages', 'apps', 'examples']; - -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `ROOTS` is a runtime constant, and the derivation reads SOURCE TEXT: three - * bare top-level words carry no separator, and `hintCovers` refuses a bare - * single-segment literal by design (accepting them was priced at +139084 - * fabricated (gate, file) pairs, because `packages`, `apps` and `examples` are - * path COMPONENTS in dozens of gates that never read those roots). So this gate - * declared no path at all and was scored `undetermined` for EVERY card: it - * appeared in no dispatch brief and in no `--commands` harvest, while CI ran it - * on every pull request. The subtree spelling is the escape the idiom exists to - * be — the same claim `ROOTS` makes, written where a text scanner can read it. - * - * ⛔ Not a whole-tree marker: this gate reads three subtrees, and the liveness - * predicate that vouches for a whole-tree declaration is documented as too weak - * to tell a seeded subtree walk apart from a repo-root one. - * - * The self-test derives the coupling from `ROOTS` on both sides rather than - * re-spelling it, so widening or renaming a root cannot leave this declaration - * describing the old population. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**', 'apps/**', 'examples/**']; const SKIP_DIRS = new Set(['node_modules', 'dist', '.turbo', 'coverage', '.next', 'build']); /** @@ -460,29 +436,6 @@ function selfTest() { battery('9. `use strict` and friends are not live DDL'); check('does not flag a non-identifier use', violationsIn(`'use strict';`).length === 0); - // 10. the dispatch-gates population declaration - battery('10. the dispatch-gates population declaration'); - check( - 'every separator-less ROOT is declared in the subtree spelling (a bare root is refused as too ' - + 'generic, so it needs the glob)', - ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), - ); - check( - 'and it declares no root this gate does not walk — a declaration that can drift from the scan ' - + 'replaces a silent gate with a lying one', - ROOT_DIR_WATCH_HINTS.every((h) => ROOTS.includes(h.replace(/\/\*+$/, ''))), - ); - check( - 'the declared form is NOT a ROOTS entry — the glob form would send the walk at a directory the ' - + 'tree does not have', - !ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), - ); - check( - 'the declaration is not empty — an empty hint list reads exactly like the undetermined verdict ' - + 'it exists to leave', - ROOT_DIR_WATCH_HINTS.length === ROOTS.length, - ); - // The floor runs BEFORE the verdict below, so a success line can only be // printed by a run in which every declared battery registered its cases. for (const message of batteryFloorFailures()) cases.push({ label: message, ok: false }); diff --git a/scripts/check-meta-type-normalized.mjs b/scripts/check-meta-type-normalized.mjs index d781da5268..9fdee8a1ec 100644 --- a/scripts/check-meta-type-normalized.mjs +++ b/scripts/check-meta-type-normalized.mjs @@ -90,30 +90,6 @@ const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); /** Directories scanned. Route handlers that read `:type` live here. */ const SCAN_DIRS = [join('packages', 'rest', 'src')]; -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `SCAN_DIRS` is assembled with `join()`, one SEGMENT per literal, so the - * derivation — which reads SOURCE TEXT — sees three bare words and no path at - * all. This gate was therefore scored `undetermined` for EVERY card, absent from - * every dispatch brief and every `--commands` harvest, while CI ran it on each - * pull request. - * - * ⚠️ The hint is `packages/rest/src/**`, NOT `packages/**`. The scan is one - * package's source directory; the wider spelling would paste this gate onto - * every card under `packages/`, which is the costlier error — a lead that is - * wrong on thousands of files rather than a gate that is quiet. - * - * ⛔ And not a whole-tree marker for the same reason, one size up. - * - * The self-test derives the coupling from `SCAN_DIRS` on both sides rather than - * re-spelling it, so a moved or widened scan directory cannot leave this - * declaration describing the old population. The POSIX normalisation is - * load-bearing: `join()` yields a platform separator, and the declaration is - * read as text by a scanner that only knows `/`. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/rest/src/**']; - /** * Blessed raw comparisons: `'::'` -> reason. * Empty by design — see the header. @@ -242,12 +218,11 @@ const SELF_TEST_VERDICT = 'check-meta-type-normalized self-test reached its verd // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-meta-type-normalized self-test': 4, - 'the dispatch-gates population declaration': 3, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 2; +const SELF_TEST_BATTERY_FLOOR = 1; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -320,28 +295,6 @@ function selfTest() { if (hits.length !== 5) problems.push(`expected 5 findings total, saw ${hits.length} — a pass-through or a comment was flagged`); }); - // ── The dispatch-gates population declaration ──────────────────────── - battery('the dispatch-gates population declaration'); - const scannedPosix = SCAN_DIRS.map((d) => d.split(sep).join('/')); - check(() => { - if (!scannedPosix.every((d) => ROOT_DIR_WATCH_HINTS.includes(`${d}/**`))) { - problems.push('a SCAN_DIRS entry is not declared in the subtree spelling — the hint extractor ' - + 'reads source text, and a join()-assembled path is invisible to it'); - } - }); - check(() => { - if (!ROOT_DIR_WATCH_HINTS.every((h) => scannedPosix.includes(h.replace(/\/\*+$/, '')))) { - problems.push('ROOT_DIR_WATCH_HINTS declares a directory this gate does not walk — a declaration ' - + 'that has drifted from the scan replaces a silent gate with a lying one'); - } - }); - check(() => { - if (ROOT_DIR_WATCH_HINTS.some((h) => !h.startsWith('packages/rest/src'))) { - problems.push('the declaration widened past this gate\'s own package — `packages/**` would paste ' - + 'this gate onto every card under packages/, which is worse than the silence it replaces'); - } - }); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-optional-error-sink-contract.mjs b/scripts/check-optional-error-sink-contract.mjs index 80c86f0dbd..1f7eac8713 100644 --- a/scripts/check-optional-error-sink-contract.mjs +++ b/scripts/check-optional-error-sink-contract.mjs @@ -243,27 +243,6 @@ const BASELINE_PATH = join(HERE, 'optional-error-sink-contract.baseline.json'); /** Where the PUBLISHED contracts live. See "Scope" in the header. */ const SCAN_ROOTS = ['packages']; -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `SCAN_ROOTS` is a runtime constant and the derivation reads SOURCE TEXT, so - * the bare word `packages` contributes NOTHING: `hintCovers` refuses a - * single-segment literal by design, because `packages` is a path COMPONENT in - * dozens of gates that never read that root. This gate therefore declared no - * path at all, was scored `undetermined` for EVERY card, and appeared in no - * dispatch brief and no `--commands` harvest while CI ran it on every pull - * request. The subtree spelling is the escape the idiom exists to be. - * - * ⛔ Not a whole-tree marker: `packages/**` is a subtree, and a whole-tree - * declaration would put this gate on every card in the repo on a population it - * does not read. - * - * The self-test derives the coupling from `SCAN_ROOTS` on both sides rather - * than re-spelling it, so a widened or renamed root cannot leave this - * declaration describing the old population. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**']; - const SKIP_DIRS = new Set([ 'node_modules', 'dist', 'build', 'coverage', '.turbo', '.next', '.cache', 'json-schema', '.git', ]); @@ -847,12 +826,11 @@ let selfTestReachedVerdict = false; // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-optional-error-sink-contract self-test': 66, - 'the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 2; +const SELF_TEST_BATTERY_FLOOR = 1; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -1168,36 +1146,6 @@ check(() => { } } - // ── The dispatch-gates population declaration ─────────────────────────── - battery('the dispatch-gates population declaration'); - const declFail = (msg) => { failures++; console.error(` ✗ ${msg}`); }; -check(() => { - const separatorless = SCAN_ROOTS.filter((r) => !r.includes('/')); - if (!separatorless.every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))) { - declFail('a separator-less SCAN_ROOT is not declared in the subtree spelling — a bare root is ' - + 'refused as too generic, so the hint extractor sees nothing and this gate goes back to ' - + 'scoring `undetermined` for every card.'); - } -}); -check(() => { - if (!ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, '')))) { - declFail('ROOT_DIR_WATCH_HINTS declares a root this gate does not walk — a declaration that has ' - + 'drifted from the scan replaces a silent gate with a lying one.'); - } -}); -check(() => { - if (SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))) { - declFail('the declared form is a SCAN_ROOTS entry — the glob form would send the walk at a ' - + 'directory the tree does not have.'); - } -}); -check(() => { - if (ROOT_DIR_WATCH_HINTS.length !== SCAN_ROOTS.length) { - declFail('the declaration is not one hint per walked root — an empty or short hint list reads ' - + 'exactly like the undetermined verdict it exists to leave.'); - } -}); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-resume-authority-declared.mjs b/scripts/check-resume-authority-declared.mjs index 744edf52a7..2f7959babd 100644 --- a/scripts/check-resume-authority-declared.mjs +++ b/scripts/check-resume-authority-declared.mjs @@ -112,29 +112,6 @@ import { parseSourceFile } from './ts-parse.mjs'; const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const DEFAULT_SCAN_ROOTS = ['packages', 'examples']; -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `DEFAULT_SCAN_ROOTS` is a runtime constant and the derivation reads SOURCE - * TEXT, so two bare top-level words contribute NOTHING — `hintCovers` refuses a - * single-segment literal by design, because `packages` and `examples` are path - * COMPONENTS in dozens of gates that never read those roots. This gate declared - * no path at all, so it was scored `undetermined` for EVERY card and reached no - * dispatch brief and no `--commands` harvest while CI ran it on every pull - * request. The subtree spelling is the escape the idiom exists to be. - * - * ⛔ Not a whole-tree marker: these are two subtrees, and a whole-tree row - * appears on every card in the repo — a fabricated lead unless the gate really - * reads every file. - * - * The self-test derives the coupling from `DEFAULT_SCAN_ROOTS` on both sides - * rather than re-spelling it, so widening or renaming a root cannot leave this - * declaration describing the old population. `--dir` narrows the scan for a - * single manual run; the DEFAULT is what CI schedules and what a card can - * implicate, which is why the declaration is held against that constant. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**', 'examples/**']; - /** The factory whose argument IS an action descriptor (packages/spec). */ const FACTORY = 'defineActionDescriptor'; @@ -387,12 +364,11 @@ const SELF_TEST_BATTERIES = Object.freeze({ 'A dynamically assembled argument is recorded, never judged.': 2, 'A same-named local factory is not the spec\'s. Deliberately still counted:': 2, 'Wiring: discovery must reach the real tree, and specifically the four': 5, - 'The dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 8; +const SELF_TEST_BATTERY_FLOOR = 7; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -521,22 +497,6 @@ const b = defineActionDescriptor({ type: 'b', version: '1.0.0', name: 'B', suppo expect(`discovery reaches the '${t}' pausing built-in`, pausingTypes.has(t)); } - // ── The dispatch-gates population declaration - battery('The dispatch-gates population declaration'); - const separatorless = DEFAULT_SCAN_ROOTS.filter((r) => !r.includes('/')); - expect('every separator-less scan root is declared in the subtree spelling (a bare root is refused ' - + 'as too generic, so the extractor reads nothing without the glob)', - separatorless.every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))); - expect('and it declares no root this gate does not walk — a declaration that drifts from the scan ' - + 'replaces a silent gate with a lying one', - ROOT_DIR_WATCH_HINTS.every((h) => DEFAULT_SCAN_ROOTS.includes(h.replace(/\/\*+$/, '')))); - expect('the declared form is NOT a DEFAULT_SCAN_ROOTS entry — the glob form would send the walk at ' - + 'a directory the tree does not have', - !DEFAULT_SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))); - expect('one hint per walked root — a short list reads exactly like the undetermined verdict it ' - + 'exists to leave', - ROOT_DIR_WATCH_HINTS.length === DEFAULT_SCAN_ROOTS.length); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ─── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-runner-env-posture.mjs b/scripts/check-runner-env-posture.mjs index 94783857a4..28ed071a91 100644 --- a/scripts/check-runner-env-posture.mjs +++ b/scripts/check-runner-env-posture.mjs @@ -111,12 +111,11 @@ const SELF_TEST_BATTERIES = Object.freeze({ 'Population.': 7, 'Wiring. Unwiring the gate must redden HERE rather than go quiet.': 3, 'The corpus itself, as a case rather than as the run\'s only evidence.': 1, - 'The dispatch-gates population declaration.': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 9; +const SELF_TEST_BATTERY_FLOOR = 8; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -196,31 +195,6 @@ const ROOT = resolve(HERE, '..'); /** Trees that can hold product source. */ export const SCANNED_ROOTS = ['packages', 'apps', 'examples']; -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `SCANNED_ROOTS` is a runtime constant and the derivation reads SOURCE TEXT, - * so three bare top-level words contribute NOTHING: `hintCovers` refuses a - * single-segment literal by design, because `packages`, `apps` and `examples` - * are path COMPONENTS in dozens of gates that never read those roots. This gate - * therefore declared no path at all and was scored `undetermined` for EVERY - * card — absent from every dispatch brief and every `--commands` harvest, while - * CI ran it on every pull request. The subtree spelling is the escape the idiom - * exists to be. - * - * ⛔ Not a whole-tree marker: three subtrees are not the tree, and a whole-tree - * row appears on every card whether or not the gate reads the file. - * - * The hints name the WALKED roots, not the narrower `isProductSource` filter - * applied inside them. That is the honest claim for a lead: the filter decides - * what the gate REPORTS on, the roots decide what it READS, and a card under a - * walked root can move this gate's verdict by adding a `src/` file to it. - * - * The self-test derives the coupling from `SCANNED_ROOTS` on both sides rather - * than re-spelling it. - */ -export const ROOT_DIR_WATCH_HINTS = ['packages/**', 'apps/**', 'examples/**']; - /** Directory names never descended into. */ const SKIP_DIRS = new Set(['node_modules', 'dist', 'build', '.turbo', '.next', 'coverage', '.git']); @@ -447,16 +421,6 @@ export function selfTest() { battery('The corpus itself, as a case rather than as the run\'s only evidence.'); t('today\'s tree is clean', scanTree().length, 0); - // --- The dispatch-gates population declaration. - battery('The dispatch-gates population declaration.'); - t('every separator-less scanned root is declared in the subtree spelling', - SCANNED_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), true); - t('and no root is declared that this gate does not walk', - ROOT_DIR_WATCH_HINTS.every((h) => SCANNED_ROOTS.includes(h.replace(/\/\*+$/, ''))), true); - t('the declared form is NOT a SCANNED_ROOTS entry', - SCANNED_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), false); - t('one hint per walked root', ROOT_DIR_WATCH_HINTS.length, SCANNED_ROOTS.length); - // The floor runs BEFORE the verdict below, so a success line can only be // printed by a run in which every declared battery registered its cases. for (const message of batteryFloorFailures()) cases.push([message, false, true]); diff --git a/scripts/check-settings-bind-window.mjs b/scripts/check-settings-bind-window.mjs index dd3ef9766a..74df37bf1e 100644 --- a/scripts/check-settings-bind-window.mjs +++ b/scripts/check-settings-bind-window.mjs @@ -113,27 +113,6 @@ import { parseSourceFile } from './ts-parse.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); -/** The trees this gate walks. Plugin units live under `packages/`. */ -const SCAN_ROOTS = ['packages']; - -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * The walk root used to be an inline `'packages'` argument. The derivation reads - * SOURCE TEXT and `hintCovers` refuses a bare single-segment literal by design - * (admitting them was priced at +139084 fabricated (gate, file) pairs, because - * `packages` is a path COMPONENT in dozens of gates that never read that root), - * so this gate declared no path at all: scored `undetermined` for EVERY card, - * absent from every dispatch brief and every `--commands` harvest, while CI ran - * it on each pull request. The subtree spelling is the escape the idiom exists - * to be, and `SCAN_ROOTS` is the constant it is held against — the walk reads - * the same constant, so a moved read reds in this file's own self-test. - * - * ⛔ Not a whole-tree marker: `packages/**` is a subtree, and a whole-tree row - * lands on every card in the repo whether or not the gate reads the file. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**']; - const DECLARATION_FIELDS = ['dependencies', 'optionalDependencies', 'requiresServices', 'providesServices']; /** The service name whose provider late-binds its engine — see the header. */ @@ -198,7 +177,7 @@ function discoverFiles() { out.push(relative(ROOT, full).split(sep).join('/')); } }; - for (const root of SCAN_ROOTS) walk(join(ROOT, root)); + walk(join(ROOT, 'packages')); return out.sort(); } @@ -1059,29 +1038,6 @@ function selfTest() { assert(stale.length === 1, 'a ledger entry with no matching problem is stale'); } - // 17. The dispatch-gates population declaration: the subtree spelling names - // the roots the walk really reads, and only those. - assert( - SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), - 'every separator-less SCAN_ROOT is declared in the subtree spelling — a bare root is refused as ' - + 'too generic, so without the glob this gate scores `undetermined` for every card', - ); - assert( - ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), - 'no root is declared that this gate does not walk — a declaration that has drifted from the scan ' - + 'replaces a silent gate with a lying one', - ); - assert( - !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), - 'the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a directory ' - + 'the tree does not have', - ); - assert( - discoverFiles().every((f) => ROOT_DIR_WATCH_HINTS.some((h) => f.startsWith(`${h.replace(/\/\*+$/, '')}/`))), - 'and the WALK agrees with the declaration on the live tree — the half the assertions above cannot ' - + 'hold, since they read the constant rather than what discoverFiles() returns', - ); - console.log(`✓ settings bind-window guard self-test: all cases pass.`); } diff --git a/scripts/check-startup-registry-verdict.mjs b/scripts/check-startup-registry-verdict.mjs index 8935383f7c..2422b4e2db 100644 --- a/scripts/check-startup-registry-verdict.mjs +++ b/scripts/check-startup-registry-verdict.mjs @@ -154,29 +154,6 @@ import { parseSourceFile } from './ts-parse.mjs'; import { isEntrypoint } from './invoked-as.mjs'; const ROOT = fileURLToPath(new URL('..', import.meta.url)); - -/** The trees this gate walks by default. Plugin units live under `packages/`. */ -const SCAN_ROOTS = ['packages']; - -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * The default scan root used to be an inline `'packages'` argument. The - * derivation reads SOURCE TEXT and `hintCovers` refuses a bare single-segment - * literal by design (admitting them was priced at +139084 fabricated - * (gate, file) pairs, because `packages` is a path COMPONENT in dozens of gates - * that never read that root), so this gate declared no path at all: scored - * `undetermined` for EVERY card, absent from every dispatch brief and every - * `--commands` harvest, while CI ran it on each pull request. The subtree - * spelling is the escape the idiom exists to be. - * - * The declaration is held against the DEFAULT root, which is what CI schedules - * and what a card can implicate; `--packages-dir` retargets a single manual run - * and is not a population any card can predict. - * - * ⛔ Not a whole-tree marker: `packages/**` is a subtree. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**']; const BASELINE_PATH = join(ROOT, 'scripts', 'startup-registry-verdict.baseline.json'); // ── Vocabulary ─────────────────────────────────────────────────────────────── @@ -928,7 +905,7 @@ function baselineKey(f) { } function run({ list = false, packagesDir } = {}) { - const scanRoot = packagesDir ? resolve(packagesDir) : join(ROOT, SCAN_ROOTS[0]); + const scanRoot = packagesDir ? resolve(packagesDir) : join(ROOT, 'packages'); const relBase = packagesDir ? resolve(packagesDir, '..') : ROOT; // The scan root must resolve BEFORE anything is concluded from the scan. The // old guard was `existsSync`, which accepts a file: the run then fell through @@ -1529,19 +1506,6 @@ function selfTest() { rmSync(dir, { recursive: true, force: true }); } - // --- The dispatch-gates population declaration. --------------------------- - // Filed through `expectRoot` rather than as a battery, deliberately: the - // roster above is one row per CASE in the table, and the floor block - // cross-checks the two — a battery with no table row would red that - // cross-check for a case that ran. - expectRoot('every separator-less SCAN_ROOT is declared in the subtree spelling', - SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), true); - expectRoot('no root is declared that this gate does not walk', - ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), true); - expectRoot('the declared form is NOT a SCAN_ROOTS entry (the glob form would send the walk at a directory the tree does not have)', - SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), false); - expectRoot('one hint per walked root', ROOT_DIR_WATCH_HINTS.length, SCAN_ROOTS.length); - // ── The floor: every declared row RAN, and ran its case (#13489) ─────── // // Evaluated after every row has had its chance and BEFORE the verdict, so the diff --git a/scripts/check-verify-stand-in-erasure.mjs b/scripts/check-verify-stand-in-erasure.mjs index d5bdea0c65..116b814354 100644 --- a/scripts/check-verify-stand-in-erasure.mjs +++ b/scripts/check-verify-stand-in-erasure.mjs @@ -81,27 +81,6 @@ const { VERIFY_STAND_IN_CHECKS } = await requireDependency('../eslint.config.mjs const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const VERIFY_SRC = join(REPO_ROOT, 'packages', 'verify', 'src'); const SCAN_ROOTS = ['packages', 'examples']; - -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * `SCAN_ROOTS` is a runtime constant and the derivation reads SOURCE TEXT, so - * two bare top-level words contribute NOTHING — `hintCovers` refuses a - * single-segment literal by design, because `packages` and `examples` are path - * COMPONENTS in dozens of gates that never read those roots. This gate declared - * no path at all and was scored `undetermined` for EVERY card: absent from every - * dispatch brief and every `--commands` harvest, while CI ran it on each pull - * request. The subtree spelling is the escape the idiom exists to be. - * - * ⛔ Not a whole-tree marker: two subtrees are not the tree. - * - * `VERIFY_SRC` is inside `packages/**` and needs no second hint — declaring it - * separately would name the same population twice and say nothing new. - * - * The self-test derives the coupling from `SCAN_ROOTS` on both sides rather - * than re-spelling it. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**', 'examples/**']; const SKIP_DIRS = new Set(['node_modules', 'dist', 'build', '.next', '.turbo', 'coverage']); const SOURCE_RE = /\.(ts|tsx|mts|cts)$/; @@ -435,12 +414,11 @@ const SELF_TEST_BATTERIES = Object.freeze({ 'CLEAN: the scan separates an asserted driver argument from a clean one.': 9, 'DISCOVERED: the shape test, on synthetic sources.': 2, 'Wiring: discovery must reach the REAL tree, and reach the two helpers': 13, - 'The dispatch-gates population declaration.': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 4; +const SELF_TEST_BATTERY_FLOOR = 3; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -617,21 +595,6 @@ function selfTest() { realSites.length >= 10, ); - // --- The dispatch-gates population declaration. - battery('The dispatch-gates population declaration.'); - expect('every separator-less scan root is declared in the subtree spelling (a bare root is refused ' - + 'as too generic, so the extractor reads nothing without the glob)', - SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`))); - expect('and it declares no root this gate does not walk — a declaration that drifts from the scan ' - + 'replaces a silent gate with a lying one', - ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, '')))); - expect('the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a ' - + 'directory the tree does not have', - !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r))); - expect('one hint per walked root — a short list reads exactly like the undetermined verdict it ' - + 'exists to leave', - ROOT_DIR_WATCH_HINTS.length === SCAN_ROOTS.length); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ─── // // Evaluated after every battery has had its chance and BEFORE the verdict, so diff --git a/scripts/check-wildcard-fallthrough.mjs b/scripts/check-wildcard-fallthrough.mjs index a2ae326a98..59ca1b6909 100644 --- a/scripts/check-wildcard-fallthrough.mjs +++ b/scripts/check-wildcard-fallthrough.mjs @@ -83,25 +83,6 @@ import { parseSourceFile } from './ts-parse.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); -/** The trees this gate walks. Router mounts live under `packages/`. */ -const SCAN_ROOTS = ['packages']; - -/** - * The population this gate walks, declared for `scripts/pm/dispatch-gates.mjs`. - * - * The walk root used to be an inline `'packages'` argument, and every path-shaped - * literal this file DOES carry is a LEDGER KEY (`: `), - * which the extractor cannot read as a path. So the derivation saw no population - * at all: this gate was scored `undetermined` for EVERY card, absent from every - * dispatch brief and every `--commands` harvest, while CI ran it on each pull - * request. `hintCovers` refuses a bare single-segment literal by design, so the - * subtree spelling is the escape — held against `SCAN_ROOTS`, which the walk - * now reads, so a moved read reds in this file's own self-test. - * - * ⛔ Not a whole-tree marker: `packages/**` is a subtree. - */ -const ROOT_DIR_WATCH_HINTS = ['packages/**']; - /** * Every namespace-claiming wildcard mount in the repo. Keyed by * `: ` so two mounts in one file stay distinguishable. @@ -214,7 +195,7 @@ function discoverFiles() { out.push(relative(ROOT, full).split(sep).join('/')); } }; - for (const root of SCAN_ROOTS) walk(join(ROOT, root)); + walk(join(ROOT, 'packages')); return out.sort(); } @@ -499,12 +480,11 @@ const SELF_TEST_VERDICT = 'check-wildcard-fallthrough self-test reached its verd // to find what stopped registering. const SELF_TEST_BATTERIES = Object.freeze({ 'check-wildcard-fallthrough self-test': 18, - 'the dispatch-gates population declaration': 4, }); // DELETING an entry silences that battery's floor exactly as effectively as // zeroing it, so the roster's own size is pinned too. -const SELF_TEST_BATTERY_FLOOR = 2; +const SELF_TEST_BATTERY_FLOOR = 1; // The key an assertion is filed under when no battery is open. It is not a // declared battery, so it reds by the same set difference rather than silently @@ -594,29 +574,6 @@ function selfTest() { 'method is part of the key', ); - // ── The dispatch-gates population declaration ───────────────────────────── - battery('the dispatch-gates population declaration'); - assert( - SCAN_ROOTS.filter((r) => !r.includes('/')).every((r) => ROOT_DIR_WATCH_HINTS.includes(`${r}/**`)), - 'every separator-less SCAN_ROOT is declared in the subtree spelling — a bare root is refused as ' - + 'too generic, so without the glob this gate scores `undetermined` for every card', - ); - assert( - ROOT_DIR_WATCH_HINTS.every((h) => SCAN_ROOTS.includes(h.replace(/\/\*+$/, ''))), - 'no root is declared that this gate does not walk — a declaration that has drifted from the scan ' - + 'replaces a silent gate with a lying one', - ); - assert( - !SCAN_ROOTS.some((r) => ROOT_DIR_WATCH_HINTS.includes(r)), - 'the declared form is NOT a SCAN_ROOTS entry — the glob form would send the walk at a directory ' - + 'the tree does not have', - ); - assert( - discoverFiles().every((f) => ROOT_DIR_WATCH_HINTS.some((h) => f.startsWith(`${h.replace(/\/\*+$/, '')}/`))), - 'and the WALK agrees with the declaration on the live tree — the half the assertions above cannot ' - + 'hold, since they read the constant rather than what discoverFiles() returns', - ); - // ── The floor: every declared battery RAN, and ran its cases (#13489) ──── // // Evaluated after every battery has had its chance and BEFORE the verdict, so