Skip to content

fix(tooling): declare check:where-matcher's test-file population where dispatch-gates can read it - #13231

Merged
os-elon merged 1 commit into
mainfrom
claude/issue-13163-where-matcher-hint
Aug 29, 2026
Merged

fix(tooling): declare check:where-matcher's test-file population where dispatch-gates can read it#13231
os-elon merged 1 commit into
mainfrom
claude/issue-13163-where-matcher-hint

Conversation

@os-elon

Copy link
Copy Markdown
Collaborator

Fixes#13163

scripts/pm/dispatch-gates.mjs derives a card's gate list from the path literals in each gate's own source. check-where-matcher-conformance.mjs declared its population twice and the derivation could read neither: once in prose (the extractor masks comment ranges by construction) and once as const SCAN_ROOT = 'packages', a single-segment literal looksPathy refuses as no hint at all.

The deliverable is DERIVABILITY, not a green gate

The gate always worked. What follows is therefore the reverse proof over the specimen the card names — the test file PR #13146 adds, packages/core/src/security/resolve-authz-context.platform-admin-config.test.ts — and not a run of the gate.

node scripts/pm/dispatch-gates.mjs packages/core/src/security/resolve-authz-context.platform-admin-config.test.ts
beforeafter
check:where-matcher in the MATCHED columnabsentmatched via ... gate source 'packages/**/*.test.ts'
matched / silent / roster-only / residue20 / 127 / 26 / 16321 / 126 / 25 / 162

The whole accounting moves by exactly one, in every bucket at once: the gate leaves the silent class, and specifically the "declare ONLY tracked FILES — an artifact roster" sub-class, which is the card's diagnosis stated in the tool's own vocabulary.

Both negative directions hold, so this is a narrowing and not the bare root wearing a glob:

  • packages/core/src/security/resolve-authz-context.ts (a non-test source in the same directory) — still not named, 0 hits.
  • docs/README.md — still not named, 0 hits.

What was measured, including one falsification

A2.3 — the card's extractor reading reproduces, exactly.extractWatchHints over the gate returned ["scripts/where-matcher-conformance.baseline.json"] — one hint, the gate's own baseline. After: ["scripts/where-matcher-conformance.baseline.json", "packages/**/*.test.ts"], exactly one hint added.

A2.1 — the two populations are genuinely identical, checked before copying.check-objectql-double-limit.mjs and this gate hold the same const SCAN_ROOT = 'packages', and their testFilesUnder functions are byte-identical (sha256 of both nine-line bodies: beb4ed6b2f863688) — same skip set, same /\.test\.ts$/ admission — and both are called as testFilesUnder(join(repoRoot, SCAN_ROOT)). So the copied spelling declares a population this gate really scans.

A2.2 — the "n/a" in the sibling's hint array is NOT a declaration, and is deliberately not copied. It is a byproduct: wrapOrder: 'n/a' is a verdict token in that gate's judge() and measure() — module-scope code, so not masked — and looksPathy admits any literal containing a separator. Measured: it reaches 0 tracked files, i.e. an inert hint, and isNonPathNamespace('n/a') is false so nothing filters it. Copying it would have added a dead hint for no reason.

