--- name: wf-spec-drive description: Run the whole lifecycle for one spec, calling the other skills in order and advancing one legal transition at a time until it reaches a target state (default complete), stopping to ask at irreversible gates. Use when the user wants a spec taken from wherever it is to done rather than running each step by hand — and start here when unsure which single-spec skill applies. argument-hint: [target-status=complete] user-invocable: true --- # Drive a Spec Through the Lifecycle Advance the spec at the first argument toward a target state (default `complete`), one or more **legal** transitions at a time, reporting the new state at the end of every turn. This is the orchestrator: it reads reality, picks the next step, runs the right `/wf-spec-*` sub-skill (or transition API call), and stops at gates. It is built to be **re-invoked**: under a `/goal` the Stop-hook evaluator re-runs you each turn with the remaining work, so each turn must (a) make concrete progress and (b) end by stating the spec's current `status` in your message, so the evaluator can judge whether the goal is met. Within a turn, carry the spec through every legal, non-gated transition you can; end the turn at a gate, at the target, or when the next step waits on work outside this session. ## The canonical lifecycle Seven states. **`status` is the single source of truth; transitions must follow the legal edges below — there is no `implemented`/`in_progress` state, and `validated → complete` is ILLEGAL.** A spec reaches `complete` only through `testing`, where a drift verdict is rendered. ``` vague → drafted | archived drafted → validated | stale | archived validated → testing | stale testing → complete | stale | archived complete → stale | archived stale → drafted | validated | archived archived → drafted (resurrection) ``` Server-automatic vs. agent-initiated: | Edge | Who drives it | | --- | --- | | drafted → validated | agent (`validate` action) or folder-dispatch auto-promote | | validated → testing | **server** on task-done (drift pipeline); or wrap-up for the direct path | | testing → complete / stale | **server** drift verdict; or `force-complete`; or wrap-up's verdict | | any → stale (fan-out) | **server** on task-done / chat-edit; agent may `stale` manually | | any → archived, archived → drafted | agent (`archive` / `unarchive`) | ## How status changes (hybrid) By default there is no server: advance the status by editing the spec's frontmatter along a legal edge and committing it, exactly as the other skills do. Where a transition API is present, prefer it because it is authoritative, validates the edge, runs drift / stale fan-out, and commits: `POST /api/specs/transition` with `{ "action": "", "path": "" }`. Actions: `dispatch`, `undispatch`, `archive`, `unarchive`, `validate`, `stale`, `unstale`, `dismiss-stale`, `force-complete`, `migrate`. `/wf-spec-dispatch` uses the same endpoint. Whether you edit frontmatter or call the API, only ever move along a **legal edge** above. Never write an illegal jump (e.g. `validated → complete`). Note there is no API action to enter `testing` or to `complete` from `validated` directly; the server enters `testing` on task-done, and `force-complete` only does `testing → complete`. The direct-implement path (below) therefore walks `validated → testing → complete` itself. ## Step 1: Read reality 1. Read the spec's frontmatter: `status`, `dispatched_task_id`, `depends_on`, `affects`, and whether it has a child-spec directory (non-leaf). 2. If `dispatched_task_id` is set, check the linked task's status (done / in_progress / failed) on the board, where one exists. 3. Establish the **target** (arg 2, default `complete`) and confirm the spec is not already there or past it. ## Step 2: Pick the next step (decision table) Match the current `status` and choose the next action toward the target: | Current | Condition | Next step | | --- | --- | --- | | `vague` | — | `/wf-spec-refine` (or `/wf-spec-create` follow-up) to make it concrete → `drafted`. Then re-loop. | | `drafted` | large / many open questions | `/wf-spec-breakdown` (design) → child specs; then drive the lead child. **Gate?** No. | | `drafted` | small, items clear | `/wf-spec-validate` (lint), then `validate` action → `validated`. | | `validated` | leaf, build in one pass | `/wf-spec-implement` (direct, **autonomous mode** — no plan-mode pause under a goal), which finishes via `/wf-spec-wrapup` (testing→complete). | | `validated` | wants board execution | **GATE**: dispatching to the board is outward — confirm with the user, then `/wf-spec-dispatch`. | | `validated` | non-leaf with task children | dispatch/implement each leaf (drive children); parent completes when leaves do. | | `testing` | task done, server idle | `/wf-spec-wrapup` renders the verdict → `complete` or `stale`. | | `testing` | tester failed (`testing_pending`) | report; offer `force-complete` (a gate — confirm). | | `complete` | — | At target. If the user wanted downstream specs driven, pick the next unblocked dependent. | | `stale` | — | `/wf-spec-refine` → `drafted`/`validated`, then re-loop. | | `archived` | — | Stop unless the user asked to resurrect (`unarchive` → `drafted`). | Dependencies: before implementing/dispatching, confirm every `depends_on` is `complete` (per the sub-skills' own gates). If a dependency is not complete and the target requires it, drive the dependency first or report the block. ## Step 3: Gate check before acting **Pause and ask the user** (do not execute) when the next step is: - **Dispatch to the board** (creates outward work / a running task). - **Archive** (retires the spec + descendants; relocates files). - **Stale fan-out across a dependency tree** (marks other people's specs stale) — manual `stale` on a spec with dependents. - **`force-complete`** (overrides the drift gate). For all other steps (refine, validate, breakdown, implement-direct, wrap-up of a spec you implemented this run), proceed without pausing. ## Step 4: Execute, then report Run the chosen sub-skill / API call. Make all the **non-gated, legal** progress you can in this turn (e.g. validate → implement → wrap-up is one turn for a small leaf); stop at the first gate, the target, or a step that waits on work outside this session, such as a dispatched board task. End every turn with a status line the goal evaluator can read, e.g.: ``` Spec : status → . Target: . Next: | DONE>. ``` ## Running under a `/goal` (what is and isn't truly hands-off) A user sets, e.g., `/goal spec reaches status complete`. Each turn the Stop-hook evaluator reads your transcript; if the spec is not yet at the target it re-invokes you with what remains. You don't manage the loop: you make and report progress each turn. The harness pauses the goal when the evaluator keeps finding it unmet, and clears it when met. Be honest about the reach of an **unattended** loop (no human watching): - **Fully autonomous** — the non-gated, in-session transitions: `refine`, `validate`, `breakdown`, `implement` (autonomous mode, no plan-mode pause), and `wrap-up` through the `testing` gate. A small validated leaf can therefore go all the way to `complete` unattended. - **Stalls and needs a human** — every gate in Step 3 (dispatch to the board, archive, `force-complete`, stale fan-out). The evaluator can't approve them and can't run commands, so an unattended loop cannot pass them, and repeated unmet checks pause the goal. When you reach a gate, **state it plainly and end the turn**: report "GATE: (needs you)", so when the user returns they can unblock with one message. - **Completes outside the loop** — a *dispatched* spec finishes asynchronously on the task board; the drift pipeline (server) renders its verdict on task-done. The goal loop can't wait that out, and the evaluator can't observe the task finishing. So a goal targeting a spec you dispatch will pause at the dispatch gate; after the board task is done, re-run `/wf-spec-drive` (or `/wf-spec-wrapup`) to pick up `testing → complete`. Net: `/goal` + `/wf-spec-drive` runs the in-session path to `complete` hands-off, and turns every outward/async step into a clearly-reported stop rather than a silent hang. Don't claim more autonomy than that. ## Guidelines - **One source of truth** — never invent a status; only ever move along the legal edges above. When unsure a transition is legal, prefer the server API (it rejects illegal edges) over a YAML edit. - **Don't double-manage dispatched specs** — once a spec is dispatched, the server drives `validated → testing → complete/stale` on task-done. Don't hand-set its status; let the server, then run `/wf-spec-wrapup` only to enrich the Outcome. - **End every turn with the status line** — the closing `status` line is the contract with the goal evaluator; keep it accurate. - **Respect the gates** — autonomy stops at outward/irreversible actions.