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

@ -358,6 +358,24 @@ The wave-1 fields are **additive-optional on read**: a `progress.json` written
before them validates and resumes unchanged (no `schema_version` bump). `null`
means "not set yet". When present, `progress-validator.mjs` shape-checks them.
**Wave-2 coupling fields (order 6, additive-optional, same rule).** Each is a
contract CLI's exit said in words; `not-measured` / `not-run` are never green.
| Field | Level | Values | Source |
|---|---|---|---|
| `step_check` | step | `clean \| findings \| not-measured` | K9 `lib/verification/step-check.mjs` exit 0 / 1 / 2 (Sub-step D4) |
| `regression` | step | `passed \| failed \| unrunnable \| not-run \| absent` | K10 `lib/verification/regression-check.mjs` — the step's `Regression:` run through the criteria runner; `absent` = no field |
| `plan_approval` | run | `approved \| not-checked` | K2 `approval-log.mjs verify --kind plan` (Phase 1); `not-checked` = a session spec |
| `arch_rules` | run | `pass \| violation \| not-measured` | K5 `lib/verification/arch-rules.mjs` exit 0 / 1 / 2 (Phase 7) |
| `scope_sweep` | run | `{status: pass \| deviation \| not-measured, outside: [paths]}` | K6 `lib/verification/plan-scope-sweep.mjs` exit 0 / 1 / 2 (Phase 7) |
| `simplify` | run | `applied \| clean \| reverted \| not-run` | `/simplify` in Phase 7.2 |
| `review` | run | `{round ≥ 1, path, gate_exit: 0 \| 1 \| 2, verdict}` | K7 `lib/review/verdict-gate.mjs` on `review.md` (Phase 7.2; Phase 8 locks on it) |
`plan_verification.failed_criteria[]` carries `exit_code` (integer, or `null`
for a criterion that never ran). The criteria runner reports `exitCode`; the
executor translates the key, and the validator rejects the runner's key or a
missing `exit_code` (C15, `PROGRESS_FAILED_CRITERIA_KEY`).
**Validation strategy:** `progress-validator.mjs` runs at:
1. `/trekexecute --validate` (alongside plan-validator)
2. `/trekexecute --resume` entry (must pass `checkResumeReadiness`)
@ -377,6 +395,8 @@ means "not set yet". When present, `progress-validator.mjs` shape-checks them.
- `PROGRESS_FIX_ROUNDS_INVALID` → `fix_rounds` not an integer 0..5; resume halts
- `PROGRESS_START_SHA_INVALID` / `PROGRESS_REPORT_PATH_INVALID` / `PROGRESS_RED_PROOF_INVALID` / `PROGRESS_TEST_LOCK_INVALID` → a wave-1 step field of the wrong shape; resume halts
- `PROGRESS_DECISION_INVALID` → `decisions` is not an array of `{decision, cost_if_wrong}`; resume halts
- `PROGRESS_STEP_CHECK_INVALID` / `PROGRESS_REGRESSION_INVALID` / `PROGRESS_PLAN_APPROVAL_INVALID` / `PROGRESS_ARCH_RULES_INVALID` / `PROGRESS_SCOPE_SWEEP_INVALID` / `PROGRESS_SIMPLIFY_INVALID` / `PROGRESS_REVIEW_INVALID` → a wave-2 coupling field of the wrong shape; resume halts
- `PROGRESS_FAILED_CRITERIA_KEY` → a `failed_criteria` entry with the runner's `exitCode`, or without `exit_code`; resume halts. This one is a tightening, not an addition: a progress file written before it with the runner's key (the C15 defect itself) no longer resumes until the key is renamed to `exit_code`
---

View file

@ -80,9 +80,11 @@ If `{project_dir}/architecture/overview.md` exists (typically produced by an opt
| `--step N` | Execute only step N |
| `--fg` | Force foreground — run all steps sequentially, ignore Execution Strategy |
| `--session N` | Execute only session N from plan's Execution Strategy |
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. It adds no question of its own before a merge: the guard asks there (operator decision 2026-10-08). |
| `--profile <name>` | (v4.1.0) Model profile for the execute phase. Inherited from plan.md frontmatter `profile:` if present. |
Every mode that executes refuses a plan whose approval in the approval log does not cover its current sha256 (K2). A run ends with the review it starts by itself (`/simplify` → `/trekreview` → verdict gate); a BLOCK or an undecided verdict keeps the merge into main closed. `TREKEXECUTE_MAX_REVIEW_ROUNDS` (default 3) caps the reviews per run.
## /trekreview modes
| Flag | Behavior |

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: