# Spec Completion Review

Source: https://flow-next.dev/skills/spec-completion-review/

Verify the combined implementation of all tasks in a spec satisfies the spec requirements.

`/flow-next:spec-completion-review` confirms that, taken together, the implementations of every task in a spec actually satisfy the acceptance criteria.

This is **not** a code-quality review. That belongs to `/flow-next:impl-review`. Completion review answers one question: did the combined work meet the spec?

## When to use it

Run completion-review when every task in a spec is marked done, after any per-task `/flow-next:impl-review` has shipped, and before `/flow-next:make-pr` opens the PR. The reviewer re-reads the spec and verifies that the combined diff covers every R-ID - gaps that no individual task fully owned surface here.

Specifically:

* Long-running spec where individual tasks were reviewed in isolation but no one checked the whole.
* Spec where task descriptions drifted away from the original acceptance criteria during execution.
* Any non-trivial spec before opening a PR for human review.

The work loop offers to run this automatically when all tasks complete. You can also invoke it manually at any time.

## What gets checked

* Every R-ID in the spec maps to evidence in the diff or the committed code.
* No acceptance criterion is missing, half-implemented, or quietly dropped.
* Boundaries and non-goals are respected.
* Decisions captured during implementation are consistent with the spec’s decision context.

If an R-ID has no evidence, the review surfaces it as a gap - not as a stylistic finding.

## Standing criteria compliance

When the project has a `.flow/criteria.md`, completion review is also the surface that judges it. Every G-ID in that file is judged against the whole implementation, on every backend, and each gets one status: `met`, `violated`, or `n/a`.

The verdicts land in the ordinary review receipt:

```json
"criteria": [
  {"id": "G1", "status": "met"},
  {"id": "G3", "status": "violated", "note": "route added without contract regen"}
]
```

Every violation is also reported as a normal finding at reviewer-judged severity, so the findings list stays the one place to read detail. Per-task `/flow-next:impl-review` never judges criteria: the spec is the unit of compliance.

An invalid criteria file fails the review before a round is reserved (`flowctl criteria prompt-block` exits nonzero), so a typo’d bullet is a fix-and-re-run, not a silently rule-less review. No criteria file means no criteria content in the prompt and no `criteria` field in the receipt.

Full model: [Standing Criteria](https://flow-next.dev/reference/standing-criteria/).

## Backend selection

Same resolution as the other review skills; the ladder is in [Review backends](https://flow-next.dev/reference/review-backends/).

With `review.backend none` this skill exits cleanly instead of running, which means nothing verifies R-ID coverage at the end of the spec. The in-host quality audit inside work is not a substitute: it reviews the diff when a change is large or risky, and it never walks the R-ID table. To keep this gate without a second CLI, use `host`. See [What each layer costs](https://flow-next.dev/understand/what-each-layer-costs/#turning-the-dial-none-and-host).

## Outcomes

| Verdict      | Meaning                                                                           |
| ------------ | --------------------------------------------------------------------------------- |
| `SHIP`       | Every R-ID covered. Safe to PR.                                                   |
| `NEEDS_WORK` | One or more R-IDs missing or under-delivered. Findings cite the R-ID and the gap. |

A `NEEDS_WORK` verdict often means a new task, not a rewrite. Use `/flow-next:plan` or `flowctl task create` to add the missing work, then re-run.

## Why a separate skill

A per-task review can confidently SHIP a task that delivered exactly what its description asked for, even when the task description itself missed something the spec required. Completion review re-grounds on the spec, not on the task list, so spec-level gaps stop hiding behind passing task reviews.

## Worked example

```plaintext
/flow-next:spec-completion-review fn-12-export-json-flag
```

```text
Spec-level review (cross-model): does the sum of tasks implement the spec?
  R1 export --json emits valid JSON      covered (task .1, commit a1b2c3d)
  R2 null-owner rows serialize           covered (task .1 fix round, commit f7c8d9e)
  R3 docs + tests                        covered (task .2, commit e4f5a6b)
No drift found between task done-summaries and the diff. VERDICT: SHIP
```

Task-level reviews check each tree; this gate checks the forest - drift hides in the gaps between tasks.

* Run it when all tasks are done and before the PR - it is the last moment where a missed criterion is a task, not a review comment.
* The classic catch: two tasks each “done” correctly that together still miss an R-ID both assumed the other covered.
* Autonomous loops run this gate automatically; interactively it is your call, priced at one review for whole-spec confidence.

## Dynamic usage

Recipes that compose with spec-completion-review in the [cookbook](https://flow-next.dev/guides/cookbook/):

* [Evidence-first](https://flow-next.dev/guides/cookbook/#evidence-first) - the R-ID-to-commit mapping it verifies is the same one the PR body will publish.
* [One-shot chains](https://flow-next.dev/guides/cookbook/#one-shot-chains) - chain it between “work” and “make the PR” in a single instruction.

## Next step

```bash
/flow-next:make-pr <spec-id>
```
