# Drive

> 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.

- Skill: `latere-ai/drive` (Agent Skill)
- Install (CLI): `npx skillmds@latest add latere-ai/drive`
- Raw SKILL.md: https://api.skillmd.com/api/skills/latere-ai/drive/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: latere-ai (https://skillmd.com/u/latere-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/latere-ai/drive

---


# 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 `/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. Do not try to finish everything in one
turn — finish what's legal now, report status, and let the loop continue.

## 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": "<action>", "path": "<workspace-relative spec path>" }`. Actions:
`dispatch`, `undispatch`, `archive`, `unarchive`, `validate`, `stale`,
`unstale`, `dismiss-stale`, `force-complete`, `migrate` (the switch in
the server's action switch). `spec:dispatch` already uses this.

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) — `GET /api/tasks/{id}` or 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` | — | `/spec:refine` (or `/spec:create` follow-up) to make it concrete → `drafted`. Then re-loop. |
| `drafted` | large / many open questions | `/spec:breakdown` (design) → child specs; then drive the lead child. **Gate?** No. |
| `drafted` | small, items clear | `/spec:validate` (lint), then `validate` action → `validated`. |
| `validated` | leaf, build in one pass | `/spec:implement` (direct, **autonomous mode** — no plan-mode pause under a goal), which finishes via `/spec:wrapup` (testing→complete). |
| `validated` | wants board execution | **GATE**: dispatching to the board is outward — confirm with the user, then `/spec:dispatch`. |
| `validated` | non-leaf with task children | dispatch/implement each leaf (drive children); parent completes when leaves do. |
| `testing` | task done, server idle | `/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` | — | `/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 one stage, then report

Run the chosen sub-skill / API call. Do as much **non-gated, legal** progress as
fits this turn (e.g. validate → implement → wrap-up can be one turn for a small
leaf), but stop at the first gate, the target, or a genuinely long step.

End every turn with a status line the goal evaluator can read, e.g.:

```
Spec <path>: status <old> → <new>. Target: <target>. Next: <next step | GATE: <what> | DONE>.
```

## Running under a `/goal` (what is and isn't truly hands-off)

A user sets, e.g., `/goal spec <path> 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 caps consecutive auto-continues (≈8) and the goal
auto-clears 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; it will burn blocks
  and the harness force-stops (~8). When you reach a gate, **state it plainly and
  stop asking-into-the-void**: report "GATE: <what> — 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 (≈8 blocks) 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 `/spec:drive` (or `/spec:wrapup`)
  to pick up `testing → complete`.

Net: `/goal` + `/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 `/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.

