test(r8): move the live tests out of the round files

R8 of cleanup R-a (plan .claude/projects/2026-11-07-cleanup-r-a, appendix A).
The live tests of the round files move into the test named after their
source; each moved test was seen red under a mutation of its source.
New: tests/lib/lib-imports.test.mjs, tests/lib/timing.test.mjs (from
timing-under-load). The [#1] --gates rule and shim-line pins move into
tests/lib/autonomy-gate.test.mjs.

Removed: the round test files (retterunde, retterunde-prose-pins,
trial-mechanical-fixes, trial2-fixes, trial2-minor, trial2-minor-prose-pins,
fix-round-4-5a-prose, fix-round-4-5b2-b-prose, timing-under-load), the 8 R8
e2e scripts, and seven round test files on the R-a removal list that pinned
them (fix-round-4-5b-prose, fix-round-4-5b-part-2/3/4-scripts,
fix-round-4-5b-part-4-prose, fix-round-4-5b2-b/c-scripts). The diff-mode e2e
pin (test 24) and the red-script round-wrapper cases go too.

tests/synthetic/plan-run-C.md becomes tests/fixtures/plan-run-c.md,
regenerated from buildPlan({ version: '1.9' }). The red judge, reporter and
judge test headers now name the shared red script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-11-07 10:19:49 +01:00
commit 651be3468b
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
60 changed files with 1755 additions and 7965 deletions

View file

@ -691,7 +691,6 @@ test('acceptOpen after round 3 lists only the real majors, never a lowered one',
const HERE = dirname(fileURLToPath(import.meta.url));
const ROOT = join(HERE, '..', '..');
const GATE = join(ROOT, 'lib', 'validators', 'plan-gate.mjs');
const E2E = join(ROOT, 'tests', 'e2e-critic-diff-mode.sh');
const GIT_CLEAN = { GIT_DIR: undefined, GIT_WORK_TREE: undefined, GIT_INDEX_FILE: undefined };
function gate(cwd, args, input) {
@ -935,13 +934,63 @@ test('23 (CLI): --record on a plan outside any git repo keeps no snapshot anywhe
}
});
test('24: the e2e script is ASCII only and bash -n clean', () => {
assert.ok(existsSync(E2E), 'tests/e2e-critic-diff-mode.sh exists');
const buf = readFileSync(E2E);
assert.equal(buf.findIndex(b => b > 127), -1, 'ASCII only');
assert.match(buf.toString('utf-8'), /e2e: ok/);
const r = spawnSync('/bin/bash', ['-n', E2E], { encoding: 'utf-8', env: childEnv() });
assert.equal(r.status, 0, r.stderr);
// The pipe /trekplan Phase 9 runs: the raw reviewer payload through the dedup
// CLI's --stdin, its stdout into the gate's --record (no in-process dedup).
const DEDUP = join(ROOT, 'lib', 'review', 'plan-review-dedup.mjs');
/** One round through the two CLIs: --hash, dedup --stdin on `payload`, then --record on its output. */
function pipeRound(dir, p, payload) {
const reviewed = hashOf(dir, p);
const d = spawnSync(process.execPath, [DEDUP, '--stdin'], { cwd: dir, input: JSON.stringify(payload), encoding: 'utf-8', env: childEnv(GIT_CLEAN) });
assert.equal(d.status, 0, `plan-review-dedup --stdin: ${d.stdout}${d.stderr}`);
const r = gate(dir, ['--record', p, '--reviewed', reviewed], d.stdout);
const lines = r.out.split('\n').filter(l => l !== '');
return { ...r, reviewed, j: lines.length ? JSON.parse(lines[lines.length - 1]) : null };
}
test('CLI pipe: dedup --stdin into --record counts round 2 by rule A, and a refused and a malformed lowering reach the gate as blockers', () => {
withRepo(buildPlan(), (p, dir) => {
const t1 = readPlan(p);
const raw = (findings, previous) => ({ findings, ...(previous ? { previous } : {}) });
const r1 = pipeRound(dir, p, {
plan_critic: raw([f('major', at(t1, S1_VERIFIES), 'Step 1 verification never states the expected return value')]),
scope_guardian: raw([]),
});
assert.equal(r1.code, 0, r1.out + r1.err);
assert.equal(r1.j.verdict, 'REVISE', r1.out);
const id = verdictIn(p).findings[0].id;
assert.match(id, /^[0-9a-f]{40}$/);
// Round 2: the round-1 major resolved by both, a new major on a line outside the edit.
const t2 = editA(readPlan(p));
writeFileSync(p, t2);
const prev = [{ id, resolved: true }];
const r2 = pipeRound(dir, p, { plan_critic: raw([guard(t2)], prev), scope_guardian: raw([], prev) });
assert.equal(r2.code, 0, r2.out + r2.err);
assert.equal(r2.j.verdict, 'PASS', r2.out);
assert.equal(r2.j.diff_base, r1.reviewed, 'round 2 diffs against round 1');
const g2 = gate(dir, [p]);
assert.equal(g2.code, 0, g2.out + g2.err);
// Round 3 (plan unchanged): a minor merged with its copy that claims a lowering
// from blocker, and a minor whose lowered_from is not a severity.
const t3 = readPlan(p);
const M9 = 'Step 1 never names the exit code its verify command expects';
const G9 = 'The revert for step one is never run against a dirty tree';
const r3 = pipeRound(dir, p, {
plan_critic: raw([f('minor', at(t3, S1_VERIFIES), M9)]),
scope_guardian: raw([
f('minor', at(t3, S1_VERIFIES), M9, { lowered_from: 'blocker', caught_by: 'npm test' }),
{ ...f('minor', at(t3, S1_ROLLBACK), G9, { lowered_from: 'high', caught_by: 'npm test' }), rule_key: 'gap' },
]),
});
assert.equal(r3.code, 0, r3.out + r3.err);
assert.equal(r3.j.verdict, 'BLOCK', r3.out);
assert.match(r3.out, /"blocker":2/, `round 3 counts two blockers: ${r3.out}`);
const g3 = gate(dir, [p]);
assert.equal(g3.code, 1, g3.out + g3.err);
assert.match(g3.out + g3.err, /PLAN_GATE_OPEN_BLOCKER/);
});
});
// ---- the matcher needs overlapping texts; a new id never repeats an old one ----