Skip to content

Commit 9527980

Browse files
os-warrenclaude
andauthored
docs(pm): state the skill line-ratchet's coverage boundary in its header (#9962)
The CEILINGS map covers 18 files — the .claude/ instruction surfaces plus root AGENTS.md — and zero files under the published skills/ catalog, while the header read as though the ceiling covered the instruction surface as a category. A reader could not see the published root was outside it without diffing the map against the filesystem. State the covered set as an enumeration, state the published root as deliberately outside with the two reasons (the ratchet prices per-seat/ per-Routine full-file reads, which the published catalog is not on; and the published catalog is already a governed human-merge-only surface), and name coverage extension as a policy change needing its own card and a maintainer. Pin the boundary in the self-test: enforcement cannot hold it, because a ceiling on a real published SKILL.md would run green like any other row. No CEILINGS entry added; no enforcement behaviour changed. Claude-Session: https://claude.ai/code/session_01AeA3nU1B5Q2pgxqxgUrexd Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9b64884 commit 9527980

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

scripts/pm/check-skill-line-ratchet.mjs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,39 @@
2525
* see check-skill-id-lint.mjs). Without a gate that intent erodes one
2626
* well-meaning paragraph at a time.
2727
*
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+
*
2861
* ## The ratchet discipline (shrink-only, per file)
2962
*
3063
* - A ceiling may be LOWERED by any PR that shrinks its file — lowering is
@@ -142,6 +175,12 @@ function selfTest() {
142175
['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],
143176
['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],
144177
['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],
145184
];
146185
let failed = 0;
147186
for (const [name, actual, expected] of cases) {

0 commit comments

Comments
 (0)