/execute-plan — Plan Executor (judgment layer)
The deterministic runtime — task loop, retries, worktree lanes,
review-fix cycles, report assembly — lives in
workflows/run-plan.mjs and runs via the Workflow tool. This skill
owns everything that requires judgment: preflight gates, ambiguity
handling, disposition decisions, verdict interpretation, postmortem.
Before the first user update, read simplify. Apply its output guidance to every assistant-written progress update, task or milestone summary (including legacy waves), blocker, decision request, and final response. The technical messages below describe internal conditions: explain what each means for the user's goal instead of quoting gate numbers or failure codes as the user-facing summary. Preserve exact diagnostics in the report. Explain raw Workflow output when relaying it; the skill cannot intercept host-rendered logs.
Preflight (all gates must pass before the workflow launches)
Repo-delivery contract. Read
CLAUDE.md ## Commandsper_internal/repo-delivery. Missing → halt with:Repo missing required CLAUDE.md ## Commands section.Validate plan — refuse contract. Run
/validate-plan <path>.FAIL→ refuse to execute; surface findings. Only an explicit human--forceoverrides, and its use goes in the final report.Workspace. Refuse to run on
default_branch. If needed, createexecute-plan/<slug>-<timestamp>offdefault_branch. RecordbaseSha(HEAD) andplanSha(sha256 of the plan file).Pre-execution clarification (codebase-aware).
This is NOT a re-validation of the plan.
/validate-plan(gate 2) has already passed — the plan's structure, acceptance criteria, and closed decisions are fine. Gate 4 is a separate, codebase-aware gate that fires only when the plan, read against the actual repo state, has more than one reasonable execution. It cannot run until the repo is present, which is why it happens here and not inside/validate-plan.When gate 4 pauses, explain it with this framing so the operator does not read it as "the plan is bad":
The plan is ready, but <named requirement> could apply to either <concrete option A> or <concrete option B> in this project. <Explain the practical difference and recommendation, if supported.> <Ask for the specific choice needed before starting that work.>Never phrase gate 4 output as "the plan tasks are not atomic" or "the plan has problems" — that contradicts the verdict that just passed and is the single biggest UX defect this flow has shipped.
The executor must distinguish ambiguity (→ pause or abort) from uncertainty (→ try). An ambiguity is a point where the plan has more than one reasonable reading given the repo and picking silently would produce code that might not match the author's intent. The heuristic:
Would a human reading the plan and seeing what I'm about to do say "yes, that's obviously what I meant"? If yes, proceed. If no, pause.
Three categories that count as ambiguity
- Referent ambiguity — the plan names a thing and the repo has
more than one candidate. "Modify the user service" when
src/services/user.ts,src/api/user/controller.ts, andsrc/models/user.tsall plausibly fit. - Existing-state ambiguity — the plan prescribes an addition and the repo already has something overlapping. "Add a rate limiter" when IP-level throttling is already present; add-on, replace, or stack are all defensible.
- Scope-boundary ambiguity — the plan prescribes a change and the change's natural boundary crosses something the plan didn't mention. "Refactor the auth middleware into a service class" when the middleware calls a helper in a sibling module and is hooked by a logger.
What is NOT ambiguity (proceed, do not pause)
- "I don't know how to implement this." That's an executor-skill issue; try.
- "There's a better way than the plan specifies." That's scope
discipline; follow the plan, log a
minorfinding. - General uncertainty about outcomes — not the same as the plan having multiple reasonable readings.
Record every ambiguity — answered or aborted — as a
plan-ambiguityfinding in the final report.Interactive session → surface each ambiguity with AskUserQuestion and record the answer as a closed decision appended to the plan (this changes planSha — recompute). Autonomous session → halt listing the ambiguities as open questions.
- Referent ambiguity — the plan names a thing and the repo has
more than one candidate. "Modify the user service" when
Ontology revision. When the plan's source PRD has a sibling
ONTOLOGY.md, read its Extension Log and itssettledrows. A task or closed decision in the plan that contradicts asettledrow without a matchingrevisionentry in that Extension Log → halt with anontology-revisionfinding naming the row and the contradicting task.An
additionentry in theONTOLOGY.mdExtension Log passes.A revision — one of exactly five kinds per
_internal/ontology-readiness§ Completeness and Extension Rule 4: changed reference scheme, homonym split, tightened constraint, reclassified modality, retrofitted temporality — is mode-dependent, and the mode is read from themode:header ofONTOLOGY.md: infeaturemode anyrevisionentry in the Extension Log is a halt condition and halts with anontology-revisionfinding;refreshmode follows thefeaturerule, so anyrevisionentry halts the same way; ingreenfieldmode arevisionentry is itself a defect — nothing existed to revise — and halts the same way; inrewritemode arevisionentry must be matched by a confirmed closed decision in the PRD, and is a halt — the sameontology-revisionfinding — only if it is not.This gate does not score readiness.
/execute-prdand/kickoffown theOntology:verdict; gate 5 only refuses a plan that silently rewrites a settled domain fact.
Launch the runtime
Invoke the Workflow tool:
Workflow({
scriptPath: "<this-skill-dir>/workflows/run-plan.mjs",
args: {
planPath, planSha, baseSha, branch,
commands: { install, lint, build, test, defaultBranch }, // from ## Commands
flags: { maxRetries: 20, maxFixCycles: 3, acceptRisk: [<from --accept-risk>], adversarial: "<auto|always|never>" },
timestamp: "<ISO now>"
}
})
<this-skill-dir> is the Base directory for this skill: path
printed when this skill loaded. run-plan.mjs is a Workflow-tool
script, not a Node module: pass its absolute path as scriptPath and
nothing else — do not run it with node, import it, or paste its
contents into script. This instruction is the operator's opt-in to
multi-agent orchestration; no further confirmation is needed. If the
session has no Workflow tool, halt and say so — do not emulate the
script with the Agent tool.
While it runs, do not implement tasks yourself — the workflow owns
execution. On a thrown error the run is preserved (worktree branches
and commits stay); diagnose, then resume with the same scriptPath and
resumeFromRunId from the failed run — completed agent calls replay
from cache.
Interpreting the result
The workflow returns the report object. Write
execution-report.json verbatim and render execution-report.md
from it (tables: per-task, findings with disposition statuses,
deviations, retry stats).
Verdict rules (apply the disposition rubric in
_internal/disposition/SKILL.md; open is not a valid end-state):
- PASS — all tasks done; every critical/major finding is
fixedoraccepted-risk; onlyminor/nit/plan-deviation/plan-ambiguityfindings may remain (in terminal statuses); checkpoint passes; plan aligned. - WARN — all tasks done; some
minor/nitfindings remain in terminal status (open,defer,disagree-with-evidence); anyplan-deviationfindings have a terminal disposition (disagree-with-evidence,defer, oraccepted-risk); no blocking criticals/majors; checkpoint passes. - FAIL — any
criticalormajorfinding endsopen; anyplan-deviationorplan-ambiguityendsopen(these severities demand explicit disposition); checkpoint fails; or plan alignment has undispositioned gaps.
Plan-deviations that are terminally dispositioned (including
accepted-risk via --accept-risk) do not push the verdict to
FAIL. They count as WARN.
The professional grade does not affect the verdict. A junior-graded
component still PASSes if it's bug-free. The grade is informational — the
team decides what to do with it.
Disposition vocabulary and end-state rules are canonical in
_internal/disposition/SKILL.md; the workflow emits statuses from
that vocabulary and this skill never invents new ones.
Decision records
Write records per _internal/decision-record/SKILL.md for choices a
future run could plausibly reverse — ambiguity resolutions from
preflight gate 4 and accepted-risk deviations always qualify.
Postmortem
Fire when verdict is WARN/FAIL, the retry budget was exhausted, or
any deviation ended accepted-risk. Output lands next to the execution
report; append to docs/postmortems/index.json.
Markdown structure (full mode)
# Postmortem
## Run reference
- **Plan:** <plan-file>
- **Verdict:** <verdict> Gate: <gate_state>
- **Branch / base / head:** ...
- **Trigger:** <which auto rule fired, or "--postmortem=always">
- **Mode:** full | lightweight
## What happened
<2–4 sentence narrative — not a chat transcript, not a restatement
of findings.>
## What worked
<Process strengths observed: which gates caught what, which auto-fix
cycles converged cleanly, where the closed decisions saved time.>
## What broke down
### Tool and skill usage
<Which gates fired or didn't fire, and whether that was correct.
Threshold issues (e.g. adversarial review missed a 187-line auth diff
because the threshold is 200). Skills invoked at the wrong time, or
not invoked when they should have been. Repo-delivery flags or
`adversarial_triggers` paths that need tuning.>
### Requirements fit
<Ambiguity in the source PRD/AERS that drove rework. Plan-deviations
or plan-ambiguities whose root cause was an unsettled product
decision. Closed decisions that should have existed but didn't.
aers-readiness rubric items that the source missed, and ontology items
it missed — missing reference schemes, non-total lifecycles, unstated
temporality.>
## What the process missed
<Gaps only visible in hindsight. Coverage holes (link to `unproved`
rows). Reviewer blind spots. Plan structure that hid risk.>
## Recommendations
<Specific, actionable. Each recommendation MUST cite a target from
the taxonomy below so the recommendation can aggregate across runs.
Free-text recommendations that don't aggregate are a bug.>
| # | Target | Type | Summary |
|---|---|---|---|
| 1 | `_internal/disposition` | tune-threshold | Disposition loop allowed 3 cycles where 2 would have caught the same fix |
| 2 | `closed-decisions/auth/session-cookie-name` | new-decision | Session cookie name was re-debated this run; capture as closed decision |
In lightweight mode, omit What worked and the two named lenses.
The remaining shape is What happened → What broke down (free
form) → Recommendations (still structured).
Recommendation taxonomy
Every recommendation row in the markdown table corresponds to a
structured object in postmortem.json. The target and type fields
use a fixed vocabulary so cross-run aggregation works.
target vocabulary (where the recommendation lands):
target value |
What it points at |
|---|---|
_internal/disposition |
The disposition rubric |
_internal/repo-delivery |
The repo-delivery contract / ## Commands schema |
_internal/<other> |
Any other rubric in the skill library |
closed-decisions/<category>/<slug> |
A new or updated closed decision fragment |
claude-md/commands |
The repo's CLAUDE.md ## Commands section |
claude-md/conventions |
The repo's CLAUDE.md conventions section |
adversarial-triggers |
The adversarial_triggers glob list |
auto-accept-deviations |
The auto_accept_deviations category list |
plan-template |
The plan author's template (drives /execute-prd step 7) |
aers-readiness |
The AERS readiness rubric |
ontology-readiness |
The ontology readiness rubric |
execute-plan-skill |
This skill's own behaviour (gates, phases, defaults) |
execute-prd-skill |
The /execute-prd skill's behaviour |
domain-review-profile |
A domain-review profile (breakpoint or full) |
process-doc/<name> |
Any project-level process doc not covered above |
If a recommendation genuinely doesn't fit, use target: other and put
the intent in summary — but treat that as a smell, not a release
valve. Repeated other values are a sign the taxonomy needs an entry.
type vocabulary (what kind of change):
type value |
Meaning |
|---|---|
tune-threshold |
Numeric threshold needs adjustment (line counts, retry counts, timeouts) |
tune-trigger |
A glob, signal, or condition that controls when something fires |
new-decision |
Add a closed decision capturing a settled fact |
update-decision |
Modify an existing closed decision |
new-convention |
Add a project convention to CLAUDE.md |
add-rubric-rule |
Extend an existing rubric with a new rule |
tighten-gate |
Make an existing gate stricter |
relax-gate |
Make an existing gate less strict (rare; needs evidence) |
add-gate |
Introduce a new gate or phase |
remove-gate |
Remove a gate that produces no signal |
improve-prompt |
Reword an instruction passed to a worker or reviewer |
documentation |
The skill or process is correct but the docs don't reflect reality |
JSON schema (postmortem.json)
{
"run": "2026-05-05-143000",
"plan_file": "docs/plans/<plan-slug>.md",
"verdict": "WARN",
"gate_state": "completed-with-accepted-risk",
"trigger": "unproved-rows",
"mode": "full",
"recommendations": [
{
"id": "R-001",
"target": "adversarial-triggers",
"type": "tune-threshold",
"summary": "Adversarial threshold of 200 lines missed a 187-line auth diff",
"evidence": "execution-report.json#findings.F-014",
"actionable": true,
"confidence": "high"
}
],
"headline": "<one-line summary, copied from the highest-confidence actionable recommendation>"
}
actionable: true means a future skill could mechanically apply the
change. confidence: high|medium|low lets /process-tune weight
recurring recommendations.
Cross-run aggregation
After writing postmortem.md and postmortem.json, append a row to
the project-level postmortem index:
- Path:
docs/postmortems/index.json(relative to the repo root, not the run folder). - Append, never rewrite. The index is an event log; old rows are immutable evidence even if the recommendation later proved wrong.
- Schema:
[ { "run": "2026-05-05-143000", "run_folder": "docs/runs/2026-05-05-143000/", "plan_slug": "<plan-slug>", "verdict": "WARN", "gate_state": "completed-with-accepted-risk", "trigger": "unproved-rows", "recommendations": [ { "id": "R-001", "target": "adversarial-triggers", "type": "tune-threshold", "summary": "...", "actionable": true, "confidence": "high" } ] } ]
If docs/postmortems/index.json does not exist, create it as []
before appending. Do not gate on the directory existing — create it.
/process-tune (the symmetric consumer skill) reads this index,
groups by target + type, and proposes concrete artefact edits when
the same recommendation appears across multiple runs.
Hard rules
- Not a second requirements document. Do not restate scope.
- Not a chat-transcript summary. No turn-by-turn replay.
- Not a restatement of review findings. Findings are in the execution report; postmortem analyses the process around them.
- Not a blame document. No "the model should have known" framing.
- Length cap: target one page (full mode) or half a page (lightweight). A long postmortem signals the run itself was unrecoverable and the next action is human review, not a longer document.
- Recommendations must use the taxonomy. Free-text targets that
bypass the
target/typevocabulary defeat aggregation. If the taxonomy doesn't fit, the taxonomy needs extending — not bypassing.
Enforcement notes (not prose rules — actual config)
Destructive git commands are denied by settings.template.json
permissions (git reset --hard, git push --force*, git clean -f,
git branch -D). This skill assumes those rules are installed; it
does not restate them as instructions.
Contract
- Inputs:
<path>to a plan file in the_internal/plan-formatcontract; optional--force(override a/validate-planFAIL),--accept-risk <category>,--adversarial <auto|always|never>, andresumeFromRunIdwhen resuming a failed run. Calls/validate-plan(preflight gate 2) and theworkflows/run-plan.mjsWorkflow script, which owns the task loop. Consults_internal/repo-delivery,_internal/disposition,_internal/decision-record, and_internal/ontology-readiness(preflight gate 5). - Preconditions: the session has the Workflow tool; repo has a
CLAUDE.md ## Commandssection; the plan validates (or a human--forceis explicit and recorded); the working branch is notdefault_branch. - Outputs:
execution-report.jsonwritten verbatim from the workflow result plusexecution-report.mdrendered from it; decision records for choices a future run could reverse; a postmortem plus adocs/postmortems/index.jsonentry when the verdict is WARN/FAIL, the retry budget was exhausted, or any deviation endedaccepted-risk. - Postconditions: a PASS / WARN / FAIL verdict is stated against the
rules above; no
criticalormajorfinding is leftopenwithout the verdict being FAIL; everyplan-ambiguityresolved or raised in preflight gate 4 appears in the report; commits and worktree branches from a thrown run are preserved for resume. - Failure modes: missing
CLAUDE.md ## Commands→ halt;/validate-planFAIL without--force→ refuse to execute; ondefault_branch→ refuse; preflight-gate-4 ambiguity in an autonomous session → halt listing the open questions asplan-ambiguityfindings; a task or closed decision contradicting asettledONTOLOGY.mdrow with no matchingrevisionentry in its Extension Log — or, inrewritemode, arevisionentry with no matching confirmed closed decision in the PRD → halt with anontology-revisionfinding (preflight gate 5), whileadditionentries pass; no Workflow tool → halt and say so, never emulaterun-plan.mjswith the Agent tool.
When NOT to Use
- No plan exists — use
/execute-prd(PRD input) or superpowers:writing-plans (ad-hoc). - Plan doesn't follow the plan-format contract — superpowers:executing-plans is the lighter general executor.
- Trivial single-file change — edit directly.