Skip to content

[finding] dispatch-gates never names check:parse-guard for a scripts/ card — its literal scripts is refused as too generic #10790

Description

@claude

Found while working #10533, whose entire diff is one file under scripts/.

node scripts/pm/dispatch-gates.mjs did not name check:parse-guard in the local gate list, even
though that gate's population is exactly the directory the card edits. It appears instead under
Unreachable BY CONSTRUCTION:

3 unreachable BY CONSTRUCTION — the literal is not a path this derivation can reach,
and no change to the gate or the tree makes it one:
- pnpm check:parse-guard [lint.yml] dead: 'scripts' — the tree HAS it;
the covering rule refuses the literal as too generic (no path separator)

The gate is real and it read my file: run directly it reports

✓ check:parse-guard: 125 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
EXIT=0

The mechanism

hintCovers refuses a bare single-segment literal as too generic by design — that refusal is
measured, and scripts/check-role-word.mjs carries the measurement in its own header (teaching the
extractor to accept bare top-level directory words was priced at +139084 fabricated (gate, file)
pairs). So the refusal is correct; what is missing is the escape hatch.

scripts/check-parse-guard.mjs spells its population as scripts/** in prose throughout its
header, but the only string literal the extractor can reach is the bare 'scripts' on line 267:

returnn==='*'||n.startsWith('**')||n==='scripts'||n.startsWith('scripts/');

Why this is the same class the repo has already solved once

check-role-word.mjs hit exactly this for its skills root, paid for it as a repair round on
PR #10038 (a skills-only docs fix that derived a green local union and met the gate as red CI),
and closed it with a declaration rather than a wider extractor:

constROOT_DIR_WATCH_HINTS=['skills/**'];

with a self-test pinning both halves (every separator-less ROOT is declared; nothing declared is
itself a ROOTS entry). The same three lines would make check:parse-guard reachable for every
scripts/ card. Note the tension worth resolving in the same pass: the derivation prints
"no change to the gate or the tree makes it one", while its own residue text documents the escape
("a gate whose population really is a root file reaches it by declaring the subtree spelling").
One of those two sentences is wrong for this case.

Impact

Every card whose diff is scripts/** — a large share of gate/tooling work — gets a brief with this
gate missing, and CI enforces it anyway (lint.yml carries no path filter). The cost is a repair
round, paid by whoever happens to trip it.

Related, not duplicate

#10784 reports the same symptom for check:entry-guard and the same directory, but a different
mechanism (its population is an enumeration of the files that already exist, so a NEW file can never
appear in it). This one is a bare too-generic literal. Merge them if triage prefers one card for
"dispatch-gates blind spots over scripts/".

Not fixed in #10533's PR: different gate, different family, and it would widen a gate-semantics diff
past what its own card can be reviewed against.

Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions