chore(voyage): release v5.0.1 — drop standalone HTML render; print literal /playground document-critique invocation

The v5.0.0 stop-gap had /trekbrief, /trekplan, and /trekreview each render
a read-only {artifact}.html (via scripts/render-artifact.mjs) AND print a
vague "run the /playground plugin" instruction. In practice the read-only
HTML was redundant with what /playground produces and the instruction
wasn't copy-paste-ready — the operator had to guess the right invocation.

v5.0.1 deletes scripts/render-artifact.mjs + its test + npm run render,
and makes each producing command end with a single boxed, literal,
copy-paste-ready line:

    /playground build a document-critique playground for {artifact_path}

One paste from the operator launches the official playground skill's
document-critique template, which builds an interactive HTML — artifact
on the left, per-line Approve/Reject/Comment cards on the right, Copy
Prompt button at the bottom. Mark suggestions, click Copy Prompt, paste
back, Claude revises the .md. Doc-consistency test pins the literal
invocation so the prose cannot soften back into vagueness.

npm test green: 503 tests, 501 pass, 0 fail, 2 skipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-13 13:24:32 +02:00
commit 2e0892cdaf
15 changed files with 206 additions and 563 deletions

View file

@ -400,13 +400,13 @@ test('commands/trekplan.md Phase 8 seals Opus-4.7 schema-drift defense', () => {
);
});
// --- v5.0.0 — bespoke playground + /trekrevise + Handover 8 removed ---
// --- v5.0.0 / v5.0.1 — bespoke playground removed; /playground invocation explicit ---
//
// The v4.2/v4.3 bespoke playground SPA, the /trekrevise command, and
// Handover 8 (annotation → revision) were removed in v5.0.0. Producing
// commands now render artifacts to self-contained HTML via
// scripts/render-artifact.mjs and direct operators at the official
// `/playground` plugin for annotation. These pins lock the removal in.
// v5.0.0 removed the bespoke playground SPA, /trekrevise, and Handover 8.
// v5.0.1 dropped the v5.0.0 stop-gap (scripts/render-artifact.mjs) and made
// the producing commands print a literal, copy-paste-ready /playground
// document-critique invocation instead. These pins lock both removals in
// AND pin the new copy-paste invocation as the operator-facing contract.
import { existsSync } from 'node:fs';
@ -430,36 +430,55 @@ test('Handover 8 deleted from HANDOVER-CONTRACTS.md (back to seven handovers)',
assert.ok(text.includes('## Handover 7'), 'Handover 7 must remain');
});
test('scripts/render-artifact.mjs exists (v5.0.0 render-and-link step)', () => {
test('scripts/render-artifact.mjs no longer exists (removed in v5.0.1)', () => {
assert.ok(
existsSync(join(ROOT, 'scripts/render-artifact.mjs')),
'scripts/render-artifact.mjs is required — producing commands call it to render artifacts to HTML',
!existsSync(join(ROOT, 'scripts/render-artifact.mjs')),
'scripts/render-artifact.mjs should be deleted — v5.0.1 drops the redundant standalone HTML render in favour of the /playground document-critique invocation printed by the producing commands',
);
});
test('producing commands reference render-artifact.mjs (render-and-link step)', () => {
test('producing commands print a literal /playground document-critique invocation', () => {
// The exact substring must appear in each producing command's prose so the
// operator copy-pastes a verbatim line. Drift on this is the friction point
// that motivated v5.0.1 — fail loudly if the prose softens back to "run the
// /playground plugin" without the literal command.
const REQUIRED = '/playground build a document-critique playground for';
for (const f of ['trekbrief.md', 'trekplan.md', 'trekreview.md']) {
assert.ok(
read(`commands/${f}`).includes('render-artifact.mjs'),
`commands/${f} must wire the render-artifact.mjs render-and-link step (v5.0.0)`,
read(`commands/${f}`).includes(REQUIRED),
`commands/${f} must include the literal invocation "${REQUIRED}" so the operator copy-pastes it directly (v5.0.1)`,
);
}
});
test('producing commands point operators at the /playground plugin for annotation', () => {
test('producing commands no longer reference the removed scripts/render-artifact.mjs', () => {
for (const f of ['trekbrief.md', 'trekplan.md', 'trekreview.md']) {
assert.ok(
read(`commands/${f}`).includes('/playground'),
`commands/${f} must mention the /playground plugin as the annotation path (v5.0.0)`,
!read(`commands/${f}`).includes('render-artifact.mjs'),
`commands/${f} still references scripts/render-artifact.mjs — that script was removed in v5.0.1`,
);
}
});
test('package.json no longer has an "npm run render" script (removed in v5.0.1)', () => {
const pkg = JSON.parse(read('package.json'));
assert.equal(
pkg.scripts && pkg.scripts.render,
undefined,
'package.json scripts.render should be gone in v5.0.1',
);
});
test('CHANGELOG.md has v5.0.0 entry', () => {
const cl = read('CHANGELOG.md');
assert.match(cl, /## v5\.0\.0\b/, 'CHANGELOG.md must include "## v5.0.0" entry');
});
test('CHANGELOG.md has v5.0.1 entry', () => {
const cl = read('CHANGELOG.md');
assert.match(cl, /## v5\.0\.1\b/, 'CHANGELOG.md must include "## v5.0.1" entry');
});
test('CHANGELOG.md retains v4.2.0 entry (history is not rewritten)', () => {
const cl = read('CHANGELOG.md');
assert.match(cl, /## v4\.2\.0\b/, 'CHANGELOG.md must keep the historical "## v4.2.0" entry');