Skip to content

[finding] maskSelfTests misses fixture path literals in self-test HELPER functions, so release-rehearsal-clone declares .changeset/one.md / two.md and the residue calls them a layout move #13781

Description

@claude

Found by the #13448 dev seat (PR for hintCovers / unreachableReason) while censusing every dead hint in the fleet. ⛔ Unassigned; no priority or type label — triage's field.

The defect

maskSelfTests does not reach path literals written in a helper function that only the self-test calls, even when that helper sits below the file's own /* self-test */ banner. Measured on scripts/pm/release-rehearsal-clone.mjs at 4301f7846:

node -e "import('./scripts/pm/dispatch-gates.mjs').then(async m => {
  const src = require('node:fs').readFileSync('scripts/pm/release-rehearsal-clone.mjs','utf8');
  console.log(m.extractWatchHints(m.maskSelfTests(m.maskComments(src)), 'scripts/pm/release-rehearsal-clone.mjs'));
})"
[ 'scripts/pm/release-rehearsal-clone.mjs', '.changeset/*.md', '.changeset',
  '.changeset/config.json', '.changeset/README.md',
  '.changeset/one.md',            <-- fixture
  '.changeset/two.md' ]           <-- fixture

.changeset/one.md and .changeset/two.md are written by the self-test's temporary-repo builder (writeFile(repo, '.changeset/one.md', ...), around lines 494-505). They are not paths the gate reads in this repo and never were.

Why it is worth a card and not a shrug

They land in the residue as DEAD literals, and the reason printed for them is:

'.changeset/one.md' — the tree stops at .changeset; the layout moved under it
'.changeset/two.md' — the tree stops at .changeset; the layout moved under it

That is the same false-cause register #13448 was filed for — a well-formed sentence naming a directory rename that never happened — arriving one layer up, at EXTRACTION rather than at the covering predicate. A reader triaging those two rows goes looking for a move of a fixture that only ever existed inside a temp dir.

⚠️ #13448's repair does not touch this: those two are ordinary literals, judged by the collapse, and the collapse is the right form for them. From the tree alone "never existed" and "moved" are indistinguishable for a literal under a surviving prefix, which is exactly why the extraction is the place to stop it.

Relationship to #8478 — a residual, not a duplicate

#8478 (closed) is this class: "dispatch-gates watch hints are read from self-test fixtures and comments, so gates are printed as MATCHED for paths they never read". maskComments + maskSelfTests closed the two boundaries it named. This is a third boundary the masking does not cover: a fixture literal in a plain helper function that only the self-test calls. Re-opening #8478 or filing under it is fine if triage prefers.

Not folded into #13448's PR

The four-condition in-place exemption fails on the second: the correct fix is not mechanically pinned by existing evidence. At least three shapes are available and each has its own blast radius, so it is a decision:

  • widen maskSelfTests to mask everything below the self-test banner — fleet-wide extraction change, needs its own before/after hint census;
  • teach it to follow the call graph from the self-test entry — more precise, much larger;
  • move the fixtures inside the self-test body, or spell them so the extractor drops them — cheapest, but only fixes this one gate and leaves the mechanism.

Dedup declaration

search_issues (MCP), one targeted query, semantic. ⚠️ The channel is proven live for this session: the same query returned #13448 itself, a known-must-hit control, so the result is a reading and not a false zero. REST GET /search/issues is 403 for this seat, so it could not be used as the second channel. Nearest neighbours examined: #8478 (closed, this class, different boundary — discussed above), #12299 / #12371 / #12470 (module-relative literal depth — a different extraction defect), #13448 (the covering predicate, this card's parent run). ⚠️ One semantic query only; a duplicate worded very differently would not have been seen.

Refs


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions