Filed unassigned while implementing #12392 (extending the published-skills token ratchet to the hand-authored bundle). Out of that card's scope: its declared file surface is scripts/check-skills-token-ratchet.mjs plus that gate's own pin suite. This is an observation about two other files that describe that gate's population and are about to stop being true.
⛔ Not fixed in #12392's PR deliberately — see "Why this was not fixed in place" below.
What changes under #12392
scripts/check-skills-token-ratchet.mjs stops enumerating skills/<name>/SKILL.md and starts walking every published skill directory recursively. Measured on c026b0d2d:
| before | after |
|---|
| files the gate enumerates | 11 | 49 |
| files carrying a ceiling | 11 | 38 |
| files excluded as generator-owned | 0 | 11 |
The two stale statements
1. scripts/pm/bare-root-worklist.mjs, the check-skills-token-ratchet.mjs SKILLS_DIR skills TRIAGE row. Its why reads:
one named file per child directory, 11 of 50 (22%). It already reaches its own cards through the artifact roster it names file by file, so the miss is smaller than the row
Both halves stop describing the tree: the population is no longer "one named file per child directory" (it is a recursive subtree walk), and it is no longer 11 of 50 (it is 49 of 50). The row's verdict may well still be REFUSE-UNSPELLABLE — the true population skills/*/** collapses to a double-slash spelling no tree can hold, the same reasoning the sibling check:skill-refs row already records — but it would hold for a different reason than the one written down.
⚠️ That file's --self-test cannot catch this, and says so at :121-124: it "audits keys and verdicts, never what a why SAYS". Verified — the self-test runs green against the changed gate (46 live row(s), 39 unreachable as spelled, 39 recorded verdict(s) — none stale, none missing).
2. #12369's measured table. That decision card enumerates 17 rows whose REFUSE-UNSPELLABLE basis was invalidated by #12300, and lists for each a measured 100%-precise live spelling. One of its rows is this gate:
| skills/*/SKILL.md | 11 / 11 | 1 |
After #12392 that spelling covers 11 of the gate's 49 files, so it is no longer a precise spelling of this population — it is a 22% one. The row does not leave the 17-row class (it still has a basis problem); its entry in the table needs re-measuring before any of options A–D is priced against it. Option A in particular ("declare the precise spelling next to each gate's population constant") would, for this row, now be declaring skills/*/** rather than skills/*/SKILL.md.
Why this was not fixed in place
#12392's bounded-in-place-fix test fails on condition ②, "mechanical, with the correct form already pinned by existing evidence". Re-writing a TRIAGE row's why is not mechanical here: the TRIAGE map is shrink-only, the row's verdict may need re-judging rather than re-wording, and #12369 is an open needs-user-decision card holding exactly that adjudication for this row among 16 others. An execution seat rewriting one of the 17 rows mid-decision would be adjudicating a slice of the card the maintainer is holding. #12328 stopped at this same boundary for the same reason.
Suggested handling
Fold the re-measurement into #12369 rather than treating this as an independent repair — it is an input to that decision, not a separate defect. Whichever option lands, this row's numbers should be read off mainafter#12392 merges, not from the table as written.
Related: #12392 (the PR that moves it) · #12369 (the decision card holding this row) · #12328 · #12289 (same family: TRIAGE rows whose prose stopped describing the tree) · #12300 (the change that invalidated the shared basis)
Generated by Claude Code
Filed unassigned while implementing #12392 (extending the published-skills token ratchet to the hand-authored bundle). Out of that card's scope: its declared file surface is
scripts/check-skills-token-ratchet.mjsplus that gate's own pin suite. This is an observation about two other files that describe that gate's population and are about to stop being true.⛔ Not fixed in #12392's PR deliberately — see "Why this was not fixed in place" below.
What changes under #12392
scripts/check-skills-token-ratchet.mjsstops enumeratingskills/<name>/SKILL.mdand starts walking every published skill directory recursively. Measured onc026b0d2d:The two stale statements
1.
scripts/pm/bare-root-worklist.mjs, thecheck-skills-token-ratchet.mjs SKILLS_DIR skillsTRIAGE row. Itswhyreads:Both halves stop describing the tree: the population is no longer "one named file per child directory" (it is a recursive subtree walk), and it is no longer 11 of 50 (it is 49 of 50). The row's verdict may well still be
REFUSE-UNSPELLABLE— the true populationskills/*/**collapses to a double-slash spelling no tree can hold, the same reasoning the siblingcheck:skill-refsrow already records — but it would hold for a different reason than the one written down.--self-testcannot catch this, and says so at:121-124: it "audits keys and verdicts, never what awhySAYS". Verified — the self-test runs green against the changed gate (46 live row(s), 39 unreachable as spelled, 39 recorded verdict(s) — none stale, none missing).2. #12369's measured table. That decision card enumerates 17 rows whose
REFUSE-UNSPELLABLEbasis was invalidated by #12300, and lists for each a measured 100%-precise live spelling. One of its rows is this gate:After #12392 that spelling covers 11 of the gate's 49 files, so it is no longer a precise spelling of this population — it is a 22% one. The row does not leave the 17-row class (it still has a basis problem); its entry in the table needs re-measuring before any of options A–D is priced against it. Option A in particular ("declare the precise spelling next to each gate's population constant") would, for this row, now be declaring
skills/*/**rather thanskills/*/SKILL.md.Why this was not fixed in place
#12392's bounded-in-place-fix test fails on condition ②, "mechanical, with the correct form already pinned by existing evidence". Re-writing a
TRIAGErow'swhyis not mechanical here: theTRIAGEmap is shrink-only, the row's verdict may need re-judging rather than re-wording, and #12369 is an openneeds-user-decisioncard holding exactly that adjudication for this row among 16 others. An execution seat rewriting one of the 17 rows mid-decision would be adjudicating a slice of the card the maintainer is holding. #12328 stopped at this same boundary for the same reason.Suggested handling
Fold the re-measurement into #12369 rather than treating this as an independent repair — it is an input to that decision, not a separate defect. Whichever option lands, this row's numbers should be read off
mainafter#12392 merges, not from the table as written.Related: #12392 (the PR that moves it) · #12369 (the decision card holding this row) · #12328 · #12289 (same family: TRIAGE rows whose prose stopped describing the tree) · #12300 (the change that invalidated the shared basis)
Generated by Claude Code