voyage/tests/lib/manifest-schema-extensions.test.mjs
Kjell Tore Guttormsen 2a35d067d9
chore(cleanup): R-b R3 — profiles, phase signals and the effort dialog removed, one fixed path per command
The four profiles, the resolver, the profile validator and docs/profiles.md go;
/trekbrief Phase 3.5 and the brief's phase_signals checks go (an older brief's
key is ignored); MANIFEST_PROFILE_DRIFT and profile_used go. Every Profile,
Composition rule, Sequencing gate and High-effort section leaves the commands.
Decision 209: /trekresearch runs the full swarm with contrarian-researcher as
wave 2 every run; /trekreview and the coordinator run all four passes with no
high-effort normalization. Voyage agents are spawned with no model (their own
model: opus applies); the two built-in spawns pass model "opus". --profile
stays in the parser as a retired flag that swallows its value. §Model & effort
moves to docs/architecture.md; the sequencing-gate eval case goes.

Files removed: 44 (43 from the R3 list + tests/commands/trekreview.test.mjs,
whose every test pinned removed text). Files edited: 43.
Tests: 2467 (2466 pass / 0 fail / 1 skipped) before, 2309 (2309 pass / 0 fail /
0 skipped) after. Durable check: all three groups green, none pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 21:12:57 +01:00

98 lines
3.6 KiB
JavaScript

// tests/lib/manifest-schema-extensions.test.mjs
// Cover the OPTIONAL_KEYS extension to lib/parsers/manifest-yaml.mjs:
// - skip_commit_check (boolean, default false)
// - memory_write (boolean, default false)
//
// Defaults must NOT break the REQUIRED_KEYS contract.
// Non-boolean values must produce MANIFEST_OPTIONAL_TYPE error.
import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { parseManifest, OPTIONAL_KEYS, OPTIONAL_STRING_KEYS } from '../../lib/parsers/manifest-yaml.mjs';
const BASE = `### Step 1: Cover
- Manifest:
\`\`\`yaml
manifest:
expected_paths:
- lib/foo.mjs
min_file_count: 1
commit_message_pattern: "^feat:"
bash_syntax_check: []
forbidden_paths: []
must_contain: []`;
function bodyWithExtras(extras) {
return `${BASE}\n${extras}\n \`\`\`\n`;
}
function bodyOnlyRequired() {
return `${BASE}\n \`\`\`\n`;
}
test('OPTIONAL_KEYS exports skip_commit_check + memory_write', () => {
assert.deepEqual(
[...OPTIONAL_KEYS].sort(),
['memory_write', 'skip_commit_check'].sort(),
'OPTIONAL_KEYS export drift — pin contract',
);
});
test('absence of optional keys → defaults to false (both fields)', () => {
const r = parseManifest(bodyOnlyRequired());
assert.equal(r.valid, true, JSON.stringify(r.errors));
assert.equal(r.parsed.skip_commit_check, false);
assert.equal(r.parsed.memory_write, false);
});
test('skip_commit_check: true honored', () => {
const r = parseManifest(bodyWithExtras(' skip_commit_check: true'));
assert.equal(r.valid, true, JSON.stringify(r.errors));
assert.equal(r.parsed.skip_commit_check, true);
assert.equal(r.parsed.memory_write, false);
});
test('memory_write: true honored', () => {
const r = parseManifest(bodyWithExtras(' memory_write: true'));
assert.equal(r.valid, true, JSON.stringify(r.errors));
assert.equal(r.parsed.memory_write, true);
assert.equal(r.parsed.skip_commit_check, false);
});
test('both optional fields together — both honored', () => {
const r = parseManifest(bodyWithExtras(' skip_commit_check: true\n memory_write: true'));
assert.equal(r.valid, true, JSON.stringify(r.errors));
assert.equal(r.parsed.skip_commit_check, true);
assert.equal(r.parsed.memory_write, true);
});
test('skip_commit_check: non-boolean rejected with MANIFEST_OPTIONAL_TYPE', () => {
const r = parseManifest(bodyWithExtras(' skip_commit_check: "yes"'));
assert.equal(r.valid, false);
const found = r.errors.find(e => e.code === 'MANIFEST_OPTIONAL_TYPE');
assert.ok(found, `expected MANIFEST_OPTIONAL_TYPE, got: ${JSON.stringify(r.errors)}`);
assert.match(found.message, /skip_commit_check/);
});
test('memory_write: numeric rejected with MANIFEST_OPTIONAL_TYPE', () => {
const r = parseManifest(bodyWithExtras(' memory_write: 1'));
assert.equal(r.valid, false);
const found = r.errors.find(e => e.code === 'MANIFEST_OPTIONAL_TYPE');
assert.ok(found, `expected MANIFEST_OPTIONAL_TYPE, got: ${JSON.stringify(r.errors)}`);
assert.match(found.message, /memory_write/);
});
test('extension does NOT break REQUIRED_KEYS contract', () => {
const r = parseManifest(bodyOnlyRequired());
assert.equal(r.valid, true);
for (const k of ['expected_paths', 'min_file_count', 'commit_message_pattern',
'bash_syntax_check', 'forbidden_paths', 'must_contain']) {
assert.ok(k in r.parsed, `required key ${k} missing after extension`);
}
});
// v4.1 Step 3 — OPTIONAL_STRING_KEYS dispatch; its one key went in cleanup R-b.
test('OPTIONAL_STRING_KEYS exports no key', () => {
assert.deepEqual([...OPTIONAL_STRING_KEYS], [], 'OPTIONAL_STRING_KEYS export drift — pin contract');
});