feat(voyage)!: marketplace handoff — rename plugins/ultraplan-local to plugins/voyage [skip-docs]
Session 5 of voyage-rebrand (V6). Operator-authorized cross-plugin scope. - git mv plugins/ultraplan-local plugins/voyage (rename detected, history preserved) - .claude-plugin/marketplace.json: voyage entry replaces ultraplan-local - CLAUDE.md: voyage row in plugin list, voyage in design-system consumer list - README.md: bulk rename ultra*-local commands -> trek* commands; ultraplan-local refs -> voyage; type discriminators (type: trekbrief/trekreview); session-title pattern (voyage:<command>:<slug>); v4.0.0 release-note paragraph - plugins/voyage/.claude-plugin/plugin.json: homepage/repository URLs point to monorepo voyage path - plugins/voyage/verify.sh: drop URL whitelist exception (no longer needed) Closes voyage-rebrand. bash plugins/voyage/verify.sh PASS 7/7. npm test 361/361.
This commit is contained in:
parent
8f1bf9b7b4
commit
7a90d348ad
149 changed files with 26 additions and 33 deletions
92
plugins/voyage/tests/lib/manifest-schema-extensions.test.mjs
Normal file
92
plugins/voyage/tests/lib/manifest-schema-extensions.test.mjs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// 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 } 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`);
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue