feat(voyage)!: bulk content rewrite ultra -> voyage/trek prose [skip-docs]

Sed-pipeline (16 patterns, longest-match-first) sweeper residuelle ultra*-treff
i prose, command-narrativ, agent-prompts, hook-kommentarer, doc-prosa.

Pipeline-utvidelser fra V4-prompten:
- BSD-syntax [[:<:]]ultra[[:>:]] istedenfor \bultra\b (BSD sed mangler \b)
- 6 compound-patterns for ultraplan/ultraexecute/ultraresearch/ultrabrief/
  ultrareview/ultracontinue uten -local-suffiks
- ultra*-stats glob -> trek*-stats glob
- Linje-eksklusjon redusert til ultra-cc-architect (Q8); session-state-
  eksklusjonen var over-protektiv
- File-eksklusjon utvidet til settings.json, package.json, plugin.json,
  hele .claude/-treet (gitignored + V5-territorium)

Q8-undantak holdt: architecture-discovery.mjs + project-discovery.mjs urort.
Filnavn-konvensjon holdt: .session-state.local.json + *.local.* preservert.

Manuell narrative-fix: tests/lib/agent-frontmatter.test.mjs linje 10
mangled "/ultra*-local" til "/voyage*-local" (ingen slik kommando finnes);
korrigert til "/trek*".

