chore(release): v5.10.0 — STORM bounded loop (default-off) + the spawn-name defect

Version sync across the five surfaces that carry it (plugin.json, package.json,
package-lock.json x2, README badge) plus the CHANGELOG section for the 38
commits since v5.9.1. The two docs that print "voyage 5.9.1" are measurement
records and keep the version they were measured against.

Suite 1013 (1011 pass / 0 fail / 2 skip), unchanged by the bump.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018w5KWrbxzmki5wdXULT8nU
This commit is contained in:
Kjell Tore Guttormsen 2026-08-18 16:49:02 +02:00
commit 692a4a526c
5 changed files with 103 additions and 5 deletions

View file

@ -1,7 +1,7 @@
{
"name": "voyage",
"description": "Voyage — brief, research, plan, execute, review, continue. Contract-driven Claude Code pipeline. /trekbrief, /trekplan, and /trekreview each end by building a self-contained operator-annotation HTML (scripts/annotate.mjs, modelled on claude-code-100x): select text or click any element, pick intent (Fiks/Endre/Spørsmål), write comment, copy structured prompt, paste back, Claude revises the .md.",
"version": "5.9.1",
"version": "5.10.0",
"author": {
"name": "Kjell Tore Guttormsen"
},

View file

@ -4,6 +4,104 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## v5.10.0 — 2026-08-18 — STORM bounded research loop (default-off) + the Agent-tool `name` spawn defect
Additive. Every new research mechanism ships **inert**: `VOYAGE_STORM_ENABLED` is
unset by default, and with it unset both new `/trekresearch` phases are no-ops.
The one change that affects consumers regardless of flags is the spawn rule under
*Fixed* — it changes how any repo should call the Agent tool.
### STORM bounded loop — shipped, default-off, behind a pre-registered adoption gate
- `/trekresearch` Phase 4.5 (dimension discovery, under the existing
`maxDimensions: 8` ceiling) and Phase 5 (bounded multi-turn follow-up,
replacing the single follow-up pass) run only at `effort: high` **and** only
when `VOYAGE_STORM_ENABLED=1`. Unset, Phase 5 is inert because
`lib/util/research-loop-cap.mjs` grants a budget of 0, and Phase 4.5 is inert
because its skip-guard reads the flag directly (it never calls the cap) — two
independent off-switches, so a bug in one does not silently activate the other.
- `TREKRESEARCH_MAX_CONV_TURNS` (default `3`; invalid values fall back to `3`)
sets turns per dimension. The total budget is that value × `maxDimensions`.
- New `lib/util/research-loop-cap.mjs`: an append-only ledger the cap counts its
own turns from. Each turn slot is claimed with `O_EXCL`, so the bound survives
concurrent turns; an unreadable ledger **fails closed** in both modules; and
the enforcement boundary is a denial tombstone rather than the turn count, so
a crash mid-turn cannot hand back a free turn.
- New `hooks/scripts/pre-agent-cap.mjs`, registered as a `PreToolUse` hook on
`WebSearch|WebFetch|Task`: the budget is enforced by the harness, not by prose
in a command file. `VOYAGE_DISABLE_CAP_HOOK=1` switches it off.
`docs/spike-pretooluse-subagent-reach.md` records the measured reach of
`PreToolUse` into sub-agent tool calls — including where the gap is.
- Five measurement fields (`unique_sources`, `dimensions_baseline`, `conv_turns`,
`empty_turns`, `dimensions_baseline_preserved`) are emitted to
`trekresearch-stats.jsonl` and allowlisted in `lib/exporters/field-allowlist.mjs`.
All five are counters or booleans — none carry prose or paths.
- `scripts/storm-measure.mjs` + `docs/storm-measurement.md`: the adoption gate,
with thresholds registered **before** the first measurement by design.
≥ 30 % improvement on either metric → adopt; < 15 % → decline; an empty arm is
`insufficient-data`, not a decline. Decline is a no-op — the mechanism simply
stays default-off; adopt is one constant. No measurement has been run yet.
### Added — outbound query privacy gate
- `lib/validators/query-privacy-gate.mjs` inspects a research query before it
leaves the machine, in the same two-tier shape as the existing SSRF gate: a
WARN tier (absolute filesystem paths, repo-internal identifiers) that
`--soft` / `VOYAGE_QUERY_PRIVACY_ALLOW=1` can override, and a HARD-BLOCK tier
(secret-shaped tokens) that **nothing** overrides. Called only from the two new
high-effort steps; the existing single-pass path is unchanged.
### Fixed — the Agent tool's `name` parameter silently breaks a subagent's return channel
- **Consumers of this pipeline should read `docs/agent-return-channel-defect.md`.**
Passing `name` to the Agent tool does not label a subagent — it changes what is
spawned: `taskKind: "in_process_teammate"` / `spawnDepth: 0` instead of a real
subagent (`spawnDepth: 1`). A teammate's final text is not a return value; it
reaches the parent only if the teammate itself calls `SendMessage(to: "main")`.
Voyage's reviewer agents carry `tools: [Read, Glob, Grep]` — no `SendMessage`
so when named they are *structurally* unable to answer. No error, no warning.
Measured numerators (66-line target): named without explicit `SendMessage`
**0/5** returned · named + explicit `SendMessage` **1/1** · unnamed **3/3** ·
work actually performed while named **5/5** — only delivery fails, and the
output is recoverable from
`~/.claude/projects/<project>/<session>/subagents/agent-*.jsonl`.
Independently confirmed at 3730 lines / 277 KB by `akashic-intelligence`
(4/4 correct final text on disk); the *returning* arm above 66 lines remains
inferred rather than observed, and the doc says so.
- The four spawning commands (`trekbrief`, `trekplan`, `trekresearch`,
`trekreview`) now state the rule at their spawn sites and name the mechanism.
`trekexecute` spawns nothing and is excluded. The `doc-consistency` test
**derives** the spawning set from the command files, so the pin cannot go
vacuous when a command starts or stops spawning.
### Fixed — hook and validator hardening
- The destructive-command rule anchored on command position rather than any
substring (a path containing a blocked word no longer trips it), and the
bypasses that anchoring itself opened are closed.
- The secret-detection validator hard-blocks token formats the run-length
patterns missed.
- The exporter allowlist covers `/trekresearch`'s `engine` field, with the JSONL
schema fixture pinned to agree — a new stats field is otherwise dropped
silently at export.
### Docs
- README: first screen aligned with the org repo standard, complete AI
disclosure, and the Gemini MCP tool contract described inline instead of via a
dead cookbook link. Governance keeps one canonical file, not a local copy.
- `/trekresearch`: STORM mechanisms documented across four surfaces; the
Independence crossing's two risks split, each naming its own control.
- `docs/*.pdf` is gitignored — `origin` is a public mirror and must never carry
operator PDFs.
### Tests
- Suite baseline 832 (830 pass / 0 fail / 2 skip) → **1013 (1011 / 0 / 2)**.
New coverage: research-loop-cap (including the concurrency and fail-closed
paths), the cap hook's crash-time marker branches, the query privacy gate, the
measurement harness's decision rule, and the spawn-rule doc pin.
## v5.9.1 — 2026-07-03 — Fix /trekendsession load-time crash (eager-exec placeholders)
Patch, no functional additions.

View file

@ -2,7 +2,7 @@
Contract-driven Claude Code pipeline: brief, research, plan, execute, review. Agent swarms, research triangulation, adversarial review, multi-session resumption.
![Version](https://img.shields.io/badge/version-5.9.1-blue)
![Version](https://img.shields.io/badge/version-5.10.0-blue)
![License](https://img.shields.io/badge/license-MIT-green)
![Platform](https://img.shields.io/badge/platform-Claude%20Code-purple)

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "voyage",
"version": "5.9.1",
"version": "5.10.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "voyage",
"version": "5.9.1",
"version": "5.10.0",
"license": "MIT",
"engines": {
"node": ">=18"

View file

@ -1,6 +1,6 @@
{
"name": "voyage",
"version": "5.9.1",
"version": "5.10.0",
"description": "Voyage — brief, research, plan, execute, review, continue. Contract-driven Claude Code pipeline. /trekbrief, /trekplan, and /trekreview each end by building a self-contained operator-annotation HTML (scripts/annotate.mjs, modelled on claude-code-100x): select text or click any heading/paragraph/list-item, pick intent (Fiks/Endre/Spørsmål), write comment, copy structured prompt, paste back, Claude revises the .md.",
"type": "module",
"engines": {