You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
pm: add a line-ratchet ceiling for root CLAUDE.md (#11274)
Root CLAUDE.md is the other repo-root instruction file — same read path
(every seat session), same governance — and structurally growth-prone: it
exists to inline the rules that must never be missed, so every new such
rule argues for appending to it. Maintainer ruling 2026-08-20 on the card:
add a CEILINGS row. Set at its measured count, 86, headroom 0.
Coupled in the same commit, all inside the ratchet:
- the header's boundary sentence no longer names CLAUDE.md as uncovered
- ROOT_FILE_WATCH_HINTS gains 'CLAUDE.md/**' (the existing self-test
requires a hint for every separator-less ceiling), matching the spelling
check-governed-merges.mjs already uses for the two root files
- a self-test case pinning the new row, and the AGENTS.md-exclusivity case
replaced with the two-root-file form
Claude-Session: https://claude.ai/code/session_01RMTpSRF5CjMmQBFfPtPCwJ
Co-authored-by: Claude <noreply@anthropic.com>
if(lineCount===0)return{ok: false,msg: `${rel} read as empty — refusing to treat a missing/empty input as a pass (#4690).`};
@@ -248,13 +260,14 @@ function selfTest() {
248
260
['all seven lane job descriptions are covered',['engine','services','cli','devx','skills','spec','hotcrm'].every((n)=>CEILINGS.has(`.claude/skills/pm-dispatch/references/lanes/${n}.md`)),true],
249
261
['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],
250
262
['root AGENTS.md is covered (#9792)',CEILINGS.has('AGENTS.md'),true],
263
+
['root CLAUDE.md is covered (#9965)',CEILINGS.has('CLAUDE.md'),true],
251
264
// The dispatch-gates declaration (#9964). Enforcement cannot hold any of
252
265
// these: the declaration is read by another tool entirely, so a wrong or
253
266
// missing entry runs perfectly green here and only shows up as a dev
254
267
// dispatched on a root-file card with an empty gate brief.
255
268
['every separator-less ceiling declares a root-file watch hint',[...CEILINGS.keys()].filter((k)=>!k.includes('/')).every((k)=>ROOT_FILE_WATCH_HINTS.includes(`${k}/**`)),true],
256
269
['and the declaration names no file the map does not cover',ROOT_FILE_WATCH_HINTS.every((h)=>CEILINGS.has(h.replace(/\/\*+$/,''))),true],
257
-
['AGENTS.md is the root file it declares',ROOT_FILE_WATCH_HINTS.includes('AGENTS.md/**'),true],
270
+
['both root instruction files are declared',ROOT_FILE_WATCH_HINTS.join(',')==='AGENTS.md/**,CLAUDE.md/**',true],
258
271
// Provenance, never a lookup key: `run` opens every CEILINGS key, so the
259
272
// glob form appearing there would make the ratchet read a path that does
260
273
// not exist — red under #4690's cannot-read rule, for a file that is fine.
0 commit comments