test(tok): hermetic HOME in runScanner — deterministic on populated ~/.claude

token-hotspots.test.mjs ran scan() under the developer's real HOME, so
readActiveConfig leaked ~/.claude (user CLAUDE.md cascade + ambient MCP/
plugins) into every fixture result. This made assertions machine-dependent:
green on a clean HOME, red on a populated one (small-cascade tipped past the
10k-token threshold; sonnet-era gained ambient MCP findings).

Wrap the HOME-dependent scan() call in the shared withHermeticHome helper —
same isolation the OST test and the snapshot/byte-stability suite already use.
Full suite (1055) now green on BOTH real and clean HOME.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-06-21 13:45:53 +02:00
commit c1409ae9b9

View file

@ -5,6 +5,7 @@ import { fileURLToPath } from 'node:url';
import { resetCounter } from '../../scanners/lib/output.mjs';
import { scan } from '../../scanners/token-hotspots.mjs';
import { discoverConfigFiles } from '../../scanners/lib/file-discovery.mjs';
import { withHermeticHome } from '../helpers/hermetic-home.mjs';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const FIXTURES = resolve(__dirname, '../fixtures');
@ -17,7 +18,16 @@ async function runScanner(fixtureName) {
resetCounter();
const path = resolve(FIXTURES, fixtureName);
const discovery = await fixtureDiscovery(fixtureName);
return scan(path, discovery);
// Hermetic HOME: scan() calls readActiveConfig, which resolves the user
// ~/.claude/CLAUDE.md cascade + plugins/MCP from process.env.HOME. Without
// this override the developer's real ~/.claude leaks into every fixture
// result — small-cascade tips past the 10k-token threshold and sonnet-era
// picks up ambient MCP findings — making assertions machine-dependent
// (green on a clean HOME, red on a populated one). Mirrors the OST test.
// NOTE: residual coupling — the cascade's ancestor walk still climbs from
// the fixture path through the real repo CLAUDE.md (an ancestor of tests/),
// but that contribution is deterministic per-checkout, not user-dependent.
return withHermeticHome(() => scan(path, discovery));
}
describe('TOK scanner — healthy-project', () => {