From 6c65287c351e5c6694b16d7b4fb45122cf352a75 Mon Sep 17 00:00:00 2001 From: norvalbv Date: Mon, 3 Aug 2026 11:43:20 +0100 Subject: [PATCH 1/2] fix(deps): bump biome to 2.5.6 to stop the LSP daemon memory leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why The Biome LSP daemon for this repo was sitting at **9.7 GB RSS-equivalent and 95% CPU** after ~2.5 days of uptime. `footprint` showed 9,944 MB spread across **112,109 un-freed mmap regions** — a leak signature, not heap growth. (`ps` reported only 1.8 MB RSS because macOS had compressed essentially all of it.) This is a known upstream regression, [biomejs/biome#10658](https://github.com/biomejs/biome/issues/10658), fixed in **2.5.1** by [#10689](https://github.com/biomejs/biome/pull/10689): > The issue was caused by the "Go-to definition" editor feature, which was enabled by default … the feature **triggers the scanner to build the module graph**. This caused memory leak issues. That matches the observed daemon exactly — its logs showed **8,082 `update_module_graph_internal`** spans in a single hour, plus 8,901 `open_file_internal` with `reason=Index`. 2.5.1 also fixed the daemon failing to shut down when the editor closes mid-scan, which is why the leaking process was orphaned at PPID 1, outliving its editor session by over a day. devkit was the only project on the affected machine still pinned to 2.5.0 — every other repo was on 2.5.1+ and idle at ~2 MB. The `^2.5.0` range already permitted 2.5.6; it was the **lockfile** holding it back. ## What changed **Config (3 files)** - `package.json` + `bun.lock` — `@biomejs/biome` 2.5.0 → **2.5.6** - `biome.jsonc` — `$schema` bumped to match, and `!!dist` force-ignore added On the force-ignore: `dist/` is already unlinted (it is not in the `files.includes` allowlist), but a single `!` still lets the LSP scanner index it for the module graph, and it is rewritten wholesale on every build. `!!` keeps the scanner out entirely, per Biome's own guidance for output folders. Verified zero lint-coverage change — `biome check dist/...` already reported "paths were provided but ignored". **Formatting (17 files)** Biome 2.5.6 changed how `it.each([...])(…)` calls are broken. These are pure formatter output from `biome check --write`, scoped to exactly the affected files. **Correctness (1 file)** `cli/__tests__/reconcile-detect-merged.test.mts` — 2 × `lint/correctness/noUnsafeOptionalChaining`, caught by a rule 2.5.0 missed. `mock.calls[0]?.[2]` short-circuits to `undefined` and then `.stdio` is read off it; the `as { stdio?: unknown }` cast hid it from TypeScript. Completed the optional chain rather than asserting non-null, so a missing mock call now fails the assertion cleanly instead of throwing a TypeError. ## Verification - `biome check` — clean on all 18 touched files - `bun run typecheck` — exit 0 - `bunx vitest run cli/__tests__/reconcile-detect-merged.test.mts` — 9/9 passing ## Notes for review - `cli/lib/install/package-json.mts:48` still writes `'@biomejs/biome': '^2.5.0'` into consumer projects. The caret means fresh installs already resolve to 2.5.6, so no consumer is getting the leak — but anyone with a pre-existing lockfile is pinned to it exactly as this repo was. Left out deliberately: it needs a `dist` rebuild and belongs with a release rather than as a drive-by. - The formatting churn is a direct consequence of the version bump, not unrelated cleanup. It was scoped to the 18 affected files; a repo-wide `--write` would have touched 119 files of unrelated in-flight work. --- biome.jsonc | 9 +- bun.lock | 20 +- cli/__tests__/checklist-scripts.test.mts | 201 +++++++-------- cli/__tests__/decision-edit-guard.test.mts | 20 +- cli/__tests__/knip-check-hook.test.mts | 18 +- .../reconcile-detect-merged.test.mts | 4 +- cli/__tests__/review-asset-runtime.test.mts | 48 ++-- cli/__tests__/review-gate-supervisor.test.mts | 13 +- .../review-private-dependencies.test.mts | 44 ++-- cli/lib/install/install-hooks.test.mts | 34 +-- .../coverage/__tests__/produce.test.mts | 12 +- gate-engine/coverage/__tests__/run.test.mts | 24 +- .../__tests__/capture-normalizer.test.mts | 72 +++--- .../__tests__/evidence-bindings.test.mts | 90 ++++--- .../__tests__/evidence-lineage.test.mts | 228 +++++++++--------- .../__tests__/immutable-file.test.mts | 97 ++++---- .../__tests__/persistence-lock.test.mts | 100 ++++---- .../lifecycle/work-quarantine.test.mts | 54 ++--- .../deterministic/__tests__/run.test.mts | 24 +- .../judge/__tests__/verdict-store.test.mts | 57 ++--- package.json | 2 +- 21 files changed, 584 insertions(+), 587 deletions(-) diff --git a/biome.jsonc b/biome.jsonc index b89fc91a..66dd2417 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -7,7 +7,7 @@ // being linted in-place (the name maps into node_modules, which is not the working // tree here), so the relative path is the correct seam for self-linting. Consumers // still extend the bare subpath — see biome/base.jsonc's header. - "$schema": "https://biomejs.dev/schemas/2.5.0/schema.json", + "$schema": "https://biomejs.dev/schemas/2.5.6/schema.json", "extends": ["./biome/base.jsonc"], "files": { "includes": [ @@ -28,7 +28,12 @@ // templates/ holds literal emitted configs (verbatim fixtures) that may not // match devkit's own formatting — exclude. "!templates", - "!bun.lock" + "!bun.lock", + // dist/ is build output — already unlinted (not in the includes allowlist), but a + // single "!" still lets the LSP scanner index it for the module graph, and it is + // rewritten wholesale on every build. Force-ignore ("!!") keeps the scanner out + // entirely, per Biome's own guidance for output folders. + "!!dist" ] }, "overrides": [ diff --git a/bun.lock b/bun.lock index b829b922..fce8afb9 100644 --- a/bun.lock +++ b/bun.lock @@ -12,7 +12,7 @@ "ts-morph": "^28.0.0", }, "devDependencies": { - "@biomejs/biome": "^2.5.0", + "@biomejs/biome": "^2.5.6", "@types/node": "^25.9.3", "@vitest/coverage-v8": "^4.1.10", "husky": "^9.1.7", @@ -35,23 +35,23 @@ "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], - "@biomejs/biome": ["@biomejs/biome@2.5.0", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.0", "@biomejs/cli-darwin-x64": "2.5.0", "@biomejs/cli-linux-arm64": "2.5.0", "@biomejs/cli-linux-arm64-musl": "2.5.0", "@biomejs/cli-linux-x64": "2.5.0", "@biomejs/cli-linux-x64-musl": "2.5.0", "@biomejs/cli-win32-arm64": "2.5.0", "@biomejs/cli-win32-x64": "2.5.0" }, "bin": { "biome": "bin/biome" } }, "sha512-4kURkd9hAPrdDM3C9n82ycYgx8hvQcW6MjKTEejruj8rK0N8P3OPpdy8BvI8kt3KWY4ycF5XtDOrktetEfhfuw=="], + "@biomejs/biome": ["@biomejs/biome@2.5.6", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.6", "@biomejs/cli-darwin-x64": "2.5.6", "@biomejs/cli-linux-arm64": "2.5.6", "@biomejs/cli-linux-arm64-musl": "2.5.6", "@biomejs/cli-linux-x64": "2.5.6", "@biomejs/cli-linux-x64-musl": "2.5.6", "@biomejs/cli-win32-arm64": "2.5.6", "@biomejs/cli-win32-x64": "2.5.6" }, "bin": { "biome": "bin/biome" } }, "sha512-lxVNjv7UF6KfhMJfL9gaUHbWdJdHbsAj6OSmwSYNdhRuG67NxNQ4Xdvh3TUxsSK9sBzJBQhEJj3AopmmNJ5pSA=="], - "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Mn3Fwi3SA5fgmfCPqmzpWF2DLZnms3BVAhM088nTnGrTZmHS3wwIjcoZPqpXeNgd3DrrLH6xp8vTLIBuJoZiXw=="], + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zMOLZP4oMrjh6m1zcSj1ud2awUPgTuMVbmQhYYWL7J8HwCnbHHBvTm7VBTRuY7epT5bez76IpKYQ11ZAqHFlnw=="], - "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-rg3VPL5P8mYro6pqlXYXuJWph21slVp3SZtAqWSrkZs40d2gTzYmHF8E/X1iTID25btmNKltNDJ926sqVBp7DQ=="], + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-JAC1VqzvO7Th5ZplU0G2uGfkZbxEe9uDDektPAhF0JLusoz1w+T4okp2bkykI0bbaO2vslKiRfj4gU43JaGreA=="], - "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-tl+LW8fdD96/xdeWtWwc82LIOc5CoY7N2AsogLTp5R4ECErYt+8Jl/N68ezN9vzSiqPTxw6vjcihoLPYKZHrlw=="], + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-6XsYwCFkp5sMxl85ffhgeGpGgs6A7dRYFnkceZ7WVxvycuTnGdD5xa534Z3xfrBQ0JCMK/mujT6ZNPJoghedwg=="], - "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-vQdM4oSGaf7ZNeGO9w5+Y8SBtyser9M6znxYbm7Ec8wInxJu1WiKxFYZW5Auj2d80bcVvefuGGRxoFOE0eee8g=="], + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-eUa3jeeYvfMt19LBeh6E5PUZpxnTC4JqNWo+EDjTtQjAr2xLGnWaxACtVU1DQqmHYbvThlJzLX+ZsYgrqh2qVw=="], - "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.0", "", { "os": "linux", "cpu": "x64" }, "sha512-zpEGf4RQbFEh8Vt7OmavLyyOzRbtcE9osCqrS1kfvt8jDvxwhKXLSf7n0ebr/ov0RJ9ssP+lhs6C8a9WwFvrQA=="], + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-Pop9VXCFUhFTMfFefZ39S+u2rOPyNp5iHlxbZRwXGACHLy2r0jjiRgJHmaEKJzL3SyxlVeGShXhvvElvWowonA=="], - "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+9hIcMngJ+yGUahXqZuZ8CoWKJE9SAZsFsM3QDvXpNsLbXZ9lqVzgBhOk/jTSYkOA0GLP9eu3teukqpLUojHMg=="], + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-2Vp13QdKysH3HIWLaYLhUUwbK+jbZonJD1K+Lr0d0RO4wH7mkYd43vJixEDm8cUWrowoRz4UUHF1nm9Ae7ym8A=="], - "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-jB0wAvTLI4itx5VidqVUejPQFhRUxiZ9l9FvZ26D5fl6t3qme+ZB4PD3bTSeL1vZ8NI2Rx/zj6H9zcESuGHKGw=="], + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-tDGshcm6BdkZOCGnTDX0Y8/U4IfBSlnUU7T56nNDuPEfed+aHg+u8G36NB43fJVl0Os6+QURXIE1yuD7AaEofA=="], - "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.0", "", { "os": "win32", "cpu": "x64" }, "sha512-VT/lF+GId+67j8aDfLkxdxNoVApsPSTbyAtB3jJq0IWTrY77WXfbPfpngxq0bA6JCEv/7k8C9qWjDRKRznDlyw=="], + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.6", "", { "os": "win32", "cpu": "x64" }, "sha512-WN05KwXnTO/2J45RQPvzZMXf7tZUIofHoR35xIPfCo7pQ2RFidxI8sfb5mGsaTxdMmEOzHzOPRCdA5/fCpc7xQ=="], "@clack/core": ["@clack/core@1.4.1", "", { "dependencies": { "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-FILJa1gGKEFTGZAJE9RpVhrjKz3c3h4ar60dSv6cGuDqufQ84YEIS3GAGvZiN+H6yaLbbvTFNejjCC4tXpZEuw=="], diff --git a/cli/__tests__/checklist-scripts.test.mts b/cli/__tests__/checklist-scripts.test.mts index f6212dd2..a1c8c97d 100644 --- a/cli/__tests__/checklist-scripts.test.mts +++ b/cli/__tests__/checklist-scripts.test.mts @@ -73,72 +73,74 @@ describe('skill checklist script (spawned source)', () => { expect(state.items.length).toBeGreaterThan(0); }); - it.each( - REVIEW_ROOT_CASES, - )('%s consumes the exact review-mode roots injected by the gate', (skill, envName, stateName) => { - const repo = mkdtempSync(join(tmpdir(), 'checklist-review-roots-')); - dirs.push(repo); - const git = (args) => execFileSync('git', args, { cwd: repo, encoding: 'utf8' }); - git(['init', '-q']); - writeFileSync( - join(repo, 'guard.config.json'), - JSON.stringify({ review: { backendRoots: [], frontendRoots: [] } }), - ); - mkdirSync(join(repo, 'apps', 'web'), { recursive: true }); - mkdirSync(join(repo, 'outside'), { recursive: true }); - writeFileSync( - join(repo, 'apps', 'web', 'changed.tsx'), - 'export const login = (password) => fetch("/api", { body: password });\n', - ); - writeFileSync(join(repo, 'outside', 'ignored.tsx'), 'export const unrelated = true;\n'); - git(['add', '.']); - const script = fileURLToPath( - new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), - ); - const r = spawnSync('node', [script, 'generate'], { - cwd: repo, - encoding: 'utf8', - env: { - ...process.env, - DEVKIT_RUN_MODE: 'review', - [envName]: JSON.stringify([' apps/web ']), - }, - }); - expect(r.status, r.stderr).toBe(0); - const state = JSON.parse(readFileSync(join(repo, '.claude', stateName), 'utf8')); - expect(state.files ?? state.items).not.toHaveLength(0); - expect(JSON.stringify(state)).not.toContain('outside/ignored.tsx'); - }); + it.each(REVIEW_ROOT_CASES)( + '%s consumes the exact review-mode roots injected by the gate', + (skill, envName, stateName) => { + const repo = mkdtempSync(join(tmpdir(), 'checklist-review-roots-')); + dirs.push(repo); + const git = (args) => execFileSync('git', args, { cwd: repo, encoding: 'utf8' }); + git(['init', '-q']); + writeFileSync( + join(repo, 'guard.config.json'), + JSON.stringify({ review: { backendRoots: [], frontendRoots: [] } }), + ); + mkdirSync(join(repo, 'apps', 'web'), { recursive: true }); + mkdirSync(join(repo, 'outside'), { recursive: true }); + writeFileSync( + join(repo, 'apps', 'web', 'changed.tsx'), + 'export const login = (password) => fetch("/api", { body: password });\n', + ); + writeFileSync(join(repo, 'outside', 'ignored.tsx'), 'export const unrelated = true;\n'); + git(['add', '.']); + const script = fileURLToPath( + new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), + ); + const r = spawnSync('node', [script, 'generate'], { + cwd: repo, + encoding: 'utf8', + env: { + ...process.env, + DEVKIT_RUN_MODE: 'review', + [envName]: JSON.stringify([' apps/web ']), + }, + }); + expect(r.status, r.stderr).toBe(0); + const state = JSON.parse(readFileSync(join(repo, '.claude', stateName), 'utf8')); + expect(state.files ?? state.items).not.toHaveLength(0); + expect(JSON.stringify(state)).not.toContain('outside/ignored.tsx'); + }, + ); - it.each( - CHECKLIST_CASES, - )('%s preserves its artifact for independent review-mode verification', (skill, stateName) => { - const repo = mkdtempSync(join(tmpdir(), 'checklist-review-cleanup-')); - dirs.push(repo); - const stateDir = join(repo, '.claude'); - const stateFile = join(stateDir, stateName); - mkdirSync(stateDir, { recursive: true }); - writeFileSync(stateFile, '{}'); - const script = fileURLToPath( - new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), - ); + it.each(CHECKLIST_CASES)( + '%s preserves its artifact for independent review-mode verification', + (skill, stateName) => { + const repo = mkdtempSync(join(tmpdir(), 'checklist-review-cleanup-')); + dirs.push(repo); + const stateDir = join(repo, '.claude'); + const stateFile = join(stateDir, stateName); + mkdirSync(stateDir, { recursive: true }); + writeFileSync(stateFile, '{}'); + const script = fileURLToPath( + new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), + ); - const reviewCleanup = spawnSync('node', [script, 'cleanup'], { - cwd: repo, - encoding: 'utf8', - env: { ...process.env, DEVKIT_RUN_MODE: 'review' }, - }); - expect(reviewCleanup.status, reviewCleanup.stderr).toBe(0); - expect(existsSync(stateFile)).toBe(true); + const reviewCleanup = spawnSync('node', [script, 'cleanup'], { + cwd: repo, + encoding: 'utf8', + env: { ...process.env, DEVKIT_RUN_MODE: 'review' }, + }); + expect(reviewCleanup.status, reviewCleanup.stderr).toBe(0); + expect(existsSync(stateFile)).toBe(true); - const normalCleanup = spawnSync('node', [script, 'cleanup'], { - cwd: repo, - encoding: 'utf8', - env: { ...process.env, DEVKIT_RUN_MODE: 'commit' }, - }); - expect(normalCleanup.status, normalCleanup.stderr).toBe(0); - expect(existsSync(stateFile)).toBe(false); - }); + const normalCleanup = spawnSync('node', [script, 'cleanup'], { + cwd: repo, + encoding: 'utf8', + env: { ...process.env, DEVKIT_RUN_MODE: 'commit' }, + }); + expect(normalCleanup.status, normalCleanup.stderr).toBe(0); + expect(existsSync(stateFile)).toBe(false); + }, + ); it('correctness unions scanRoots with injected domain roots outside the static topology', () => { const repo = mkdtempSync(join(tmpdir(), 'checklist-correctness-review-roots-')); @@ -179,45 +181,46 @@ describe('skill checklist script (spawned source)', () => { expect(JSON.stringify(state)).not.toContain('static-api/excluded.ts'); }); - it.each( - REVIEW_ROOT_CASES, - )('%s rejects unsafe injected roots before constructing a Git pathspec', (skill, envName) => { - const repo = repoWithCraftedFile(); - const script = fileURLToPath( - new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), - ); - for (const roots of [ - [], - [''], - [' '], - ['/outside'], - ['../outside'], - ['src/../outside'], - ['C:\\outside'], - [':(exclude)**'], - ['./:(exclude)**'], - [3], - ]) { - const r = spawnSync('node', [script, 'generate'], { + it.each(REVIEW_ROOT_CASES)( + '%s rejects unsafe injected roots before constructing a Git pathspec', + (skill, envName) => { + const repo = repoWithCraftedFile(); + const script = fileURLToPath( + new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), + ); + for (const roots of [ + [], + [''], + [' '], + ['/outside'], + ['../outside'], + ['src/../outside'], + ['C:\\outside'], + [':(exclude)**'], + ['./:(exclude)**'], + [3], + ]) { + const r = spawnSync('node', [script, 'generate'], { + cwd: repo, + encoding: 'utf8', + env: { ...process.env, DEVKIT_RUN_MODE: 'review', [envName]: JSON.stringify(roots) }, + }); + expect(r.status, `${JSON.stringify(roots)}\n${r.stderr}`).not.toBe(0); + expect(r.stderr).toContain(envName); + } + + const dot = spawnSync('node', [script, 'generate'], { cwd: repo, encoding: 'utf8', - env: { ...process.env, DEVKIT_RUN_MODE: 'review', [envName]: JSON.stringify(roots) }, + env: { + ...process.env, + DEVKIT_RUN_MODE: 'review', + [envName]: JSON.stringify([' . ']), + }, }); - expect(r.status, `${JSON.stringify(roots)}\n${r.stderr}`).not.toBe(0); - expect(r.stderr).toContain(envName); - } - - const dot = spawnSync('node', [script, 'generate'], { - cwd: repo, - encoding: 'utf8', - env: { - ...process.env, - DEVKIT_RUN_MODE: 'review', - [envName]: JSON.stringify([' . ']), - }, - }); - expect(dot.status, dot.stderr).toBe(0); - }); + expect(dot.status, dot.stderr).toBe(0); + }, + ); it('ignores review-only injected roots outside review mode', () => { const repo = repoWithCraftedFile(); diff --git a/cli/__tests__/decision-edit-guard.test.mts b/cli/__tests__/decision-edit-guard.test.mts index ad902b5d..0d25fa7d 100644 --- a/cli/__tests__/decision-edit-guard.test.mts +++ b/cli/__tests__/decision-edit-guard.test.mts @@ -20,17 +20,15 @@ const payload = (toolName: string, filePath: string, cursor = false) => ({ }); describe('decision-edit-guard path policy', () => { - it.each([ - 'Edit', - 'Write', - 'MultiEdit', - 'Delete', - ])('blocks %s inside the default decisions directory', (toolName) => { - const reason = decide(payload(toolName, join(root, 'docs/decisions/axis.md')), root); - expect(reason).toContain('docs/decisions'); - expect(reason).toContain('guard-decisions add'); - expect(reason).toContain('guard-decisions amend'); - }); + it.each(['Edit', 'Write', 'MultiEdit', 'Delete'])( + 'blocks %s inside the default decisions directory', + (toolName) => { + const reason = decide(payload(toolName, join(root, 'docs/decisions/axis.md')), root); + expect(reason).toContain('docs/decisions'); + expect(reason).toContain('guard-decisions add'); + expect(reason).toContain('guard-decisions amend'); + }, + ); it('honours a custom decisionsDir and Cursor path-shaped input', () => { writeFileSync( diff --git a/cli/__tests__/knip-check-hook.test.mts b/cli/__tests__/knip-check-hook.test.mts index 4f4bcab1..e2b2f136 100644 --- a/cli/__tests__/knip-check-hook.test.mts +++ b/cli/__tests__/knip-check-hook.test.mts @@ -54,16 +54,14 @@ const run = (dir, { stopHookActive = false, edits = ['KNIP_RAN.ts'] } = {}) => { describe.skipIf(!HAS_BUN)('knip-check.sh gate behaviour', () => { // Forms the ORIGINAL hook missed (it checked only knip.json/.jsonc/.ts/.config.ts). Parametrised // so dropping any arm of the detection loop regresses a test — the bug was an INCOMPLETE list. - it.each([ - '.knip.json', - '.knip.jsonc', - 'knip.js', - 'knip.config.js', - ])('Defect C: runs knip for a %s config (a newly-supported form)', (configFile) => { - const r = run(fixture({ [configFile]: '{}', 'package.json': withKnipScript() })); - expect(r.status).toBe(2); - expect(r.stderr).toContain('KNIP_RAN'); - }); + it.each(['.knip.json', '.knip.jsonc', 'knip.js', 'knip.config.js'])( + 'Defect C: runs knip for a %s config (a newly-supported form)', + (configFile) => { + const r = run(fixture({ [configFile]: '{}', 'package.json': withKnipScript() })); + expect(r.status).toBe(2); + expect(r.stderr).toContain('KNIP_RAN'); + }, + ); it('Defect C: runs knip for a package.json#knip config key (no separate config file)', () => { const r = run(fixture({ 'package.json': withKnipScript({ knip: {} }) })); diff --git a/cli/__tests__/reconcile-detect-merged.test.mts b/cli/__tests__/reconcile-detect-merged.test.mts index 3e21412f..ba38f5b4 100644 --- a/cli/__tests__/reconcile-detect-merged.test.mts +++ b/cli/__tests__/reconcile-detect-merged.test.mts @@ -73,7 +73,7 @@ describe('detectMerged — DEVKIT_RECONCILE_DEBUG stderr seam', () => { const errSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); mockExec.mockReturnValue('MERGED\n'); expect(detectMerged({ repo: 'o/r', prNumber: 1, branch: 'feat' })).toBe('MERGED'); - expect((mockExec.mock.calls[0]?.[2] as { stdio?: unknown }).stdio).toEqual([ + expect((mockExec.mock.calls[0]?.[2] as { stdio?: unknown } | undefined)?.stdio).toEqual([ 'ignore', 'pipe', 'ignore', @@ -98,7 +98,7 @@ describe('detectMerged — DEVKIT_RECONCILE_DEBUG stderr seam', () => { const errSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); mockExec.mockReturnValue('MERGED\n'); expect(detectMerged({ repo: 'o/r', prNumber: 1, branch: 'feat' })).toBe('MERGED'); - expect((mockExec.mock.calls[0]?.[2] as { stdio?: unknown }).stdio).toEqual([ + expect((mockExec.mock.calls[0]?.[2] as { stdio?: unknown } | undefined)?.stdio).toEqual([ 'ignore', 'pipe', 'pipe', diff --git a/cli/__tests__/review-asset-runtime.test.mts b/cli/__tests__/review-asset-runtime.test.mts index 83cd324a..a4dfb347 100644 --- a/cli/__tests__/review-asset-runtime.test.mts +++ b/cli/__tests__/review-asset-runtime.test.mts @@ -173,31 +173,31 @@ describe('packaged reviewer asset runtime', () => { ]); }); - it.each([ - '.mts', - '.mjs', - ] as const)('materializes a usable private package runtime from %s package modules', (extension) => { - const source = packageFixture('devkit-review-package-', extension); - const captured = materializeReviewAssetRuntime(source, destination()); - const entrypoint = join(captured.root, `${PACKAGED_REVIEW_RUNTIME_ENTRYPOINT}${extension}`); - - expect(captured.paths).toEqual(expectedRuntimePaths(extension)); - expect(existsSync(entrypoint)).toBe(true); - expect( - existsSync( - join( - captured.root, - `${PACKAGED_REVIEW_RUNTIME_ENTRYPOINT}${extension === '.mts' ? '.mjs' : '.mts'}`, + it.each(['.mts', '.mjs'] as const)( + 'materializes a usable private package runtime from %s package modules', + (extension) => { + const source = packageFixture('devkit-review-package-', extension); + const captured = materializeReviewAssetRuntime(source, destination()); + const entrypoint = join(captured.root, `${PACKAGED_REVIEW_RUNTIME_ENTRYPOINT}${extension}`); + + expect(captured.paths).toEqual(expectedRuntimePaths(extension)); + expect(existsSync(entrypoint)).toBe(true); + expect( + existsSync( + join( + captured.root, + `${PACKAGED_REVIEW_RUNTIME_ENTRYPOINT}${extension === '.mts' ? '.mjs' : '.mts'}`, + ), ), - ), - ).toBe(false); - const result = spawnSync(process.execPath, [entrypoint], { - encoding: 'utf8', - env: { ...process.env, DEVKIT_REVIEW_PACKAGE_ROOT: captured.root }, - }); - expect(result.status, result.stderr).toBe(0); - expect(result.stdout).toBe('frozen-baseline'); - }); + ).toBe(false); + const result = spawnSync(process.execPath, [entrypoint], { + encoding: 'utf8', + env: { ...process.env, DEVKIT_REVIEW_PACKAGE_ROOT: captured.root }, + }); + expect(result.status, result.stderr).toBe(0); + expect(result.stdout).toBe('frozen-baseline'); + }, + ); it('mirrors the hook extension preference and rejects an incomplete preferred module set', () => { const source = packageFixture(); diff --git a/cli/__tests__/review-gate-supervisor.test.mts b/cli/__tests__/review-gate-supervisor.test.mts index 4e12d604..3965d762 100644 --- a/cli/__tests__/review-gate-supervisor.test.mts +++ b/cli/__tests__/review-gate-supervisor.test.mts @@ -305,13 +305,14 @@ describe('review gate supervisor', () => { expect(result.status, result.stderr).toBe(127); }); - it.each([ - 124, 129, 130, 131, 143, - ])('normalizes a natural reserved exit %d to an ordinary rejection', (status) => { - const result = supervisor('5', '--', process.execPath, '-e', `process.exit(${status})`); + it.each([124, 129, 130, 131, 143])( + 'normalizes a natural reserved exit %d to an ordinary rejection', + (status) => { + const result = supervisor('5', '--', process.execPath, '-e', `process.exit(${status})`); - expect(result.status, result.stderr).toBe(1); - }); + expect(result.status, result.stderr).toBe(1); + }, + ); it('can preserve a natural reserved exit for the synchronous test-process boundary', async () => { await expect( diff --git a/cli/__tests__/review-private-dependencies.test.mts b/cli/__tests__/review-private-dependencies.test.mts index 003727a4..edd4896e 100644 --- a/cli/__tests__/review-private-dependencies.test.mts +++ b/cli/__tests__/review-private-dependencies.test.mts @@ -321,27 +321,29 @@ describe('private review dependency runtime', () => { expect(existsSync(join(destination, 'node_modules'))).toBe(false); }); - it.each([ - 'review', - 'review-baseline', - ])('prepares %s with private dependencies and without target-owned reviewer assets', (purpose) => { - const { parent, source, destination } = fixture(`prepare-${purpose}`); - const manifest = join(parent, `${purpose}.json`); - write(source, '.husky/_/pre-commit', 'runner\n'); - write(source, 'node_modules/pkg/index.js'); - write(source, '.claude/agents/reviewer.md'); - write(source, '.claude/skills/reviewer/SKILL.md'); - - const result = prepare(source, destination, purpose, manifest); - - expect(result.status, result.stderr).toBe(0); - expect(lstatSync(join(destination, 'node_modules')).isSymbolicLink()).toBe(false); - expect(readFileSync(join(destination, 'node_modules/pkg/index.js'), 'utf8')).toBe('runtime\n'); - expect(existsSync(join(destination, '.claude'))).toBe(false); - expect(existsSync(manifest)).toBe(true); - write(destination, 'node_modules/.cache/state', 'private\n'); - expect(existsSync(join(source, 'node_modules/.cache/state'))).toBe(false); - }); + it.each(['review', 'review-baseline'])( + 'prepares %s with private dependencies and without target-owned reviewer assets', + (purpose) => { + const { parent, source, destination } = fixture(`prepare-${purpose}`); + const manifest = join(parent, `${purpose}.json`); + write(source, '.husky/_/pre-commit', 'runner\n'); + write(source, 'node_modules/pkg/index.js'); + write(source, '.claude/agents/reviewer.md'); + write(source, '.claude/skills/reviewer/SKILL.md'); + + const result = prepare(source, destination, purpose, manifest); + + expect(result.status, result.stderr).toBe(0); + expect(lstatSync(join(destination, 'node_modules')).isSymbolicLink()).toBe(false); + expect(readFileSync(join(destination, 'node_modules/pkg/index.js'), 'utf8')).toBe( + 'runtime\n', + ); + expect(existsSync(join(destination, '.claude'))).toBe(false); + expect(existsSync(manifest)).toBe(true); + write(destination, 'node_modules/.cache/state', 'private\n'); + expect(existsSync(join(source, 'node_modules/.cache/state'))).toBe(false); + }, + ); it('omits source-only workspace dependencies from the baseline while final review stays strict', () => { const { parent, source, destination } = fixture('prepare-new-workspace'); diff --git a/cli/lib/install/install-hooks.test.mts b/cli/lib/install/install-hooks.test.mts index 26f492bd..3fca531c 100644 --- a/cli/lib/install/install-hooks.test.mts +++ b/cli/lib/install/install-hooks.test.mts @@ -181,23 +181,23 @@ describe('installHookRegistrations', () => { expect(paths.map((path) => readFileSync(path, 'utf8'))).toEqual(bytes); }); - it.each([ - 'codex', - 'cursor', - ])('transfers same-destination ownership across %s mode changes', (provider) => { - const root = tmpRepo(); - execFileSync('git', ['init'], { cwd: root, stdio: 'ignore' }); - installHookRegistrations(root, ['agentHooks'], { targets: [provider] }); - installHookRegistrations(root, ['agentHooks'], { targets: [provider], overlay: true }); - expect( - checkHookRegistrations(root, ['agentHooks'], { targets: [provider], overlay: true }).ok, - ).toBe(true); - expect(ledger(root).entries.every((entry) => entry.installScope === 'overlay')).toBe(true); - - installHookRegistrations(root, ['agentHooks'], { targets: [provider] }); - expect(checkHookRegistrations(root, ['agentHooks'], { targets: [provider] }).ok).toBe(true); - expect(ledger(root).entries.every((entry) => entry.installScope === 'shared')).toBe(true); - }); + it.each(['codex', 'cursor'])( + 'transfers same-destination ownership across %s mode changes', + (provider) => { + const root = tmpRepo(); + execFileSync('git', ['init'], { cwd: root, stdio: 'ignore' }); + installHookRegistrations(root, ['agentHooks'], { targets: [provider] }); + installHookRegistrations(root, ['agentHooks'], { targets: [provider], overlay: true }); + expect( + checkHookRegistrations(root, ['agentHooks'], { targets: [provider], overlay: true }).ok, + ).toBe(true); + expect(ledger(root).entries.every((entry) => entry.installScope === 'overlay')).toBe(true); + + installHookRegistrations(root, ['agentHooks'], { targets: [provider] }); + expect(checkHookRegistrations(root, ['agentHooks'], { targets: [provider] }).ok).toBe(true); + expect(ledger(root).entries.every((entry) => entry.installScope === 'shared')).toBe(true); + }, + ); it('recovers when added ownership was published before its provider config', () => { const root = tmpRepo(); diff --git a/gate-engine/coverage/__tests__/produce.test.mts b/gate-engine/coverage/__tests__/produce.test.mts index f7d5a4a2..a0a355cc 100644 --- a/gate-engine/coverage/__tests__/produce.test.mts +++ b/gate-engine/coverage/__tests__/produce.test.mts @@ -205,12 +205,12 @@ describe('pruneStaleRuns', () => { describe('reservesCoverageDir', () => { // vitest rejects a duplicated --coverage.reportsDirectory itself, but with a raw stack trace // naming our internal run directory. Catching it first is about the message, not correctness. - it.each([ - ['--coverage.reportsDirectory=/tmp/elsewhere'], - ['--coverage.reportsDirectory'], - ])('spots the reserved flag in %s', (arg) => { - expect(reservesCoverageDir(['run', arg])).toBe(true); - }); + it.each([['--coverage.reportsDirectory=/tmp/elsewhere'], ['--coverage.reportsDirectory']])( + 'spots the reserved flag in %s', + (arg) => { + expect(reservesCoverageDir(['run', arg])).toBe(true); + }, + ); it('lets every other vitest argument through', () => { expect(reservesCoverageDir(['src/foo.test.ts', '--coverage.reporter=json', '--bail=1'])).toBe( diff --git a/gate-engine/coverage/__tests__/run.test.mts b/gate-engine/coverage/__tests__/run.test.mts index fd36814a..091aa649 100644 --- a/gate-engine/coverage/__tests__/run.test.mts +++ b/gate-engine/coverage/__tests__/run.test.mts @@ -223,18 +223,18 @@ describe('runCoverage — fail-closed gate', () => { }); describe('runCoverage — GUARD_COVERAGE_OK per-run bypass', () => { - it.each([ - 'GUARD_COVERAGE_OK', - 'GUARD_NO_COVERAGE', - ])('%s=1 + NO artifact → exit 0 (the field case: base debt, absent coverage data)', (key) => { - const root = makeRoot(); - process.env[key] = '1'; - const s = spy(); - expect(runCoverage(root)).toBe(0); - expect(text(s.log)).toMatch(/BYPASSED/); - // Must NOT read as the repo-wide opt-out — a log reader has to tell the two apart. - expect(text(s.log)).not.toMatch(/guard\.config\.json/); - }); + it.each(['GUARD_COVERAGE_OK', 'GUARD_NO_COVERAGE'])( + '%s=1 + NO artifact → exit 0 (the field case: base debt, absent coverage data)', + (key) => { + const root = makeRoot(); + process.env[key] = '1'; + const s = spy(); + expect(runCoverage(root)).toBe(0); + expect(text(s.log)).toMatch(/BYPASSED/); + // Must NOT read as the repo-wide opt-out — a log reader has to tell the two apart. + expect(text(s.log)).not.toMatch(/guard\.config\.json/); + }, + ); it('bypasses a real threshold shortfall too', () => { const root = makeRoot(); diff --git a/gate-engine/critique/__tests__/capture-normalizer.test.mts b/gate-engine/critique/__tests__/capture-normalizer.test.mts index 0afb18ee..bae030ec 100644 --- a/gate-engine/critique/__tests__/capture-normalizer.test.mts +++ b/gate-engine/critique/__tests__/capture-normalizer.test.mts @@ -164,31 +164,31 @@ describe('normalizePlanCritiqueCompletedCallback', () => { }); }); - it.each([ - 'wrong_phase', - 'aborted', - ] as const)('preserves valid %s status without inventing reviewed facts', (status) => { - const root = temporaryRoot(); - const captured = capturePlanCritiqueCompletedCallback(callback(bytes(skipResponse(status))), { - root, - }); - expect(captured.record.contract).toMatchObject({ - state: 'valid', - error: null, - status, - verdict: null, - criticalCount: null, - }); - expect(storedProjection(captured, root).value).toMatchObject({ - status, - verdict: null, - feasibilityStatus: null, - frameMeta: 'SKIP', - contentTrust: 'untrusted', - redacted: false, - truncated: false, - }); - }); + it.each(['wrong_phase', 'aborted'] as const)( + 'preserves valid %s status without inventing reviewed facts', + (status) => { + const root = temporaryRoot(); + const captured = capturePlanCritiqueCompletedCallback(callback(bytes(skipResponse(status))), { + root, + }); + expect(captured.record.contract).toMatchObject({ + state: 'valid', + error: null, + status, + verdict: null, + criticalCount: null, + }); + expect(storedProjection(captured, root).value).toMatchObject({ + status, + verdict: null, + feasibilityStatus: null, + frameMeta: 'SKIP', + contentTrust: 'untrusted', + redacted: false, + truncated: false, + }); + }, + ); it('records malformed, fenced, and non-UTF-8 exact responses as invalid contract evidence', () => { const cases = [ @@ -518,18 +518,16 @@ describe('normalizePlanCritiqueCompletedCallback', () => { ).toBe(codex.record.execution.callbackHash); }); - it.each([ - '', - ' ', - 'line\nbreak', - 'x'.repeat(PLAN_CRITIQUE_CALLBACK_IDENTITY_MAX_BYTES + 1), - ])('rejects an unsafe callback identity', (callbackIdentity) => { - const input = callback(bytes(JSON.stringify(REVIEWED_RESPONSE))); - input.callbackIdentity = callbackIdentity; - expect(() => capturePlanCritiqueCompletedCallback(input, { root: temporaryRoot() })).toThrow( - 'invalid plan critique callback identity', - ); - }); + it.each(['', ' ', 'line\nbreak', 'x'.repeat(PLAN_CRITIQUE_CALLBACK_IDENTITY_MAX_BYTES + 1)])( + 'rejects an unsafe callback identity', + (callbackIdentity) => { + const input = callback(bytes(JSON.stringify(REVIEWED_RESPONSE))); + input.callbackIdentity = callbackIdentity; + expect(() => capturePlanCritiqueCompletedCallback(input, { root: temporaryRoot() })).toThrow( + 'invalid plan critique callback identity', + ); + }, + ); it('rejects an unsupported runtime provider before returning a callback hash', () => { const input = callback(bytes(JSON.stringify(REVIEWED_RESPONSE))); diff --git a/gate-engine/critique/__tests__/evidence-bindings.test.mts b/gate-engine/critique/__tests__/evidence-bindings.test.mts index 42db44fe..473e80d7 100644 --- a/gate-engine/critique/__tests__/evidence-bindings.test.mts +++ b/gate-engine/critique/__tests__/evidence-bindings.test.mts @@ -749,55 +749,51 @@ describe('plan critique evidence bindings', () => { }); }); - it.each([ - 'corrupt_json', - 'open_schema', - 'oversized', - 'public_mode', - 'wrong_filename', - ] as const)('fails open on a %s binding', (corruption) => { - const repository = createRepository(); - const root = evidenceRoot(); - const record = storedRecord(repository, root, `binding-${corruption}`); - persistPlanCritiqueBinding(record.critiqueId, { cwd: repository, evidenceRoot: root }); - const file = bindingFile(repository, record.workId); - if (corruption === 'corrupt_json') writeFileSync(file, '{'); - if (corruption === 'open_schema') { - const binding = JSON.parse(readFileSync(file, 'utf8')) as Record; - binding.unexpected = true; - writeFileSync(file, canonicalPlanCritiqueRecordJson(binding)); - } - if (corruption === 'oversized') writeFileSync(file, Buffer.alloc(16 * 1024 + 1)); - if (corruption === 'public_mode') chmodSync(file, 0o644); - if (corruption === 'wrong_filename') - renameSync(file, path.join(path.dirname(file), `${'0'.repeat(64)}.json`)); - - expect(resolvePlanCritiqueBinding({ cwd: repository, evidenceRoot: root })).toEqual({ - status: 'unavailable', - reason: 'malformed_binding', - candidates: 1, - }); - }); + it.each(['corrupt_json', 'open_schema', 'oversized', 'public_mode', 'wrong_filename'] as const)( + 'fails open on a %s binding', + (corruption) => { + const repository = createRepository(); + const root = evidenceRoot(); + const record = storedRecord(repository, root, `binding-${corruption}`); + persistPlanCritiqueBinding(record.critiqueId, { cwd: repository, evidenceRoot: root }); + const file = bindingFile(repository, record.workId); + if (corruption === 'corrupt_json') writeFileSync(file, '{'); + if (corruption === 'open_schema') { + const binding = JSON.parse(readFileSync(file, 'utf8')) as Record; + binding.unexpected = true; + writeFileSync(file, canonicalPlanCritiqueRecordJson(binding)); + } + if (corruption === 'oversized') writeFileSync(file, Buffer.alloc(16 * 1024 + 1)); + if (corruption === 'public_mode') chmodSync(file, 0o644); + if (corruption === 'wrong_filename') + renameSync(file, path.join(path.dirname(file), `${'0'.repeat(64)}.json`)); + + expect(resolvePlanCritiqueBinding({ cwd: repository, evidenceRoot: root })).toEqual({ + status: 'unavailable', + reason: 'malformed_binding', + candidates: 1, + }); + }, + ); - it.each([ - 'missing_record', - 'corrupt_record', - 'corrupt_blob', - ] as const)('fails open on a %s after binding', (corruption) => { - const repository = createRepository(); - const root = evidenceRoot(); - const record = storedRecord(repository, root, `record-${corruption}`); - persistPlanCritiqueBinding(record.critiqueId, { cwd: repository, evidenceRoot: root }); - const recordFile = path.join(root, 'records', `${record.critiqueId}.json`); - if (corruption === 'missing_record') unlinkSync(recordFile); - if (corruption === 'corrupt_record') writeFileSync(recordFile, '{}\n'); - if (corruption === 'corrupt_blob') - writeFileSync(path.join(root, record.exactResponse.ref), 'x'); + it.each(['missing_record', 'corrupt_record', 'corrupt_blob'] as const)( + 'fails open on a %s after binding', + (corruption) => { + const repository = createRepository(); + const root = evidenceRoot(); + const record = storedRecord(repository, root, `record-${corruption}`); + persistPlanCritiqueBinding(record.critiqueId, { cwd: repository, evidenceRoot: root }); + const recordFile = path.join(root, 'records', `${record.critiqueId}.json`); + if (corruption === 'missing_record') unlinkSync(recordFile); + if (corruption === 'corrupt_record') writeFileSync(recordFile, '{}\n'); + if (corruption === 'corrupt_blob') + writeFileSync(path.join(root, record.exactResponse.ref), 'x'); - expect( - resolvePlanCritiqueBinding({ cwd: repository, evidenceRoot: root, workId: record.workId }), - ).toEqual({ status: 'unavailable', reason: 'malformed_record', candidates: 1 }); - }); + expect( + resolvePlanCritiqueBinding({ cwd: repository, evidenceRoot: root, workId: record.workId }), + ).toEqual({ status: 'unavailable', reason: 'malformed_record', candidates: 1 }); + }, + ); it('does not bind an ineligible record and rechecks eligibility during resolution', () => { const repository = createRepository(); diff --git a/gate-engine/critique/__tests__/evidence-lineage.test.mts b/gate-engine/critique/__tests__/evidence-lineage.test.mts index 27836d4f..2cf7c711 100644 --- a/gate-engine/critique/__tests__/evidence-lineage.test.mts +++ b/gate-engine/critique/__tests__/evidence-lineage.test.mts @@ -10,129 +10,127 @@ function recordForCallback(exact: Uint8Array, callback: string) { } describe('plan critique evidence lineage', () => { - it.each([ - 'blocking_verdict', - 'critical_findings', - ] as const)('requires contiguous parents after a %s while retaining later attempts', (parentReason) => { - const root = temporaryRoot(); - const parentBytes = bytes('{"pass":1}'); - const parent = recordForCallback(parentBytes, `parent:${parentReason}`); - parent.contract.verdict = - parentReason === 'blocking_verdict' ? 'RETHINK' : 'PROCEED_WITH_CHANGES'; - parent.contract.criticalCount = 1; - parent.contract.eligibility = { eligible: false, reason: parentReason }; - persistPlanCritiqueRecord(parent, { exactResponse: parentBytes }, { root }); + it.each(['blocking_verdict', 'critical_findings'] as const)( + 'requires contiguous parents after a %s while retaining later attempts', + (parentReason) => { + const root = temporaryRoot(); + const parentBytes = bytes('{"pass":1}'); + const parent = recordForCallback(parentBytes, `parent:${parentReason}`); + parent.contract.verdict = + parentReason === 'blocking_verdict' ? 'RETHINK' : 'PROCEED_WITH_CHANGES'; + parent.contract.criticalCount = 1; + parent.contract.eligibility = { eligible: false, reason: parentReason }; + persistPlanCritiqueRecord(parent, { exactResponse: parentBytes }, { root }); - const childBytes = bytes('{"pass":2}'); - const child = recordForCallback(childBytes, `child:${parentReason}`); - child.lineage = { pass: 2, parentCritiqueId: parent.critiqueId }; - child.critiqueId = derivePlanCritiqueId(child); - child.contract.eligibility = { eligible: false, reason: 'unnecessary_recheck' }; - expect(() => persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root })).toThrow( - /contract\.eligibility/, - ); - child.contract.eligibility = { eligible: true, reason: 'eligible' }; - expect(persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root }).state).toBe( - 'created', - ); - - const thirdBytes = bytes('{"pass":3}'); - const third = recordForCallback(thirdBytes, `third:${parentReason}`); - third.lineage = { pass: 3, parentCritiqueId: child.critiqueId }; - third.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; - third.critiqueId = derivePlanCritiqueId(third); - expect(persistPlanCritiqueRecord(third, { exactResponse: thirdBytes }, { root }).state).toBe( - 'created', - ); - - const fourthBytes = bytes('{"pass":4}'); - const fourth = recordForCallback(fourthBytes, `fourth:${parentReason}`); - fourth.lineage = { pass: 4, parentCritiqueId: third.critiqueId }; - fourth.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; - fourth.critiqueId = derivePlanCritiqueId(fourth); - expect(persistPlanCritiqueRecord(fourth, { exactResponse: fourthBytes }, { root }).state).toBe( - 'created', - ); + const childBytes = bytes('{"pass":2}'); + const child = recordForCallback(childBytes, `child:${parentReason}`); + child.lineage = { pass: 2, parentCritiqueId: parent.critiqueId }; + child.critiqueId = derivePlanCritiqueId(child); + child.contract.eligibility = { eligible: false, reason: 'unnecessary_recheck' }; + expect(() => + persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root }), + ).toThrow(/contract\.eligibility/); + child.contract.eligibility = { eligible: true, reason: 'eligible' }; + expect(persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root }).state).toBe( + 'created', + ); - const missingParent = recordForCallback(bytes('missing'), `missing:${parentReason}`); - missingParent.lineage = { pass: 2, parentCritiqueId: `pc1_${'f'.repeat(64)}` }; - missingParent.critiqueId = derivePlanCritiqueId(missingParent); - expect(() => - persistPlanCritiqueRecord(missingParent, { exactResponse: bytes('missing') }, { root }), - ).toThrow(/parentCritiqueId/); + const thirdBytes = bytes('{"pass":3}'); + const third = recordForCallback(thirdBytes, `third:${parentReason}`); + third.lineage = { pass: 3, parentCritiqueId: child.critiqueId }; + third.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; + third.critiqueId = derivePlanCritiqueId(third); + expect(persistPlanCritiqueRecord(third, { exactResponse: thirdBytes }, { root }).state).toBe( + 'created', + ); - const skippedPass = recordForCallback(bytes('skip'), `skip:${parentReason}`); - skippedPass.lineage = { pass: 3, parentCritiqueId: parent.critiqueId }; - skippedPass.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; - skippedPass.critiqueId = derivePlanCritiqueId(skippedPass); - expect(() => - persistPlanCritiqueRecord(skippedPass, { exactResponse: bytes('skip') }, { root }), - ).toThrow(/lineage\.pass/); + const fourthBytes = bytes('{"pass":4}'); + const fourth = recordForCallback(fourthBytes, `fourth:${parentReason}`); + fourth.lineage = { pass: 4, parentCritiqueId: third.critiqueId }; + fourth.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; + fourth.critiqueId = derivePlanCritiqueId(fourth); + expect( + persistPlanCritiqueRecord(fourth, { exactResponse: fourthBytes }, { root }).state, + ).toBe('created'); - for (const mismatch of ['work', 'repository'] as const) { - const mismatchBytes = bytes(`mismatch:${mismatch}`); - const mismatched = recordForCallback(mismatchBytes, `${mismatch}:${parentReason}`); - mismatched.lineage = { pass: 2, parentCritiqueId: parent.critiqueId }; - if (mismatch === 'work') mismatched.workId = 'other-work'; - else mismatched.repository.fingerprint = '0'.repeat(64); - mismatched.critiqueId = derivePlanCritiqueId(mismatched); + const missingParent = recordForCallback(bytes('missing'), `missing:${parentReason}`); + missingParent.lineage = { pass: 2, parentCritiqueId: `pc1_${'f'.repeat(64)}` }; + missingParent.critiqueId = derivePlanCritiqueId(missingParent); expect(() => - persistPlanCritiqueRecord(mismatched, { exactResponse: mismatchBytes }, { root }), + persistPlanCritiqueRecord(missingParent, { exactResponse: bytes('missing') }, { root }), ).toThrow(/parentCritiqueId/); - } - }); - it.each([ - 'sound', - 'invalid', - 'wrong_phase', - 'aborted', - ] as const)('retains a pass 2 after a %s parent as an unnecessary recheck', (parentState) => { - const root = temporaryRoot(); - const parentBytes = bytes(`parent:${parentState}`); - const parent = recordForCallback(parentBytes, `parent:${parentState}`); - if (parentState === 'invalid') { - parent.contract = { - state: 'invalid', - error: { code: 'MALFORMED_JSON', path: '$' }, - status: null, - verdict: null, - criticalCount: null, - eligibility: { eligible: false, reason: 'invalid_contract' }, - }; - } else if (parentState === 'wrong_phase' || parentState === 'aborted') { - parent.contract = { - state: 'valid', - error: null, - status: parentState, - verdict: null, - criticalCount: null, - eligibility: { eligible: false, reason: parentState }, - }; - } - parent.critiqueId = derivePlanCritiqueId(parent); - persistPlanCritiqueRecord(parent, { exactResponse: parentBytes }, { root }); + const skippedPass = recordForCallback(bytes('skip'), `skip:${parentReason}`); + skippedPass.lineage = { pass: 3, parentCritiqueId: parent.critiqueId }; + skippedPass.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; + skippedPass.critiqueId = derivePlanCritiqueId(skippedPass); + expect(() => + persistPlanCritiqueRecord(skippedPass, { exactResponse: bytes('skip') }, { root }), + ).toThrow(/lineage\.pass/); - const childBytes = bytes(`child:${parentState}`); - const child = recordForCallback(childBytes, `child:${parentState}`); - child.lineage = { pass: 2, parentCritiqueId: parent.critiqueId }; - child.critiqueId = derivePlanCritiqueId(child); - expect(() => persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root })).toThrow( - /contract\.eligibility/, - ); + for (const mismatch of ['work', 'repository'] as const) { + const mismatchBytes = bytes(`mismatch:${mismatch}`); + const mismatched = recordForCallback(mismatchBytes, `${mismatch}:${parentReason}`); + mismatched.lineage = { pass: 2, parentCritiqueId: parent.critiqueId }; + if (mismatch === 'work') mismatched.workId = 'other-work'; + else mismatched.repository.fingerprint = '0'.repeat(64); + mismatched.critiqueId = derivePlanCritiqueId(mismatched); + expect(() => + persistPlanCritiqueRecord(mismatched, { exactResponse: mismatchBytes }, { root }), + ).toThrow(/parentCritiqueId/); + } + }, + ); + + it.each(['sound', 'invalid', 'wrong_phase', 'aborted'] as const)( + 'retains a pass 2 after a %s parent as an unnecessary recheck', + (parentState) => { + const root = temporaryRoot(); + const parentBytes = bytes(`parent:${parentState}`); + const parent = recordForCallback(parentBytes, `parent:${parentState}`); + if (parentState === 'invalid') { + parent.contract = { + state: 'invalid', + error: { code: 'MALFORMED_JSON', path: '$' }, + status: null, + verdict: null, + criticalCount: null, + eligibility: { eligible: false, reason: 'invalid_contract' }, + }; + } else if (parentState === 'wrong_phase' || parentState === 'aborted') { + parent.contract = { + state: 'valid', + error: null, + status: parentState, + verdict: null, + criticalCount: null, + eligibility: { eligible: false, reason: parentState }, + }; + } + parent.critiqueId = derivePlanCritiqueId(parent); + persistPlanCritiqueRecord(parent, { exactResponse: parentBytes }, { root }); + + const childBytes = bytes(`child:${parentState}`); + const child = recordForCallback(childBytes, `child:${parentState}`); + child.lineage = { pass: 2, parentCritiqueId: parent.critiqueId }; + child.critiqueId = derivePlanCritiqueId(child); + expect(() => + persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root }), + ).toThrow(/contract\.eligibility/); - child.contract.eligibility = { eligible: false, reason: 'unnecessary_recheck' }; - expect(persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root }).state).toBe( - 'created', - ); + child.contract.eligibility = { eligible: false, reason: 'unnecessary_recheck' }; + expect(persistPlanCritiqueRecord(child, { exactResponse: childBytes }, { root }).state).toBe( + 'created', + ); - const thirdBytes = bytes(`third:${parentState}`); - const third = recordForCallback(thirdBytes, `third:${parentState}`); - third.lineage = { pass: 3, parentCritiqueId: child.critiqueId }; - third.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; - third.critiqueId = derivePlanCritiqueId(third); - expect(persistPlanCritiqueRecord(third, { exactResponse: thirdBytes }, { root }).state).toBe( - 'created', - ); - }); + const thirdBytes = bytes(`third:${parentState}`); + const third = recordForCallback(thirdBytes, `third:${parentState}`); + third.lineage = { pass: 3, parentCritiqueId: child.critiqueId }; + third.contract.eligibility = { eligible: false, reason: 'retry_limit_exceeded' }; + third.critiqueId = derivePlanCritiqueId(third); + expect(persistPlanCritiqueRecord(third, { exactResponse: thirdBytes }, { root }).state).toBe( + 'created', + ); + }, + ); }); diff --git a/gate-engine/critique/__tests__/immutable-file.test.mts b/gate-engine/critique/__tests__/immutable-file.test.mts index 45f295cc..d66e88d8 100644 --- a/gate-engine/critique/__tests__/immutable-file.test.mts +++ b/gate-engine/critique/__tests__/immutable-file.test.mts @@ -169,56 +169,57 @@ describe('immutable private files', () => { } }); - it.each([ - 0o500, 0o600, - ])('waits for a concurrent creator to secure a mode-%s directory', async (initialMode) => { - const anchor = temporaryRoot(); - const directory = path.join(anchor, 'records'); - mkdirSync(directory, { mode: initialMode }); - chmodSync(directory, initialMode); - const contender = path.join(anchor, 'contender.mts'); - const moduleUrl = pathToFileURL( - path.join(import.meta.dirname, '..', 'immutable-file.mts'), - ).href; - writeFileSync( - contender, - `import { managedPath } from ${JSON.stringify(moduleUrl)};\n` + - `process.stdout.write('ready\\n');\n` + - `process.stdout.write(String(managedPath(process.argv[2], ['records'], true)));\n`, - ); + it.each([0o500, 0o600])( + 'waits for a concurrent creator to secure a mode-%s directory', + async (initialMode) => { + const anchor = temporaryRoot(); + const directory = path.join(anchor, 'records'); + mkdirSync(directory, { mode: initialMode }); + chmodSync(directory, initialMode); + const contender = path.join(anchor, 'contender.mts'); + const moduleUrl = pathToFileURL( + path.join(import.meta.dirname, '..', 'immutable-file.mts'), + ).href; + writeFileSync( + contender, + `import { managedPath } from ${JSON.stringify(moduleUrl)};\n` + + `process.stdout.write('ready\\n');\n` + + `process.stdout.write(String(managedPath(process.argv[2], ['records'], true)));\n`, + ); - const child = spawn(process.execPath, [contender, anchor], { - stdio: ['ignore', 'pipe', 'pipe'], - }); - let stdout = ''; - let stderr = ''; - let releaseScheduled = false; - let releaseDirectory = Promise.resolve(); - child.stdout.on('data', (chunk) => { - stdout += String(chunk); - if (!releaseScheduled && stdout.startsWith('ready\n')) { - releaseScheduled = true; - releaseDirectory = new Promise((resolve) => { - setTimeout(() => { - chmodSync(directory, 0o700); - resolve(); - }, 20); - }); - } - }); - child.stderr.on('data', (chunk) => { - stderr += String(chunk); - }); - const code = await new Promise((resolve, reject) => { - child.once('error', reject); - child.once('close', resolve); - }); - await releaseDirectory; + const child = spawn(process.execPath, [contender, anchor], { + stdio: ['ignore', 'pipe', 'pipe'], + }); + let stdout = ''; + let stderr = ''; + let releaseScheduled = false; + let releaseDirectory = Promise.resolve(); + child.stdout.on('data', (chunk) => { + stdout += String(chunk); + if (!releaseScheduled && stdout.startsWith('ready\n')) { + releaseScheduled = true; + releaseDirectory = new Promise((resolve) => { + setTimeout(() => { + chmodSync(directory, 0o700); + resolve(); + }, 20); + }); + } + }); + child.stderr.on('data', (chunk) => { + stderr += String(chunk); + }); + const code = await new Promise((resolve, reject) => { + child.once('error', reject); + child.once('close', resolve); + }); + await releaseDirectory; - expect({ code, stderr }).toEqual({ code: 0, stderr: '' }); - expect(stdout.trim().split('\n').at(-1)).toBe(realpathSync(directory)); - expect(lstatSync(directory).mode & 0o777).toBe(0o700); - }); + expect({ code, stderr }).toEqual({ code: 0, stderr: '' }); + expect(stdout.trim().split('\n').at(-1)).toBe(realpathSync(directory)); + expect(lstatSync(directory).mode & 0o777).toBe(0o700); + }, + ); it('bounds immutable comparison against an oversized existing destination', () => { const anchor = temporaryRoot(); diff --git a/gate-engine/critique/__tests__/persistence-lock.test.mts b/gate-engine/critique/__tests__/persistence-lock.test.mts index b2a44549..35462288 100644 --- a/gate-engine/critique/__tests__/persistence-lock.test.mts +++ b/gate-engine/critique/__tests__/persistence-lock.test.mts @@ -326,59 +326,57 @@ describe('plan critique persistence lock', () => { expect(existsSync(moved)).toBe(true); }); - it.each([ - 'remove', - 'remove_parent', - 'remove_release_failure', - 'replace', - ] as const)('does not authorize a root %s while waiting', async (mutation) => { - const scratch = temporaryDirectory(`critique-existing-root-${mutation}-`); - const { alias, real } = aliasRoots(scratch); - const canonical = resolvePlanCritiqueEvidenceRoot({ root: real }, true) as string; - const parent = path.dirname(canonical); - const entered = path.join(scratch, 'holder-entered'); - const contenderWaiting = path.join(scratch, 'contender-waiting'); - const mutationComplete = path.join(scratch, 'mutation-complete'); - const holder = runChild(rootMutationHolderScript(scratch), [ - real, - entered, - contenderWaiting, - mutationComplete, - mutation, - ]); - await waitForFile(entered); - - let actionCalled = false; - const contend = () => - signalMainLockAttempt( + it.each(['remove', 'remove_parent', 'remove_release_failure', 'replace'] as const)( + 'does not authorize a root %s while waiting', + async (mutation) => { + const scratch = temporaryDirectory(`critique-existing-root-${mutation}-`); + const { alias, real } = aliasRoots(scratch); + const canonical = resolvePlanCritiqueEvidenceRoot({ root: real }, true) as string; + const parent = path.dirname(canonical); + const entered = path.join(scratch, 'holder-entered'); + const contenderWaiting = path.join(scratch, 'contender-waiting'); + const mutationComplete = path.join(scratch, 'mutation-complete'); + const holder = runChild(rootMutationHolderScript(scratch), [ + real, + entered, contenderWaiting, mutationComplete, - () => - withExistingPlanCritiquePersistenceLock({ root: alias }, () => { - actionCalled = true; - return 'called'; - }), - mutation === 'remove_release_failure', - ); - if (mutation === 'replace') - expect(contend).toThrow( - /^plan critique evidence root changed while acquiring persistence lock$/, - ); - else if (mutation === 'remove_release_failure') - expect(contend).toThrow(/^injected release failure$/); - else expect(contend()).toEqual({ status: 'absent' }); - - expect(await holder).toEqual({ code: 0, stderr: '' }); - expect(actionCalled).toBe(false); - expect(existsSync(canonical)).toBe(mutation === 'replace'); - expect(existsSync(parent)).toBe(mutation !== 'remove_parent'); - if (existsSync(parent)) { - const remainingLocks = readdirSync(parent).filter((name) => - name.startsWith('.plan-critique-'), - ); - expect(remainingLocks).toHaveLength(mutation === 'remove_release_failure' ? 1 : 0); - } - }); + mutation, + ]); + await waitForFile(entered); + + let actionCalled = false; + const contend = () => + signalMainLockAttempt( + contenderWaiting, + mutationComplete, + () => + withExistingPlanCritiquePersistenceLock({ root: alias }, () => { + actionCalled = true; + return 'called'; + }), + mutation === 'remove_release_failure', + ); + if (mutation === 'replace') + expect(contend).toThrow( + /^plan critique evidence root changed while acquiring persistence lock$/, + ); + else if (mutation === 'remove_release_failure') + expect(contend).toThrow(/^injected release failure$/); + else expect(contend()).toEqual({ status: 'absent' }); + + expect(await holder).toEqual({ code: 0, stderr: '' }); + expect(actionCalled).toBe(false); + expect(existsSync(canonical)).toBe(mutation === 'replace'); + expect(existsSync(parent)).toBe(mutation !== 'remove_parent'); + if (existsSync(parent)) { + const remainingLocks = readdirSync(parent).filter((name) => + name.startsWith('.plan-critique-'), + ); + expect(remainingLocks).toHaveLength(mutation === 'remove_release_failure' ? 1 : 0); + } + }, + ); it('serializes child processes that use real and alias roots', async () => { const scratch = temporaryDirectory('critique-persistence-processes-'); diff --git a/gate-engine/critique/lifecycle/work-quarantine.test.mts b/gate-engine/critique/lifecycle/work-quarantine.test.mts index 20b9108f..ca44ecef 100644 --- a/gate-engine/critique/lifecycle/work-quarantine.test.mts +++ b/gate-engine/critique/lifecycle/work-quarantine.test.mts @@ -119,34 +119,32 @@ describe('plan critique work quarantine', () => { expect(() => readdirSync(root)).toThrow(/ENOENT/); }); - it.each([ - 'invalid-json', - 'wrong-identity', - 'non-canonical', - 'oversized', - ])('fails closed for %s persisted bytes', (corruption) => { - const root = temporaryRoot(); - persistPlanCritiqueWorkQuarantine(identity(), { root }); - const file = quarantineFile(root); - if (corruption === 'invalid-json') writeFileSync(file, '{'); - if (corruption === 'wrong-identity') { - const record = JSON.parse(readFileSync(file, 'utf8')); - record.workId = 'pcw1_other-work'; - writeFileSync(file, `${JSON.stringify(record)}\n`); - } - if (corruption === 'non-canonical') { - const record = JSON.parse(readFileSync(file, 'utf8')); - writeFileSync(file, `${JSON.stringify(record, null, 2)}\n`); - } - if (corruption === 'oversized') writeFileSync(file, Buffer.alloc(16 * 1024 + 1)); - expect(getPlanCritiqueWorkQuarantine(identity(), { root })).toEqual({ - status: 'unavailable', - reason: 'malformed_quarantine', - }); - expect(() => clearPlanCritiqueWorkQuarantine(identity(), { root })).toThrow( - /malformed plan critique work quarantine|immutable evidence/, - ); - }); + it.each(['invalid-json', 'wrong-identity', 'non-canonical', 'oversized'])( + 'fails closed for %s persisted bytes', + (corruption) => { + const root = temporaryRoot(); + persistPlanCritiqueWorkQuarantine(identity(), { root }); + const file = quarantineFile(root); + if (corruption === 'invalid-json') writeFileSync(file, '{'); + if (corruption === 'wrong-identity') { + const record = JSON.parse(readFileSync(file, 'utf8')); + record.workId = 'pcw1_other-work'; + writeFileSync(file, `${JSON.stringify(record)}\n`); + } + if (corruption === 'non-canonical') { + const record = JSON.parse(readFileSync(file, 'utf8')); + writeFileSync(file, `${JSON.stringify(record, null, 2)}\n`); + } + if (corruption === 'oversized') writeFileSync(file, Buffer.alloc(16 * 1024 + 1)); + expect(getPlanCritiqueWorkQuarantine(identity(), { root })).toEqual({ + status: 'unavailable', + reason: 'malformed_quarantine', + }); + expect(() => clearPlanCritiqueWorkQuarantine(identity(), { root })).toThrow( + /malformed plan critique work quarantine|immutable evidence/, + ); + }, + ); it('fails closed for non-private persisted evidence', () => { const root = temporaryRoot(); diff --git a/gate-engine/deterministic/__tests__/run.test.mts b/gate-engine/deterministic/__tests__/run.test.mts index 79bfeae4..442638a1 100644 --- a/gate-engine/deterministic/__tests__/run.test.mts +++ b/gate-engine/deterministic/__tests__/run.test.mts @@ -334,18 +334,18 @@ describe('prefixCacheScope', () => { // THE anti-laundering property. Without the salt a GUARD_COVERAGE_OK ship records an all-green key // that a later un-bypassed ship of the identical tree would HIT — skipping every gate, so coverage // never runs again. The two runs must never share a key. - it.each([ - 'GUARD_COVERAGE_OK', - 'GUARD_NO_COVERAGE', - ])('%s salts the scope away from a clean run', (key) => { - const cleanDefault = prefixCacheScope(); - const cleanCustom = prefixCacheScope('custom'); - process.env[key] = '1'; - expect(prefixCacheScope()).toBe('devkit-guards:coverage-bypassed'); - expect(prefixCacheScope('custom')).toBe('custom:coverage-bypassed'); - expect(prefixCacheScope()).not.toBe(cleanDefault); - expect(prefixCacheScope('custom')).not.toBe(cleanCustom); - }); + it.each(['GUARD_COVERAGE_OK', 'GUARD_NO_COVERAGE'])( + '%s salts the scope away from a clean run', + (key) => { + const cleanDefault = prefixCacheScope(); + const cleanCustom = prefixCacheScope('custom'); + process.env[key] = '1'; + expect(prefixCacheScope()).toBe('devkit-guards:coverage-bypassed'); + expect(prefixCacheScope('custom')).toBe('custom:coverage-bypassed'); + expect(prefixCacheScope()).not.toBe(cleanDefault); + expect(prefixCacheScope('custom')).not.toBe(cleanCustom); + }, + ); it('composes with the review salt rather than replacing it', () => { process.env.DEVKIT_RUN_MODE = 'review'; diff --git a/gate-engine/judge/__tests__/verdict-store.test.mts b/gate-engine/judge/__tests__/verdict-store.test.mts index a6e772c1..4d51570b 100644 --- a/gate-engine/judge/__tests__/verdict-store.test.mts +++ b/gate-engine/judge/__tests__/verdict-store.test.mts @@ -452,34 +452,35 @@ describe('verdict store mutations', () => { }); expect(existsSync(`${file}.lock`)).toBe(false); }, 10_000); - it.each([ - 'release', - 'reap', - ] as const)('preserves a replacement installed at the %s pathname gap', async (operation) => { - const root = tempRoot(`verdict-${operation}-replacement`); - const file = path.join(root, 'review-cache.json'); - const state = markers(root, operation); - if (operation === 'reap') { - const crashed = markers(root, 'crashed'); - await spawnWorker('crash', file, 'crashed', crashed).done; - expect(existsSync(`${file}.lock`)).toBe(true); - } - const worker = spawnWorker(operation, file, operation, state); - await waitForFile(state.loaded); - const replacement = replacePublishedLock(file, operation); - writeFileSync(state.release, 'release\n'); - await worker.done; - const owner = JSON.parse(readFileSync(`${file}.lock/owner.json`, 'utf8')) as { - token: string; - }; - expect(owner.token).toBe(replacement.token); - expect(existsSync(replacement.displaced)).toBe(true); - expect(loadEntries(file)).toEqual( - operation === 'release' - ? { release: { at: '2026-07-19T00:00:00.000Z', worker: 'release' } } - : {}, - ); - }, 10_000); + it.each(['release', 'reap'] as const)( + 'preserves a replacement installed at the %s pathname gap', + async (operation) => { + const root = tempRoot(`verdict-${operation}-replacement`); + const file = path.join(root, 'review-cache.json'); + const state = markers(root, operation); + if (operation === 'reap') { + const crashed = markers(root, 'crashed'); + await spawnWorker('crash', file, 'crashed', crashed).done; + expect(existsSync(`${file}.lock`)).toBe(true); + } + const worker = spawnWorker(operation, file, operation, state); + await waitForFile(state.loaded); + const replacement = replacePublishedLock(file, operation); + writeFileSync(state.release, 'release\n'); + await worker.done; + const owner = JSON.parse(readFileSync(`${file}.lock/owner.json`, 'utf8')) as { + token: string; + }; + expect(owner.token).toBe(replacement.token); + expect(existsSync(replacement.displaced)).toBe(true); + expect(loadEntries(file)).toEqual( + operation === 'release' + ? { release: { at: '2026-07-19T00:00:00.000Z', worker: 'release' } } + : {}, + ); + }, + 10_000, + ); it('orders clear after an in-flight save instead of resurrecting cleared checkpoints', async () => { const root = tempRoot('verdict-clear-race'); const file = path.join(root, 'review-cache.json'); diff --git a/package.json b/package.json index ef947531..f91c478d 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "build": "tsc -p tsconfig.build.json && node scripts/copy-dist-assets.mjs" }, "devDependencies": { - "@biomejs/biome": "^2.5.0", + "@biomejs/biome": "^2.5.6", "@types/node": "^25.9.3", "@vitest/coverage-v8": "^4.1.10", "husky": "^9.1.7", From 57e27ed19881f1eade7fccaedb4e9c4fd971597a Mon Sep 17 00:00:00 2001 From: norvalbv Date: Mon, 3 Aug 2026 12:05:14 +0100 Subject: [PATCH 2/2] test(checklist): prove the injected ' . ' root drives the scan, not just that it is accepted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the CodeRabbit review comment on PR #317. `expect(dot.status).toBe(0)` proved only that `' . '` was *accepted* — it passed equally if the script ignored `DEVKIT_REVIEW_*_ROOTS` and fell back to the fixture's configured `backendRoots: ['src']`, which already covers the crafted file. Now the fixture's configured roots are pointed at `no-such-root` (both backend and frontend), so nothing but the injected root can reach `src/auth\$(touch INJECTED).ts`. The test then asserts the generated state contains that path, using the `stateName` element already present in `REVIEW_ROOT_CASES` but previously unused by this case. Verified load-bearing by mutation: swapping `' . '` for a valid-but-non-matching root fails all 6 cases on the new assertion. 39/39 pass as written; biome and tsc clean. --- cli/__tests__/checklist-scripts.test.mts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cli/__tests__/checklist-scripts.test.mts b/cli/__tests__/checklist-scripts.test.mts index a1c8c97d..2ba5e0be 100644 --- a/cli/__tests__/checklist-scripts.test.mts +++ b/cli/__tests__/checklist-scripts.test.mts @@ -183,8 +183,18 @@ describe('skill checklist script (spawned source)', () => { it.each(REVIEW_ROOT_CASES)( '%s rejects unsafe injected roots before constructing a Git pathspec', - (skill, envName) => { + (skill, envName, stateName) => { const repo = repoWithCraftedFile(); + // Point the CONFIGURED roots away from the crafted file. Without this, the final + // `' . '` case's `status === 0` also passes when the script ignores the env var + // entirely and falls back to the fixture's backendRoots: ['src'] — so it would + // prove the root was accepted, not that it actually drove the scan. + writeFileSync( + join(repo, 'guard.config.json'), + JSON.stringify({ + review: { backendRoots: ['no-such-root'], frontendRoots: ['no-such-root'] }, + }), + ); const script = fileURLToPath( new URL(`../../skills/${skill}/scripts/checklist.mjs`, import.meta.url), ); @@ -219,6 +229,10 @@ describe('skill checklist script (spawned source)', () => { }, }); expect(dot.status, dot.stderr).toBe(0); + // ...and the injected root must be what got scanned: ' . ' normalises to the repo + // root, so the crafted file is reached despite no configured root covering it. + const state = JSON.parse(readFileSync(join(repo, '.claude', stateName), 'utf8')); + expect(JSON.stringify(state)).toContain('src/auth$(touch INJECTED).ts'); }, );