voyage/tests/commands/trekreview.test.mjs
Kjell Tore Guttormsen 651be3468b
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>
2026-11-07 10:19:49 +01:00

130 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// tests/commands/trekreview.test.mjs
// v5.1 prose-pin tests + v5.1.1 runtime SC4 + SC7 tests for /trekreview.
import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { resolvePhaseSignal } from '../../lib/profiles/phase-signal-resolver.mjs';
import { validateBriefContent } from '../../lib/validators/brief-validator.mjs';
import { parseDocument } from '../../lib/util/frontmatter.mjs';
const HERE = dirname(fileURLToPath(import.meta.url));
const ROOT = join(HERE, '..', '..');
const COMMAND_FILE = join(ROOT, 'commands', 'trekreview.md');
const MODES_DOC = join(ROOT, 'docs', 'command-modes.md');
const PHASE = 'review';
function read() { return readFileSync(COMMAND_FILE, 'utf8'); }
function readModes() { return readFileSync(MODES_DOC, 'utf8'); }
function readFixture(name) { return readFileSync(join(ROOT, 'tests', 'fixtures', name), 'utf8'); }
function frontmatterOf(text) {
const doc = parseDocument(text);
return doc.parsed && doc.parsed.frontmatter;
}
// --- Pattern D prose-pins ---
test('trekreview — sequencing-gate surface mentions BRIEF_V51_MISSING_SIGNALS + phase_signals', () => {
const text = read();
assert.ok(text.includes('BRIEF_V51_MISSING_SIGNALS'),
'/trekreview must surface the BRIEF_V51_MISSING_SIGNALS sequencing gate');
assert.ok(text.includes('phase_signals'),
'/trekreview must reference phase_signals (v5.1 composition rule)');
});
test('trekreview — low-effort path references --quick equivalent', () => {
const text = read();
const compIdx = text.indexOf('## Composition rule (v5.1)');
assert.ok(compIdx >= 0, 'Composition rule (v5.1) section missing');
const section = text.slice(compIdx, compIdx + 2000);
assert.match(section, /--quick/, 'Low-effort path must mention --quick equivalent');
});
// --- v5.1.1 runtime SC4 + SC7 ---
test('trekreview — SC4: low-effort fixture → resolver returns {effort: low, model: sonnet}', () => {
const fm = frontmatterOf(readFixture('brief-effort-low.md'));
const r = resolvePhaseSignal(fm, PHASE);
assert.equal(r.effort, 'low');
assert.equal(r.model, 'sonnet');
});
test('trekreview — SC4: standard-effort fixture → resolver returns {effort: standard, model: undefined}', () => {
const fm = frontmatterOf(readFixture('brief-effort-standard.md'));
const r = resolvePhaseSignal(fm, PHASE);
assert.equal(r.effort, 'standard');
assert.equal(r.model, undefined);
});
test('trekreview — SC4: high-effort fixture → resolver returns {effort: high, model: opus}', () => {
const fm = frontmatterOf(readFixture('brief-effort-high.md'));
const r = resolvePhaseSignal(fm, PHASE);
assert.equal(r.effort, 'high');
assert.equal(r.model, 'opus');
});
test('trekreview — SC7: brief_version 2.1 + no phase_signals + no partial → BRIEF_V51_MISSING_SIGNALS', () => {
// Falsification via brief-v21-no-signals fixture: validator must catch missing signals.
const r = validateBriefContent(readFixture('brief-v21-no-signals.md'), { strict: true });
assert.equal(r.valid, false);
assert.ok(
r.errors.find(e => e.code === 'BRIEF_V51_MISSING_SIGNALS'),
`sequencing gate must fire; errors=${JSON.stringify(r.errors)}`,
);
});
// --- S11 (NW2 part B) — opt-in --workflow substrate routing ---
test('trekreview — Phase 1 flag table documents the --workflow opt-in flag', () => {
const text = read();
assert.match(text, /--workflow/,
'commands/trekreview.md must document the --workflow opt-in flag (NW2 part B)');
});
test('trekreview — --workflow routes Phase 5–6 to the validated NW2 Workflow port script', () => {
const text = read();
assert.ok(text.includes('scripts/trekreview-armB.workflow.mjs'),
'the --workflow route must reference the bake-off-validated NW2 Workflow port script');
});
test('trekreview — Workflow path is opt-in; default stays prose (portability floor)', () => {
const text = read();
assert.match(text, /opt-in/i, '--workflow must be described as opt-in');
assert.ok(text.includes('Default stays prose'),
'the command must state the default Phase 5–6 path stays prose (not Workflow)');
});
test('trekreview — Workflow opt-in documents the Claude Code 2.1.154+ floor', () => {
const text = read();
assert.match(text, /2\.1\.154/,
'the --workflow path raises the consumer floor and must document Claude Code 2.1.154+');
});
test('trekreview — bake-off evidence (fidelity-equivalent / T2 results) is cited for the opt-in', () => {
const text = read();
assert.ok(
text.includes('T2-bakeoff-results.md') && /fidelity-equivalent/i.test(text),
'the opt-in must cite the S10 bake-off (docs/T2-bakeoff-results.md) fidelity-equivalence verdict',
);
});
test('command-modes.md — /trekreview table documents --workflow + its CC floor', () => {
const text = readModes();
const start = text.indexOf('## /trekreview modes');
assert.ok(start >= 0, 'command-modes.md missing "## /trekreview modes" section');
const end = text.indexOf('\n## ', start + 1);
const section = text.slice(start, end === -1 ? undefined : end);
assert.match(section, /--workflow/,
'command-modes.md /trekreview table must list the --workflow opt-in flag');
assert.match(section, /2\.1\.154/,
'command-modes.md /trekreview --workflow row must note the Claude Code 2.1.154+ floor');
});
test('trekreview — stats write through stats-append, never silently skipped', () => {
const md = read();
assert.match(md, /node \$\{CLAUDE_PLUGIN_ROOT\}\/lib\/stats\/stats-append\.mjs trekreview <<'JSON'/);
assert.doesNotMatch(md, /skip (stats )?silently|silently skip/i);
assert.doesNotMatch(md, /\$\{CLAUDE_PLUGIN_DATA\}\/trekreview-stats\.jsonl/);
});