feat(config-audit): TOK flags CLAUDE.md cascade > 10k tokens (v5 M4) [skip-docs]

- New Pattern E in TOK: emits medium finding when activeConfig.claudeMd.estimatedTokens > 10_000
- Uses cascade tokens, file count, and calibration note as evidence
- New fixtures: large-cascade (37k bytes / 14475 cascade tokens) + small-cascade (5k baseline)

572 → 574 tests, all green.
This commit is contained in:
Kjell Tore Guttormsen 2026-05-01 06:53:12 +02:00
commit 25ca6139b4
4 changed files with 1073 additions and 0 deletions

View file

@ -44,6 +44,10 @@ const VOLATILE_PATTERNS = [
const MAX_IMPORT_DEPTH = 2;
// v5 M4: cascades above this contribute >10k tokens to every turn even before
// any tool description loads. Heuristic for "context budget under pressure".
const CASCADE_TOKEN_THRESHOLD = 10_000;
const HOTSPOTS_MAX = 10;
// v5 F7: shared evidence note appended to every TOK pattern finding.
@ -330,6 +334,29 @@ export async function scan(targetPath, discovery) {
}
}
// ── Pattern E: CLAUDE.md cascade > CASCADE_TOKEN_THRESHOLD (v5 M4) ──
if (activeConfig?.claudeMd?.estimatedTokens > CASCADE_TOKEN_THRESHOLD) {
const cascadeTokens = activeConfig.claudeMd.estimatedTokens;
const fileCount = activeConfig.claudeMd.files?.length ?? 0;
findings.push(finding({
scanner: SCANNER,
severity: SEVERITY.medium,
title: 'CLAUDE.md cascade exceeds 10k tokens per turn',
description:
`The active CLAUDE.md cascade for this repo (${fileCount} files: managed + user + ` +
`ancestors + project + @imports) totals ~${cascadeTokens} tokens. Every turn loads this ` +
'whole prefix; budget pressure compounds with tool schemas and MCP servers.',
file: activeConfig.claudeMd.files?.find(f => f.scope === 'project')?.path || null,
evidence:
`cascade_tokens=${cascadeTokens}; threshold=${CASCADE_TOKEN_THRESHOLD}; ` +
`files=${fileCount}${CALIBRATION_NOTE}`,
recommendation:
'Trim the user/project CLAUDE.md, push reference material into @imports that load ' +
'on-demand, or move long sections to skills. Aim for <10k tokens in the cascade.',
category: 'token-efficiency',
}));
}
// ── Hotspots ranking ──
const hotspots = await buildHotspots(discovery, targetPath, activeConfig);