feat(trekexecute): couple the executor to the review gate, the plan approval and the step checks

Wave 2, order 6. /trekexecute now:
- refuses a plan whose logged approval does not cover its current sha256
  (K2, approval-log verify --kind plan), before step 1;
- runs the step check (K9) and the step's optional Regression: (K10, new
  lib/verification/regression-check.mjs through the criteria runner) at step
  end, before the checkpoint; exit 2 is "not measured", never green;
- runs the architecture rules (K5) and the plan-file sweep (K6) after the last
  step; a violation or a file outside the plan turns completed into partial;
- reviews by itself in the closing run (Phase 7.2): run the thing, /simplify,
  /trekreview, verdict-gate; a BLOCK adds the review's remediation steps after
  the plan validator accepts them and the operator re-approves the plan, capped
  at TREKEXECUTE_MAX_REVIEW_ROUNDS (3);
- makes the main-merge gate a lock on the verdict: BLOCK or undecided keeps
  the merge closed; when open, the executor merges and the guard's question is
  the one question (operator decision 2026-10-08). The --gates pause before
  the wave merge-back is gone for the same reason.

The guard refuses a merge into main and a push in the permission mode that
shows no prompts, since no one can be asked (operator decision 2026-10-09; two
mode-read exemptions approved by the operator).

progress.json gains optional coupling fields (Handover 5); the validator
rejects the runner's exitCode in plan_verification.failed_criteria (C15).
Pointer lines name the skills test-first and debugging (S2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-09 19:22:00 +02:00
commit 920fbd3c47
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
15 changed files with 1310 additions and 64 deletions

View file

@ -16,6 +16,8 @@ All four pipeline commands accept a boolean `--gates {true|false}` flag. Presenc
Under the hood: `lib/util/autonomy-gate.mjs` runs the state machine `idle → gates_on | auto_running → paused_for_gate → completed`. `start` routes to `gates_on` when `--gates true`, else `auto_running`; a `phase_boundary` from `gates_on` pauses at `paused_for_gate` (awaiting `resume`); `finish` reaches the terminal `completed`. The module is pure data with no I/O. Separately, `lib/stats/event-emit.mjs` records named lifecycle events (`brief-approved`, `main-merge-gate`, `main-merge-approved`, `main-merge-declined`, `gates_mode_flag_override`, `user_input`) to `trekexecute-stats.jsonl` in the plugin data directory (`CLAUDE_PLUGIN_DATA`, else `~/.claude/plugins/data/voyage-ktg-plugin-marketplace/`, the directory `scripts/yardstick.mjs` reads); a write that fails is reported, never skipped. The main-merge gate is the final autonomy boundary before HEAD lands on `main`.
**The main-merge gate is a lock, and the guard asks the one question** (operator decision 2026-10-08). The gate opens only when the run is `completed` and the review's verdict gate (`lib/review/verdict-gate.mjs`, K7) exits 0; BLOCK (1) and "could not decide" (2) keep it closed. When it opens, `/trekexecute` runs the merge into main itself and `pre-bash-executor` answers "ask" before it runs, in auto mode too, so that question is the only one. In the permission mode where Claude Code shows no prompts, the guard refuses the merge (and any push) instead, since no one can be asked (operator decision 2026-10-09). The executor no longer asks "ready to merge?" first, and `--gates` no longer adds a pause before the wave merge-back: the guard asks there as well, once per session, because the push and the merge go in one call. Before this, one merge cost two questions in three places: the `--gates` pause before the wave merge-back, the gate's own question after the waves were merged, and the gate's question on the single-session path followed by the guard's at the merge itself.
### Path A/B/C decision (v3.4.0; Path C closed 2026-05-05)
Three architectural options were considered for the speedup work: