# 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.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 ``/`