Residualer utenfor scope (V5 handterer): package.json + .claude-plugin/
plugin.json (Step 12-14 versjons-bump). .claude/* er gitignored
spec-historikk med tilsiktet BEFORE/AFTER-narrativ.

Part of voyage-rebrand session 3 (Wave 4 / Step 10).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-05 15:08:20 +02:00
commit 14ecda886c
81 changed files with 672 additions and 672 deletions

View file

@ -1,8 +1,8 @@
// tests/commands/ultracontinue.test.mjs
// Regression tests for /ultracontinue-local (commands/ultracontinue-local.md).
// tests/commands/trekcontinue.test.mjs
// Regression tests for /trekcontinue (commands/trekcontinue.md).
//
// Steps 2 + 4 of the v3.4.1 hot-fix plan
// (project 2026-05-04-v3.3.1-ultracontinue-fixes).
// (project 2026-05-04-v3.3.1-trekcontinue-fixes).
//
// Pattern mix:
// - Pattern B (tmp-dir, mkdtempSync + try/finally) — fixture builds
@ -64,10 +64,10 @@ function completedState(updatedAtIso) {
// Step 2 — Bug 1 regression tests (SC-1, SC-2)
// ---------------------------------------------------------------
test('ultracontinue Bug 1 — Phase 1 documents auto-discovery sort by Date.parse(updated_at) DESC', () => {
test('trekcontinue Bug 1 — Phase 1 documents auto-discovery sort by Date.parse(updated_at) DESC', () => {
// Fixture-builds two project dirs and verifies our chosen sort key
// matches what Phase 1 prose documents.
const root = mkdtempSync(join(tmpdir(), 'ultracontinue-disc-'));
const root = mkdtempSync(join(tmpdir(), 'trekcontinue-disc-'));
try {
const projectsRoot = join(root, '.claude', 'projects');
mkdirSync(join(projectsRoot, '2026-05-04-fixture-a'), { recursive: true });
@ -103,7 +103,7 @@ test('ultracontinue Bug 1 — Phase 1 documents auto-discovery sort by Date.pars
}
});
test('ultracontinue Bug 1 — Phase 0 dispatches via parsed flags, not substring contains', () => {
test('trekcontinue Bug 1 — Phase 0 dispatches via parsed flags, not substring contains', () => {
const phase0 = extractPhase(readCommand(), '## Phase 0 ');
// Must NOT use the legacy "contains --help or -h" substring dispatch.
assert.doesNotMatch(
@ -121,7 +121,7 @@ test('ultracontinue Bug 1 — Phase 0 dispatches via parsed flags, not substring
);
});
test('ultracontinue Bug 1 — Phase 1 documents empty-args path explicitly to auto-discovery', () => {
test('trekcontinue Bug 1 — Phase 1 documents empty-args path explicitly to auto-discovery', () => {
const phase1 = extractPhase(readCommand(), '## Phase 1 ');
// Some explicit text mentioning the empty / whitespace path so a future reader
// can't misread Phase 0 as "fall through to usage on empty".
@ -137,7 +137,7 @@ test('ultracontinue Bug 1 — Phase 1 documents empty-args path explicitly to au
);
});
test('ultracontinue Bug 1 sub — Phase 1 emits SC-2 diagnostic for .md positional arg', () => {
test('trekcontinue Bug 1 sub — Phase 1 emits SC-2 diagnostic for .md positional arg', () => {
const phase1 = extractPhase(readCommand(), '## Phase 1 ');
// SC-2 verbatim diagnostic strings.
assert.match(
@ -162,7 +162,7 @@ test('ultracontinue Bug 1 sub — Phase 1 emits SC-2 diagnostic for .md position
// Step 4 — Bug 2 regression tests (SC-3)
// ---------------------------------------------------------------
test('ultracontinue Bug 2 — pre-bash-executor ALLOWS resolved validator invocation', async () => {
test('trekcontinue Bug 2 — pre-bash-executor ALLOWS resolved validator invocation', async () => {
// (d-1) Sanity-check that the planned Phase 2 Bash form (validator
// invocation with a concrete absolute path) is not blocked by the
// marketplace pre-bash-executor hook chain.
@ -175,7 +175,7 @@ test('ultracontinue Bug 2 — pre-bash-executor ALLOWS resolved validator invoca
// Step 8 — Bug 3 regression test (Phase 1.5 consistency wire-up)
// ---------------------------------------------------------------
test('ultracontinue Bug 3 — Phase 1.5 documents consistency check between Phase 1 and Phase 2', () => {
test('trekcontinue Bug 3 — Phase 1.5 documents consistency check between Phase 1 and Phase 2', () => {
const cmd = readCommand();
// Phase 1.5 must exist literally in the prose between Phase 1 and Phase 2.
assert.match(cmd, /## Phase 1\.5 /, 'Phase 1.5 header must be present');
@ -187,8 +187,8 @@ test('ultracontinue Bug 3 — Phase 1.5 documents consistency check between Phas
'Phase 1.5 must appear before Phase 2');
});
test('ultracontinue Bug 3 (e) — CLI consistency mode flags producer mismatch in JSON output', () => {
const root = mkdtempSync(join(tmpdir(), 'ultracontinue-fm-'));
test('trekcontinue Bug 3 (e) — CLI consistency mode flags producer mismatch in JSON output', () => {
const root = mkdtempSync(join(tmpdir(), 'trekcontinue-fm-'));
try {
const projectDir = join(root, '.claude', 'projects', '2026-05-04-fixture-c');
mkdirSync(projectDir, { recursive: true });
@ -207,7 +207,7 @@ test('ultracontinue Bug 3 (e) — CLI consistency mode flags producer mismatch i
}, null, 2),
);
// Project-dir prompt: produced_by ultraexecute-local at T-1
// Project-dir prompt: produced_by trekexecute at T-1
const projectPrompt = join(projectDir, 'NEXT-SESSION-PROMPT.local.md');
writeFileSync(projectPrompt,
'---\nproduced_by: trekexecute\nproduced_at: 2026-05-04T15:30:00.000Z\n---\n\n# Session 2\n');
@ -245,7 +245,7 @@ test('ultracontinue Bug 3 (e) — CLI consistency mode flags producer mismatch i
}
});
test('ultracontinue Bug 2 — Phase 2 contains no {state-file-path} or any {curly-template} placeholder', () => {
test('trekcontinue Bug 2 — Phase 2 contains no {state-file-path} or any {curly-template} placeholder', () => {
// (d-2) Pattern D structure test. The fix must eliminate the
// {state-file-path} placeholder and any other {anything} curly-brace
// template syntax from Phase 2 — substitution failures are the
@ -272,7 +272,7 @@ test('ultracontinue Bug 2 — Phase 2 contains no {state-file-path} or any {curl
// Step 10 — Bug 4 regression tests (Phase 0.5 wire-up + cleanup f-1/f-2/f-3)
// ---------------------------------------------------------------
test('ultracontinue Bug 4 — Phase 0.5 documents cleanup mode dispatch', () => {
test('trekcontinue Bug 4 — Phase 0.5 documents cleanup mode dispatch', () => {
const cmd = readCommand();
assert.match(cmd, /## Phase 0\.5 /, 'Phase 0.5 header must be present');
// Phase 0.5 must come BETWEEN Phase 0 and Phase 1.
@ -288,9 +288,9 @@ test('ultracontinue Bug 4 — Phase 0.5 documents cleanup mode dispatch', () =>
assert.match(cmd, /--cleanup --confirm/, 'usage must mention --cleanup --confirm');
});
test('ultracontinue Bug 4 (f-1) dry-run lists candidates without deleting', async () => {
test('trekcontinue Bug 4 (f-1) dry-run lists candidates without deleting', async () => {
const { cleanupProject } = await import('../../lib/util/cleanup.mjs');
const root = mkdtempSync(join(tmpdir(), 'ultracontinue-cleanup-'));
const root = mkdtempSync(join(tmpdir(), 'trekcontinue-cleanup-'));
try {
const dir = join(root, 'project-completed');
mkdirSync(dir, { recursive: true });
@ -314,10 +314,10 @@ test('ultracontinue Bug 4 (f-1) dry-run lists candidates without deleting', asyn
}
});
test('ultracontinue Bug 4 (f-2) confirm deletes and (f-3) idempotent re-run handles already-clean dir', async () => {
test('trekcontinue Bug 4 (f-2) confirm deletes and (f-3) idempotent re-run handles already-clean dir', async () => {
const { cleanupProject } = await import('../../lib/util/cleanup.mjs');
const { existsSync } = await import('node:fs');
const root = mkdtempSync(join(tmpdir(), 'ultracontinue-cleanup-'));
const root = mkdtempSync(join(tmpdir(), 'trekcontinue-cleanup-'));
try {
const dir = join(root, 'project-completed');
mkdirSync(dir, { recursive: true });

View file

@ -1,4 +1,4 @@
# ultrareview determinism fixtures
# trekreview determinism fixtures
Synthetic fixtures for the Jaccard-similarity determinism test in
`tests/lib/review-determinism.test.mjs`.
@ -24,7 +24,7 @@ fall out of sync.
## Why synthetic for v1.0
Hand-curated for v1.0. Edit JSON IDs directly to test new Jaccard scenarios.
Real-LLM determinism measurement is deferred to v1.1 once `/ultrareview-local`
Real-LLM determinism measurement is deferred to v1.1 once `/trekreview`
has produced enough real outputs to capture as fixtures.
These fixtures prove the Jaccard PIPELINE works given a known input — they do
@ -42,6 +42,6 @@ verify the model-level claim is open work for v1.1.
```
3. Add the IDs to `findings:` block-style YAML in frontmatter and to `### <id>`
subsections in the body.
4. Run `node lib/validators/review-validator.mjs --json tests/fixtures/ultrareview/review-run-X.md`
4. Run `node lib/validators/review-validator.mjs --json tests/fixtures/trekreview/review-run-X.md`
to confirm the fixture validates.
5. Update `tests/lib/review-determinism.test.mjs` if you want a new assertion.

View file

@ -8,14 +8,14 @@ source_findings:
# Remediation Plan: JWT auth review findings
> Generated by ultraplan-local v3.2.0 on 2026-05-01 — `plan_version: 1.7`.
> Generated by trekplan v3.2.0 on 2026-05-01 — `plan_version: 1.7`.
>
> Synthetic fixture — Handover 6 SC3(b) structural test only.
## Context
This synthetic plan is consumed by `tests/lib/source-findings.test.mjs` to verify
the structural contract of Handover 6: a plan generated from a `type: ultrareview`
the structural contract of Handover 6: a plan generated from a `type: trekreview`
brief carries a `source_findings:` block-style YAML list of 40-char hex IDs in
its frontmatter. The IDs trace back to the consumed findings in `review.md`.

View file

@ -88,7 +88,7 @@ NOT the output of a real LLM review.
## Remediation Summary
5 findings total: 1 BLOCKER, 3 MAJOR, 1 MINOR. Run a remediation plan via
`/ultraplan-local --brief review.md` — it will pick up BLOCKER + MAJOR findings as
`/trekplan --brief review.md` — it will pick up BLOCKER + MAJOR findings as
plan goals and emit `source_findings: [<id>, ...]` audit trail (Handover 6).
```json

View file

@ -99,7 +99,7 @@ Run A's set is a strict subset of Run B's set, giving Jaccard = 5/6 = 0.833.
6 findings total: 1 BLOCKER, 4 MAJOR, 1 MINOR. Same merge gate as Run A; one
extra MAJOR (PLACEHOLDER_IN_CODE) that Run A missed. Run a remediation plan via
`/ultraplan-local --brief review.md`.
`/trekplan --brief review.md`.
```json
{

View file

@ -7,7 +7,7 @@
// MUST include the `Agent` tool in their tools allowlist (they spawn the swarm).
//
// When this test fails, fix the agent file — do NOT relax the assertion to
// hide drift. The contract is what /ultra*-local commands rely on for
// hide drift. The contract is what /trek* commands rely on for
// disciplined model selection + tool scoping.
import { test } from 'node:test';

View file

@ -2,66 +2,66 @@ import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { parseArgs } from '../../lib/parsers/arg-parser.mjs';
test('ultrabrief — empty args', () => {
test('trekbrief — empty args', () => {
const r = parseArgs('', 'trekbrief');
assert.equal(r.command, 'trekbrief');
assert.deepEqual(r.flags, {});
});
test('ultrabrief — --quick boolean', () => {
test('trekbrief — --quick boolean', () => {
const r = parseArgs('--quick', 'trekbrief');
assert.equal(r.flags['--quick'], true);
});
test('ultraresearch — --project value capture', () => {
test('trekresearch — --project value capture', () => {
const r = parseArgs('--project .claude/projects/2026-04-30-foo', 'trekresearch');
assert.equal(r.flags['--project'], '.claude/projects/2026-04-30-foo');
});
test('ultraresearch — --quick --local combined', () => {
test('trekresearch — --quick --local combined', () => {
const r = parseArgs('--quick --local', 'trekresearch');
assert.equal(r.flags['--quick'], true);
assert.equal(r.flags['--local'], true);
});
test('ultraplan — --research multi-value', () => {
test('trekplan — --research multi-value', () => {
const r = parseArgs('--research a.md b.md c.md', 'trekplan');
assert.deepEqual(r.flags['--research'], ['a.md', 'b.md', 'c.md']);
});
test('ultraplan — --research multi stops at next flag', () => {
test('trekplan — --research multi stops at next flag', () => {
const r = parseArgs('--research a.md b.md --project /x', 'trekplan');
assert.deepEqual(r.flags['--research'], ['a.md', 'b.md']);
assert.equal(r.flags['--project'], '/x');
});
test('ultraplan — --brief required-value flag', () => {
test('trekplan — --brief required-value flag', () => {
const r = parseArgs('--brief brief.md', 'trekplan');
assert.equal(r.flags['--brief'], 'brief.md');
});
test('ultraplan — missing value for --brief produces error', () => {
test('trekplan — missing value for --brief produces error', () => {
const r = parseArgs('--brief --quick', 'trekplan');
assert.ok(r.errors.find(e => e.code === 'ARG_MISSING_VALUE'));
});
test('ultraplan — --decompose value flag', () => {
test('trekplan — --decompose value flag', () => {
const r = parseArgs('--decompose plan.md', 'trekplan');
assert.equal(r.flags['--decompose'], 'plan.md');
});
test('ultraexecute — --resume + --project', () => {
test('trekexecute — --resume + --project', () => {
const r = parseArgs('--resume --project /tmp/p', 'trekexecute');
assert.equal(r.flags['--resume'], true);
assert.equal(r.flags['--project'], '/tmp/p');
});
test('ultraexecute — --step N value', () => {
test('trekexecute — --step N value', () => {
const r = parseArgs('--step 3', 'trekexecute');
assert.equal(r.flags['--step'], '3');
});
test('ultraexecute — unknown flag goes to unknown[]', () => {
test('trekexecute — unknown flag goes to unknown[]', () => {
const r = parseArgs('--mystery foo', 'trekexecute');
assert.ok(r.unknown.includes('--mystery'));
});
@ -76,28 +76,28 @@ test('unknown command reported as error', () => {
assert.ok(r.errors.find(e => e.code === 'ARG_UNKNOWN_COMMAND'));
});
test('ultrareview — --project value capture', () => {
test('trekreview — --project value capture', () => {
const r = parseArgs('--project .claude/projects/2026-05-01-foo', 'trekreview');
assert.equal(r.flags['--project'], '.claude/projects/2026-05-01-foo');
});
test('ultrareview — --since <ref> value', () => {
test('trekreview — --since <ref> value', () => {
const r = parseArgs('--since HEAD~5', 'trekreview');
assert.equal(r.flags['--since'], 'HEAD~5');
});
test('ultrareview — --quick + --validate combined', () => {
test('trekreview — --quick + --validate combined', () => {
const r = parseArgs('--quick --validate', 'trekreview');
assert.equal(r.flags['--quick'], true);
assert.equal(r.flags['--validate'], true);
});
test('ultrareview — unknown flag goes to unknown[]', () => {
test('trekreview — unknown flag goes to unknown[]', () => {
const r = parseArgs('--mystery foo', 'trekreview');
assert.ok(r.unknown.includes('--mystery'));
});
test('ultracontinue — empty args produce no flags and no positional', () => {
test('trekcontinue — empty args produce no flags and no positional', () => {
const r = parseArgs('', 'trekcontinue');
assert.equal(r.command, 'trekcontinue');
assert.deepEqual(r.flags, {});
@ -105,35 +105,35 @@ test('ultracontinue — empty args produce no flags and no positional', () => {
assert.deepEqual(r.errors, []);
});
test('ultracontinue — --help boolean flag', () => {
test('trekcontinue — --help boolean flag', () => {
const r = parseArgs('--help', 'trekcontinue');
assert.equal(r.flags['--help'], true);
});
test('ultracontinue — -h treated as positional (no alias resolution)', () => {
test('trekcontinue — -h treated as positional (no alias resolution)', () => {
const r = parseArgs('-h', 'trekcontinue');
assert.deepEqual(r.positional, ['-h']);
assert.deepEqual(r.errors, []);
assert.equal(r.flags['--help'], undefined);
});
test('ultracontinue — --cleanup boolean flag', () => {
test('trekcontinue — --cleanup boolean flag', () => {
const r = parseArgs('--cleanup', 'trekcontinue');
assert.equal(r.flags['--cleanup'], true);
});
test('ultracontinue — --cleanup --confirm both flags', () => {
test('trekcontinue — --cleanup --confirm both flags', () => {
const r = parseArgs('--cleanup --confirm', 'trekcontinue');
assert.equal(r.flags['--cleanup'], true);
assert.equal(r.flags['--confirm'], true);
});
test('ultracontinue — positional project dir captured', () => {
test('trekcontinue — positional project dir captured', () => {
const r = parseArgs('.claude/projects/2026-05-04-foo', 'trekcontinue');
assert.deepEqual(r.positional, ['.claude/projects/2026-05-04-foo']);
});
test('ultracontinue — .md positional accepted by parser (rejection is command-level)', () => {
test('trekcontinue — .md positional accepted by parser (rejection is command-level)', () => {
const r = parseArgs('NEXT-SESSION-PROMPT.local.md', 'trekcontinue');
assert.deepEqual(r.positional, ['NEXT-SESSION-PROMPT.local.md']);
assert.deepEqual(r.errors, []);

View file

@ -27,9 +27,9 @@ test('splitFrontmatter — no frontmatter', () => {
});
test('parseFrontmatter — string scalars', () => {
const r = parseFrontmatter('type: ultrabrief\nslug: jwt-auth\n');
const r = parseFrontmatter('type: trekbrief\nslug: jwt-auth\n');
assert.equal(r.valid, true);
assert.equal(r.parsed.type, 'ultrabrief');
assert.equal(r.parsed.type, 'trekbrief');
assert.equal(r.parsed.slug, 'jwt-auth');
});
@ -60,10 +60,10 @@ test('parseFrontmatter — rejects nested dict', () => {
});
test('parseDocument — full pipeline', () => {
const text = '---\ntype: ultrabrief\nresearch_topics: 2\n---\n\n# Body\n\ncontent\n';
const text = '---\ntype: trekbrief\nresearch_topics: 2\n---\n\n# Body\n\ncontent\n';
const r = parseDocument(text);
assert.equal(r.valid, true);
assert.equal(r.parsed.frontmatter.type, 'ultrabrief');
assert.equal(r.parsed.frontmatter.type, 'trekbrief');
assert.match(r.parsed.body, /content/);
});

View file

@ -9,7 +9,7 @@ import {
} from '../../lib/parsers/project-discovery.mjs';
function setupProject(structure) {
const root = mkdtempSync(join(tmpdir(), 'ultraplan-disc-'));
const root = mkdtempSync(join(tmpdir(), 'trekplan-disc-'));
for (const [path, content] of Object.entries(structure)) {
const full = join(root, path);
mkdirSync(join(full, '..'), { recursive: true });

View file

@ -1,7 +1,7 @@
// tests/lib/source-findings.test.mjs
// SC3(b) structural test for Handover 6.
//
// The brief requires `plan.md` produced from a `type: ultrareview` brief to
// The brief requires `plan.md` produced from a `type: trekreview` brief to
// contain `source_findings: [<id>, ...]` in its frontmatter. Without an
// automated test, SC3(b) is unverified.
//

View file

@ -50,7 +50,7 @@ steps:
# Synthetic plan run A — Add --verbose flag to CLI
This fixture represents one synthesized run of `/ultraplan-local` against a
This fixture represents one synthesized run of `/trekplan` against a
hand-calibrated brief. It is paired with `plan-run-B.md` for the
`plan-determinism.test.mjs` Jaccard floor (≥ 0.833).

View file

@ -50,7 +50,7 @@ steps:
# Synthetic plan run B — Add --verbose flag to CLI
This fixture represents a second synthesized run of `/ultraplan-local` against
This fixture represents a second synthesized run of `/trekplan` against
the same hand-calibrated brief used for `plan-run-A.md`. The two runs differ
on 2 step titles (modeling realistic LLM variation).

View file

@ -41,7 +41,7 @@ findings:
# Synthetic review run A — JWT authentication with refresh-token rotation
This fixture represents one synthesized run of `/ultrareview-local` on a
This fixture represents one synthesized run of `/trekreview` on a
hand-calibrated brief. It is paired with `review-run-B.md` for the
`review-determinism.test.mjs` Jaccard floor (≥ 0.833).

View file

@ -6,7 +6,7 @@ import { join } from 'node:path';
import { discoverArchitecture } from '../../lib/validators/architecture-discovery.mjs';
function setup(structure) {
const root = mkdtempSync(join(tmpdir(), 'ultraplan-arch-'));
const root = mkdtempSync(join(tmpdir(), 'trekplan-arch-'));
for (const [path, content] of Object.entries(structure)) {
const full = join(root, path);
mkdirSync(join(full, '..'), { recursive: true });

View file

@ -95,9 +95,9 @@ test('validateBrief — missing frontmatter is hard error', () => {
const REVIEW_AS_BRIEF = `---
type: trekreview
task: "Review delivered ultrareview-local v1.0"
slug: ultrareview-local
project_dir: .claude/projects/2026-05-01-ultrareview-local/
task: "Review delivered trekreview v1.0"
slug: trekreview
project_dir: .claude/projects/2026-05-01-trekreview/
findings:
- 0123456789abcdef0123456789abcdef01234567
- fedcba9876543210fedcba9876543210fedcba98
@ -107,7 +107,7 @@ findings:
## Intent
Adversarial review of delivered ultrareview-local v1.0.
Adversarial review of delivered trekreview v1.0.
## Goal
@ -118,12 +118,12 @@ Find what was missed.
- All BLOCKER findings get a fix-plan.
`;
test('validateBrief — ultrareview type accepted with findings array', () => {
test('validateBrief — trekreview type accepted with findings array', () => {
const r = validateBriefContent(REVIEW_AS_BRIEF, { strict: true });
assert.equal(r.valid, true, JSON.stringify(r.errors));
});
test('validateBrief — ultrareview without findings rejected (BRIEF_MISSING_FIELD)', () => {
test('validateBrief — trekreview without findings rejected (BRIEF_MISSING_FIELD)', () => {
const t = REVIEW_AS_BRIEF.replace(/findings:\n - 0123[\s\S]*?- fedcba[0-9a-f]+\n/, '');
const r = validateBriefContent(t);
assert.equal(r.valid, false);
@ -133,7 +133,7 @@ test('validateBrief — ultrareview without findings rejected (BRIEF_MISSING_FIE
);
});
test('validateBrief — ultrareview with findings as scalar (not array) rejected (BRIEF_BAD_FINDINGS_TYPE)', () => {
test('validateBrief — trekreview with findings as scalar (not array) rejected (BRIEF_BAD_FINDINGS_TYPE)', () => {
const t = REVIEW_AS_BRIEF.replace(
/findings:\n - 0123[\s\S]*?- fedcba[0-9a-f]+/,
'findings: not-an-array',

View file

@ -108,7 +108,7 @@ test('validateSessionStateContent — malformed JSON returns SESSION_STATE_PARSE
});
test('validateSessionState — missing file returns SESSION_STATE_NOT_FOUND', () => {
const r = validateSessionState('/tmp/nonexistent-ultracontinue-test-9b2f4e.json');
const r = validateSessionState('/tmp/nonexistent-trekcontinue-test-9b2f4e.json');
assert.equal(r.valid, false);
assert.ok(r.errors.find(e => e.code === 'SESSION_STATE_NOT_FOUND'));
});