feat(config-audit): remove TOK Pattern D detectSonnetEra (v5 F5)

Pattern D was the v4 sonnet-era signature: 'config is structurally
clean but uses no Opus-4.7-specific features'. Two problems:
- It triggered on any minimal config that happened to lack skills/MCP
- The advice was generic and not actionable

The hotspots ranking and per-pattern findings (A/B/C) cover the same
ground with concrete, file-anchored signal. Dropping the noise.

BREAKING (intentional): scanners no longer emit the sonnet-era info
finding. Suppression entries and downstream tooling that reference
the v4 finding ID should be updated. Doc sweep follows in Step 8b.

Tests: sonnet-era fixture now asserts zero findings.
This commit is contained in:
Kjell Tore Guttormsen 2026-05-01 06:31:43 +02:00
commit 2810ee6f62
2 changed files with 16 additions and 43 deletions

View file

@ -1,14 +1,18 @@
/**
* TOK Scanner Token Hotspots / Opus 4.7 patterns
*
* Detects four structural Opus 4.7-era token-efficiency patterns:
* Detects three structural Opus 4.7-era token-efficiency patterns:
* CA-TOK-001 cache-breaking volatile top in CLAUDE.md (medium)
* CA-TOK-002 redundant tool/permission declarations (low)
* CA-TOK-003 deep @import chain (>2 hops) (medium)
* CA-TOK-004 sonnet-era signature clean config with no Opus 4.7 features (info)
*
* Note: the v4 sonnet-era signature pattern was removed in v5 F5 too noisy
* and not actionable; live token costs are better surfaced by the hotspots
* ranking and per-pattern findings.
*
* Also ranks every discovered config source by estimated tokens and exposes
* a `hotspots` array (310 entries) on the scanner result.
* a `hotspots` array (10 entries, possibly fewer for tiny projects) on the
* scanner result.
*
* Pattern catalogue: knowledge/opus-4.7-patterns.md
* Token heuristic: estimateTokens() in scanners/lib/active-config-reader.mjs
@ -151,25 +155,6 @@ function detectRedundantPermissions(settings) {
return issues;
}
/**
* Detect "sonnet-era" signature: the configuration is structurally clean
* but uses no Opus 4.7-specific features (no skills, no managed-settings,
* no plugin imports, no MCP servers, minimal hooks).
*/
function detectSonnetEra(discovery) {
const types = new Set(discovery.files.map(f => f.type));
const hasSkill = types.has('skill-md');
const hasMcp = types.has('mcp-json');
const hasHooks = types.has('hooks-json');
const hasManaged = discovery.files.some(f => f.scope === 'managed');
const hasPlugin = discovery.files.some(f => f.scope === 'plugin');
const hasClaudeMd = types.has('claude-md');
const hasSettings = types.has('settings-json');
// "Clean baseline" requires CLAUDE.md present; otherwise nothing to flag.
if (!hasClaudeMd) return false;
return !hasSkill && !hasMcp && !hasHooks && !hasManaged && !hasPlugin && hasSettings;
}
/**
* Build the ranked hotspots array.
*
@ -334,23 +319,6 @@ export async function scan(targetPath, discovery) {
}
}
// ── Pattern D: sonnet-era signature (info only) ──
if (detectSonnetEra(discovery)) {
findings.push(finding({
scanner: SCANNER,
severity: SEVERITY.info,
title: 'Sonnet-era configuration signature',
description:
'The configuration is structurally clean but does not yet leverage Opus 4.7-specific ' +
'features (no skills, no MCP servers, no plugins, no managed settings, minimal hooks). ' +
'Not a defect — a hint that token-efficiency-driven optimisations have not been applied.',
recommendation:
'Consider adopting Opus 4.7 features that fit the project: skills for shared workflows, ' +
'managed settings for cross-repo defaults, or MCP servers for external integrations.',
category: 'token-efficiency',
}));
}
// ── Hotspots ranking ──
const hotspots = await buildHotspots(discovery, targetPath, activeConfig);

View file

@ -87,15 +87,20 @@ describe('TOK scanner — opus-47/deep-imports', () => {
});
});
describe('TOK scanner — opus-47/sonnet-era', () => {
describe('TOK scanner — opus-47/sonnet-era (v5 F5: Pattern D removed)', () => {
let result;
beforeEach(async () => {
result = await runScanner('opus-47/sonnet-era');
});
it('emits no findings above info severity', () => {
const nonInfo = result.findings.filter(f => f.severity !== 'info');
assert.equal(nonInfo.length, 0, `expected only info findings, got: ${nonInfo.map(f => f.id + '=' + f.severity).join(', ')}`);
it('emits zero findings (no Pattern D / CA-TOK-004 anymore)', () => {
assert.equal(result.findings.length, 0,
`expected 0 findings on sonnet-era after F5, got: ${result.findings.map(f => f.id).join(', ')}`);
});
it('never emits CA-TOK-004 (removed in v5)', () => {
assert.ok(result.findings.every(f => f.id !== 'CA-TOK-004'),
'expected no CA-TOK-004; removed in v5 F5');
});
});