Falsified, and worth recording: the tool does NOT stay silent about this gate today. The card's headline is true of the path derivation, but check:where-matcher is already printed for the specimen in the convention-triggered section ("adds or edits a test file"), the named table #8632 added for exactly this class of ratchet — and that entry is pinned by dispatch-gates' own self-test. So what this PR changes is narrower than "the gate was unreachable": it moves the gate into the high-signal MATCHED column, the one a dev pastes and runs, for the test files it really walks. The two authorities now agree instead of only one speaking. This does not retire the convention entry, and no line of scripts/pm/dispatch-gates.mjs is touched (that is #13126, queued behind this card).

The declaration, and the pins under it

ROOT_DIR_WATCH_HINTS = ['packages/**/*.test.ts'], declared beside SCAN_ROOT under the sibling's idiom. Measured on this tree at 2889 of the 2889 files this gate's own testFilesUnder() walk admits — set-equal in both directions (nothing walked left uncovered, nothing covered left unwalked) — against 5509 tracked files under the bare root.

Four assertions were added to the gate's own --self-test, which is the right host: check:pm-dispatch-gates is the battery for the derivation tool, and a where-matcher declaration failing there would read as "the derivation broke". pnpm check:where-matcher runs the self-test before the corpus scan, so CI holds it on every PR.

The pin was ablated in both directions, each mutation proven on disk (removed-text grep -c 0, injected-text grep -c 1, and a changed git hash-object blob) with an absolute-path trap restore verified back to the exact HEAD blob:

mutationself-testextractor under mutation
declaration made computed from SCAN_ROOTexit 1, "spelled as a LITERAL ... not computed"the hint disappears — the original defect, reproduced
declaration widened to 'packages/**'exit 1, "nothing is declared that this gate does not walk"a wide, lying hint appears

Restored tree: self-test exit 0, git diff HEAD empty. No build or dist/ leg applies — this gate is executed from source by path, not resolved through a package exports map.

The second edit: the recorded verdict had to move with it

scripts/pm/bare-root-worklist.mjs recorded this row as REFUSE-UNSPELLABLE — "the population is a file-KIND filter inside the root, and NO spelling of the idiom describes it". Leaving that standing beside a gate that now declares exactly such a spelling is the lying-record failure that file exists to catch, and its own --self-test cannot see it (it audits keys and verdicts, never what a why says).

The row moves to DECLARED-NARROWER with the existing package test files spelling, re-measured on this tree rather than carried from the sibling. This is a re-decision on a shrink-only map, taken under the authorisation sentence the maintainer's 2026-08-26 ruling granted in that file and no wider one: bringing a verdict back to truth after its definitional basis moved (#12300 retired the collapse the refusal rested on) is not loosening the map. The criterion that split that class was measured downstream pull; this row had none on 2026-08-26 and now has one. The header records the re-decision as an eighteenth row. Please sanity-check this half — it is the one judgement call in the PR.

Mechanically confirmed: the row stays uncovered (packages/**/*.test.ts does not cover packages/probe.file), which is what DECLARED-NARROWER states, so the self-test's CONTRADICTED direction stays empty.

Verification

All of the following at final head 3ce97e4b4d, each exit code captured before any pipe, each verdict quoted from the gate's own output.

  • pnpm check:where-matcher — VERDICT command-exit 0 under the shared verify lock. "where-matcher conformance holds: 315 matcher(s) discovered, 315 answer the combinator battery correctly or refuse it loudly (197 refuse). 0 silently-wrong and 0 unjudged."
  • node scripts/pm/bare-root-worklist.mjs --self-test — exit 0. "50 live row(s), 43 unreachable as spelled, 43 recorded verdict(s) — none stale, none missing, none contradicted. 18 record(s) carry a spelling and every one of 9 distinct spelling(s) is pinned LIVE, PRECISE and COMPLETE."
  • pnpm check:pm-dispatch-gates — exit 0. "dispatch-gates self-test: 879 cases pass."
  • pnpm check:watch-hint-literal — exit 0. "20 ROOT_DIR_WATCH_HINTS declaration(s), every one an array of quoted literals inside its own statement."
  • The rest of the family node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack derives for this diff, all exit 0: check:agent-test-spelling, check:bash32-floor, check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard, check:pnpm-filter-targets, check:nul-bytes, scripts/check-ci-filter-parity.mjs, scripts/check-cross-package-test-inputs.mjs, scripts/check-shard-attestation.mjs.
  • The four gates the residue flags as "not evidence in EITHER direction" because their roster sits in a directory one of these paths is in, run rather than read as clearance: check:i18n-stale-fill, check:pm-label-desc-cap, scripts/check-published-list-mirrors.mjs, check:pm-dispatch-gates — all exit 0.
  • pnpm lint — whole-repo eslint . --no-inline-config, exit 0 in 70s. No narrowing claimed.
  • node scripts/check-test-completeness.mjsNOT MEASURED, not red: it printed "PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named" ([finding] check-test-completeness.mjs answers a standalone run with exit 1 + a usage line, so the derived gate family reads one false red — three independent devs paid for it in one session #13110).

No changeset: this PR touches two tooling scripts, publishes nothing, and releases no package. skip-changeset applied.

Generated by Claude Code


Generated by Claude Code

…e dispatch-gates can read it
`scripts/pm/dispatch-gates.mjs` derives a card's gate list from the path
literals in each gate's own source. `check-where-matcher-conformance.mjs`
declared its population twice and the derivation could read neither: once in
prose (the extractor masks comment ranges by construction) and once as
`const SCAN_ROOT = 'packages'`, a single-segment literal `looksPathy` refuses
as no hint at all.
Measured before this change, `extractWatchHints` over the gate returned exactly
one hint — `scripts/where-matcher-conformance.baseline.json`, the gate's own
ledger. So the derivation could name the gate only for a change set that edits
the set of files ALREADY KNOWN to be wrong, and never for a NEW silently-wrong
matcher anywhere under the root it scans: the exact inverse of what it guards.
Declares `packages/**/*.test.ts` beside `SCAN_ROOT` under the
`ROOT_DIR_WATCH_HINTS` idiom, matching the identically-populated sibling
`check-objectql-double-limit.mjs` (byte-identical `testFilesUnder`, identical
`SCAN_ROOT`, identical call site). Measured at 2889 of the 2889 files the
gate's own walk admits — set-equal in both directions — against 5509 tracked
files under the bare root. Pinned in the gate's own `--self-test`, in the four
directions the sibling pins.
The PM's bare-root worklist row is re-decided from REFUSE-UNSPELLABLE to
DECLARED-NARROWER with the same `package test files` spelling, re-measured on
this tree rather than carried from the sibling.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
@os-elonos-elon added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 29, 2026 — with Claude
@os-elon
os-elon marked this pull request as ready for review August 29, 2026 14:09
@os-elon
os-elon added this pull request to the merge queueAug 29, 2026
Merged via the queue into main with commit afef7d8Aug 29, 2026
34 checks passed
@os-elon
os-elon deleted the claude/issue-13163-where-matcher-hint branch August 29, 2026 14:38
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-elon@claude