feat(execute): one fresh helper per step, a controller on the diff, proof by command

/trekexecute no longer builds steps itself. Each plan step is built by one
fresh helper (new agent step-implementer: opus, effort high, no Agent tool)
and judged by one controller (a general helper on opus) that reads the
diff from a recorded start_sha and gives two verdicts, spec and quality.
Fix rounds go up, maximum 5: three fixes by a fresh helper, then back to
the plan, then to the operator. No cheaper-model ladder.

Proof is a command, never the model's word:
- lib/verification/red-proof.mjs: the step's test must fail at the start
  point and pass at the result (exit 0/1/2; 2 is never green). Reproduces
  the 02243c6 red-first measurement (6 of 55) through the shim fixture.
- lib/verification/test-integrity.mjs: the floor guard on the diff
  (removed asserts, skipped/deleted tests, muted checks, stubs, loosened
  thresholds). Over the last 150 commits: 149 clean, 1 real finding.
- lib/verification/done-line.mjs: DONE step N only when the test command
  exits 0.

Test first is required from plan_version 1.8. The test lock (K8) is used
through its CLI and reported as not-locked while it is missing. A run
stops only on a closed list of four classes; every other call goes into a
decision log with its cost if wrong. Without a passing run-the-thing
criterion the result is not verified end to end, never green.

Handover 5 gains optional per-step start_sha, report_path, red_proof,
test_lock, fix_rounds (0-5) and run-level decisions and end_to_end; old
progress files still validate and resume.

No isolation on the helper: measured, a worktree-isolated subagent
branches from the default branch (02f320f), not the executor's HEAD
(2c89a6b), so it would miss the earlier steps.

Borrowings credited in commands/trekexecute.md ## Credits (Superpowers,
ai-native-sdlc, Kiro, GitHub Spec Kit, agent-skills, Cherny).

