docs(voyage): S33 — reconcile agent inventory (21 spawnable + 3 reference docs) + record D1–D3 considered-and-kept
Balance-backlog S33 (DOC, non-breaking). The D1–D3 forks resolved conservatively
(balance-backlog-plan.md), collapsing the model + observability work into a
documentation record. Three deliverables, all doc-only, no code/frontmatter change:
- V35 (doc half): the "24 agents" headline is reconciled to its honest split —
21 spawnable (one dormant: synthesis-agent, Δ≈0) + 3 orchestrator reference
docs (planning-/research-/review-orchestrator document the inline /trek*
workflow; not spawned). Each orchestrator header now declares itself a
"reference document, not a spawnable capability". README + CLAUDE.md state the
split; counts in the new pins are DERIVED from agents/ so they survive reword.
- D2 (V32 rationale): docs/observability.md gains a "Why direct export rather
than a native collector" section — direct export keeps the path / SSRF /
field-allowlist guards in audited in-process code (the S21 hardening) instead
of re-hosting a collector; textfile mode remains the collector escape hatch.
- D3 (kept-opus): docs/voyage-vs-cc-balance-analysis.md §10 decision record —
opus on V09 (glue), V35 (dormant), V11 (retrieval), V16 (mechanical), V08
(researchers) was reconsidered for sonnet and KEPT (pin 40d8742 firm).
No agent frontmatter changed — tests/lib/agent-frontmatter.test.mjs is the
structural model source-of-truth and is untouched (diff is description-only:
model: opus + tools lists unchanged, no Agent tool granted). No Handover-1
change; no exporter/gemini-bridge removal. Non-breaking, no version bump.
tests/lib/doc-consistency.test.mjs: +5 S33 pins (inventory split derived from
agents/; synthesis-agent dormant; orchestrator relabel; observability D2
rationale; analysis-doc D1–D3 record). Tests 739 (737 pass / 2 skip / 0 fail),
bar `node --test`; `claude plugin validate` green (1 accepted warning).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
This commit is contained in:
parent
2849157ba2
commit
2df0cbb372
8 changed files with 160 additions and 6 deletions
|
|
@ -1100,3 +1100,83 @@ test('S32: trekbrief Phase 3 delegates Q&A turn-taking to AskUserQuestion (V01
|
|||
'question to ask (policy); AskUserQuestion does the asking (engine). No hand-rolled menu loop.',
|
||||
);
|
||||
});
|
||||
|
||||
// ── S33 — documentation consolidation: record the considered-and-kept decisions ──
|
||||
//
|
||||
// The D1–D3 forks (balance-backlog-plan.md) resolved conservatively, collapsing
|
||||
// the model + observability work into a documentation record. These pins make
|
||||
// the three deliverables enforced doc-truth:
|
||||
// • V35 (doc half) — the "24 agents" framing is reconciled to its honest split
|
||||
// (21 spawnable + 3 reference orchestrators, of which synthesis-agent is the
|
||||
// one dormant spawnable). Counts are DERIVED from agents/ so they survive
|
||||
// reword and track new files.
|
||||
// • D2 (V32 rationale) — observability.md documents why direct export rather
|
||||
// than a native collector (preserves the S21 in-process guards).
|
||||
// • D3 (kept-opus) — the analysis doc carries a decision record citing the pin
|
||||
// commit; the model frontmatter is NOT changed (agent-frontmatter.test.mjs
|
||||
// stays the structural source-of-truth and is untouched by S33).
|
||||
// Fix the SOURCE a pin guards, not the test.
|
||||
|
||||
test('S33: README + CLAUDE.md reconcile the agent inventory (spawnable + reference orchestrators = file count)', () => {
|
||||
const agentFiles = listMd('agents');
|
||||
const total = agentFiles.length;
|
||||
const orchestrators = agentFiles.filter((f) => /-orchestrator\.md$/.test(f));
|
||||
const refCount = orchestrators.length;
|
||||
const spawnable = total - refCount;
|
||||
assert.equal(refCount, 3, `expected exactly 3 *-orchestrator reference docs, got ${refCount}`);
|
||||
for (const [name, body] of [['README.md', read('README.md')], ['CLAUDE.md', read('CLAUDE.md')]]) {
|
||||
assert.ok(
|
||||
body.includes(`${spawnable} spawnable`),
|
||||
`${name} must state "${spawnable} spawnable" agents (derived: ${total} files − ${refCount} reference orchestrators)`,
|
||||
);
|
||||
assert.ok(
|
||||
body.includes(`${refCount} orchestrator reference doc`),
|
||||
`${name} must label the ${refCount} orchestrators as reference docs (not spawnable capabilities)`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('S33: the inventory framing names synthesis-agent as the one dormant spawnable', () => {
|
||||
// 1 of the spawnable agents ships dormant (Δ≈0, wired to nothing). The framing
|
||||
// must say so, so the headline count is honest about live vs. dormant capability.
|
||||
for (const [name, body] of [['README.md', read('README.md')], ['CLAUDE.md', read('CLAUDE.md')]]) {
|
||||
assert.ok(
|
||||
/synthesis-agent/.test(body) && /dormant/i.test(body),
|
||||
`${name} inventory framing must name synthesis-agent as the dormant spawnable`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('S33: the 3 orchestrator files declare themselves reference docs, not spawnable capabilities (V35 relabel)', () => {
|
||||
for (const f of listMd('agents').filter((x) => /-orchestrator\.md$/.test(x))) {
|
||||
assert.ok(
|
||||
/reference document, not a spawnable capability/i.test(read(`agents/${f}`)),
|
||||
`agents/${f} must declare "reference document, not a spawnable capability" (V35 doc-half relabel)`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('S33: docs/observability.md documents the direct-export-vs-collector rationale (D2)', () => {
|
||||
const t = read('docs/observability.md');
|
||||
assert.ok(
|
||||
/direct[- ]export/i.test(t) && /collector/i.test(t),
|
||||
'observability.md must document why Voyage exports directly rather than via a native collector (D2)',
|
||||
);
|
||||
// The rationale must anchor on the in-process security boundary it preserves
|
||||
// (the S21 hardening), not read as an unjustified re-host.
|
||||
assert.ok(
|
||||
/allowlist/i.test(t) && /(SSRF|CWE-918|CWE-212)/.test(t),
|
||||
'the direct-export rationale must cite the in-process guards it preserves (field allowlist + SSRF/path)',
|
||||
);
|
||||
});
|
||||
|
||||
test('S33: the analysis doc records the D1–D3 resolved forks (considered-and-kept, pin firm)', () => {
|
||||
const t = read('docs/voyage-vs-cc-balance-analysis.md');
|
||||
assert.ok(/Decision record/i.test(t), 'analysis doc must carry a "Decision record" addendum for the resolved forks');
|
||||
for (const d of ['D1', 'D2', 'D3']) {
|
||||
assert.ok(new RegExp(`\\b${d}\\b`).test(t), `analysis-doc decision record must name fork ${d}`);
|
||||
}
|
||||
// D3 kept the model pin firm — the record must cite the pin commit so a future
|
||||
// reader sees the downgrade was reconsidered-and-declined, not overlooked.
|
||||
assert.ok(/40d8742/.test(t), 'decision record must cite the model-pin commit 40d8742 (D3 kept firm, document-only)');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue