| name | executing-plans |
| description | Executes an approved epic one wave at a time, dispatching a worker per task and stopping at a checkpoint after each wave. |
Executing Plans
Freedom: LOW — load epic, execute one wave, checkpoint, STOP.
Overview
Execute an epic in cycles with mandatory checkpoints. Load epic → run one wave (one task, or several independent tasks in parallel) → Present checkpoint → STOP. User reviews, then invokes again to continue.
Core principle: Epic requirements are immutable. Tasks adapt to reality. STOP after each wave for human oversight — no exceptions. A wave of independent parallel tasks is one cycle with one checkpoint; running a second wave without stopping is the batching that's forbidden.
Announce at start: "I'm using gambit:executing-plans to implement this task."
Execute an epic in cycles with mandatory checkpoints. Load the approved root-session contract and wave plan → run one wave with one or more workers → create the durable checkpoint → STOP. User reviews, then invokes again to continue.
Core principle: Epic requirements are immutable. Worker briefs and later waves adapt to reality. STOP after each wave for human oversight — no exceptions. Running a second wave without stopping is the batching that's forbidden.
Announce at start: "I'm using gambit:executing-plans to implement this wave."
Execution and continuation
Each invocation runs one cycle — execute the ready work, verify, run the quality gate, commit, present the checkpoint — then STOPs (ends the turn). The skill never loops across cycles within a single turn.
STOP does not mean the epic halts; it means this turn ends and the next cycle begins on the next invocation. Two things can trigger that next invocation:
- A human re-running
/gambit:executing-plans — the default.
- A goal Stop-hook that re-invokes the skill automatically — the ONLY sanctioned way to run cycle-after-cycle without a human pause.
Continuous, no-human-pause execution is therefore authorized only by a goal Stop-hook — never self-granted. An in-session "just keep going, don't stop for me" does NOT authorize it: if the user wants unattended execution they set a goal; surface that in the checkpoint rather than batching cycles yourself. Every safeguard — quality gate, commit, checkpoint summary, and this re-invocation — runs on every cycle regardless; the goal changes only who triggers the next one, never what happens inside a cycle.
Quick Reference
| 0. Check State | TaskList | Task state tells you where to resume — never ask |
| 1. Load Epic + Enter Worktree | TaskGet on epic; enter/re-enter the epic worktree | Requirements are IMMUTABLE; never execute on main |
| 2. Execute the Wave | Mark in_progress → dispatch worker(s) → verify → integrate → mark completed | Explicit worker rung, TDD cycle, worktree-isolate a ≥2 wave |
| 3. Create Next Wave | TaskCreate every pluckable task based on learnings | As wide as pluckability allows; disjoint file sets; reflect reality |
| 0. Check State | SessionPlanRead | Wave state tells you where to resume — never ask |
| 1. Load Contract + Enter Worktree | SessionContextRead in this root session; enter/re-enter the epic worktree | Requirements are IMMUTABLE; never execute on main |
| 2. Execute the Wave | Replace the complete plan to mark one wave in progress → dispatch worker(s) → verify → integrate → report readiness while leaving the wave in progress | Explicit worker role, TDD cycle, worktree-isolate a ≥2 wave |
| 3. Create Next Wave | Prepare complete worker briefs for the checkpoint; defer plan mutation | As wide as pluckability allows; disjoint file sets; reflect reality |
| 4. Commit & Checkpoint | Commit to current branch, present summary | STOP — no exceptions |
| 4. Durable Checkpoint | Commit → present full checkpoint and next-wave briefs → replace the complete plan to complete this wave | STOP — no exceptions |
Iron Law: One wave → Checkpoint → STOP → Next cycle. No batching (no second wave this cycle). No "just one more." The STOP always happens; whether a human or a goal Stop-hook triggers the next cycle is the only thing that varies (see Execution and continuation).
When to Use
- Epic Task exists with subtasks ready to execute
- The same root session contains an approved epic contract, complete worker briefs, and native wave plan ready to execute
- Resuming implementation after a previous checkpoint
- Need to implement features iteratively with human oversight
- After
gambit:brainstorming creates the epic and first task
- After
gambit:brainstorming records the approved contract, first-wave briefs, and native plan in this root session
Don't use when:
- No epic exists → use
gambit:brainstorming
- Debugging a bug → use
gambit:debugging
- Single quick fix → just do it
The Process
0. Resumption Check (Every Invocation)
Run TaskList and analyze:
- Fresh start: All tasks "pending", none "in_progress" → Step 1
- Resume in-progress: Found task with status="in_progress" → Step 2
- Start next: Previous completed, next "pending" with empty blockedBy → Step 1 then 2
- All done: All subtasks "completed" → Step 5 (final validation)
Do NOT ask "where did we leave off?" — Task state tells you exactly where to resume.
If the task store is empty or wiped (e.g. an MCP reconnect drops the session's tasks mid-epic) — this is recoverable state loss, not a halt. You hold the epic's requirements and the current wave in your own context; recreate the epic and the in-flight tasks with TaskCreate from that context, then resume. Never abandon an epic because the store reset.
Run SessionPlanRead and analyze the wave steps:
- Fresh start: Every wave is pending, none is in progress → Step 1
- Resume in-progress: One wave has status
in_progress → Step 2
- Start next: Previous wave completed and the next wave is pending → Step 1 then 2
- All done: Every wave step is completed → Step 5 (final validation)
Do NOT ask "where did we leave off?" — the root session's wave state tells you exactly where to resume.
If native plan state is absent, use SessionContextRead to recover only from this root session's approved contract and latest checkpoint, then reconstruct the complete ordered wave list with SessionPlanWrite. If same-session context is insufficient, or native plan mutation is unavailable, fail closed and ask the user; never recover orchestration state from the repository, another session, a goal, or legacy state.
1. Load Epic Context and Enter the Worktree
Before executing ANY task, read the epic with TaskGet.
Before executing ANY wave, use SessionContextRead to reread the complete approved epic contract from this root transcript.
Extract and keep in mind:
- Requirements (IMMUTABLE — never water these down)
- Success criteria (validation checklist)
- Anti-patterns (FORBIDDEN shortcuts)
- Approaches Considered (what was already REJECTED and why)
- Delivery Constraints (non-convergence and repair circuit breakers)
- Validation Strategy (focused worker command, wave/component gate, release acceptance, freshness, and declared acceptance budget)
Why: Requirements prevent rationalizing shortcuts when implementation gets hard.
For a legacy epic that lacks Delivery Constraints or Validation Strategy, do not guess silently. Before implementation, propose the conservative defaults from this skill — the two-checkpoint convergence circuit breaker, the repair ladder ending in terminal escalation attempts repeated with updated evidence, focused and wave/component commands from repository policy, and one fresh release acceptance run after architecture/scope preflight — then obtain explicit user approval. This records delivery policy without changing immutable product requirements.
Enter the epic worktree. All epic work happens in a worktree — never directly on main. Working on main risks orphaned commits and a corrupted mainline while waves land.
On a fresh start (Step 0 found all tasks pending):
On a fresh start (Step 0 found all wave steps pending):
- Repo convention first. If the repo provides its own worktree setup (an existing
.worktrees/ or worktrees/ directory, a CLAUDE.md worktree preference, or project tooling like a just worktree target), follow it: git worktree add <dir>/<epic-slug> -b <branch> and work there.
- Otherwise use the native facility:
EnterWorktree name: "<epic-slug>" — creates the worktree under .claude/worktrees/ on a new branch and switches the session into it. The base ref follows the worktree.baseRef setting (fresh = origin default branch; head = current HEAD).
- Otherwise use standard Git: choose the base revision from the approved epic context, then run
git worktree add <dir>/<epic-slug> -b <branch> <base-ref> and enter that path. Do not assume a backend-owned worktree directory or hook setting.
Then prepare it: run the project's dependency setup (match the tooling — npm install, cargo build, direnv allow/devenv, etc.), and run the declared wave/component gate once to pin the baseline. Report baseline failures before dispatching any wave — you can't distinguish new breakage from inherited breakage without this. Do not spend release acceptance merely to establish a baseline unless the approved Validation Strategy explicitly budgets that run.
On resume: if the session is already in the epic's worktree, continue. In a fresh session, re-enter it — EnterWorktree path: "<worktree path>" for a native one (it must appear in git worktree list), or switch to a repo-managed one directly. Never dispatch a wave from main.
On resume: if the session is already in the epic's worktree, continue. Otherwise locate the existing path with git worktree list and enter it directly; if it no longer exists, recreate it through the repository convention or git worktree add. Never dispatch a wave from main.
The transient per-worker worktrees of a ≥2 wave (references/wave-dispatch.md) fork off THIS worktree's HEAD — they are orchestrator-managed and separate from the epic workspace.
2. Execute the Wave
Find and claim the wave:
TaskList → identify the ready tasks (status="pending", blockedBy=[]). The wave is those whose file sets are pairwise disjoint with no cross-dependency — usually one, sometimes several. Overlapping or dependent tasks wait for a later wave.
TaskUpdate → mark each wave task in_progress
TaskGet → load each task's full details
SessionPlanRead → identify the next pending wave step. Its workers have pairwise-disjoint file sets and no cross-dependency — usually one worker, sometimes several. Overlapping or dependent work waits for a later wave.
SessionContextRead → load every worker's complete self-contained brief from this root transcript or latest checkpoint. Individual worker state comes from native subagent threads and checkpoint results, never plan records.
SessionPlanWrite → replace the complete ordered plan, preserving every other step and marking only that single wave in_progress. At most one wave may be in progress.
Investigate first if needed — reach for a scout. Before constructing the worker brief, if you need to locate code, confirm an interface, or gather cross-task context, dispatch the read-only scout class — don't read around inline or spawn a bare generic agent. This is optional per task; skip it when the brief is already clear.
Glob **/contracts/scout.md. Resolve the scout role through contracts/models.md to its
rung. On a model rung, dispatch subagent_type: "Explore" with model: set to the rung's alias;
on an agent rung, dispatch the rung's readonly_agent and pass no model: at all. Either way,
prompt it to Read contracts/scout.md first, then ask the bounded question with the task's
repository/worktree root.
Glob **/contracts/scout.md, dispatch the scout role using explorer, and prompt it to Read contracts/scout.md first, then ask the bounded question.
The scout returns file:line evidence or NOT FOUND — never a guess.
Settle architecture before dispatching. A worker implements; it does not decide cross-file design. If a task carries an unresolved architectural question, resolve it first — scout it, record the decision in the brief, or decompose the task — then dispatch. A design question tangled into an implementation task is what produces same-pass-TDD drift.
Apply the declared validation ladder. The focused worker command proves the worker-owned behavior during TDD. The wave/component gate proves the integrated wave once. Release acceptance proves the final system claim on fresh artifacts within the approved budget. Release acceptance is not a per-worker or per-wave default; run it early only when the contract budgets a diagnostic run that answers a named system-level question.
Answer the user before you dispatch. When the user asks a direct question mid-epic, answer it in prose before or alongside your next action. A dispatch, a task update, or a checkpoint summary is never a substitute for the answer. Deferring a question to "keep the loop moving" is the drift, not the discipline; if you can't answer, say so plainly rather than fabricating (e.g. per-worker token cost isn't surfaced to you — point the user at the session telemetry, don't guess a number).
Dispatch the wave to workers:
The ready work is a wave — one or more ready tasks whose file sets are pairwise disjoint and that have no semantic dependency on each other (a task needing another's output belongs in a later wave). One cycle dispatches one wave. The orchestrator does not write implementation code in the main context and stays a coordinator: it plans, verifies, integrates, and checkpoints while a fresh worker on the resolved worker rung does the mechanical work. Every worker is governed by the shared contracts/worker.md — blast-radius confinement, TDD with RED/GREEN evidence, fail-fast Stop Triggers, and a 4-state return.
The ready work is a wave — one or more ready tasks whose file sets are pairwise disjoint and that have no semantic dependency on each other (a task needing another's output belongs in a later wave). One cycle dispatches one wave. The orchestrator does not write implementation code in the main context — it dispatches a fresh general-purpose worker per task and stays a coordinator: it plans, verifies, integrates, and checkpoints while a cheaper, faster model does the mechanical work. Every worker is governed by the shared contracts/worker.md — blast-radius confinement, TDD with RED/GREEN evidence, fail-fast Stop Triggers, and a 4-state return.
- Single-task wave → dispatch one worker; it works directly in the epic's working tree.
- Wave of ≥2 → run each worker in its OWN isolated worktree so their tests, lints, and builds cannot interfere; give every brief exact
## Files owned, ## Hidden shared surfaces, and ## Neighbors allowlists; then use scripts/integrate_wave.py for commit-based atomic integration and one combined wave/component gate. Never let two workers edit the same working tree. Full mechanics: references/wave-dispatch.md — read it whenever a wave has ≥2 tasks.
Resolve the contract path once. Glob **/contracts/worker.md at the start of the epic to get its absolute path and pass that path to the worker — do NOT Read worker.md into your own context, and do NOT hardcode or reuse a stale absolute path from an earlier session (plugin store paths change; re-Glob). The worker reads it in its fresh context (exactly as the review skill passes reviewers/*.md by path); reading it yourself loads ~1.4k tokens into the long-lived orchestrator context on every epic, for nothing. The worker re-reads it on every dispatch, including retries — keep worker.md lean.
-
Resolve the worker rung. Resolve the worker role through contracts/models.md before the initial dispatch. Use the role's entry rung, or a higher rung on its ladder when the task brief states difficulty that warrants it — never a rung below the entry, and never a rung the worker picks for itself. On a model rung, always set model: explicitly to the rung's alias — never omit it, never pass inherit (that silently inherits the expensive session model). On an agent rung, dispatch the rung's agent and pass no model: at all — a foreign model id in model: is silently substituted rather than rejected. Never write a concrete model ID into this skill.
-
Dispatch the wave — emit every worker together in one message so a ≥2 wave runs concurrently.
The prompt starts with the absolute worker-contract directive, then contains the complete constructed brief and its exact ## Files owned, ## Hidden shared surfaces, ## Context, and ## Neighbors; the focused command, exact worktree and branch, and correct wave base; never session history:
Agent subagent_type="general-purpose" model="<worker rung alias — contracts/models.md>" description="Implement: <task subject>"
prompt="Read <abs>/contracts/worker.md first and follow it exactly. <complete constructed brief and dispatch fields described above>"
On an agent rung the same dispatch becomes Agent subagent_type="<worker rung agent>" with the model= field removed entirely; the prompt is unchanged. Worktree isolation and integrate_wave.py are unchanged either way.