/verify-done
The end gate of the loop: cleanup → extract-links → blueprint → goal-prep → /goal → **/verify-done**.
It answers "does it actually work, including what the plan didn't think of?" — not "are the boxes ticked?".
Letter = spirit. If a rule blocks you from reaching the goal it was written for, the rule is wrong, not the goal. Here the goal is an honest verdict — never a false DONE, never a FAIL for something that just couldn't be verified.
Gate, not fixer.
/verify-donehas noEdit/Write. It verifies and reports; fixing goes back to/goal(autonomous) or/simplify(quality).
Usage
/verify-done [<plan-or-spec path>] [--deep] [--block-on-quality]
- No path → locate the most recent
/blueprintplan (<spec-stem>/tasks.md, whose## Tasksblocks carry theDone when:proofs, + its sibling<spec-stem>/reference.mdfor context; or a single<spec>.md) orgoal.mdcharter; or use an approved native plan-mode plan / an inline plan / "the diff + what it was meant to do" straight from the conversation. Ask viaAskUserQuestiononly if the intent is genuinely unclear. --deep→ Tier 2 generates scenarios across all requirements + adversarial inputs (default is light: top high/med-risk only).--block-on-quality→ high-severity Tier 3 findings flip the verdict to NOT-DONE (default: Tier 3 is advisory, never blocks).
Weaknesses and when NOT to use
- Needs a runnable environment. If the
Done when:proofs / scenarios can't run (no server, missing deps), they come back UNKNOWN → verdict NOT-DONE "could not verify". That's honest, not a failure of the change — but it means/verify-donecan't bless work it can't exercise. - Only as good as the original intent it's handed. Tier 2 grounds scenarios in the ORIGINAL intent (the reference file / plan / notes). Garbage intent → shallow scenarios.
- Unstructured plan = softer verdict. With no
Done when:proofs (a plan-mode/inline plan), verification is scenario-driven rather than proof-driven — great for small tasks, weaker for critical ones. For high-stakes work, write proofs (/blueprint). - Not a bug hunter or a linter. Correctness bugs →
/code-review; per-change behaviour →/verify; maintainability auto-fixes →/simplify./verify-doneis whole-plan acceptance. - Workflow tool may be unavailable (plan-gated). Then it falls back to a sequential prose
Agentfan-out — same verdict shape, just slower.
What it does
- Resolve inputs (thin part — keep it cheap).
/verify-doneis plan-source-agnostic — use whichever you have:- Structured (best, proof-driven): a
/blueprintplan —<spec-stem>/tasks.md(or a single<spec>.md). Parse theDone when:lines from its## Tasks### TASK-nblocks intodoneWhenProofs = [{id, title, cmd}]; intent = the sibling<spec-stem>/reference.mdcontext (## Overview/## Requirements/…), or the single<spec>.mditself. Or agoal.mdcharter (proofs from its audit table, intent from its stated outcome). If tasks.md## Needs your attentionhas unresolved blocking❓ NEEDS YOUitems, pass them inintentNotes— an open blocking decision means the plan isn't acceptable yet; surface each in the verdict's NOT-covered bucket rather than blessing around it. - Unstructured (plan-mode / inline / just-the-diff, scenario-driven): an approved native plan-mode plan, an inline description, or "here's the change + what it was supposed to do." No
Done when:lines exist, so: (a) derive a few concrete shell proofs from what the plan promises (an endpoint/CLI/behaviour it claims → a command that exercises it) intodoneWhenProofs; (b) the plan prose is the intent → pass it verbatim asintentNotes. ⚠️ A plan-mode plan lives only in the conversation — the Workflow's sub-agents can't see it, so YOU read it from context and pass it inintentNotes(and any derived proofs). - Always: grab
buildCmd/testCmd/regressionCmdfrom the repo if obvious (else null). If nothing identifies the real intent, ask once viaAskUserQuestion. - Sandbox: prefer a throwaway git worktree (
ToolSearchforEnterWorktree; use it if present), else a temp dir, elsenone. Scenarios/proofs run there so the repo isn't mutated. - Knobs:
--deep,--block-on-quality. Load the text BETWEEN theBEGIN_PROMPTandEND_PROMPTsentinels inroles/quality-review.mdintoqualityPrompt(skip the provenance header aboveBEGIN_PROMPTand the sentinel lines themselves — they're meta, not instructions).
- Structured (best, proof-driven): a
- Run the gate — invoke the workflow (heavy work stays in its sub-agents; only the verdict returns):
Fallback (Workflow unavailable /Workflow({ scriptPath: "workflows/verify-done.workflow.js", args: { doneWhenProofs, buildCmd, testCmd, regressionCmd, coverageCmd, intentNotes, deep, blockOnQuality, qualityPrompt, sandboxKind, sandboxDir } })scriptPathdoesn't resolve): run the same three tiers as a sequentialAgent(subagent_type="general-purpose")fan-out — identical schemas, just not parallel. (IfscriptPathfails, pass the script viascript:inline.) - Report the short verdict + three honest buckets. Hand findings back to
/goalor/simplify. Do not fix anything yourself.
The three tiers (in the workflow)
- Tier 1 — Conformance: re-run every
Done when:proof (explicit or derived) + build/test/regression in the sandbox →PASS|FAIL|UNKNOWN. With an unstructured plan and nothing derivable, Tier 1 falls back to build/test only; if those don't exist either it's empty → the verdict leans on Tier 2 (report it — softer than proof-driven). - Tier 2 — Independent scenarios: one agent reads the original intent and generates risk-ranked user-case/edge/adversarial scenarios (light by default,
--deepwidens); the runnable ones execute in the sandbox. Catches what the plan's own proofs didn't. - Tier 3 — Quality (advisory): runs LAST and only if behaviour works;
roles/quality-review.md(thermo substance) emits structured maintainability findings. Advisory unless--block-on-quality.
Honesty rails (non-negotiable)
- UNKNOWN ≠ pass/fail. Can't run it → UNKNOWN with a reason. No runnable env → all UNKNOWN → NOT-DONE "could not verify" — never a false DONE, never a FAIL.
- Don't invent requirements. Every Tier-2 scenario carries
groundedIn(a quote from the original intent). A "system doesn't do X" where X was never asked → UNKNOWN + "confirm with human", not an auto-FAIL. Ungrounded candidates are discarded and counted. - No silent truncation. The
notCoveredlist always reports what wasn't run/covered (UNKNOWNs, unrunnable scenarios).
Output
VERDICT: DONE | NOT-DONE — <reason>
Tier 1 (conformance): N/M PASS, K UNKNOWN
Tier 2 (scenarios): generated G (D discarded), ran R; confirmed gaps: …
Tier 3 (quality): F findings (advisory|blocking) — listed
NOT covered (check manually): …
DONE ⟺ Tier 1 fully PASS and Tier 2 has no confirmed (high-confidence, grounded) gap and (quality not blocking, unless --block-on-quality). Otherwise NOT-DONE with the three buckets: confirmed failures / UNKNOWN-to-check / suspected-out-of-scope.
Connections
- Input: a
/blueprintplan (a<spec-stem>/directory withtasks.md+reference.md, or a single<spec>.md), agoal-prepgoal.mdcharter, or — for small tasks — a native plan-mode / inline plan straight from the conversation (native plan mode → implement → /verify-done).goal-prepwrites "hand finished work to/verify-done" into the charter; this is that hand-off. - Per-stage vs end: the lightweight per-stage
Done when:check lives in the execution loop (seeded by goal-prep);/verify-doneis the heavy, holistic END gate. Don't run the full gate per stage. - Downstream of a NOT-DONE: confirmed failures → back to
/goalor manual; quality findings →/simplify. - Not
/verify(single change), not/code-review(diff bugs), not/blueprintPhase 7.6 (reviews the plan before build;/verify-donereviews the result after).
Self-check before reporting
- Did every
Done when:proof actually run, or is it honestly UNKNOWN (not silently PASS)? - Are all Tier-2 scenarios grounded in the original intent (none invented)?
- Is the verdict NOT-DONE whenever behaviour is unverified (UNKNOWN), never a hopeful DONE?
- Did I stay a gate — zero edits to the codebase?