| name | executor |
| description | Wave execution engine: runs the locked wave plan wave by wave, gated and receipted. Use when a reviewed wave plan is ready, /execute, or resuming. Not for writing or validating the plan. |
Executor
You run the plan. You do not write the plan (decompose does) and you do not invent scope (the wave
plan declares it). You orchestrate, wave by wave: checkpoint โ guard โ implement โ verify, with
error routing at every step and a receipt after every wave.
The loop is domain-neutral. What "implement" means โ write code, build a model, draft a lesson,
produce a report โ is whatever the wave plan's outputs declare; executor produces exactly those, no
more, no less.
What this does / does not do
Does: read the locked wave plan and run it wave by wave (checkpoint โ guard โ implement โ verify),
route errors by type, write a receipt after every wave, gate the final receipt on a
deliverable-acceptance check, and signal archive. Does not: write the wave plan (decompose),
validate it pre-wave (guard) or post-wave (verifier), or auto-transition to archive without user confirmation.
Hard Gates (check all four before any wave begins)
| Gate | Condition | Action on violation |
|---|
locked-spec-only (I1) | a locked <workspace>/specs/task-card.md exists with a non-empty locked_at | halt; route to specify/intake |
receipt-required (I10) | decompose-receipt.json exists before Wave 1; Wave N requires Wave N-1 receipt | halt; surface the missing receipt; never proceed on a broken chain |
space-boundary (I11) | the wave writes only to its declared space (product / workspace โ never the tool) | HARD abort; log the illegal target |
max-revise-3 (I4) | verifier REVISE cycles โค 3 per wave; at cycle 4 the verdict is BLOCKED | escalate to Attestation; never enter a 4th cycle |
A wave that reaches implementation without all four satisfied is an invariant violation. A caller
assertion ("guard already passed") may skip an expensive re-check, but never a Hard Gate.
When NOT to use
decompose-receipt.json is missing โ there is no plan to run (I10). Route to decompose.
- A wave is blocked awaiting Attestation โ executor does not bypass a pending human sign-off.
Reference Routing
| Situation | Reference |
|---|
| Context budget zones, four-bucket strategy, compaction/CONTEXT_EXHAUSTION protocol | references/context-budget.md |
| Subagent role taxonomy, write isolation, the 5-element delegation checklist | references/subagent-roles.md |
| Phase status display, wave symbols, progress log, completion-status vocabulary | references/status-formats.md |
| Wave / execution receipt write delegation | engine/shared/references/script-delegation-contract.md |
| Running guard or verifier as subagents (reduces orchestrator context) | engine/shared/references/agents-architecture.md |
| REVISE after a verification FAIL โ root-cause the failure before re-implementing | engine/shared/references/debug-protocol.md |
Inputs
<workspace>/specs/wave-plan.md (locked) ยท <workspace>/specs/task-card.md ยท <workspace>/scope.md
- all prior wave receipts (I10 chain) ยท
<workspace>/intake.json (domain)
Load in tier order to keep the cache warm: stable (invariants, role) before context (card,
plan, scope) before volatile (per-wave receipts, evidence). Place the current wave's goal and
acceptance criteria at the top of each wave prompt โ middle tokens get 10โ40% lower recall.
How to do it
Prologue (once, before Wave 1)
Confirm decompose-receipt.json exists. Enforcement is already armed by code โ the session-start
hook (engine/control/hooks/session-start.py) writes <workspace>/session/state.json with
enforcement_active: true and an empty required_receipts at session start. Verify it exists
(write it if missing โ belt and braces) and set the planning-chain requirements:
{ "enforcement_active": true,
"required_receipts": ["intake-receipt", "scopeframe-receipt", "specify-receipt", "decompose-receipt"],
"active_module": "executor", "evidence_drawers": [] }
From here, any Edit/Write/Bash requires the planning-chain receipts to exist; the pre-tool-use hook
blocks otherwise. (Arming is code-owned; executor owns the requirement list โ doc 04.) Also run the
eval-first check: state in one testable sentence what must become true, capture the baseline, and
plan to compare deltas after. If you cannot state the eval, the card is underspecified โ route to specify.
For each wave, in order
- Update state.json โ set
active_module: executor-wave-<N>; append each completed wave's
receipts to required_receipts. Never reset enforcement_active.
- Establish rollback reference โ the wave plan's
outputs list for this wave is the rollback
ground truth (revert those files to pre-wave state if needed). Honor the wave's rollback_to.
- Check
execution_mode โ AFK proceed silently; HITL emit a one-line "this wave needs your
presence" notice (informational, not a pause).
- Run guard โ inline (default) or as the guard subagent. Wait for
overall: PASS. HARD โ abort;
SPEC_VIOLATION/DEPENDENCY โ surface and pause. Never proceed past guard without PASS.
- Implement โ honor
execution_posture (test-first / characterization-first / standard). Before
building custom, run the research check (adopt > extend > compose > build). Produce exactly the
declared outputs, within scope.md. Mid-wave deviations: ADDITIVE/COSMETIC โ record in
deviations_found, continue; BREAKING โ stop, surface, loop back to specify. Spawn subagents only
under the write-isolation rule (one Write-holder; references/subagent-roles.md).
- Run verifier โ inline or subagent, using the wave's declared
verification_mode. PASS โ
continue; FAIL โ REVISE: apply the debug-protocol (root-cause the failure BEFORE re-implementing
โ feedback-loop-first, hypothesis-before-instrumentation, regression-test-before-fix; a fix must
address the cause, not the symptom; engine/shared/references/debug-protocol.md), then fix the named
cause and re-verify; max 3. At the 3rd failed fix, debug-protocol's 3-strike rule questions the
architecture โ Attestation. BLOCKED โ surface for Attestation.
- Write the wave receipt, then the session checkpoint to
<workspace>/session/checkpoints/checkpoint-wave-<N>.json โ receipt first (it confirms the wave
completed), checkpoint second.
After all waves โ deliverable acceptance gate
Before the final receipt, read the task card's deliverable type and consult the active domain pack: if
the pack (or the task) declares required acceptance artifacts for that deliverable type, verify
they exist. Absent โ emit ACCEPTANCE_NOT_COVERED (SPEC_VIOLATION): do not write
execution-receipt.json, do not signal archive, surface the missing artifact, route to acceptance
authorship. Present โ write the receipt with acceptance_verified: true. When the deliverable type
declares no acceptance requirement, write the receipt with acceptance_verified: null.
This generalizes v6's hardcoded "module-build โ tests/acceptance.md" check. Building a WabbleSpec
module still requires tests/acceptance.md โ but that requirement now lives in the
framework-maintenance domain, not in the kernel. A finance pack can require a back-test artifact; a
document pack, a review sign-off.
Final execution receipt, then closeout
Write execution-receipt.json. Present the closeout packet (references/status-formats.md):
classification (Ready for archival / Keep in active-testing / Needs reconciliation) + the 8 content
fields. Do not auto-transition to archive โ wait for the user.
Error routing
| Error | Action |
|---|
| SOFT | retry once; on second failure escalate to HARD |
| HARD | halt wave; human-confirmed rollback to the prior checkpoint |
| DEPENDENCY | pause; surface the upstream failure; await resolution |
| CONTEXT_EXHAUSTION | compress per the protected-bounds protocol (references/context-budget.md); resume from the last checkpoint |
| SPEC_VIOLATION | pause; loop back to specify/scope-frame; ACCEPTANCE_NOT_COVERED โ acceptance authorship |
| STALENESS_VIOLATION | quarantine the evidence; fetch fresh before continuing |
Output Contract
wave receipt (<workspace>/receipts/wave-<N>-receipt.json): base + wave_number,
verification_mode_used, revise_cycles (0โ3), checkpoint_path, deviations_found,
compression_occurred/compression_count.
execution-receipt.json (<workspace>/receipts/execution-receipt.json): base + waves_planned,
waves_completed, waves_failed, rollbacks_triggered, acceptance_verified (bool|null),
errors_by_type (counts). persistence: Spec-Anchored.
Proactive Triggers
- A wave reaches implementation without a guard PASS receipt: a Hard Gate was skipped โ stop and
run guard; there is no "run it anyway".
- Checkpoint not saved before the wave started: rollback is impossible โ save it first, every wave.
- More than one parallel subagent holds Write: race condition + broken rollback target โ serialize
the writes (write-isolation rule).
- Artifacts produced beyond the wave's declared
outputs: scope violation โ record as an ADDITIVE
deviation or remove; do not silently keep extra work.
- Final receipt about to be written with a missing declared acceptance artifact:
ACCEPTANCE_NOT_COVERED โ do not receipt the task as complete.
Completion Criteria
Done when: every wave has a โ VALIDATED (verifier PASS) wave receipt + checkpoint; the
deliverable acceptance gate passed (or was N/A); execution-receipt.json is written; the closeout
packet was presented.
Not done if: a wave advanced without verifier PASS; the acceptance gate was suppressed to close
out; executor auto-transitioned to archive without user confirmation.
Next step: archive (after the user confirms the closeout) โ it finalizes and bumps the product version.
Related Skills
- decompose: Produces the wave plan executor runs. NOT modified by executor โ the plan is the contract.
- guard / verifier: The pre-wave gate and post-wave gate executor invokes each wave. NOT optional.
- archive: Runs after executor signals complete and the user confirms. NOT auto-triggered by executor.