@@ -5886,57 +5886,81 @@ export function packageRootAnchoredHint(hint, base, tree, files) {
58865886 *
58875887 * ## The census, measured on this tree
58885888 *
5889- * 3,513 top-level VALUE declarations over the 230 tracked JS/TS files under
5890- * `scripts/`. 64 identifiers match the predicate; 58 carry at least one string
5891- * literal; the whole set moves 14 hints, across 6 files:
5892- *
5893- * scripts/check-doc-authoring.mjs SKIP_PATHS, SKIP_FILES,
5889+ * Re-measured with the `DEFERRED` arm in place, on objectstack-ai/objectstack
5890+ * `7ec8534127`. The METHOD, which this block used to leave implicit: run
5891+ * `topLevelDecls` over every tracked JS/TS file under `scripts/`, keep the
5892+ * non-callable declarations, test each name against the predicate, and price
5893+ * the arm by diffing `extractWatchHints` against a build of this module whose
5894+ * predicate matches nothing. Attribution is the regex engine's own — leftmost
5895+ * position first, then alternation order.
5896+ *
5897+ * 4,697 top-level VALUE declarations over the 287 tracked JS/TS files under
5898+ * `scripts/`. 75 identifiers match the predicate; 66 carry at least one string
5899+ * literal; the whole set moves 24 hints, across 8 files:
5900+ *
5901+ * scripts/check-issue-citations.mjs DEFERRED_SURFACES 8
5902+ * scripts/check-doc-authoring.mjs SKIP_DIRS, SKIP_PATHS, SKIP_FILES,
58945903 * PACKAGES_PROSE_EXCLUDED 6
58955904 * scripts/check-refd-timer-probe.mjs EXCLUDED_DIRS 4
5896- * scripts/check-corpus-claim-drift.mjs SKIP_SUBTREES 1
5897- * scripts/check-role-word.mjs SKIP_SUBTREES 1
5905+ * scripts/pm/measurement-claim-triage.mjs EXCLUDED, SKIP_DIRS 2
5906+ * scripts/check-corpus-claim-drift.mjs SKIP_DIRS, SKIP_SUBTREES 1
5907+ * scripts/check-role-word.mjs SKIP_DIRS, SKIP_SUBTREES 1
58985908 * scripts/check-keyed-text-bounds.mjs SKIP_DIRS 1
5899- * scripts/pm/check-half-states.mjs H36_SHARED_PREFIX_NOISE 1
5909+ * scripts/pm/check-half-states.mjs H36_SHARED_PATH_NOISE,
5910+ * H36_SHARED_PREFIX_NOISE 1
59005911 *
59015912 * Each was read against the gate that declares it, and each is an exclusion in
59025913 * that gate's own words: "whole subtrees skipped by path", "generated
59035914 * subtrees, excluded by PATH under ROOTS", "generated from spec/frontmatter —
59045915 * not hand-authored, don't police", "directories `git ls-files` can still name
5905- * that hold no authored source", and — for `PACKAGES_PROSE_EXCLUDED`, the one
5906- * that is a bare string rather than a list — the `continue` in the gate's own
5907- * `descend` that skips it.
5908- *
5909- * ## What the 14 cost, which is not 14
5910- *
5911- * EIGHT of them change no derivation at all, because the gate ALSO declares the
5912- * containing root as an inclusion population and `hintCovers` still reaches the
5913- * path through that. Measured per hint, probing under each dropped hint against
5914- * the surviving set: all six of check-doc-authoring's (`.claude/**`, `docs/**`,
5915- * `content/**` and `packages/**` are its `ROOT_WATCH_HINTS`) and both
5916- * `content/docs/references` (covered by `content/docs`). That gate's own
5917- * self-test already said so from the other side — every `SKIP_PATHS` entry must
5918- * sit UNDER a declared root — so the exclusion hints were pure duplication.
5919- *
5920- * SIX really leave a derivation, and every one of them is a lead that was
5916+ * that hold no authored source", "deliberately OUT, each with the reading that
5917+ * put it out", and — for `PACKAGES_PROSE_EXCLUDED`, the one that is a bare
5918+ * string rather than a list — the `continue` in the gate's own `descend` that
5919+ * skips it.
5920+ *
5921+ * ## What the 24 cost, which is not 24
5922+ *
5923+ * THIRTEEN of them change no derivation at all, because the gate ALSO declares
5924+ * the containing root as an inclusion population and `hintCovers` still reaches
5925+ * the path through that. Measured per hint, probing under each dropped hint
5926+ * against the surviving set: all six of check-doc-authoring's (`.claude/**`,
5927+ * `docs/**`, `content/**` and `packages/**` are its `ROOT_WATCH_HINTS`), both
5928+ * `content/docs/references` (covered by `content/docs`), and the five test
5929+ * globs of the deferred table (covered by check-issue-citations' own
5930+ * `packages/**`). That gate's own self-test already said so from the other
5931+ * side — every `SKIP_PATHS` entry must sit UNDER a declared root — so those
5932+ * exclusion hints were pure duplication.
5933+ *
5934+ * ELEVEN really leave a derivation, and every one of them is a lead that was
59215935 * false: `node_modules`, `dist`, `coverage` and `.turbo` off
5922- * check-refd-timer-probe's skip set, and `.changeset` twice — off
5936+ * check-refd-timer-probe's skip set; `.changeset` twice — off
59235937 * check-keyed-text-bounds' `SKIP_DIRS` and off the noise floor the card was
5924- * filed on. The changeset pair is what a dev actually saw: a card that has not
5925- * written its changeset yet is told which families it will owe once it does,
5926- * and that projection carried FOUR fabricated rows, 16 -> 12 — including
5938+ * filed on; the two gate paths measurement-claim-triage declares it skips; and
5939+ * `scripts/**`, `docs/adr/**` and `.changeset/**` off `DEFERRED_SURFACES`,
5940+ * which is what the `DEFERRED` arm retired. The changeset pair is what a dev
5941+ * actually saw when #15753 was filed: a card that has not written its
5942+ * changeset yet is told which families it will owe once it does, and that
5943+ * projection carried FOUR fabricated rows, 16 -> 12 — including
59275944 * `check-half-states.mjs --format=markdown --provenance="$PROVENANCE"`, the
59285945 * networked half-state-patrol sweep, advertised to every card in the tree as a
5929- * gate its changeset would trigger.
5946+ * gate its changeset would trigger. The deferred table is that same reading
5947+ * one gate over, and it is why this arm exists: `surfaceFor` opens by
5948+ * returning `null` for every deferred glob, so `check:issue-citations` was
5949+ * offered to a changeset path as a gate it triggers while the gate looks at
5950+ * nothing there.
59305951 *
59315952 * ## The predicate: what the census kept, and what it retired
59325953 *
59335954 * `DENY`/`DENIED` was measured and REMOVED. It matched exactly one declaration
59345955 * on this tree and that one is a false positive — an HTTP fixture, not an
59355956 * exclusion list — and "deny" in this tree names AUTHORIZATION vocabulary
5936- * (`DENY_CODE`), never a path skip list. Matches for the surviving
5937- * alternatives, first-match attribution: SKIP 47, EXCLUDED 9, NOISE 2,
5938- * SKIPPED 2, EXCLUSION 2, EXCLUSIONS 1, EXCLUDES 1, and EXCLUDE / IGNORE /
5939- * IGNORED 0. The three zero-scoring arms are kept deliberately and the reason is
5957+ * (`DENY_CODE`), never a path skip list. `DEFERRED` was measured and ADDED: it
5958+ * matches two declarations on this tree, `DEFERRED_SURFACES` and
5959+ * `DEFERRED_GLOBS` in `check-issue-citations.mjs`, and both are that gate's
5960+ * own exclusion table. Matches for the surviving alternatives, first-match
5961+ * attribution: SKIP 54, EXCLUDED 10, EXCLUSION 4, NOISE 2, SKIPPED 2,
5962+ * DEFERRED 2, EXCLUSIONS 1, and EXCLUDE / EXCLUDES / IGNORE / IGNORED 0. The
5963+ * four zero-scoring arms are kept deliberately and the reason is
59405964 * the direction this predicate fails in: over-matching DROPS a hint (a missing
59415965 * lead — one card, one CI round), while under-matching KEEPS a wrong one (a
59425966 * fabricated lead pasted into every dispatch prompt whose surface brushes it).
@@ -5959,14 +5983,16 @@ export function packageRootAnchoredHint(hint, base, tree, files) {
59595983 * is not reached — `check-test-completeness.mjs` has the one instance on this
59605984 * tree, and it costs nothing today because every literal in it is a bare
59615985 * directory word the admission rule already refuses. camelCase spellings are
5962- * not reached either: the anchor is the SCREAMING_SNAKE segment, and the four
5963- * camelCase near-misses on this tree (`scripts/docs-audit/affected-docs.mjs`)
5964- * are counters and note strings, not populations. Both are the direction that
5986+ * not reached either: the anchor is the SCREAMING_SNAKE segment, and the seven
5987+ * camelCase near-misses on this tree (five in
5988+ * `scripts/docs-audit/affected-docs.mjs`, one in
5989+ * `scripts/check-type-check-coverage.mjs`, one here) are counters, note strings
5990+ * and memo caches, not populations. Both are the direction that
59655991 * drops LESS, which is the direction a widening of this rule may not silently
59665992 * take.
59675993 */
59685994const EXCLUSION_DECL_NAME =
5969- /(?:^|_)(?:NOISE|SKIP|SKIPPED|EXCLUDE|EXCLUDED|EXCLUDES|EXCLUSION|EXCLUSIONS|IGNORE|IGNORED)(?:_|$)/;
5995+ /(?:^|_)(?:NOISE|SKIP|SKIPPED|DEFERRED| EXCLUDE|EXCLUDED|EXCLUDES|EXCLUSION|EXCLUSIONS|IGNORE|IGNORED)(?:_|$)/;
59705996
59715997/** `topLevelDecls` classifies self-tests for its OTHER caller; this one has no stake in it. */
59725998const NO_SELF_TEST_STARTS = new Set();
@@ -17145,7 +17171,7 @@ function selfTest() {
1714517171 t('and a declaration AFTER it is unaffected — the span closes where the statement does', multilineHints.includes('packages/core/src'));
1714617172 // The named spellings, one case each, so a narrowing of the predicate is
1714717173 // visible here rather than only in the live census.
17148- for (const word of ['SKIP', 'EXCLUDE', 'EXCLUDED', 'EXCLUSIONS', 'IGNORE']) {
17174+ for (const word of ['SKIP', 'EXCLUDE', 'EXCLUDED', 'EXCLUSIONS', 'IGNORE', 'DEFERRED' ]) {
1714917175 const named = `const ${word}_PATHS = ['packages/skipped/src'];`;
1715017176 t(`\`${word}\` names an exclusion too — the predicate is the convention, not one constant`, !extractWatchHints(named).includes('packages/skipped/src'));
1715117177 }
0 commit comments