ktg-plugin-marketplace/plugins/ultraplan-local/commands/ultraexecute-local.md
Kjell Tore Guttormsen 5dd7e8447c fix(ultraplan-local): CRITICAL — worktree isolation for parallel sessions
Phase 2.6 previously launched parallel claude -p sessions in the same
working directory, causing git race conditions and repository corruption.

Changes:
- Add Phase 2.55 (pre-flight safety checks): clean tree, plan file
  tracking, scope fence overlap validation, stale worktree cleanup
- Rewrite Phase 2.6 with git worktree isolation: each parallel session
  gets its own worktree and branch, merged back sequentially
- Add merge conflict detection and abort (no silent data loss)
- Add unconditional worktree cleanup (even on failure)
- Add hard rules 11-13 (worktree mandatory, cleanup, sequential merge)
- Session-scoped progress file naming for --session mode
- Update headless launch template with worktree support and cleanup trap
- Bump version to 1.5.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 22:12:53 +02:00

28 KiB
Raw Blame History

name description argument-hint model allowed-tools
ultraexecute-local Disciplined plan executor — single-session or multi-session with parallel orchestration, failure recovery, and headless support [--fg | --resume | --dry-run | --step N | --session N] <plan.md> opus Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion

Ultraexecute Local

Disciplined executor for ultraplan plans. Reads a plan file, detects if it has an Execution Strategy (multi-session), and either executes directly or orchestrates parallel headless sessions — all to realize one plan.

Designed to work identically in interactive and headless (claude -p) mode.

Phase 1 — Parse mode and validate input

Parse $ARGUMENTS for mode flags:

  1. If arguments contain --fg: extract the file path. Set mode = foreground.
  2. If arguments contain --resume: extract the file path. Set mode = resume.
  3. If arguments contain --dry-run: extract the file path. Set mode = dry-run.
  4. If arguments contain --step N (N is a positive integer): extract N and the file path. Set mode = step, target-step = N.
  5. If arguments contain --session N (N is a positive integer): extract N and the file path. Set mode = session, target-session = N.
  6. Otherwise: the entire argument string is the file path. Set mode = execute.

If no path is provided, output usage and stop:

Usage: /ultraexecute-local <plan.md>
       /ultraexecute-local --fg <plan.md>
       /ultraexecute-local --resume <plan.md>
       /ultraexecute-local --dry-run <plan.md>
       /ultraexecute-local --step N <plan.md>
       /ultraexecute-local --session N <plan.md>

Modes:
  (default)      Auto — multi-session if plan has Execution Strategy, else foreground
  --fg           Force foreground — all steps sequentially, ignore Execution Strategy
  --resume       Resume from last progress checkpoint
  --dry-run      Validate plan and show execution strategy without running
  --step N       Execute only step N (foreground)
  --session N    Execute only session N from the plan's Execution Strategy

Examples:
  /ultraexecute-local .claude/plans/ultraplan-2026-04-06-auth-refactor.md
  /ultraexecute-local --fg .claude/plans/ultraplan-2026-04-06-auth-refactor.md
  /ultraexecute-local --session 2 .claude/plans/ultraplan-2026-04-06-auth-refactor.md
  /ultraexecute-local --dry-run .claude/plans/ultraplan-2026-04-06-auth-refactor.md

If the file does not exist, report and stop:

Error: file not found: {path}

Report detected mode:

Mode: {execute | resume | dry-run | step N}
File: {path}

Phase 2 — Detect file type and parse structure

Read the file. Determine whether it is an ultraplan or a session spec:

  • Session spec: contains ## Dependencies with Entry condition: AND ## Scope Fence AND ## Exit Condition sections.
  • Ultraplan: contains ## Implementation Plan with numbered ### Step N: headings but no ## Scope Fence.

If neither structure is detected, report and stop:

Error: unrecognized file format. Expected an ultraplan or session spec.

Parse steps

