From 4504c9a8cf016dcd871e91e019e2cf28f8d8446d Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Wed, 13 May 2026 21:15:26 +0200 Subject: [PATCH] test(voyage): add 5 minimal command test files for v5.1 (sequencing-gate + low-effort) --- .../voyage/tests/commands/trekbrief.test.mjs | 42 +++++++++++++++++++ .../tests/commands/trekexecute.test.mjs | 34 +++++++++++++++ .../voyage/tests/commands/trekplan.test.mjs | 32 ++++++++++++++ .../tests/commands/trekresearch.test.mjs | 32 ++++++++++++++ .../voyage/tests/commands/trekreview.test.mjs | 32 ++++++++++++++ 5 files changed, 172 insertions(+) create mode 100644 plugins/voyage/tests/commands/trekbrief.test.mjs create mode 100644 plugins/voyage/tests/commands/trekexecute.test.mjs create mode 100644 plugins/voyage/tests/commands/trekplan.test.mjs create mode 100644 plugins/voyage/tests/commands/trekresearch.test.mjs create mode 100644 plugins/voyage/tests/commands/trekreview.test.mjs diff --git a/plugins/voyage/tests/commands/trekbrief.test.mjs b/plugins/voyage/tests/commands/trekbrief.test.mjs new file mode 100644 index 0000000..3db8030 --- /dev/null +++ b/plugins/voyage/tests/commands/trekbrief.test.mjs @@ -0,0 +1,42 @@ +// tests/commands/trekbrief.test.mjs +// v5.1 — Pattern D prose-pattern regression tests for /trekbrief Phase 3.5. +// +// Brief SC1 + SC2: end-of-brief effort dialog covering 4 downstream phases, +// with `phase_signals_partial` as the force-stop record. + +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'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(HERE, '..', '..'); +const COMMAND_FILE = join(ROOT, 'commands', 'trekbrief.md'); + +function read() { + return readFileSync(COMMAND_FILE, 'utf8'); +} + +test('trekbrief — Phase 3.5 heading is present', () => { + const text = read(); + assert.match(text, /^## Phase 3\.5 — Per-phase effort dialog$/m, + 'Phase 3.5 heading missing from commands/trekbrief.md'); +}); + +test('trekbrief — Phase 3.5 references all 4 downstream phases', () => { + const text = read(); + const startIdx = text.indexOf('## Phase 3.5'); + assert.ok(startIdx >= 0, 'Phase 3.5 not found'); + const section = text.slice(startIdx, text.indexOf('## Phase 4', startIdx)); + for (const phase of ['research', 'plan', 'execute', 'review']) { + assert.ok(section.includes(phase), + `Phase 3.5 missing reference to "${phase}"`); + } +}); + +test('trekbrief — Phase 3.5 documents phase_signals_partial force-stop', () => { + const text = read(); + assert.ok(text.includes('phase_signals_partial'), + 'phase_signals_partial not mentioned in /trekbrief command prose'); +}); diff --git a/plugins/voyage/tests/commands/trekexecute.test.mjs b/plugins/voyage/tests/commands/trekexecute.test.mjs new file mode 100644 index 0000000..e848119 --- /dev/null +++ b/plugins/voyage/tests/commands/trekexecute.test.mjs @@ -0,0 +1,34 @@ +// tests/commands/trekexecute.test.mjs +// v5.1 — sequencing-gate surface + low-effort prose check for /trekexecute. +// Plan Assumption 2 locks low-effort to --gates open + sequential-only. + +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'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(HERE, '..', '..'); +const COMMAND_FILE = join(ROOT, 'commands', 'trekexecute.md'); + +function read() { + return readFileSync(COMMAND_FILE, 'utf8'); +} + +test('trekexecute — sequencing-gate surface mentions BRIEF_V51_MISSING_SIGNALS + phase_signals', () => { + const text = read(); + assert.ok(text.includes('BRIEF_V51_MISSING_SIGNALS'), + '/trekexecute must surface the BRIEF_V51_MISSING_SIGNALS sequencing gate'); + assert.ok(text.includes('phase_signals'), + '/trekexecute must reference phase_signals (v5.1 composition rule)'); +}); + +test('trekexecute — low-effort path references --gates open + sequential', () => { + 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, /--gates open/, 'Low-effort path must mention --gates open'); + assert.match(section, /sequential/, 'Low-effort path must mention sequential-only execution'); +}); diff --git a/plugins/voyage/tests/commands/trekplan.test.mjs b/plugins/voyage/tests/commands/trekplan.test.mjs new file mode 100644 index 0000000..901936d --- /dev/null +++ b/plugins/voyage/tests/commands/trekplan.test.mjs @@ -0,0 +1,32 @@ +// tests/commands/trekplan.test.mjs +// v5.1 — sequencing-gate surface + low-effort prose check for /trekplan. + +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'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(HERE, '..', '..'); +const COMMAND_FILE = join(ROOT, 'commands', 'trekplan.md'); + +function read() { + return readFileSync(COMMAND_FILE, 'utf8'); +} + +test('trekplan — sequencing-gate surface mentions BRIEF_V51_MISSING_SIGNALS + phase_signals', () => { + const text = read(); + assert.ok(text.includes('BRIEF_V51_MISSING_SIGNALS'), + '/trekplan must surface the BRIEF_V51_MISSING_SIGNALS sequencing gate'); + assert.ok(text.includes('phase_signals'), + '/trekplan must reference phase_signals (v5.1 composition rule)'); +}); + +test('trekplan — 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'); +}); diff --git a/plugins/voyage/tests/commands/trekresearch.test.mjs b/plugins/voyage/tests/commands/trekresearch.test.mjs new file mode 100644 index 0000000..4fd2a8c --- /dev/null +++ b/plugins/voyage/tests/commands/trekresearch.test.mjs @@ -0,0 +1,32 @@ +// tests/commands/trekresearch.test.mjs +// v5.1 — sequencing-gate surface + low-effort prose check for /trekresearch. + +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'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(HERE, '..', '..'); +const COMMAND_FILE = join(ROOT, 'commands', 'trekresearch.md'); + +function read() { + return readFileSync(COMMAND_FILE, 'utf8'); +} + +test('trekresearch — sequencing-gate surface mentions BRIEF_V51_MISSING_SIGNALS + phase_signals', () => { + const text = read(); + assert.ok(text.includes('BRIEF_V51_MISSING_SIGNALS'), + '/trekresearch must surface the BRIEF_V51_MISSING_SIGNALS sequencing gate'); + assert.ok(text.includes('phase_signals'), + '/trekresearch must reference phase_signals (v5.1 composition rule)'); +}); + +test('trekresearch — 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'); +}); diff --git a/plugins/voyage/tests/commands/trekreview.test.mjs b/plugins/voyage/tests/commands/trekreview.test.mjs new file mode 100644 index 0000000..9d1a53c --- /dev/null +++ b/plugins/voyage/tests/commands/trekreview.test.mjs @@ -0,0 +1,32 @@ +// tests/commands/trekreview.test.mjs +// v5.1 — sequencing-gate surface + low-effort prose check 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'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(HERE, '..', '..'); +const COMMAND_FILE = join(ROOT, 'commands', 'trekreview.md'); + +function read() { + return readFileSync(COMMAND_FILE, 'utf8'); +} + +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'); +});