verify · git:20260721.bc2c9bc · 2026-07-21 · sha256 10a2781f9bc74417

verify git:20260721.bc2c9bcA

Immutable. This exact content never changes and is served at /api/v1/blob/10a2781f9bc74417.

---
name: verify
description: Verify-before-done — exercise the current change end-to-end against its acceptance criteria (the SDD plan's, or the ticket's) and report a per-criterion PASS/FAIL verdict, then record the outcome to memory. This is the concrete action that satisfies moflo's verify-before-done gate (`gates.verify_before_done` / `/flo -v` / `/flo -sd`). Use before `gh pr create` when the change must be proven to work, not just tested in passing. Verifies only — it does not fix; on FAIL it reports the gaps and stops.
arguments: "[issue-number | spec-slug]  (defaults to the current branch's issue/spec)"
---

# /verify — Verify Before Done

Prove the current change **actually does what it was supposed to** before it ships. `/verify` is the end-to-end completion check for moflo's SDD cycle: it takes the change's **acceptance criteria**, exercises the change against each one with concrete evidence, and returns a per-criterion verdict. It is the action that makes the [verify-before-done gate](../../guidance/moflo-sdd.md) mean something — running it is what unblocks `gh pr create` when `gates.verify_before_done` is on.

**Arguments:** $ARGUMENTS

`/verify` **verifies, it does not fix.** If a criterion fails, it reports the gap and stops — the caller (you, or the `/flo` flow) decides what to do. This separation is deliberate: a checker that also patches can rationalise its way to green.

## What satisfies the gate

Invoking this skill (name `verify`) trips the `record-verify-run` hook, which flips the `verifyRun` state the `check-before-done` gate reads. **Only `/verify` satisfies it** — `/ward` and `/quicken` are targeted audits, not an end-to-end verification. A source edit *after* verifying invalidates the result (the edit gate resets `verifyRun`), so run `/verify` as the last step before the PR.

## Step 0 — Memory first

Search memory before reading files, same as any task (satisfies `memory_first`, surfaces prior verify runs for this area):

```
mcp__moflo__memory_search { query: "verify <feature keywords>", namespace: "learnings" }
```

## Step 1 — Locate the acceptance criteria

Resolve the criteria to check against, in priority order — **stop at the first that exists**:

| Source | How to find it | When |
|--------|----------------|------|
| SDD **plan** | `flo sdd list` → the slug for this branch → read its `plan.md` "Acceptance Criteria" | `--sdd` runs |
| SDD **spec** | same slug → `spec.md` "Acceptance Criteria" | spec authored, no plan criteria |
| **Ticket** | `gh issue view <n>` → the `## Acceptance Criteria` section | plain `-v` run, no spec |
| **Inferred** | derive 2–4 checkable criteria from the diff + PR intent, and say so | nothing above exists |

Never hand-write the spec path — get it from `flo sdd` (Rule #1: the CLI builds every path with `path.join`). If an explicit `<issue-number | spec-slug>` argument was passed, use it directly.

## Step 2 — Map each criterion to a concrete check

For every acceptance criterion, pick the **cheapest evidence that actually proves it**:

| Criterion shape | Verification action |
|-----------------|---------------------|
| Logic / behavior / bug-fix | A passing test that **specifically** exercises it — reuse the suite run already done this session (see below); run only a missing/targeted test |
| Build / types / packaging | The project's build or typecheck command — reuse if already run since the last edit |
| Integration / e2e | The project's e2e or integration runner |
| User-facing / UI / CLI output | Run the real thing — use `/run` to launch the app/CLI and observe the actual output (a screenshot or captured stdout is the evidence) |
| Config / docs / non-code | Inspect the artifact directly and confirm it says what the criterion requires |

**Reuse fresh evidence — do not re-run what this session already ran.** This is the key to avoiding a **double verify**. If the tests/build already ran green this session with no source edit since — which is exactly the case when `/flo` invokes `/verify` right after its Tests phase — that run **is** the evidence: cite it, don't execute it again. `/verify`'s job is the *mapping* (which criterion is proven by which existing result) and *gap-finding* (criteria no check covers), **not** re-running the suite. Only execute a check whose evidence doesn't already exist this session.

**Discover the commands from the project — never assume.** When you *do* need to run something (a criterion nothing covered yet), read `package.json` scripts / `Makefile` / language toolchain and use what the repo already uses (`npm/yarn/pnpm test`, `vitest`, `jest`, `pytest`, `cargo test`, `go test`, …). Cross-platform (Rule #1): invoke the project's own scripts, don't shell out to `bash`-only constructs.

## Step 3 — Execute the gaps and gather evidence

Run **only the checks whose evidence doesn't already exist** this session; for everything else, cite the run that already happened. Capture, per criterion, the **specific** evidence: the passing test name, the build exit, the observed output. "The suite passed" is not evidence for a criterion unless a test actually exercises *that* criterion — if none does, that is a **gap**, not a pass (consider `/ward` to fill it, in a separate step). The distinction from a plain test run is the whole point: tests prove the code works; `/verify` proves the change did **what the ticket asked**.

## Step 4 — Verdict

Emit a per-criterion table. **PASS only when every criterion has affirmative evidence.** Any criterion with no covering check is `UNVERIFIED`, which counts as **not passing**.

```
| # | Acceptance criterion | Evidence | Verdict |
|---|----------------------|----------|---------|
| 1 | <criterion>          | <test/output/observation> | ✅ PASS / ❌ FAIL / ⚠️ UNVERIFIED |
```

Overall verdict is PASS iff no row is FAIL or UNVERIFIED.

## Step 5 — Record the outcome to memory

Always store the result (feeds routing/learning and the SDD trail):

```
mcp__moflo__memory_store {
  namespace: "learnings",
  key: "verify:<slug-or-issue>",
  value: "<overall PASS/FAIL> — per-criterion: <criterion → evidence → verdict>; commit <sha>",
  tags: ["verify", "sdd"]
}
```

## Step 6 — Report

One concise summary: overall verdict, the per-criterion table, and — on FAIL/UNVERIFIED — exactly which criteria are unproven and what evidence is missing. Do **not** open the PR or edit code from here; hand the verdict back to the caller.

## See Also

- `.claude/guidance/moflo-sdd.md` — the SDD cycle and the verify-before-done gate this skill satisfies
- `.claude/skills/fl/sdd.md` — how `/flo` invokes `/verify` at the verify step
- `.claude/skills/ward/SKILL.md` — fills coverage gaps `/verify` surfaces (audit, not a completion gate)
- `.claude/skills/run/SKILL.md` — launch the real app/CLI for user-facing criteria