Extract every ### Step N: {description} heading (in order). For each step, extract:

  • Files — file paths to create or modify
  • Changes — what to modify
  • Reuses — existing code to leverage (informational)
  • Test first — test to run before implementation (optional)
  • Verify — command to run after implementation
  • On failure — recovery action (revert/retry/skip/escalate)
  • Checkpoint — git commit command after success

If a step is missing On failure, default to escalate and record a parse warning. If a step is missing Verify, record a parse warning.

Parse session spec fields (if applicable)

  • Entry condition from ## Dependencies
  • Touch list and Never-touch list from ## Scope Fence
  • Exit condition checklist from ## Exit Condition

Parse Execution Strategy (if present)

If the plan contains an ## Execution Strategy section, extract:

  • Each ### Session N: {title} with its Steps, Wave, Depends on, and Scope fence
  • The ### Execution Order with wave definitions

Set has_execution_strategy = true.

Report:

Type: {plan | session-spec}
Steps: {N}
{if has_execution_strategy}: Execution Strategy: {S} sessions across {W} waves
{if session spec}: Entry condition: {text}
{if session spec}: Scope fence: {N} touch, {N} never-touch
{if warnings}: Warnings: {list}

Phase 2.5 — Execution strategy decision

Determine how to execute this plan:

Run as single session (foreground) when ANY of these are true:

  • --fg flag is set
  • --step N mode
  • --resume mode
  • --session N mode (runs only that session's steps, foreground)
  • Plan has no ## Execution Strategy section
  • Plan has Execution Strategy with only 1 session

Run as multi-session (parallel orchestration) when ALL of these are true:

  • mode = execute (default, no --fg)
  • Plan has ## Execution Strategy with 2+ sessions
  • At least one wave has 2+ sessions (parallelism possible)

Run as multi-session (sequential orchestration) when:

  • mode = execute (default, no --fg)
  • Plan has ## Execution Strategy with 2+ sessions
  • All sessions are in different waves (no parallelism, but still separate sessions)

For single-session: continue to Phase 3. For multi-session: jump to Phase 2.6.

Report:

Strategy: {single session | N sessions (M parallel, K sequential)}

Phase 2.55 — Pre-flight safety checks

Only runs for multi-session parallel execution. These checks prevent the catastrophic data loss that occurs when parallel sessions share a working directory.

Check 1 — Clean working tree

Run git status --porcelain. If there are ANY uncommitted or untracked changes:

Error: working tree is not clean. Parallel execution requires a clean git state.
Uncommitted changes are invisible to worktrees and will be lost during merge.

Untracked/modified files:
{output of git status --porcelain}

Commit or stash your changes, then re-run.
To run sequentially instead: /ultraexecute-local --fg {plan-path}

Stop execution. Update progress with status: "stopped".

Check 2 — Plan file is tracked by git

Run git ls-files --error-unmatch {plan-path} 2>/dev/null. If the plan file is untracked (exit code != 0):

git add {plan-path}
git commit -m "chore: track plan file for parallel execution"

Report: Plan file committed for worktree visibility.

This ensures every worktree created from HEAD will have the plan file.

Check 3 — Scope fence overlap validation

For each wave that has 2+ sessions, validate that no file appears in the Touch list of two different sessions in the same wave:

  1. For each session in the wave, extract the "Touch" list from the Execution Strategy.
  2. For each pair of sessions (A, B) in the same wave, compute the intersection of their Touch lists.
  3. If any intersection is non-empty:
Error: scope fence overlap detected in Wave {W}.
Sessions {A} and {B} both touch: {overlapping files}
These sessions cannot safely run in parallel.

Fix the Execution Strategy in the plan, or use --fg for sequential execution.

Stop execution. This is a defense-in-depth check — the planning-orchestrator should have prevented this, but verifying at execution time catches plans that were manually edited or have bugs.

Check 4 — Stale worktree cleanup

Run git worktree list. If any worktrees with paths containing ultraplan-sessions/{slug}/worktrees/ exist from a previous failed run:

git worktree remove --force {stale-path} 2>/dev/null
git worktree prune

Also check for stale branches:

git branch --list "ultraplan/{slug}/*" | while read b; do
  git branch -D "$b" 2>/dev/null
done

Report: Cleaned {N} stale worktrees and {N} branches from previous run.

If cleanup fails, report the manual commands and stop.

After all 4 checks pass:

Pre-flight: PASS (clean tree, plan tracked, no overlaps, no stale worktrees)

Phase 2.6 — Multi-session orchestration (worktree-isolated)

Only runs for multi-session execution. This phase creates isolated git worktrees for each parallel session, launches headless child sessions in their own worktrees, merges results back sequentially, and cleans up. After this phase, jump directly to Phase 8 (final report).

CRITICAL SAFETY RULE: Every parallel claude -p session MUST run in its own git worktree. Never launch two sessions in the same working directory. This rule exists because parallel git operations in a shared worktree cause index corruption, race conditions, and repository destruction.

Step 0 — Billing safety check (MANDATORY)

Before launching ANY claude -p process, check the environment:

echo "${ANTHROPIC_API_KEY:+SET}"

If the result is SET, STOP and warn the user. claude -p sessions with ANTHROPIC_API_KEY in the environment bill the API account (pay-per-token), not the user's Claude subscription (Max/Pro). Parallel Opus sessions can cost $50100+ per run.

Use AskUserQuestion with these options:

Question: "ANTHROPIC_API_KEY is set in your environment. Parallel claude -p sessions will bill your API account, not your Claude subscription. How do you want to proceed?"

Option Description
Use --fg instead (Recommended) Run all steps sequentially in this session using your subscription. No extra cost.
Continue with API billing Launch parallel sessions. Each session bills your API account at token rates.
Stop Cancel execution. Unset ANTHROPIC_API_KEY first, then re-run.

If the user chooses --fg: restart execution with mode = foreground (jump back to Phase 3, single-session).

If the user chooses Continue: proceed with Phase 2.6 Step 1.

If the user chooses Stop: report "Execution cancelled — billing safety check" and stop.

If ANTHROPIC_API_KEY is NOT set: proceed silently to Step 1.

Step 1 — Create session infrastructure

REPO_ROOT="$(git rev-parse --show-toplevel)"
SESSION_DIR="$REPO_ROOT/.claude/ultraplan-sessions/{slug}"
WORKTREE_DIR="$SESSION_DIR/worktrees"
LOG_DIR="$SESSION_DIR/logs"
mkdir -p "$WORKTREE_DIR" "$LOG_DIR"
ORIGINAL_BRANCH="$(git rev-parse --abbrev-ref HEAD)"

Record REPO_ROOT, WORKTREE_DIR, LOG_DIR, and ORIGINAL_BRANCH for use in subsequent steps. All paths must be absolute.

Step 2 — Execute waves with worktree isolation

For each wave (in order):

2a. Create worktrees for this wave's sessions:

For each session N in this wave:

BRANCH_NAME="ultraplan/{slug}/session-{N}"
WORKTREE_PATH="$WORKTREE_DIR/session-{N}"
git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" HEAD

If git worktree add fails (e.g., branch exists from a crashed run):

git branch -D "$BRANCH_NAME" 2>/dev/null
git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" HEAD

If it still fails, report the error, mark this session as failed, and skip it.

Report:

Worktree created: session-{N} → {WORKTREE_PATH} (branch: {BRANCH_NAME})

2b. Launch sessions in this wave (each in its own worktree):

For each session N in the wave:

cd "$WORKTREE_PATH" && claude -p "/ultraexecute-local --session {N} {plan-path}" \
  --dangerously-skip-permissions \
  > "$LOG_DIR/session-{N}.log" 2>&1 &

Key rules:

  • $WORKTREE_PATH is the absolute path to the session's worktree
  • $LOG_DIR is an absolute path in the main worktree (NOT inside the session worktree)
  • {plan-path} is the same relative path — it works because the worktree has the same repo content from HEAD
  • If the wave has only 1 session, run without & (no background needed)
  • Track PIDs for parallel sessions

2c. Wait for wave completion:

wait {PID1} {PID2} ...

2d. Check results after each wave:

For each session in the wave, read its log file (in $LOG_DIR, always accessible from the main worktree) and grep for "ultraexecute_summary". Parse the JSON to determine:

  • Did the session complete? (result: "completed")
  • Did it fail? (result: "failed" or "stopped")

If ANY session in the wave failed:

Wave {W} FAILED: Session {N} failed at step {S}.
Stopping — later waves depend on this wave.
See log: {LOG_DIR}/session-{N}.log

Do NOT merge. Do NOT start later waves. Jump to Step 4 (cleanup), then Phase 8.

If all sessions in the wave passed: continue to Step 2e.

2e. Merge session branches back (SEQUENTIAL, one at a time):

Return to the main worktree:

cd "$REPO_ROOT"

For each session N in the wave (in order):

git merge --no-ff "ultraplan/{slug}/session-{N}" \
  -m "merge: ultraplan session {N} — {session-title}"

If the merge succeeds (exit code 0): continue to next session.

If the merge fails (conflict):

CONFLICTS="$(git diff --name-only --diff-filter=U)"
git merge --abort

Report:

Wave {W} MERGE CONFLICT: Session {N} branch conflicts with merged state.
Conflicting files:
{CONFLICTS}

Session {N} log: {LOG_DIR}/session-{N}.log
Aborting further merges. Sessions already merged in this wave are preserved.

Mark remaining sessions as "merge-failed". Jump to Step 4 (cleanup), then Phase 8.

2f. Remove worktrees for completed wave:

After successful merge of all sessions in the wave:

for each session N in the wave:
  git worktree remove "$WORKTREE_DIR/session-{N}" --force
  git branch -d "ultraplan/{slug}/session-{N}"
done
git worktree prune

Report: Wave {W}: {N} sessions merged, worktrees cleaned up.

Continue to the next wave.

Step 3 — Run master verification

After all waves complete and merge successfully, run the plan's ## Verification section commands to verify the integrated result.

Step 4 — Cleanup (ALWAYS runs, even on failure)

This step MUST execute regardless of how Step 2 exited — success, failure, or merge conflict. It is the worktree equivalent of a finally block.

cd "$REPO_ROOT"

# Remove any remaining worktrees
for wt in "$WORKTREE_DIR"/session-*; do
  [ -d "$wt" ] && git worktree remove "$wt" --force 2>/dev/null
done
git worktree prune

# Remove session branches
git branch --list "ultraplan/{slug}/*" | while read branch; do
  git branch -D "$branch" 2>/dev/null
done

# Clean up empty directories
rmdir "$WORKTREE_DIR" 2>/dev/null

Report:

Cleanup: {N} worktrees removed, {N} branches deleted.

If cleanup fails for any worktree, report but do not fail:

Warning: failed to remove worktree {path}. Manual cleanup:
  git worktree remove {path} --force && git worktree prune

Step 5 — Aggregate results

Collect all session summaries into an aggregated report. Jump to Phase 8.

--session N mode

When mode = session N:

  1. Find session N in the Execution Strategy
  2. Extract its step numbers (e.g., Steps: 4, 5, 6)
  3. Extract its scope fence (Touch / Never touch lists)
  4. Execute ONLY those steps, in order, using the single-session protocol (Phase 3→7)
  5. Enforce the session's scope fence as if it were a session spec's scope fence
  6. Report results for those steps only

This mode is used internally by Phase 2.6 when launching child sessions. It can also be used manually to re-run a specific session.

When --session N is invoked inside a git worktree (as done by Phase 2.6), all git operations (add, commit) apply to the worktree's branch. The session does not need to know it is in a worktree — git handles this transparently.

Phase 3 — Progress file setup

The progress file lives at {plan-dir}/.ultraexecute-progress-{slug}.json where {slug} is the plan filename without extension.

Session-scoped naming: When mode = session N, use {plan-dir}/.ultraexecute-progress-{slug}-session-{N}.json instead. This prevents merge conflicts when parallel sessions each write their own progress file.

Progress file schema

{
  "schema_version": "1",
  "plan": "{path}",
  "plan_type": "{plan | session-spec}",
  "started_at": "{ISO-8601}",
  "updated_at": "{ISO-8601}",
  "mode": "{execute | resume | step}",
  "total_steps": 0,
  "current_step": 0,
  "status": "{in-progress | completed | failed | stopped}",
  "steps": {
    "1": { "status": "pending", "attempts": 0, "error": null, "completed_at": null, "commit": null }
  },
  "entry_condition_checked": false,
  "exit_condition_checked": false,
  "summary": null
}

Mode-specific behavior

mode = execute (fresh):

  • If a progress file exists with status in-progress or failed: warn that --resume is available, then wait 3 seconds (sleep 3) and start fresh. This allows headless runs to proceed without blocking.
  • Otherwise: create the progress file with all steps in pending status.

mode = resume:

  • If no progress file exists: start from step 1 (same as fresh execute).
  • If progress file exists: find the first step with status != passed.
    Resuming from step {N}. {M}/{total} steps already completed.
    

mode = dry-run:

  • Do NOT create or modify the progress file.

mode = step N:

  • Create the progress file if it does not exist.
  • Only step N will be executed.

Phase 4 — Entry condition check (session specs only)

Skip for ultraplans. Skip in dry-run mode (report what would be checked instead).

Read the entry condition. Evaluate it:

  • "none" or similar → pass immediately
  • References git state (e.g., "git status clean") → run git status --porcelain
  • References passing tests → run the specified command
  • References a previous session → check git log --oneline for commit pattern

If the entry condition fails:

Entry condition FAILED: {condition text}
Reason: {what was checked, what was found}
Complete the prerequisite first, then re-run.

Update progress file with status: "stopped". Stop execution.

If the entry condition passes:

Entry condition: PASS

Update entry_condition_checked: true in the progress file.

Phase 5 — Dry-run report (dry-run mode only)

Only runs when mode = dry-run. Produces a validation report, then stops.

## Dry Run Report: {filename}

**Type:** {plan | session-spec}
**Steps:** {N}

### Step Validation

| Step | Description | Verify | On failure | Checkpoint | Issues |
|------|-------------|--------|------------|------------|--------|
| 1 | {desc} | {cmd} | {action} | {msg} | {none / missing X} |

### File References

{For each file in Files: fields, check existence with Glob}
- {path}: EXISTS | NOT FOUND {(marked as new file) | (unexpected — may be missing)}

### Entry / Exit Conditions (session specs)

{What would be checked}

### Execution Preview (only when plan has Execution Strategy)

If `has_execution_strategy = true`, show a preview of multi-session orchestration:

Sessions: {S} across {W} waves

Wave Session Steps Depends on Command
1 Session 1: {title} {nums} none claude -p "/ultraexecute-local --session 1 {path}"
1 Session 2: {title} {nums} none claude -p "/ultraexecute-local --session 2 {path}"
2 Session 3: {title} {nums} S1, S2 claude -p "/ultraexecute-local --session 3 {path}"

Check billing status via `echo "${ANTHROPIC_API_KEY:+SET}"` and report:

Billing: ANTHROPIC_API_KEY is {SET — parallel sessions will bill API account | NOT SET — sessions will use subscription}


### Verdict

{READY | NEEDS ATTENTION — N issues found}

Stop after the dry-run report. Do not execute anything.

Phase 6 — Step execution loop

The core execution phase. Runs for modes: execute, resume, step.

Determine starting step

  • execute: step 1
  • resume: first step where status != passed
  • step N: step N only

For each step

Update progress: steps.{N}.status = "running", current_step = N, updated_at = now.

--- Step {N}/{total}: {description} ---

Sub-step A — Scope fence check (session specs only)

Before touching any file, verify that every file in the step's Files: field is in the session spec's Touch list (or is a new file to create). If ANY file is in the Never-touch list:

SCOPE VIOLATION: Step {N} requires {file} which is in the never-touch list.
Escalating — this step cannot be executed within this session's scope.

Treat this as an automatic escalate. Jump to the stop-and-report logic.

Sub-step B — Test first (if present)

If the step has a Test first: field:

  1. If test file is marked (new): note it will be created during implementation.
  2. If test file exists: run it. Expect failure (RED state).
  3. If test unexpectedly passes: warn but continue — step may already be done.

Do not block on test-first failures — they are expected.

Sub-step C — Implement changes

Read the step's Files: and Changes: fields. Implement exactly as described.

Rules:

  • Follow Changes: exactly — do not improvise, add scope, or optimize
  • Use Edit for modifications, Write for new files
  • If Reuses: references existing code, read that code first for context
  • Only touch files listed in Files: — nothing else

Sub-step D — Verification

Run the Verify: command exactly as written, via Bash.

Rules:

  • Always a fresh run — never trust prior results
  • Exit code is the authoritative truth:
    • Exit 0 + expected output (if specified) = PASS
    • Exit non-zero = FAIL regardless of output text
    • Exit 0 but wrong output = FAIL
Verify: {command}
Result: {PASS | FAIL} (exit code {N})
{if FAIL}: Output (first 10 lines): {output}

If PASS: proceed to Sub-step F (checkpoint).

Sub-step E — On failure handling

If FAIL, read the On failure: clause. Apply the retry cap: maximum 2 retries (3 total attempts). Track attempts in steps.{N}.attempts.

On failure: revert

  • If attempts < 3: analyze the failure, re-implement with adjustments, re-verify.
    Attempt {A}/3 failed. Retrying...
    
  • If attempts == 3: revert this step's changes:
    git checkout -- {files from Files: field}
    
    Record failure. Do NOT proceed to next step. Jump to Phase 7.

On failure: retry

  • If attempts < 3: use the alternative approach described in the On failure clause.
  • If attempts == 3: revert and stop. Jump to Phase 7.

On failure: skip

  • Mark step as skipped regardless of attempt count. Continue to next step.
    Step {N}: SKIPPED (non-critical per plan)
    
    Update steps.{N}.status = "skipped".

On failure: escalate

  • Stop immediately regardless of attempt count.
    Step {N}: ESCALATED — requires human judgment
    
    Commit all completed work before stopping. Stage ONLY files from steps with status: "passed" in the progress file — collect their Files: fields. Never use git add -A (risks staging secrets, binaries, or unrelated work).
    git add {files from passed steps' Files: fields} && git commit -m "wip: ultraexecute-local stopped at step {N} — escalation needed"
    
    Jump to Phase 7.

Sub-step F — Checkpoint

Run the Checkpoint: git commit command exactly as written in the plan.

If the commit fails (nothing to commit, etc.): warn but do NOT fail the step. The step's verification already passed — the commit is bookkeeping.

Step {N}: PASS (committed: {hash})

Update progress: steps.{N}.status = "passed", steps.{N}.commit = {hash}, steps.{N}.completed_at = now.

Step mode exit

If mode = step N: after completing step N (pass or fail), skip remaining steps and jump to Phase 8 (final report).

Phase 7 — Exit condition check (session specs only)

Skip for ultraplans. Run only when all steps passed (not on early stop).

Run each exit condition command from the ## Exit Condition checklist:

Exit condition check:
- [ ] {command} → {PASS | FAIL}
- [ ] {command} → {PASS | FAIL}

If all pass: exit_condition_checked: true in progress file. If any fail: record which failed. Include in final report.

Phase 8 — Final report

Always produce a final report.

Update progress file: status to completed/failed/stopped, updated_at, summary.

## Ultraexecute Local Complete

**Plan:** {path}
**Type:** {plan | session-spec}
**Mode:** {execute | resume | step N}
**Result:** {COMPLETED | FAILED at step N | STOPPED (escalation) | PARTIAL (N/total passed)}

### Step Results

| Step | Description | Result | Attempts | Commit |
|------|-------------|--------|----------|--------|
| 1 | {desc} | PASS | 1 | abc1234 |
| 2 | {desc} | FAIL | 3 | — |
| 3 | {desc} | — | 0 | — |

### Summary

- Passed: {N}/{total}
- Skipped: {N}
- Failed: {N}
- Not reached: {N}

{if all passed + exit condition passed}:
All steps completed. Exit condition: PASS.

{if failed/stopped}:
### Failure Details

Step {N}: {description}
On failure: {action}
Error: {error output, first 20 lines}
Attempts: {N}

### What Remains

{Numbered list of unexecuted steps}

To resume: /ultraexecute-local --resume {path}

JSON summary block (always at the end, machine-parseable):

{
  "ultraexecute_summary": {
    "plan": "{path}",
    "plan_type": "{plan | session-spec}",
    "result": "{completed | failed | stopped | partial}",
    "steps_total": 0,
    "steps_passed": 0,
    "steps_failed": 0,
    "steps_skipped": 0,
    "steps_not_reached": 0,
    "failed_at_step": null,
    "exit_condition": "{pass | fail | skipped | n/a}",
    "progress_file": "{path}"
  }
}

The ultraexecute_summary key makes it grep-able in log files from headless runs.

Phase 9 — Stats tracking

Append one record to ${CLAUDE_PLUGIN_DATA}/ultraexecute-stats.jsonl:

{
  "ts": "{ISO-8601}",
  "plan": "{filename only}",
  "plan_type": "{plan | session-spec}",
  "mode": "{execute | resume | dry-run | step}",
  "result": "{completed | failed | stopped | partial}",
  "steps_total": 0,
  "steps_passed": 0,
  "steps_failed": 0,
  "steps_skipped": 0,
  "failed_at_step": null
}

If ${CLAUDE_PLUGIN_DATA} is not set or not writable, skip silently. Never let stats failures block the workflow.

Hard rules

  1. No AskUserQuestion for execution decisions. All execution decisions come from the plan's On failure clauses. If the plan says escalate, stop and report — never ask. Exception: the billing safety check in Phase 2.6 Step 0 MUST ask before spending money on the user's API account.

  2. No scope creep. Only touch files listed in the step's Files: field. If a file outside the list seems to need changing, record it as a finding in the final report — do not touch it.

  3. Exit code is truth. The Verify command's exit code is authoritative. Non-zero = FAIL regardless of output. Zero with wrong output = FAIL.

  4. Fresh verification. Re-run the Verify command from scratch every time. Never trust cached or prior results.

  5. Retry cap = 3 attempts. Initial + 2 retries, then stop. Never loop forever.

  6. Never corrupt completed work. Only revert files from the failing step. Never touch files from earlier passed steps.

  7. Checkpoint discipline. Run the Checkpoint commit exactly as written. Do not combine, reorder, or skip checkpoints on passed steps.

  8. Scope fence enforcement. For session specs: never modify files in the Never-touch list, regardless of what the Changes field says.

  9. Progress file is ground truth. Resume uses the progress file, not git log.

  10. No sub-agents. The executor reads and implements directly. No Agent tool, no TeamCreate, no delegation.

  11. Worktree isolation is mandatory for parallel execution. Every parallel claude -p session MUST run in its own git worktree. Never launch two or more sessions in the same working directory. This rule has no exceptions. Sequential (single-session) execution does not require worktrees.

  12. Worktree cleanup is unconditional. Before producing the final report (Phase 8), always remove all worktrees and session branches created during this execution, even if the run failed or was stopped. Leaked worktrees consume disk space and block future runs. If automated cleanup fails, report the manual cleanup commands in the final report.

  13. Merge sequentially, abort on conflict. After a parallel wave completes, merge each session's branch into the main branch one at a time with --no-ff. If any merge produces a conflict, run git merge --abort, report the conflicting files, and do not attempt further merges. Never use --force or --strategy-option theirs/ours to silently resolve conflicts.