<!-- Markdown mirror. Canonical: https://empryo.com/docs/agents/review -->

# The reviewer

> A fresh-context agent reads what changed and returns PASS, FAIL or PARTIAL. Run it on demand, every goal-loop round, or as a CI exit code.

The agent that spent forty steps writing a patch is the worst judge of it. It remembers why each line looked right as it typed them.

The reviewer carries none of that. No transcript, no plan it defended, no memory of the argument. It opens the files that changed, reads them cold, and closes with one line your tooling can act on:

```
VERDICT: PASS — [what was verified]
VERDICT: FAIL — [file:line, what is wrong]
VERDICT: PARTIAL — [what could not be verified and why]
```

One agent, three doors: `/review` runs it once, `/goal` runs it after every round of its loop, and `--review` turns the verdict into a CI exit code.

## Ask for one

```
/review
/review check the error paths, not the happy path
```

The brief is optional. Write one and your words become the setpoint it judges against first. Leave it empty and it judges correctness over whatever your lane touched.

Empryo blocks a review while work is in flight: a streaming turn, a background agent still writing files, a goal loop that owns the lane. A judge reading a tree that keeps moving reports on a state that no longer exists by the time you read it. The button tells you which one is holding it, and lights again when the lane settles.

Type while it judges and your line reaches the reviewer at its next step. Those notes stay out of the transcript. The coder reads that transcript back on its next turn, and instructions meant for a judge would land as instructions for it.

## What lands in scope

Empryo looks in three places and reviews the first one that has files in it:

| Order | Source | What the reviewer sees |
|-------|--------|------------------------|
| 1 | This tab's edits | Only the files **this tab** wrote |
| 2 | This session's edits | Every file **any tab** wrote this session |
| 3 | git | Everything uncommitted, new files included (`.gitignore` still applies) |

With four tabs open, each `/review` judges its own work. A clean tree costs you nothing, because an empty scope never starts a model.

A review covers at most 30 files, and the verdict says which of the three it used. That is how you tell "the four files this tab wrote" from "everything uncommitted" without reading the file list.

For the first two, each file shows `+N/−M` against how it looked before this session first edited it. Those snapshots are held in memory. Restart Empryo and a restored tab falls back to git, and the report says so.

Deleted files stay in scope, marked as deleted. The reviewer does not try to open one. It checks what imported or called it instead, because a deletion that leaves callers behind is exactly what you want caught.

## Acting on a verdict

| Surface | Where you read it | How you act on it |
|---------|-------------------|-------------------|
| Desktop | The reviewer strip above the composer. Expand it for past verdicts | **apply** sends the findings to the agent. **re-review** runs a fresh judge over the same scope |
| TUI | The banner above the composer, the report in the transcript | `/review apply`, `/review list` |

Apply on a plain `/review` stays manual: one verdict, one decision, nothing moves until you say so.

Each tab keeps its last 8 verdicts with their reports, through a reload and a session restore. A re-review seeds the previous report as *context to verify, not truth*, so the second judge re-earns every claim the first one made.

## Review until pass

The manual cycle is review → read → apply → wait → review again. `/review pass` is that cycle with the waiting removed: every non-PASS verdict goes to your coder as a real turn, and the moment that turn settles a fresh judge runs again.

```
/review pass
/review pass the error paths, not the happy path
/review stop
```

On desktop the reviewer key opens a menu, **Review once** or **Review till pass**, and both take the same optional brief in the composer. The strip says which half is live (`round 2/5, judging with fresh eyes`) and carries the **stop loop** button, on the TUI the settled verdict grows a `↻ till pass` chip beside `↯ apply`.

It ends on PASS, on the round cap (5 by default, 12 hard maximum), on a review error, or the moment you stop it. **Ctrl+X** kills it in every phase, mid-review, mid-fix, and in the gap between them, and so does the stop button. The reviewer that is judging right now dies with it. Typing while it runs still steers whichever half is live: the reviewer takes your line as a bus finding, the coder as a steer.

Each round is a real turn and a real reviewer run, priced into the tab's totals like any other. A loop that runs its cap costs five judges and four coder turns, so give it a brief worth converging on.

The difference from [`/goal`](/docs/agents/goal-loop): `/goal` chases a goal you state up front and escalates models when it stalls. `/review pass` judges work that already exists, with no goal but "hold up under a fresh reading".

## In CI

```bash
empryo --headless --review
empryo --headless --review "check the migration for data loss"
empryo --headless --review --json
```

| Exit code | Meaning |
|-----------|---------|
| `0` | PASS, or nothing to review (clean tree, no model called) |
| `3` | FAIL |
| `4` | PARTIAL |
| `1` / `2` / `130` | Error / timeout / abort |

```yaml
- name: Review the diff
  run: empryo --headless --review --quiet
```

A clean tree reports `verdict: null`, never PASS. Nothing was judged, and a green tick there would tell your pipeline the code had been checked.

## Which model judges

The [task router](/docs/recipes/task-router)'s `review` slot, falling back to `goalReview`, then to the model your lane already runs. Spend the money here: a judge that misses the bug costs more than the tokens it saved. Reviewer spend lands in the tab's totals like any other side agent, so you can see what each verdict cost ([cost tracking](/docs/concepts/cost-tracking)).

## Typecheck and tests

`/review` skips both so a manual verdict lands in seconds. The goal loop runs them between rounds, where a slower and stricter judge pays for itself.
