Skip to content

extractWatchHints strips a module-relative literal's own depth, so unreachableReason prints false "never was a repo path" rows for files the gates really read — residue-side repair, shape pending the #12371 ruling #12299

Description

@yinlianghui

Split out of #12246 so it is not closed with it. #12246 filed three defects; its
re-dispatch fixed defects 1 and 2 (a glob in a non-final segment collapsed to a dead double
slash, and the "THE LAYOUT MOVED" misclassification that followed from it) and put this
third one explicitly out of surface. Filed unassigned, not graded.

The defect

extractWatchHints was written against .mjs gates, whose relative imports carry a leading
./. The packages/spec TypeScript gates use paths-mapped bare specifiers that look pathy,
and the extractor admits any quoted span carrying a slash:

lib/dist-freshness · lib/generated-output · lib/schema-name · src/kernel/protocol-version
data/field.zod.ts · ui/view.zod.ts · @objectstack/spec · typescript/bin/tsc

None of these was ever a repo path.

Measured, and re-measured on daae7aa396

Fleet-wide over 170 families x 754 distinct hints x 6816 tracked files: 640 inert
(check, hint) pairs
, of which only 21 contain a glob at all. The specifiers carry no glob
whatsoever — this is a different function and a different mechanism from the glob collapse
#12246 fixed, which is why the two were separated there rather than folded together.

The inert hints fabricate no MATCHED pair — a hint covering zero files cannot put a gate
in any card's matched column. That was measured for #12107 and is why it landed. The cost is
confined to the residue, and it is real there: these specifiers are what unreachableReason
prints, so a family's genuine reason is displaced by literals that were never repo paths.

After #12246's fix the unreachable listing is 11 families, all of them "BY CONSTRUCTION",
and 10 of the 11 print reasons drawn entirely from this class, e.g.

- pnpm --filter @objectstack/spec run check:spec-changes [lint.yml] dead:
'src/kernel/protocol-version' — no tracked path under its first segment; never was a repo path
· 'src/migrations/registry' — … · 'src/migrations/spec-changes' — … · …

The verdicts are correct; the reasons are noise.

The warning that should become a pinned test whichever way this goes

⚠️ Inert today is not inert by construction. data/field.zod.ts and
src/kernel/protocol-version are one top-level data/ or src/ directory away from covering
real files, and at that point they would fabricate in the matched column rather than in the
residue — which is the expensive direction hintCovers' docblock prices, not the cheap one.

Not asserted

No claim about the remedy. The hint set is fleet-wide, so any change here is priced the way
firstPartyImportTargets' docblock prices a widening. One shape the card that fixes it will
have to decide: whether to teach the extractor to read the owning package's tsconfig.json
paths and drop what resolves through it, or to require a leading ./ for a TS gate's
relative reads, or to leave the extraction alone and filter at the point the residue prints.

Refs: #12246 (defects 1 and 2, fixed) · #12107 (the fix that made all 23 TypeScript gates
resolve their sources, which is what surfaced this class)

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions