# Changelog 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.9.0 — 2026-07-02 — Fable model tier + deep-research engine Additive, plus one behavior alignment: profile `phase_models` now reach sub-agent spawn sites (previously documented but never wired), and the seven command orchestrators no longer pin `model: opus` — frontmatter omits `model:`, so the orchestrator follows the session model. ### Fable model tier - `fable` (→ Claude Fable 5, Mythos-class, positioned above Opus) is an accepted model value throughout the validation chain: `BASE_ALLOWED_MODELS` widened to `['sonnet', 'opus', 'fable']` in `lib/validators/profile-validator.mjs` — the single source imported by brief-validator and phase-signal-resolver (two-layer gate preserved; accept-fable AND reject-unknown-model covered at both layers). No env gate — haiku's `VOYAGE_ALLOW_HAIKU` opt-in stays as-is. - `/trekbrief` Phase 3.5 tier loop offers a 4th option: `fable → {effort: high, model: fable}`. AskUserQuestion's 4-option maximum is now fully used — a 5th tier requires a loop redesign. The fable tier reuses `effort: high` orchestration semantics; `EFFORT_LEVELS` is unchanged. - New built-in profile `lib/profiles/fable.yaml` (all six phases on `fable`, modeled on premium; registered in `BUILTIN_NAMES` with a `loadProfile('fable')` canary test so a registry regression fails loudly instead of silently resolving premium). Premium stays the default. - Reasoning effort is inherited from the session: Fable 5's default effort is `high`, NOT xhigh, and switching model resets effort — set xhigh at session level (`/effort xhigh`, the `effortLevel` setting, or `CLAUDE_CODE_EFFORT_LEVEL`). Documented canonically in `docs/profiles.md` §Model & effort axes. - `claude-fable-5` added to the cost `PRICE_TABLE` ($10/MTok input, $50/MTok output; cache write 5m $12.50 / 1h $20; cache read $1 — verified 2026-07-02 against the official platform pricing docs). `PRICE_TABLE_VERSION` bumped to `2026-07-02`. Without the entry, every fable run would report `cost_usd: null` in the observability export. - Profile tables + allowlist prose updated across README, `docs/profiles.md`, `docs/operations.md`, `docs/HANDOVER-CONTRACTS.md`, `docs/architecture.md`, `docs/command-modes.md`, templates, and CLAUDE.md; the S15 doc pins now machine-check the fable row cell-for-cell against `fable.yaml`. The `^(opus|sonnet)…` regex claim in two docs was corrected — validation is an exact string match against `BASE_ALLOWED_MODELS`; the regex never existed in code. ### Behavior alignment: profile `phase_models` now reach sub-agent spawns - Pre-existing wiring gap (found in exploration): all four pipeline commands invoked only the brief-only `phase-signal-resolver.mjs`, so the `?? profile.phase_models[]` half of the documented composition rule never executed — `--profile ` never reached sub-agent spawns. - Fixed with a single composed resolver: `resolver.mjs --resolve-phase-model` now returns `{effort, model, source}` (brief > profile > default, with effort passed through atomically) and is the one CLI the four pipeline commands invoke. A doc-consistency pin requires the composed invocation and forbids the brief-only CLI in command Bash blocks. - **Behavior change (contract alignment):** `--profile economy/balanced` now genuinely reaches sub-agent spawn sites for the first time — behavior aligns with what the docs have long claimed. The premium default is unaffected in practice (premium resolves `opus`, which equals the frontmatter fallback). - Command frontmatter: the `model: opus` line is DELETED from all seven commands — omission (not the disputed `inherit` literal) is the spelling both official surfaces document as session-inheritance, guarded by a frontmatter-absence doc pin. Accepted tradeoff: in a sonnet session the orchestrator runs on sonnet; re-add a frontmatter pin for deterministic orchestrator choice. The 24 `agents/*.md` `model: opus` pins are untouched (spawn-time injection wins; frontmatter is the fallback). `/trekcontinue`/`/trekendsession` spawn no exploration swarm and get no spawn-site injection; the continue phase is covered at resolver level and follows the session model. ### Bundled unreleased work (since v5.8.0) - `/trekresearch --engine {swarm|deep-research}` (`581489a..9374820`): opt-in delegation of the external research phase to Claude Code's built-in `/deep-research` workflow, with in-context adapter + self-check, availability fallback to swarm (never hard-fails), and doc-consistency pins across surfaces. - brief-validator CLI no-flag invocation fix (`926b768`). - Deep-research engine research notes + docs (`60e9e7a`, `9d8e043`). ### Operator + consume-side notes - The operator-global CLAUDE.md policy "Opus 4.8 default for all subagents" predates the fable tier; updating it is an operator action outside this repo. - `/plugin update` compares against a stale local marketplace clone and can report "already at the latest version" after this release (Claude Code issues #35752 / #38271, both closed-not-planned). Reliable refresh: remove + re-add the marketplace, or `git pull --ff-only` in the marketplace clone. Cross-version skew consequence: a stale cached v5.8 brief-validator REJECTS fable-bearing briefs with `BRIEF_INVALID_MODEL` — enum widening is safe for new readers of old data, not old readers of new data. - Org `availableModels` with `enforceAvailableModels: true` can make an inheriting orchestrator silently fall back to the first allowed model. ### Release hygiene - Suite (measured with bare `npm test` at release): **828 (826 pass / 0 fail / 2 skipped)** — +17 over the pre-release ground-truth baseline of 811 measured 2026-07-02 (allowlist/gate coverage, fable profile pins, composed-resolver + frontmatter-absence doc pins, PRICE_TABLE case). - Version sync: `plugin.json`, `package.json`, `package-lock.json`, README badge, CHANGELOG top entry all at `5.9.0`, guarded by `doc-consistency.test.mjs`. ## v5.8.0 — 2026-06-30 — offline gold-scored output eval (SKAL-1·4b) Additive — no behavior change, no breaking change. Internal eval infrastructure only (`lib/` + `tests/` + docs); no command, agent, profile, or Handover contract touched. ### Gold-scored output eval (SKAL-1·4b) - The review-coordinator self-eval gains its **scoring run**, building on the deterministic coordinator contract + golden corpus shipped as the 4a foundation in v5.7.0. - `lib/review/gold-scorer.mjs`: `scoreFindings(runFindings, goldFindings)` matches at **`(file, rule_key)` granularity** (line + severity deliberately ignored) → `{ tp, fp, fn, precision, recall, f1, matched, missed, spurious }`; `scoreVerdict` checks exact verdict match. Pure — no I/O, no LLM, no network. Vacuous-set conventions (empty run → recall 0; empty gold → precision 0; f1 collapses to 0) are documented in the module header. - `tests/fixtures/bakeoff-rich/runs/run-perfect.json`: the first **committed run** — reviewer payloads that, fed through `runContract`, reproduce all 5 seeded gold findings. The regression guard: any future contract change that silently suppresses or skips a seeded finding breaks the eval. - `tests/lib/gold-eval.test.mjs`: the **scoring run**, wired into `node --test`. Asserts `run-perfect` scores precision/recall/f1 = 1.0 and `verdict == expected_verdict` (BLOCK). Offline: committed payloads, no live agent spawn (the LLM-in-the-loop grading is the separate 4c tier). - **Third test-census category.** `lib/util/test-census.mjs` now reports a `goldEval` bucket (matched by `GOLD_EVAL_FILE_RE`) separately from `behavior` and `docPins` — a scoring run is neither behavior coverage nor a prose pin, so the honest-count invariant is a 3-way sum. - `docs/eval-corpus/README.md`: SKAL-1·4b moved from "Future hardening" to an implemented section documenting the scorer, run format, and census category. - Suite: **822 (820 pass / 0 fail / 2 skip)**, up from 809 (+10 scorer behavior tests, +3 eval scoring-run tests). The scorer test covers the discriminating paths (false negatives + false positives) and the degenerate empty-run / empty-gold cases, not merely the all-match case. - Version sync: `plugin.json`, `package.json`, `package-lock.json`, README badge, CHANGELOG top entry all at `5.8.0`, guarded by `doc-consistency.test.mjs`. ## v5.7.1 — 2026-06-29 — relocate agent `` blocks to body (always-loaded token trim) Performance/packaging change — no behavior change, no breaking change. (M4) ### Always-loaded token trim - The 17 example-bearing agents each carried two `` blocks (34 total) inside their `description:` frontmatter. voyage launches its agents **by name** from the orchestrator commands, so those auto-selection examples were paying a per-turn token tax for a path the pipeline never uses. They are now relocated **verbatim** into each agent's body under a `## When to use — examples` section — preserved, not deleted. - Frontmatter `description` chars across all 24 agents: **17,672 → 4,945** — roughly **3,180 fewer always-loaded tokens per turn** for every session with voyage enabled. The 7 zero-example agents are untouched; no system prompt, tools, model, or `name` changed. - New invariant test in `tests/lib/agent-frontmatter.test.mjs`: no `` in any frontmatter `description`, and ≥ 34 `` retained across agent bodies (relocation moves, never deletes). Suite: **807 pass / 0 fail / 2 skip**. - **The saving only reaches a machine after `/plugin marketplace update` + reload** — the delta is not instant on the machine that ships the release. - Version sync: `plugin.json`, `package.json`, `package-lock.json`, README badge, CHANGELOG top entry all at `5.7.1`, guarded by `doc-consistency.test.mjs`. ## v5.7.0 — 2026-06-26 — opt-in token/cost metering (SKAL-2) + eval foundation (SKAL-1·4a) Additive — no breaking change. Two unreleased work-streams land together. ### Opt-in token/cost metering (SKAL-2) — the headline - Pure token-usage parser + cache-aware USD cost (`lib/stats/token-usage.mjs`): parses MAIN-CONTEXT usage from the transcript, dedups by requestId (last-wins, streaming-placeholder mitigation), excludes sidechain records, and REFUSES to estimate (`cost_usd:null, is_estimate:true`) for models absent from the frozen PRICE_TABLE. - CWE-212 export boundary: token-usage schema allowlist in the OTLP exporter; `session_id`/`transcript_path`/`cwd` stripped at export, asserted both ways. - Cross-session aggregation in `cache-analyzer` (total tokens + cost). - Capture folded into the EXISTING `otel-export.mjs` Stop hook, gated behind the `VOYAGE_TOKEN_METER` env var (default off), fail-open. v1 scope = main-context only; sub-agent turns are a documented v2 follow-on. ### Eval foundation (SKAL-1·4a) - `gold.json` golden corpus + loader/validator; review-coordinator contract reference impl + deterministic test; two-sided gate coverage for the `BRIEF_*` BLOCKERs; eval-corpus frozen-failure home. ### Release hygiene - Version sync: `plugin.json`, `package.json`, `package-lock.json`, README badge, CHANGELOG top entry all at `5.7.0`, guarded by `doc-consistency.test.mjs`. - Canonical `node --test`: **807** (805 pass / 0 fail / 2 skipped). ## v5.6.1 — 2026-06-24 — leaner always-loaded agent listing (reference/dormant agent descriptions trimmed) Additive — no breaking change, **no runtime behavior change**. Trims the always-loaded token cost of the agent listing that Claude Code injects into every session. ### Reference/dormant agents now carry one-line descriptions - **The 3 `*-orchestrator` reference docs** (`planning-/research-/review-orchestrator`) and the **dormant `synthesis-agent`** carried multi-paragraph `description:` frontmatter (full rationale + CC-2.1.172 history + a usage example) that Claude Code injects into every session — despite none of them being spawnable from the live `/trek*` pipeline. Their `description:` is now a single line; the full rationale already lives, and remains, in each file's body. **~700 tokens trimmed** from the always-loaded agent listing, no capability change. - The three orchestrators retain the self-declaration **"reference document, not a spawnable capability"** (pinned by `doc-consistency.test.mjs`); `synthesis-agent` retains its **DORMANT / not-wired** flag and the `docs/T1-synthesis-poc-results.md` pointer. - Surfaced via dogfooding with `config-audit`'s always-loaded token audit. Canonical `node --test`: **754 pass, 0 fail** (756 total, 2 skipped); the agent-inventory + frontmatter pins stay green. ### Version sync - `plugin.json`, `package.json`, `package-lock.json`, the README badge, and the CHANGELOG top entry all at `5.6.1`, guarded by the version-consistency test in `tests/lib/doc-consistency.test.mjs`. ## v5.6.0 — 2026-06-20 — `/trekexecute` loop hardening: machine-verifiable completion + bounded recovery Additive — no breaking change. Hardens the `/trekexecute` execution loop so termination is *machine-verifiable* and recovery is *bounded by an explicit budget*, closing the "runs forever" and "declares done without proof" failure modes. Five focused changes; canonical `node --test` 744 → **756** (0 fail). ### Machine-verifiable completion gate (the headline) - **Stop-signal contract** — `/trekexecute` reports `completed` only when a machine-checkable contract holds: the Phase 7.5 manifest audit PASSes, the stop signal exits 0, and the success criteria are green. **Hard Rule 18** is promoted from prose guidance to an enforced gate, anchored in the Phase 7.5 audit rather than the model's self-assessment. ### Bounded recovery — cap hierarchy + global budget - **`TREKEXECUTE_MAX_RECOVERY_ITERATIONS`** — a global recovery-iteration budget (default **25**, env-overridable) sits above the per-step caps as a three-axis cap hierarchy (recovery depth · per-step retry · global budget), codified as **Hard Rule 20**. Stops an unbounded recover→retry→recover spiral that the per-step caps alone could not bound. - **`iterations_remaining` signal** — surfaced in the progress schema and the summary JSON, with a deterministic gate cross-check (`iterations_remaining == cap − (recovery_depth + Σ attempts-beyond-first)`) that catches a never-decremented counter. Shape-validated in `lib/.../progress-validator.mjs` (`PROGRESS_ITERATIONS_REMAINING_INVALID`: non-negative integer, additive-optional — never required at top level). ### Doc consistency - **Fan-out hedge harmonized** — the `CLAUDE.md` design-principle line is aligned to the measured claim (parallel wall-clock + structured artifact handoffs as the load-bearing benefit; main-context relief stays explicitly *not demonstrated*), with a banned-phrase **forward-guard** in `tests/lib/doc-consistency.test.mjs` so the over-claim cannot reappear. ### Release hygiene - **Version sync** — `plugin.json`, `package.json`, `package-lock.json`, the README badge, and the CHANGELOG top entry all at `5.6.0`, guarded by the version-consistency test in `tests/lib/doc-consistency.test.mjs`. ## v5.5.0 — 2026-06-18 — Coordinated release: brief framing enforcement (2.2) + W1–W3 narrow wins The coordinated release held since the framing work. Supersedes the unreleased internal milestones **v5.2–v5.4** (W2 model/effort alignment, W3 guardrail hardening, the Handover-1 public-contract formalization), landing them together with the `brief_version 2.2` schema badge and the W1 narrow wins. **Additive — no breaking change for existing consumers:** every `2.0`/`2.1` brief still validates; the new requirements gate only on briefs that *declare* `brief_version: "2.2"`. ### Brief framing enforcement — `brief_version 2.2` (the headline) Three version-gated layers ship at `brief_version ≥ 2.2`, implementing the `CLAUDE.md` cross-cutting invariant "brief framing must match operator intent": - **`framing` enum** (`preserve | refine | replace | new-direction`) — required in frontmatter, collected in `/trekbrief` Phase 2.5 *before* any prose is written, non-skippable even in `--quick`. Enum-checked on any version (`BRIEF_INVALID_FRAMING`); missing at ≥ 2.2 → `BRIEF_MISSING_FRAMING`. - **Memory-alignment dimension** — new `brief-reviewer` dimension 6 compares brief Intent/Goal + framing against operator memory, flagging *explicit* contradictions only (scores N/A when no memory is supplied); wired to the Phase 4e gate (`memory_alignment.score ≥ 4`). Emits a `status` field (`verified | n_a | contradictions`) so a score-5 N/A (no memory available) is distinguishable from a score-5 verified-aligned brief — the gate passes in both cases, and `status` is what tells the operator whether the wrong-premise defense actually ran. - **Obligatory `## TL;DR`** — ≤ 5 content lines at the top of every 2.2 brief (soft cap → `BRIEF_TLDR_TOO_LONG`). - **Opt-in version floor** — `--min-brief-version ` on `/trekplan` + `/trekresearch` (forwarded to the validator as `--min-version`) raises a `BRIEF_VERSION_BELOW_MINIMUM` *warning* — never a block — when a brief declares a version below the floor. Closes the producer-elective hole where a `2.0`/`2.1` brief silently sidesteps framing enforcement; `docs/HANDOVER-CONTRACTS.md` §Handover 1 now documents pre-2.2 = zero framing enforcement and the two remedies (require `2.2` upstream, or pass the floor flag). Existing `2.0`/`2.1` briefs stay valid (forward + backward compatible), mirroring the `phase_signals ≥ 2.1` precedent. `trekreview` briefs are exempt. ### Public contract formalization (Handover 1) `docs/HANDOVER-CONTRACTS.md` §Handover 1 (`brief.md` → research) is now labeled **PUBLIC CONTRACT** — the only public integration boundary of the pipeline. Froze `brief_version 2.1` as the baseline, then evolved it to `2.2` under the breaking-change protocol. Any conforming producer (not just `/trekbrief`) may feed Voyage; brief-schema changes are breaking for every downstream consumer. ### Model & effort alignment (W2) - **Opus 4.8 baseline** — the `opus` alias resolves to Opus 4.8 (default reasoning effort `high`). - **Native `effort:` frontmatter** (additive, static) on 8 agents: retrieval (`task-finder`, `git-historian`, `dependency-tracer`, `architecture-mapper`) → `medium`; adversarial-reasoning (`plan-critic`, `risk-assessor`, `contrarian-researcher`, `review-coordinator`) → `high`. The other 15 agents inherit the Opus-4.8 default. - **Resolver model-gate fix** — `lib/profiles/phase-signal-resolver.mjs` now gates `model` against `BASE_ALLOWED_MODELS` (mirrors the existing `effort` gate); out-of-allowlist models are dropped rather than handed to a spawn. - **Axis distinction documented** — `docs/profiles.md` §Model & effort axes separates orchestration `phase_signals.effort` (which agents/passes run) from native reasoning `effort:` (per-spawn budget) — different axes that happen to share the name `effort`. ### Guardrails & hooks hardening (W3) - **Exec-form hooks** (CC-14) — all 7 hooks in `hooks/hooks.json` migrated to `{command:"node", args:["${CLAUDE_PLUGIN_ROOT}/…"]}`, removing a class of path-quoting bugs for consumers who install Voyage under a path containing spaces. - **`disallowed-tools` enforcement** (CC-11) — `disallowed-tools: Agent, TeamCreate` added to `/trekexecute`, promoting its documented no-delegation rule from prose to enforcement (`allowed-tools` grants auto-approval but does not remove a tool from the pool; `disallowed-tools` does). - **Universal safety executors** (CC-15) — `pre-bash-executor.mjs` / `pre-write-executor.mjs` confirmed universal by design (session-agnostic safety; narrowing to execute-only sessions would only weaken protection). ### Narrow wins (W1 — NW1–NW3) - **NW1 — reviewer-output schema contract** (ungated, shipped). `lib/review/findings-schema.mjs` validates each `/trekreview` Phase 5 reviewer's JSON against a schema; on *schema* failure main re-asks for conforming JSON (bounded N=2), retiring the fragile "collect trailing JSON / re-ask on parse error" contract. - **NW2 — trekreview Workflow port as opt-in `--workflow` flag.** Phase 5–6 (`parallel([conformance, correctness])` → plain-JS dedup-by-`(file,line,rule_key)` → `agent(coordinator)`) ported to a Workflow script, reachable via `--workflow` (default stays prose, preserving the 2.1.154+ portability floor). Bake-off verdict **opt-in-defensible** (POSITIVE on the measured axes — fidelity-equivalent `review.md`, zero classifier interference at 9-agent concurrency, ≈ +4.4% tokens — but on a single un-archived run: the raw per-run data was never committed, so the numbers cannot be re-derived; see `docs/T2-bakeoff-results.md` §Reproducibility caveat). - **NW3 — synthesis-agent shipped dormant (declined per measurement).** Built + measured deterministically: Δ main-context = **0%** at all realistic BASE — delegating only trekplan Phase 7 evicts nothing, since the Phase-5 foreground reads make the outputs resident first. Not wired; re-measurement is cheap via `scripts/synthesis-measure.mjs`. See `docs/T1-synthesis-poc-results.md`. ### CC 2.1.130→181 verification dispositions - **Verified clean (no regression):** CC-29 (`subagent_type` matching now case/separator-insensitive; no Voyage agent declares multiple `Agent(...)` types), CC-31 (the tightened background worktree-isolation guard aligns with Voyage's intent — `/trekplan` `TeamCreate isolation:"worktree"` with sequential fallback, `/trekexecute` Phase 2.6 worktree waves). - **CC-08 — GH #36071 (hooks in headless `claude -p`) closed as NOT PLANNED, not fixed.** The in-prompt safety preamble is retained as the headless defense. - **Deferred (recorded, no code):** CC-07 (`fallbackModel`), CC-12 (Stop/SubagentStop `additionalContext`), CC-13 (`background_tasks`/`session_crons` in hook input). Triggers noted in `docs/cc-upgrade-2.1.181-decision-matrix.md` §S13. ### Release hygiene - **Version sync** — `plugin.json`, `package.json`, README badge, and the CHANGELOG top entry all at `5.5.0`, guarded by a new version-consistency test in `tests/lib/doc-consistency.test.mjs`. - **Honest test count (S19)** — `lib/util/test-census.mjs` + `tests/lib/test-census.test.mjs` report the behavior-test count separately from the doc-consistency prose-pin count, so the cited total no longer oversells behavior coverage. Pruned 3 redundant/tautological prose-pins from `doc-consistency.test.mjs` (each provably subsumed by a structural invariant or behavior test). Devil's-advocate audit §Top changes #8. - **`claude plugin validate` passes.** The single advisory warning (root `CLAUDE.md` not loaded as consumer project context) is **accepted by design**: it is universal across all marketplace plugins, validation still passes, and the root `CLAUDE.md` is repo/maintainer context — consumer context ships via README + command/agent frontmatter. ## v5.1.1 — 2026-05-14 — Remediation patch (11/12 review findings closed) Additive. No breaking changes against v5.1.0. Closes 11 of 12 BLOCKER/MAJOR/MINOR findings from the v5.1.0 review (sesjon 5, review.md SHA range `8cbb33e..8f4b79c`). SC8 dogfood gate (#5) is scheduled for sesjon 8 as a fresh-CC-session operator action — its closure cannot happen inside the v5.1.1 execute session. ### Bug fixes (load-bearing) - **#8 YAML-number bypass closed.** `lib/validators/brief-validator.mjs` now coerces `brief_version` to string before comparison; both `brief_version: 2.1` (parsed as Number) and `brief_version: "2.1"` (parsed as String) trigger the v5.1+ sequencing gate. Previously the unquoted form silently bypassed the gate. Three regression tests added in `tests/validators/brief-validator.test.mjs`. - **#11 Doc-consistency pin lock-in.** `tests/lib/doc-consistency.test.mjs` pins `templates/trekbrief-template.md` to emit `brief_version: "2.1"` (quoted) so future template edits can't reintroduce the bypass. ### Wiring (closes #9 + #12) - **`lib/profiles/phase-signal-resolver.mjs` helper** (new). Reads `brief.phase_signals` (or `phase_signals_partial`) and the active profile's `phase_models`, returns the resolved `{effort, model, source}` per phase. Composition rule: brief signal wins per-phase, profile fills gaps. The resolver controls only the orchestrator and the model parameter at `Agent`-spawn sites — sub-agents otherwise read `model:` from their own `agents/*.md` frontmatter (still pinned to `opus`). - **4 downstream commands wired.** `/trekplan`, `/trekresearch`, `/trekreview`, `/trekexecute` each invoke the resolver in their Phase 1 (or equivalent first-phase block), capture the result as `phase_signal_result`, and pass it to `Agent` tool calls explicitly. Per-command low-effort code-paths reuse existing `--quick`-equivalent logic. - **`resolvePhaseModel` orchestrator-override added** (#9 part A). Profile-tier model picks are overridden when `brief.phase_signals[].model` is set. Non-interference verified by new test `tests/lib/profile-resolver.test.mjs` (Step 7 TDD pair, Red→Green). - **`brief-validator --soft` gate required uniformly** in `/trekresearch` + `/trekexecute` (previously only `/trekplan` + `/trekreview`). `BRIEF_V51_MISSING_SIGNALS` halts all 4 commands with a clear hint pointing back to `/trekbrief`. ### Test refactor (closes #1 #2 #3 #4 #6 #7 #10) - **Runtime SC1 walk for `tests/commands/trekbrief.test.mjs`** (#1). Replaces prose-grep with `resolvePhaseSignal` invariant: returns non-null for all 4 entries in `PHASE_SIGNAL_PHASES` when applied to a fixture brief with a committed `phase_signals` block; returns gate-fire when applied to a v2.1 brief missing the block. - **Per-tier resolver-output + missing-signals falsification** (#2 #3 #6 #10). `tests/commands/trekplan.test.mjs`, `trekresearch.test.mjs`, `trekreview.test.mjs`, `trekexecute.test.mjs` each refactored from doc-pin pattern to runtime assertion against 4 new fixture briefs (`tests/fixtures/briefs/{low,standard,high,partial}.md`). - **Dedicated SC5 profile-resolver non-interference test** (#7). `tests/lib/profile-resolver.test.mjs` asserts that brief-emitted signals are not overridden by `VOYAGE_PROFILE`, and that `--profile` does not silently override brief-emitted answers. - **#4 SC5 invariant** locked at resolver level rather than test-strategy level (no scope expansion — see `source_findings` audit trail in plan.md frontmatter). - **Total test delta:** +12 tests (539 baseline + 12 + 4 doc-pins from Step 10 = 555 expected; actual 578 because the existing tests grew underneath us during the v5.1.0→v5.1.1 cycle). 0 fail, 2 skipped. ### Documentation (closes #5 scheduling + Decision B high-effort) - **#5 SC8 dogfood scheduling.** `REMEMBER.md` (gitignored) gains a `## v5.1.1 sesjon 8 — DOGFOOD GATE OBSERVATIONS` reserved placeholder with concrete procedure: fresh CC-session → real v5.1-eligible task → Phase 3.5 observation → 5 specific questions to answer. The actual observation is a sesjon 8 manual operator action; sesjon 7 produces scaffolding only. - **Decision B high-effort behavior locked per command** (operator-confirmed, decisions.local.json): - `/trekplan` high: gemini-bridge plan-review Pass 2 on the post-revision plan (replaces fragile plan-critic doubling per risk-assessor finding — line numbers shift after revisions, breaking dedup triplets). - `/trekresearch` high: full swarm + `contrarian-researcher` AND `gemini-bridge` always-on regardless of normal triggering rules. - `/trekreview` high: skip Pass 3 reasonableness filter; coordinator applies `PLAN_EXECUTE_DRIFT` normalization for unknown rule_keys (preserves original in `original_rule_key`). - `/trekexecute` high: `gates_mode = 'closed'` automatically; explicit `--gates` flag still wins. - **Brief Non-Goal amendment** (`.claude/projects/2026-05-13-trekflow-solo-lane/brief.md`, gitignored): low/high effort tiers now locked in v5.1.1; standard remains fallthrough default. Continue + brief phases remain effort-less. - **Brief SC1 amendment** (same file, gitignored): SC1 "4 AskUserQuestion calls" interpreted as the resolver-invariant `resolvePhaseSignal` returns non-null for all 4 entries in `PHASE_SIGNAL_PHASES`. The literal AskUserQuestion mocking interpretation would require a state-machine harness module (significant scope expansion); the resolver-invariant interpretation is authorized as equivalent. **Operator-confirmed via Pre-Step-10 autonomy gate.** ### Known scheduling SC8 (#5) dogfood-gate closure happens in sesjon 8 (fresh CC-session, manual `/trekbrief` walk-through). v5.1.1 push to Forgejo gated on sesjon 9 `/trekreview` returning `ALLOW`. If sesjon 9 returns `BLOCK`, loop back to sesjon 6 (new remediation plan). ### Source findings audit trail Plan-frontmatter `source_findings:` lists the 12 review-finding IDs each step closes. Audit trail traces `review.md` → `/trekplan --brief review.md` (Handover 6) → `plan.md` → `/trekexecute` → individual commits. ## v5.1.0 — 2026-05-13 — Per-phase effort + model dialog Additive. No breaking changes. Forward-compat with all v5.0.x briefs. ### Why The voyage pipeline runs a single profile-tier setting for every task. For typo fixes and small bugfixes the full `brief → research → plan → execute → review` ceremony is over-engineered; for risky migrations the same profile-tier is too thin. v5.1 hands ceremony-level back to the operator per phase in the same dialog that produces the brief — without removing the disciplined defaults that protect high-stakes work. Independent of v4.1's profile system: composition happens at the command level (brief signal wins per-phase, profile fills gaps). No `/trekflow`, no helper module, no per-command effort dictionary — composition is documented prose in each downstream command. ### Added - **`/trekbrief` Phase 3.5** — between Phase 3 completeness exit and Phase 4 draft, 4 tier-coupled `AskUserQuestion` calls commit an effort level (`low | standard | high`) and an optional `model` (`sonnet | opus`) per downstream phase (`research`, `plan`, `execute`, `review`). Tier mapping: `low → {effort: low, model: sonnet}`, `standard → {effort: standard}` (model omitted; composition falls through to profile), `high → {effort: high, model: opus}`. Force-stop pattern (Phase 4f verbatim) records `phase_signals_partial: true` instead. `--quick` skips Phase 3.5 entirely and auto-writes `phase_signals_partial: true`. - **`brief-validator` extension** — 6 new issue codes: `BRIEF_INVALID_PHASE_SIGNALS`, `BRIEF_INVALID_PHASE_SIGNAL_PHASE`, `BRIEF_INVALID_EFFORT`, `BRIEF_INVALID_MODEL`, `BRIEF_SIGNALS_MUTUALLY_EXCLUSIVE`, `BRIEF_V51_MISSING_SIGNALS` + exported `PHASE_SIGNAL_PHASES` + `EFFORT_LEVELS` constants. The `BASE_ALLOWED_MODELS` const in `lib/validators/profile-validator.mjs` was promoted to `export const` so the brief validator can re-use it. - **HANDOVER-CONTRACTS amendments** — Handover 1 gets 5 inserts: versioning row → `2.1`, two new schema-table rows (`phase_signals`, `phase_signals_partial`), v5.1 sequencing-gate validation row, versioning-paragraph expansion explaining the version-conditional gate, 6 new failure-mode bullets. - **Template bump** — `templates/trekbrief-template.md` → `brief_version 2.1` with a default `phase_signals:` block (4 phases × `effort: standard`, model omitted) and a commented `phase_signals_partial: true` line showing the force-stop alternative. - **Composition rule (v5.1)** — new `## Composition rule (v5.1)` sub-section in each of `commands/{trekplan,trekresearch,trekexecute, trekreview}.md`. Documents `effort_for_phase = brief.phase_signals[ ]?.effort ?? 'standard'` and `model_for_phase = brief.phase_signals[]?.model ?? profile.phase_models[]`. Per command: `effort == low` activates that command's existing `--quick`-equivalent code-path (`/trekplan` skips Phase 5 agent swarm, `/trekresearch` inline research, `/trekreview` correctness-only, `/trekexecute` `--gates open` + sequential-only). - **Sequencing-gate surface** in 4 downstream commands — when `brief-validator.mjs` returns `BRIEF_V51_MISSING_SIGNALS` in `errors`, halt with a one-line user-readable message pointing back to `/trekbrief`. Enforcement is validator-only. - **5 new minimal command test files** under `tests/commands/` — `trekbrief.test.mjs` (3 cases), `trekplan.test.mjs` / `trekresearch.test.mjs` / `trekreview.test.mjs` (2 cases each), `trekexecute.test.mjs` (2 cases). Pattern D (read .md, assert prose patterns). Verifies sequencing-gate surface + low-effort prose. - **5 new doc-consistency pins** — template `brief_version 2.1` + `phase_signals:` block, HANDOVER schema rows, voyage CLAUDE.md + README.md mention `phase_signals`. - **2 new fixtures** — `tests/fixtures/brief-with-phase-signals.md` + `brief-without-phase-signals.md` (backward-compat). ### Changed - `brief_version` bumped `2.0 → 2.1`. The bump exists because v2.1 activates the **version-conditional sequencing gate** — the only check in the brief validator that triggers on `brief_version` rather than field-presence. The forward-compat policy still applies to the field itself (unknown frontmatter keys flow through). ### Notes - Test count grows by ≥ 17 new cases minimum: 6 brief-validator + 11 command-test minimums. Realistic delta is ~25 new cases (Step 6 adds 5 doc-consistency pins on top). Target ≥ 533 pass at Step 10 verify. - `MIGRATION.md` was deliberately NOT created — v5.1 is an additive minor (brief_version 2.0 → 2.1, not major). v5.4 may promote `phase_signals` from optional to required (breaking change → 3.0). - High-effort behaviors for `/trekplan` / `/trekresearch` / `/trekreview` are deferred to v5.1.1 per brief Non-Goal ("No complete per-phase effort dictionary"). v5.1 locks only the low-effort floor. - `phase_signals_present` stats emission is also deferred to v5.1.1 (opt-in observability per Research 03 Q5). ## v5.0.3 — 2026-05-13 — Annotation UX matches the claude-code-100x reference **No new breaking changes beyond v5.0.0.** Forks consuming v5.0.2's annotation HTML keep working — the file path and entry point are unchanged. The internal localStorage key bumps from `voyage-annotate:` to `voyage-annotate:v2:` to avoid mixing the v5.0.2 shape (line-click, freeform notes) with the v5.0.3 shape (intent-tagged annotations). ### Why v5.0.2 shipped a too-simple annotation surface: click a line, write a freeform note, save. The operator pointed at the existing `claude-code-100x/build-site.js` annotation system as the actual reference — pencil-toggle mode, text-selection capture, three intent categories (**Fiks** / **Endre** / **Spørsmål**), a popover form at the cursor, structured markdown export with intent labels. v5.0.3 brings `scripts/annotate.mjs` up to that pattern. This reference had been mentioned by the operator early in the conversation; the iteration through v5.0.0 / v5.0.1 / v5.0.2 reflects me reading past it and trying alternatives instead of just matching it. The loss is real and is documented here in plain terms so future maintainers don't repeat it. ### Changed - **`scripts/annotate.mjs`** — rewritten to match the `claude-code-100x/build-site.js` UX: - **Article rendering** — markdown is rendered to proper HTML elements (`

