docs(claude-md): 8.10 — fix hooks count + add doc-consistency test for hook-table sync
This commit is contained in:
parent
ba5f2b64ad
commit
97c5c9d934
2 changed files with 77 additions and 1 deletions
|
|
@ -84,3 +84,78 @@ describe('doc-consistency — v2 cutoffs are documented in unified prose', () =>
|
|||
assert.match(content, /score\s*[≥>=]+\s*65/);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// D4 (Batch C, Wave D): Hooks count must stay synchronized across three
|
||||
// surfaces — the CLAUDE.md `## Hooks (N)` header, the markdown table directly
|
||||
// underneath that header, and the canonical hooks/hooks.json definition.
|
||||
// Drift previously masked a missing `pre-compact-scan.mjs` row in CLAUDE.md.
|
||||
// This block fails fast if any of the three surfaces drift.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('doc-consistency — Hooks count consistency (D4)', () => {
|
||||
const CLAUDE_MD = join(PLUGIN_ROOT, 'CLAUDE.md');
|
||||
const HOOKS_JSON = join(PLUGIN_ROOT, 'hooks', 'hooks.json');
|
||||
|
||||
function readHeaderNumber(text) {
|
||||
const match = text.match(/^##\s+Hooks\s*\((\d+)\)\s*$/m);
|
||||
if (!match) throw new Error('No `## Hooks (N)` header found in CLAUDE.md');
|
||||
return parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
function readTableRowCount(text) {
|
||||
// Section spans from `## Hooks (N)` to next `^## ` heading.
|
||||
const startIdx = text.search(/^##\s+Hooks\s*\(\d+\)\s*$/m);
|
||||
if (startIdx < 0) throw new Error('Hooks header not found');
|
||||
const tail = text.slice(startIdx);
|
||||
const nextHeader = tail.search(/\n##\s+\S/);
|
||||
const section = nextHeader > 0 ? tail.slice(0, nextHeader) : tail;
|
||||
// Count rows that look like `| \`<name>.mjs\` | ...`.
|
||||
// Excludes the header row (which uses bare `Script` not a backtick).
|
||||
const rows = section.match(/^\|\s*`[^`|]+\.mjs`\s*\|/gm) || [];
|
||||
return rows.length;
|
||||
}
|
||||
|
||||
function readJsonHookCount(jsonText) {
|
||||
const parsed = JSON.parse(jsonText);
|
||||
const seen = new Set();
|
||||
for (const eventArr of Object.values(parsed.hooks || {})) {
|
||||
for (const entry of eventArr) {
|
||||
for (const h of entry.hooks || []) {
|
||||
// Dedupe by command path — a hook registered to multiple events
|
||||
// counts as one script.
|
||||
if (h.command) seen.add(h.command);
|
||||
}
|
||||
}
|
||||
}
|
||||
return seen.size;
|
||||
}
|
||||
|
||||
it('header count, table row count, and hooks.json count agree', () => {
|
||||
const claudeText = readFileSync(CLAUDE_MD, 'utf-8');
|
||||
const hooksJsonText = readFileSync(HOOKS_JSON, 'utf-8');
|
||||
|
||||
const headerNumber = readHeaderNumber(claudeText);
|
||||
const tableRowCount = readTableRowCount(claudeText);
|
||||
const jsonHookCount = readJsonHookCount(hooksJsonText);
|
||||
|
||||
assert.equal(
|
||||
headerNumber,
|
||||
jsonHookCount,
|
||||
`CLAUDE.md '## Hooks (${headerNumber})' header disagrees with hooks/hooks.json (${jsonHookCount} hooks). ` +
|
||||
`Update the header to match.`,
|
||||
);
|
||||
assert.equal(
|
||||
tableRowCount,
|
||||
jsonHookCount,
|
||||
`CLAUDE.md hooks table has ${tableRowCount} rows but hooks/hooks.json defines ${jsonHookCount} hooks. ` +
|
||||
`Add/remove rows in the table to match.`,
|
||||
);
|
||||
assert.equal(
|
||||
headerNumber,
|
||||
tableRowCount,
|
||||
`CLAUDE.md header (${headerNumber}) and table row count (${tableRowCount}) disagree. ` +
|
||||
`These two surfaces must stay in sync.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue