Use at a specflo project's execute phase, when turning a validated plan.md into committed, verified code one task at a time. Triggers include "execute the plan", "start building", "work the next task", or `specflo status` showing the execute phase. Do NOT use before a plan has been validated, or for trivial fixes outside the pipeline.
Installs into .claude/skills of the current project.
Are you the author of Specflo Execute?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tacotakumi-specflo-execute)
---
name: specflo-execute
description: Use at a specflo project's execute phase, when turning a validated plan.md into committed, verified code one task at a time. Triggers include "execute the plan", "start building", "work the next task", or `specflo status` showing the execute phase. Do NOT use before a plan has been validated, or for trivial fixes outside the pipeline.
---
# execute
Drive a validated `plan.md` to a complete project: work each `T-NN` task as a
thin vertical slice — implement, test, verify, review, commit — then complete the
project behind a reconcile gate and a fresh-context final review. The CLI owns
state and the gates (`specflo task show`, `task start|done|block`, `validate
execute`, `advance`); this skill carries the loop, the implementation judgement,
and the discipline.
## When to use
- At the **execute phase**, after `specflo validate plan` passed and `specflo
advance` moved the project into execute.
- **Synthesize, don't re-plan** — the plan decided *what* and *in what order*;
execute *implements* it. If the plan is wrong, supersede a task — don't replan
in place.
## When NOT to use
- Before a plan is validated, or with no active project at the execute phase.
- For trivial one-off fixes that don't warrant the pipeline.
## HARD-GATE
Work the plan as written. If a task can't be done as specified, **supersede it**
(`specflo task add --supersedes T-NN …`) or recommend a phase split / a
superseding requirement — never silently mutate a task or drift off its
`Implements: REQ-NN`. *"I'll just change the plan"* is replanning, not executing.
## Process
1. **Preflight** — confirm an active project at the execute phase. Run `specflo
task show` to get the next actionable task's brief (its acceptance, verify
step, cited `REQ-NN` sections, and Global constraints). Read **only** the
brief — not the whole spec (keep context low).
2. **Per-task loop** — for the task from `task show`:
1. `specflo task start T-NN` (→ in_progress).
2. Implement the thinnest slice that satisfies the acceptance criterion. For
behavior-adding tasks, write the failing test first (**RED**), then the
minimal code (**GREEN**) — the task's Verify names the test.
3. Run the task's **Verify** step; capture the passing evidence.
4. **Self-review**: the verify step actually ran and passed; the diff matches
the acceptance criterion; only the task's files changed; no scope creep.
**No record keywords in anything that ships**: `REQ-`, `T-`, `D-`, `M-`
codes, review round, finding and probe numbers, and the project slug never
appear in code, comments, docstrings, tests, string literals or commit
messages — not even as identifiers (marker strings, env names, path
prefixes). Write the reason the citation stands for, or leave it out. A
reference you want to keep goes in the record: `specflo task note T-NN`
or `specflo task done --note`. The record cites commits, never the
reverse.
5. **Commit** one atomic commit for the task — stage only the files it
touched, never `git add -A`, so any point is a clean `git revert`.
6. `specflo task done T-NN` (it refuses unless the task is in_progress).
7. Next: `specflo task show` again.
3. **Checkpoint freely** — it is safe to stop between any two tasks: run `specflo
checkpoint` and clear context; resume drops you back at the next actionable
task. Long executions should clear context between tasks to stay sharp.
4. **Failure / blocked** — when a task's verify fails or you hit a wall, run a
bounded diagnose loop (reproduce → hypothesise → fix → re-verify). If
unresolved, `specflo task block T-NN --reason "…"` and escalate to the human —
never power through. If the *plan* is wrong, supersede the task.
5. **Stop on irreversibility** — destructive migrations, data deletion, secret
handling, posting/outbound actions, or "anything you can't undo with `git
revert`": stop and checkpoint with the human before proceeding.
6. **Readiness** — when `specflo task show` reports no actionable task (every
active task done, coverage holding), run the **final review in fresh
context**. Don't wait for a clean `specflo validate execute`: the review gate
lives *inside* that validator, so it keeps reporting the missing review
**until the round is closed** — a failing validate here is the reminder to
review, not a reason to hold off:
- Run the whole test suite once, before round 1: the command
`specflo config get test_command` prints, or the project's usual full test
command when it prints nothing. Review rounds run only the tests for the
files in scope.
- Open the round: `specflo review start` mints `review-N.md` and prints its
scope. Round 1 reviews the whole branch. Every later round is a delta
round: it reviews only the diff since the last reviewed round and checks
each earlier blocker and should-fix item (`--full` reviews the whole branch
again and still checks the items).
- Hand the reviewer the brief `specflo review prompt` prints, so every round
works to the same rules. With subagents: dispatch a reviewer on the most
capable model — it verifies the diff, not your report. Without subagents:
do **not** review inline (it defeats fresh eyes and burns context) —
`specflo checkpoint`, then run the review in a fresh session.
- The reviewer records findings through the CLI: `specflo review finding add
--severity blocker|should-fix|nit --at <file>:<line>[-<line>] --text "…"`
for each finding (`--at` is required for a blocker or should-fix; the CLI
marks a regression itself), `specflo review finding check F-NN
closed|open` for each earlier item, and `- none` as the only line under
Findings for a clean round.
- Close the round with `specflo review done`. The CLI sets the verdict from
the findings: any blocker or should-fix item, or an earlier item still
open, is changes-requested; nits never block and go to one follow-up.
`--file <path>` ingests a reviewer's report as the round's body.
- On changes-requested, fix each open blocker and should-fix item, never the
nits, with a fix task of its own: `specflo task add --fixes F-NN`. Its
acceptance lists every path that reaches the defect, with a test for each,
and its verify names the pin test, red then green: it fails before the fix
and passes after. Work each fix task through the loop above, then run
`specflo review start` again for the next round; it refuses while an open
item has no done fix task. A path the fix missed keeps the item open, and
an item a round checked open needs a new fix task (fresh or `--supersedes`
the failed one) before the next round.
- Defer or reject an item only on the user's say; ask, do not pick for them.
`specflo review finding defer F-NN --do "<what>"` files a follow-up and
settles the item (refused on a hosted project);
`specflo review finding reject F-NN --reason "<why>"` settles it as not a
defect. A changes-requested round whose blocking items are all settled
passes the completion gate.
- At the round budget (`review_max_rounds`, 2 rounds per level by default),
`review start` refuses and the choice is the user's: one more round with
`specflo review start --over-budget`, or `specflo review waive --reason
<why>`. Ask; do not pick for them.
- **Hardening** is available for a deeper look than the gate round gives:
`specflo review start --harden` opens a harden round, a fresh review of the
whole branch outside the round budget. `specflo review done` closes it as
hardened; its blocker and should-fix findings become items with a fix task
each, like any other, and its nits stay in the round. Completion still
needs the latest gate round to pass and no open item. After two quiet
harden rounds in a row the next-step hint suggests stopping; that is the
user's call. At the stop, run the whole test suite once
(`specflo config get test_command`, or the usual full test command when it
prints nothing).
- When any round was changes-requested, run the whole test suite again
before completion (`specflo config get test_command`, or the usual full
test command when it prints nothing).
On ready-to-merge, **pause before completing — don't auto-complete**: the work
is done and reviewed and the **checkpoint is saved** (the project's
`checkpoint.md`), so this is a safe place to stop. `specflo advance` completes
the project — the user's to call; **wait** for their go.
**Auto-mode carve-out.** The boundary pauses above are the *manual* default.
Under an opt-in `specflo auto` run, the auto-mode bootstrap's **boundary
override** (marked `== specflo auto-mode bootstrap ==`) drives the loop into
and through execute without pausing at boundaries; completion then follows the
bootstrap's terminal-stop — the loop halts on the CLI's `Completed project`
signal (or a guardrail/kill escalation) and never auto-completes, so
`specflo advance` still remains the user's call. This carve-out applies only
under that bootstrap; absent it, pause as above.
## Milestones
When the plan groups tasks into **milestones**, the CLI surfaces two soft signals
in the `specflo task show` brief (and in `status` / `checkpoint`) — honour them,
don't reimplement them:
- **Boundary verify beat.** When a milestone's last task completes, the brief
surfaces the just-completed milestone's **Exit checklist** with a soft,
user-gated *proceed* prompt. It never blocks the loop: pause, verify the Exit
items with the human, then continue. There is deliberately no "milestone done"
verb — the beat is derived, not marked.
- **Working-ahead label.** With no ready task left in the current milestone,
`task show` steers to the earliest ready later-milestone task, labelled
*working ahead* — fine to take, just know you've crossed the boundary.
Inspect milestones read-only with `specflo milestone list` / `specflo milestone
show M-NN`; milestone state is derived from task progress, never hand-edited.
## Fan-out
The project's **execution mode** is a recorded fact: read it from
`specflo status` (the `Execution:` line, or the `execution` key of `--json`).
Under **linear** the loop above is unchanged — work one task at a time exactly
as written. Under **fan-out** you are the *orchestrator*: the loop above is what
each *subagent* does for its task, and you drive the frontier:
1. **Frontier.** `specflo task list --json` — the tasks with `ready: true` are
dispatchable now; the CLI has already removed file conflicts with in-progress
work and pools with no free slot. The `pools` map shows every pool's size and
its current holders. An empty ready set with work still in progress means
**wait** for a running agent to finish — never re-`task start` a task that
is already `in_progress`.
2. **Dispatch.** Per ready task: `specflo task start T-NN`, then spawn
**one subagent** with the full `specflo task show T-NN` brief and, for each
pool in its `Needs`, the concrete **pool member** it is assigned (which GPU,
which venv, which port). Subagents **never run `git` or `specflo`** — plan
state and commits are yours — and edit only the task's **Files** plus any
**new test files** they create.
3. **Close.** When a subagent returns, **re-run the Verify** step yourself; its
report is not evidence. On pass: stage the task's files **by path** (never
`git add -A`), commit **one task per commit**, then `specflo task done T-NN`.
On fail: send the failure back (or start a fresh subagent with the same brief
plus the failure) — never mark it done.
4. **Long tasks** (downloads, benches, anything measured in minutes) run in the
**background**; keep dispatching the rest of the frontier and act on the
completion notification. Never predict a pending agent's result.
5. **The `user` pool.** A task needing `user` is **never delegated**: it runs in
the main session with the user, and holds the one `user` slot while it does.
6. **Recovery.** A slot held by a **dead** or abandoned agent is released with
`specflo task reopen T-NN` (→ pending): the task returns to the frontier and
its files and pool slots free.
7. **Daemon pools (hosted mode only).** In hosted mode a task whose `Needs`
names a daemon pool runs on a leased member of that pool. Run
`specflo lease request <pool>` before the task: the agent it prints is the
task's pool member, and you drive it with `specflo agent prompt <agent> <text>`.
Run `specflo lease release <lease>` after the task, success or failure:
also when the subagent or a prompt fails, and when you abandon the task or
`task reopen` it. A lease you keep holds a slot that other orchestrators
wait for. The ready set already counts the daemon's capacity for such a
name, whatever the plan's own `Pools` section says, so a task listed as
blocked on a pool is not dispatched. A request can still wait, up to 600 s
by default, when another orchestrator takes the slot first: run it as a
background task, or pass a `--wait` you can live with. The lease verbs, the
team form and the lease-ended errors are in the **specflo-agent** skill. In
local mode there is no daemon and `specflo lease request` is refused: a
local plan keeps its plan-level pools and its subagents as above.
Re-read the frontier after every `task done` / `task reopen` — the ready set
changes as slots and files free. Milestone boundaries still surface their Exit
checklist; the working-ahead note is suppressed under fan-out because lanes
crossing milestones is the expected shape.
## `task done` is earned
A task is done when its Verify step ran and passed and the diff matches the
acceptance — not when it "looks done." Check the diff, not your own report; a
stated rationale never downgrades a real gap.
## Correcting and annotating tasks
Never hand-edit `plan.md` — the CLI owns it. Two commands cover everything a
session needs, and which one applies is decided by the task's state: **edit
before done, annotate after.**
- **A task that is not yet done is wrong on its face** (a stale `Files` list, a
missing dependency, a typo in `Acceptance`): fix it with `specflo task edit
T-NN --acceptance "…"` — also `--title`, `--verify`, `--scope`, `--files`,
`--needs`, `--implements`, and the repeatable `--add-depends-on` /
`--drop-depends-on`. This is a correction, not a re-plan: if the *work* the
task describes is wrong, the **HARD-GATE** still applies — supersede it.
- **A task that is done is history.** Record what you learned against it with
`specflo task note T-NN --text "…" --label Design`, or replace the work with
`specflo task add --supersedes T-NN`. `task edit` refuses a done task unless
you pass `--force`, which is for a genuine correction to a finished entry and
appends an `[Edit]` note carrying the value it overwrote.
- **A superseded entry is frozen** — `task edit` refuses it with or without
`--force`. Edit the task that superseded it instead.
- **Labels** are a closed set: `Note` (the default), `Design`, `Resolution`,
`Descoped`. `Edit` is reserved for `task edit --force` and rejected from
`--label`. Note text is one line; notes accumulate at the bottom of the entry
and surface in `specflo task show`, nowhere else.
- **Closing a task with a note**: `specflo task done T-NN --note "…"` and
`specflo task reopen T-NN --note "…"` record the note in the same write as the
state change.
## Levels
At quick level the project is worked with the `specflo-quick` skill, not this
one. At fast level this loop runs as written, with two additions.
**Targeted tests per task.** At fast level, run the task's Verify for each
task, not the whole suite. If a Verify runs the whole suite (a bare
`uv run pytest`), correct it before you start the task with
`specflo task edit T-NN --verify "<the tests the task touches>"`. Run the full
suite once (`specflo config get test_command`, or the usual full test command
when it prints nothing), when `specflo task show` reports no actionable task,
before the review round.
**Uncovered work stops the loop.** At quick or fast level, when you find work
the goal needs that the brief or the plan does not cover, stop. Do not add
tasks for it, and do not do it on the side. Offer the user the move up:
`specflo level fast` from quick, `specflo level full` from fast. The move keeps
every document and every done task. With the user's agreement, the work can
instead go to the deferred list (the brief's Deferred section, or the
brainstorm's Out of scope / Deferred section), where a later level of this
project picks it up. Work the goal does not need does not stop the loop: it is
a follow-up (see **Follow-ups**).
**In a ladder run** (the auto payload carries a "Ladder run:" line) there is no
user to offer the move to: put the uncovered work on the deferred list and
carry on. The ladder moves up when the level completes, and the next level
picks the deferred work up.
## Follow-ups
The deferred list and the follow-ups hold different work. The deferred list
holds work inside this project's goal, for a later level of this project. A
follow-up is work this project will not do. Record it, do not drop it, and do
not do it on the side.
- **Work the goal does not need** (a flaky test, a gap in a neighbouring
command, a review finding this project will not fix):
`specflo followup add "<title>" --do "<what a later project should do>" --from "<the task, finding or test it came from>"`.
It gets an `FU-NN` ID in this project's followup document, and `specflo
advance` lists it when the project completes.
- **Deferred work left at the end.** Before `specflo advance` completes the
project, add a follow-up for each item on the deferred list that is still
work to do: nothing reads the deferred list after completion. An item that
only marks the scope (what the project chose not to do) is not work and
stays where it is. In a ladder run, do this only when the advance completes
the project; below that, the next level picks the deferred work up.
- **A follow-up this project settles.** When a task settles an open follow-up
that an earlier project left (the brainstorm names the ones this project
takes up), close it when you mark the task done after its commit:
`specflo task done T-NN --closes FU-NN --note "<what was done>"`. The
follow-up records the task as what closed it. Work outside any task closes
with `specflo followup close FU-NN --note "<what was done>" --by <commit>`.
## Ad hoc work: briefs
A project that lives past its plan grows by work the plan never named: the
user reports a problem or an idea, you do recon, you report findings and
options, the user picks, and tasks follow. That recon and those picks need
a home. The **brief** is it: one file per feature inside the project
(`briefs/B-NN-<slug>.md`), with the sections Ask, Facts, Decisions, Contract
and Deferred. The project keeps its level and phase. Size the ask first, then
take one of two paths.
**A bare task is enough** when you can see the fix without recon and the
user has nothing to pick: file one task (`specflo task add --from REQ-NN`,
or `--from B-NN` when it belongs to a brief that exists) and work it through
the per-task loop above. The task is the whole record.
**Use a brief** when any of these holds: recon is needed, the user has a
pick to make, more than one task comes out, or the result changes a decision
already made. Then:
1. `specflo brief add "<title>"` mints `B-NN`, records the current commit as
the brief's start, and prints its locator. Write the user's own words and
the date into Ask: `specflo brief set B-NN Ask --file <path>` (or
`--stdin`).
2. Do the recon and write what you found, with file references, into Facts
(`specflo brief set B-NN Facts`). Report findings, options and questions
to the user as you do now.
3. Record each pick the moment it lands: `specflo decision add --brief B-NN
--text "..." --rationale "..."`. Add `--diverges` when the pick departs
from the reference design the project follows; `specflo decision list
--diverges` then lists every approved divergence. Decisions take the
project's one `D-NN` sequence, so `--supersedes D-NN` works across the
brainstorm and every brief.
4. Write Contract (what is true after the brief's tasks are done) and
Deferred (what the brief found and does not do).
5. File the tasks with `specflo task add --from B-NN`. Acceptance is one or
two sentences about that task's slice; the facts and decisions live in
the brief, and `specflo task show` prints the brief under the task, so a
fresh session reads what the task depends on without reading the plan.
6. Work each task through the per-task loop above. When the last task that
cites the brief is done, `specflo task done` prints the offer to review
it: `specflo review start --brief B-NN` opens a round that reviews only
the brief's commits, from its start commit to HEAD, outside the level's
round budget. Take the offer: hand the reviewer `specflo review prompt`,
record findings and close the round as in **Readiness**. A blocker or
should-fix item gets a fix task (`specflo task add --fixes F-NN`) like
any other.
**A task that outgrew its path.** When a bare task turns out to need recon or
a pick, file the brief then and point the task at it: `specflo task edit
T-NN --implements B-NN` (keep any `REQ-NN` it already cites).
**Long fields.** The acceptance, verify and note fields are one line each.
When the text is long or full of quotes, write it to a file and pass
`--acceptance-file`, `--verify-file` or `--text-file` (`-` reads stdin); the
CLI folds it to one line.
## Anti-sycophancy
Do not open with "All done!", "Looks perfect", or similar. State what's
unverified or incomplete plainly. A green checkbox over an unrun verify step is
worse than an honest "blocked."
## Rationalizations
| Rationalization | Reality |
|---|---|
| "It basically works." | Completion needs fresh verification evidence, not a vibe — run the Verify step. |
| "The test will slow me down." | A behavior-adding task without a failing-then-passing test isn't done. |
| "I'll just tweak the plan as I go." | That's replanning — supersede the task instead (**HARD-GATE**). |
| "I'll mark it done and circle back." | `task done` means done and verified; don't flip ahead of the evidence. |
| "I'll review my own work inline." | The final review must be fresh context — subagent or a fresh session. |
## Red flags
- Calling `task done` without having run the task's Verify step.
- A commit that stages unrelated files (`git add -A`) instead of the task's own.
- Editing a task in place instead of superseding it when the plan is wrong.
- Advancing to completion without a fresh-context whole-branch review.
- Fixing nits in the project, or choosing between one more round and a waive
for the user at the round budget.
- Loading the whole spec instead of the `task show` brief.
## Verification
Before completing the project:
- [ ] Every active task is `done` and each earned its own atomic commit.
- [ ] `specflo validate execute` exits 0. It stays red
**until the round is closed**, so expect it to pass only once the review
below is recorded — not before it.
- [ ] A fresh-context final review ran under `specflo review start` and was
closed with `specflo review done`; the latest gate round is
ready-to-merge or has every blocking item settled (or a reasoned waive),
and no item is left open.
- [ ] The whole test suite ran again after the fixes when a round was
changes-requested.
- [ ] Then, and only then, surface the checkpoint-saved phase-end beat and leave `specflo advance` (project completion) to the user.