|
25 | 25 | * see check-skill-id-lint.mjs). Without a gate that intent erodes one |
26 | 26 | * well-meaning paragraph at a time. |
27 | 27 | * |
| 28 | + * ## What is covered — and the published catalog, which deliberately is not |
| 29 | + * |
| 30 | + * "The whole surface" above means the CEILINGS map below, which is an |
| 31 | + * ENUMERATION, never a root glob: the pm-dispatch surface (SKILL.md, its |
| 32 | + * references/, the per-lane job descriptions), the four other |
| 33 | + * `.claude/skills/` playbook SKILL.md files, the dev-agent definition |
| 34 | + * `.claude/agents/os-dev.md`, and the root `AGENTS.md`. Read a file's absence |
| 35 | + * from the map as a fact to check, not an oversight to infer — `.claude/hooks/`, |
| 36 | + * `.claude/settings.json` and `CLAUDE.md` carry no ceiling either. |
| 37 | + * |
| 38 | + * The **published** `skills/` catalog — the one that ships to customer projects |
| 39 | + * — is deliberately OUTSIDE the ceiling. It is the omission worth stating |
| 40 | + * because it is by far the larger surface: eleven published SKILL.md totalling |
| 41 | + * ~10,400 lines, against ~3,700 covered here. Two reasons, both about the cost |
| 42 | + * curve the ratchet prices rather than about size (#9923): |
| 43 | + * |
| 44 | + * - What the ratchet prices is a full-file token read paid PER SEAT SESSION |
| 45 | + * and PER ROUTINE FIRE, which is what every covered file above costs. The |
| 46 | + * published catalog is read by customer projects, not by this repo's seats |
| 47 | + * — a different cost curve, and not the one this gate was built against. |
| 48 | + * - The published catalog is already a governed, human-merge-only surface |
| 49 | + * (Prime Directive #14), so growth there passes a human eye by |
| 50 | + * construction — a control a ratchet would merely duplicate. Note this |
| 51 | + * reason does not separate the two roots by itself: the covered files are |
| 52 | + * governed at merge too. What no reviewer prices THERE is the recurring |
| 53 | + * per-session read of reason one, which is why they still carry ceilings |
| 54 | + * and the published catalog does not. |
| 55 | + * |
| 56 | + * Extending coverage to the published root is therefore a POLICY CHANGE, not a |
| 57 | + * maintenance edit: it needs its own card and a maintainer's ruling, not a |
| 58 | + * CEILINGS row added in passing. The self-test pins this boundary, because |
| 59 | + * enforcement cannot — a published-root entry would run perfectly green. |
| 60 | + * |
28 | 61 | * ## The ratchet discipline (shrink-only, per file) |
29 | 62 | * |
30 | 63 | * - A ceiling may be LOWERED by any PR that shrinks its file — lowering is |
@@ -142,6 +175,12 @@ function selfTest() { |
142 | 175 | ['all six lane job descriptions are covered', ['engine', 'services', 'cli', 'devx', 'skills', 'spec'].every((n) => CEILINGS.has(`.claude/skills/pm-dispatch/references/lanes/${n}.md`)), true], |
143 | 176 | ['the other four skills are covered (#9473)', ['checklist-test', 'checklist-author', 'dogfood-verification', 'spec-property-retirement'].every((n) => CEILINGS.has(`.claude/skills/${n}/SKILL.md`)), true], |
144 | 177 | ['root AGENTS.md is covered (#9792)', CEILINGS.has('AGENTS.md'), true], |
| 178 | + // The boundary the header states, pinned (#9923). Enforcement cannot hold |
| 179 | + // it: a ceiling on a real published SKILL.md runs green like any other row, |
| 180 | + // so without this case the header paragraph could drift from the map |
| 181 | + // silently. Extending coverage to the published catalog is a policy change |
| 182 | + // — it lands with a maintainer ruling that also deletes this case. |
| 183 | + ['the published skills/ catalog is deliberately uncovered', [...CEILINGS.keys()].some((k) => k.startsWith('skills/')), false], |
145 | 184 | ]; |
146 | 185 | let failed = 0; |
147 | 186 | for (const [name, actual, expected] of cases) { |
|
0 commit comments