Tests: 1411 -> 1457 (1455 pass, 0 fail, 2 skipped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-06 19:58:18 +02:00
commit abc3083c1e
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
28 changed files with 2052 additions and 103 deletions

View file

@ -296,7 +296,25 @@ Exploration uses 6–8 agents in parallel (architecture-mapper, dependency-trace
Reads a plan from `/trekplan` and implements it with strict discipline. No guessing, no improvising — follows the plan exactly.
Per step: apply Changes exactly as written → run Verify (exit code is truth) → manifest audit (expected paths, forbidden paths, commit pattern) → follow the plan's failure clause if anything fails (revert / retry / skip / escalate) → Checkpoint commit. After all steps: independent Phase 7.5 manifest audit from git log + filesystem (ignoring agent bookkeeping); drift triggers Phase 7.6 bounded recovery.
Per step: record the start point → **one fresh helper** (`step-implementer`) writes the step's test first, proves it red, locks it, then applies Changes exactly as written → the executor proves it by command: **red at the start point, green at the result** (`red-proof.mjs`), Verify (exit code is truth), manifest audit, and the **floor guard** on the diff (`test-integrity.mjs`: removed asserts, skipped or deleted tests, muted checks, stubs, loosened thresholds) → **one controller** reads the diff — never the helper's summary — and gives two verdicts, *spec* and *quality* → a script writes the step's **done line** only when the test command exits 0 (`done-line.mjs`) → Checkpoint commit. After all steps: independent Phase 7.5 manifest audit from git log + filesystem (ignoring agent bookkeeping); drift triggers Phase 7.6 bounded recovery. A plan with no passing run-the-thing criterion ends **not verified end to end**, never green.
### The step loop
| Part | What it does | Why |
|------|--------------|-----|
| Fresh helper per step | `voyage:step-implementer` (opus, effort high, no Agent tool) builds one step and writes a report: **ran · saw · did NOT check** | Each step starts from the repository and the plan, not from a long context |
| Start point | `start_sha` recorded before the step; every check reads `git diff {start_sha}` | The review package is the diff, not a story |
| Proof of red | the step's test must fail at the start point and pass at the result — run by `red-proof.mjs`, not claimed | A test that passes without the change proves nothing |
| Test lock | the helper locks its test files after the red proof (`test-lock.mjs`, when installed; otherwise "not-locked" is reported) | The code moves to meet the test, never the reverse |
| Floor guard | `test-integrity.mjs` reads the diff for weakened tests; exit 2 ("could not run") is never green | Cheating the tests is caught by a command |
| Controller | one general helper, two verdicts (spec, quality), re-checks only what a fix round changed | An independent judge of the diff |
| Done line | `done-line.mjs` appends `DONE step N` only when the test command exits 0 | "Done" is an exit code |
The helper works in your working tree, not in a worktree of its own: measured 2026-10-06, a worktree-isolated subagent branches from the default branch rather than your `HEAD`, so it would not see the earlier steps (only the operator setting `worktree.baseRef: "head"` changes that).
### Unattended: what stops a run
A run stops only on a **closed list**: something that cannot be undone · something security-sensitive · something outside the working copy (merge to main, push, publish) · a plan so broken that everything after it is guesswork. Everything else the executor decides itself and logs in the final report's **Decisions taken** table, each with what it costs if it is wrong.
### Modes
@ -337,11 +355,11 @@ Use `--fg` to run every step sequentially in the current session instead, even w
### Failure recovery
- **3-attempt retry cap** — retries twice, then stops (never loops forever)
- **On failure: revert** — undo changes, stop
- **On failure: retry** — try alternative approach, then revert if still failing
- **Fix rounds go up, maximum 5** — rounds 1–3: a fresh helper fixes exactly the controller's findings; after three failed fixes the question is the architecture: round 4 sends the step back to planning (`/trekplan` revises it, then `--resume`), round 5 to you. Never a fourth guess, never a cheaper model
- **On failure: revert** — fix rounds, then undo the step's changes when it goes up
- **On failure: retry** — the alternative approach goes to the first fix round; revert when it goes up
- **On failure: skip** — non-critical step, continue
- **On failure: escalate** — stop everything, needs human judgment
- **On failure: escalate** — stop at the first failed round, needs human judgment
### Security hardening
@ -623,7 +641,7 @@ Solid arrows are the forward pipeline; dashed are conditional/internal edges (`-
### Agents per phase
Every command orchestrates its agents inline from the main context (all sub-agents are `model: opus`-pinned). `/trekexecute` is the exception — it spawns **no** sub-agents.
Every command orchestrates its agents inline from the main context (all sub-agents are `model: opus`-pinned). `/trekexecute` spawns no swarm: one fresh `step-implementer` per plan step, in order, and one controller per round.
```mermaid
flowchart TB
@ -640,8 +658,8 @@ flowchart TB
PLC["Phase 9 — parallel · plan-critic · scope-guardian"]
PLG --> PLS --> PLC
end
subgraph EX["/trekexecute · no sub-agents"]
EXI["inline step-loop + session orders per wave (worktrees)<br/>+ Phase 7.5/7.6 manifest audit (deterministic)"]
subgraph EX["/trekexecute · one helper per step"]
EXI["per step: step-implementer → controller (spec + quality)<br/>+ red proof · floor guard · done line (commands)<br/>+ session orders per wave (worktrees) + Phase 7.5/7.6 audit"]
end
subgraph RV["/trekreview"]
RVR["Phase 5 — parallel · code-correctness-reviewer · brief-conformance-reviewer*"]
@ -803,7 +821,7 @@ Default JSONL stats stream (`${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl`) is unchan
The default `premium` profile runs **Opus on every phase** of the pipeline's agent work — the exploration and review swarms (5–10 sub-agents per command; spawn sites inject the composed brief > profile > frontmatter resolution, with `agents/*.md` `model: opus` pins as the fallback) and the executor (one per plan session). The command orchestrator itself is not profile-controlled: as of v5.9, command frontmatter omits `model:`, so the orchestrator follows the session model. For cheaper runs, opt into `--profile balanced` (Sonnet on brief/research/execute/continue, Opus on plan + review) or `--profile economy` (Sonnet everywhere); for maximum quality, `--profile fable` (Fable 5.1 on every phase). Per-command cost is published in `${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl` if you want exact numbers.
On the Anthropic API the `opus` alias resolves to **Opus 5.5** and `sonnet` to **Sonnet 5.5** (both default to reasoning effort `medium`), and `fable` to **Fable 5.1** (the most capable model in Claude Code; default reasoning effort `high` — xhigh must be chosen explicitly, see [`docs/profiles.md`](docs/profiles.md)). Other providers resolve `opus` and `sonnet` to other versions. Note two distinct effort axes that share the word "effort": brief `phase_signals.effort` (low/standard/high) tunes *orchestration shape* — how many agents and passes run — while native `effort:` (eight agents pin `high`; the rest follow the session) tunes the *per-spawn reasoning budget*. See [`docs/profiles.md`](docs/profiles.md) § Model & effort axes.
On the Anthropic API the `opus` alias resolves to **Opus 5.5** and `sonnet` to **Sonnet 5.5** (both default to reasoning effort `medium`), and `fable` to **Fable 5.1** (the most capable model in Claude Code; default reasoning effort `high` — xhigh must be chosen explicitly, see [`docs/profiles.md`](docs/profiles.md)). Other providers resolve `opus` and `sonnet` to other versions. Note two distinct effort axes that share the word "effort": brief `phase_signals.effort` (low/standard/high) tunes *orchestration shape* — how many agents and passes run — while native `effort:` (nine agents pin `high`; the rest follow the session) tunes the *per-spawn reasoning budget*. See [`docs/profiles.md`](docs/profiles.md) § Model & effort axes.
For per-profile cost estimates, see [`docs/profiles.md`](docs/profiles.md).
@ -819,8 +837,8 @@ Top-level layout:
```
trekplan/
├── agents/ 23 specialized agents (all `model: opus`-pinned; per-phase model set by `--profile`)
│ └ 20 spawnable (1 dormant: synthesis-agent, Δ≈0) + 3 orchestrator reference docs (not spawned)
├── agents/ 24 specialized agents (all `model: opus`-pinned; per-phase model set by `--profile`)
│ └ 21 spawnable (1 dormant: synthesis-agent, Δ≈0) + 3 orchestrator reference docs (not spawned)
├── commands/ 6 slash commands (trekbrief, trekresearch, trekplan, trekexecute, trekreview, trekcontinue) + trekendsession helper
├── templates/ Frontmatter templates for brief, research, plan, session
├── hooks/ 8 hooks (pre-bash, pre-write, pre-agent-cap, session-title, post-bash-stats, pre-compact-flush, post-compact-flush, otel-export)