`/`

`/`

    `/`
  • `/``/`
    `/`
    `), not as
        line-numbered raw lines. Document reads as a normal article.
      - **Annotatable elements** — every heading, paragraph, list item, table
        cell, blockquote, and code block gets a stable `data-anchor-id`.
      - **Pencil-toggle button** in the topbar — annotation mode default ON.
        Toggle OFF to read normally and follow links.
      - **Click any annotatable element** (in mode) → opens a form popover
        at the cursor with: section context (auto-detected from nearest
        h1/h2), anchored snippet (the exact selected substring via
        `window.getSelection()` if any text is highlighted, else the
        element's text content up to 200 chars), three intent buttons
        (**Fiks** / **Endre** / **Spørsmål**), comment textarea, Cancel +
        Save. Save is disabled until an intent is picked.
      - **Sidebar panel** — collapsed by default; "Show annotations" button
        in the topbar opens it. Annotations grouped by section, sorted by
        document order. Each card shows the intent badge (colored by
        category), the anchored snippet, the operator comment, and a delete
        button. Click a card to scroll the article to that element + flash
        highlight.
      - **Copy Prompt** — structured markdown:
        `### N. [Intent] Section: 
    ` + `Quote: «»` + `Comment: `. Copies to clipboard. - **Clear all** — wipes every annotation for the current artifact (after confirm). - **Persistence** — `localStorage` key `voyage-annotate:v2:`. Refresh/close/reopen the same HTML keeps every annotation. - **Toast feedback** for save / copy / clear. - **`tests/scripts/annotate.test.mjs`** — refreshed for the v5.0.3 shape: pins the three intent buttons (`data-intent="fiks"` / `"endre"` / `"spørsmål"`), form popover, selection capture, section auto-detect, `voyage-annotate:v2:` storage key prefix, `data-anchor-id` coverage, Copy Prompt + Clear all affordances, and the markdown renderer's heading / list / table / blockquote / code-fence output. 12 tests (up from 10), all passing. ### Notes - The producing commands (`/trekbrief` Step 4g, `/trekplan` Phase 10, `/trekreview` Phase 8) call `scripts/annotate.mjs` the same way as in v5.0.2 — no change to their wiring beyond the build-output now being the v5.0.3 interactive surface. - `npm test`: 518 tests, 516 pass, 0 fail, 2 skipped (up from 516 — 2 new annotate tests for hostile-content escape + renderMarkdown table/ blockquote coverage). - Reference: `~/repos/claude-code-100x/claude-code-100x/build-site.js` lines 1431–2255 (annotation UI section). - Version bump 5.0.2 → 5.0.3 in `.claude-plugin/plugin.json`, `package.json`, `package-lock.json`, plugin `README.md` badge. ## v5.0.2 — 2026-05-13 — Operator-driven annotation HTML (the actual fix) **No new breaking changes beyond v5.0.0.** Forks that consumed the v5.0.1 `/playground document-critique` invocation from the producing commands' final report should switch to opening the `.html` that `scripts/annotate.mjs` now produces directly. ### Why v5.0.0 added a read-only `scripts/render-artifact.mjs` HTML render that didn't afford annotation. v5.0.1 deleted that and pointed operators at `/playground document-critique` instead — but the `document-critique` template pre-generates **Claude's** suggestions and asks the operator to approve/reject them. The operator asked for the opposite: a surface where **they** select content and write **their own** notes, then ship those notes back to Claude. v5.0.1 still missed the actual ask. v5.0.2 ships `scripts/annotate.mjs` — a small, focused, zero-dependency Node script that takes any artifact `.md` and writes a self-contained HTML next to it. The HTML renders the document with line numbers, lets the operator click any line to attach their own note, keeps a sidebar of all notes (editable + deletable, persisted in `localStorage` per artifact path so refresh doesn't lose work), and exposes a "Copy Prompt" button that gathers every note into one structured prompt. The operator copies that prompt and pastes it back into Claude; Claude revises the `.md` freehand from the notes. **One file → one HTML → click + write notes → copy prompt → paste back.** No Claude-generated suggestions in the loop. The operator drives every annotation. This is the v4.2/v4.3 *concept* (operator-driven annotation) without the broken v4.2/v4.3 UX, without the 388 KB SPA, without `/trekrevise`, without anchor parsers + Handover 8 + the JSON batch round-trip. ~430 lines of self-contained `.mjs`. Zero npm deps. Deterministic. ### Added - **`scripts/annotate.mjs`** — operator-annotation HTML generator. Takes ``, writes `.html` (or `--out `). Self-contained, design-system-aligned (light + dark + print), zero external network, deterministic. CLI: `node scripts/annotate.mjs [--out ]`. Also `npm run annotate -- `. - **`tests/scripts/annotate.test.mjs`** (10 tests) — self-contained HTML shape, no external ``/`