Uh oh!
There was an error while loading. Please reload this page.
docs(pm): state the skill line-ratchet's coverage boundary in its header - #9962
Merged
Merged
Conversation
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. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeA3nU1B5Q2pgxqxgUrexd
os-warrenforce-pushed
the
claude/issue-9923-ratchet-boundary-honesty
branch
from
August 19, 2026 10:29
b1881ad to
021dfbcCompareos-warren
marked this pull request as ready for review
August 19, 2026 10:32
os-warren
enabled auto-merge
August 19, 2026 10:32
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#9923
Header honesty only. No
CEILINGSentry added; no enforcement behaviour changed.The gap
scripts/pm/check-skill-line-ratchet.mjsends its "Why ceilings" section with "the ceiling now covers the whole surface, per file" — which reads as a claim about the instruction surface as a category. Re-measured onorigin/mainat merge base5989b0de9:CEILINGSentries.claude/AGENTS.mdskills/rootThe published catalog is eleven
SKILL.mdtotalling 10,443 lines, against 3,664 lines of ceiling covered here. A reader could not see the published root was outside the boundary without diffing the map against the filesystem.Note the card said 16 entries; its own enumeration (6 + 6 + 4 + 1 + 1) sums to 18, and 18 is what the map holds. The load-bearing measurement — zero published-root entries — is unaffected.
The fix, per the ruling on the card
Deliberately uncovered stays uncovered. The header now states:
.claude/hooks/,.claude/settings.json,CLAUDE.md) so absence reads as a fact to check rather than an oversight to infer.skills/catalog is deliberately outside, with both reasons: the ratchet prices a full-file token read paid per seat session and per Routine fire, and the published catalog is read by customer projects rather than this repo's seats — a different cost curve; and the published catalog is already a governed, human-merge-only surface (Prime Directive feat: Comprehensive CRM example demonstrating all ObjectStack protocol features #14), so growth there passes a human eye by construction.CEILINGSrow added in passing.One precision added while writing reason 2, because the header must not itself state something false: the governed-surface reason does not separate the two roots on its own — the covered files are human-merge-only too (Prime Directive #14 names
.claude/**andAGENTS.md), so taken alone that reason would argue against theAGENTS.mdceiling that already exists. The header now says so and points at the recurring per-session read as the property that actually does the separating.The boundary is pinned, because enforcement cannot hold it
One self-test case in the file's existing idiom asserts no
CEILINGSkey starts with the published root. This is not decoration — see the reverse verification below: a ceiling on a real publishedSKILL.mdruns perfectly green through the enforcement path, so without the pin the header paragraph could drift from the map silently.Reverse verification (direction predicted in writing before running)
RV-1 — the pin catches a published-root ceiling. Mutation: add
['skills/objectstack-formula/SKILL.md', 556], a real path at its true line count, chosen so enforcement stays green. Predicted: enforcement GREEN, self-test RED. Observed exactly that:Restored with
git checkout HEAD -- ...from the committed state;git status --porcelainclean afterwards (noMM), mutation absent.RV-2 — header prose must not change derived watch hints.
scripts/pm/dispatch-gates.mjsmachine-reads this file viaextractWatchHints, which masks comments first. Predicted: hint set byte-identical before and after, since any change would silently widen the ratchet family's watch set — an enforcement/derivation change this card forbids.This leg falsified its prediction on the first run, and the failure was real. The initial header spelled a glob whose asterisk and slash form a comment terminator, closing the docblock early. Node reported
SyntaxError: Unexpected identifier 'AGENTS', and the orphaned prose — now parsed as module body — leaked seven phantom hints (.claude,.claude/hooks,.claude/settings.json,.claude/skills,origin/main,references,skills). Rewritten without the terminator;node --checkpasses and the hint set is identical to the base (17 hints, unchanged) at final head. The threedispatch-gatesself-test cases that pin this file's hints stay green.The generalisable trap: a path glob containing an asterisk followed by a slash cannot be written literally inside a block comment.
Gates
node scripts/pm/dispatch-gates.mjswith no args, deriving from the real diff, re-run on final commit021dfbcbb;scripts/**addscheck:nul-bytesper the dispatch. Each gate's own verdict line, from that head:pnpm check:pm-skill-ratchet—check-skill-line-ratchet self-test: 15 cases pass.andcheck-skill-line-ratchet: AGENTS.md is 958 lines (ceiling 958; headroom 0).(whole tree still passes)pnpm check:cross-package-test-inputs—OK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.pnpm check:nul-bytes—check-nul-bytes: OK (scanned 6314 text file(s) -- 6314 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).pnpm check:pm-dispatch-gates(not derived; run because it pins this file's hints) —dispatch-gates self-test: 310 cases pass.skip-changeset: internal PM tooling, nothing user-visible ships.Generated by Claude Code