Agents & DispatchStable

Review & approval

How o8 decides what's safe to merge — risk-classified blind review and a five-layer recovery ladder with a hard cost ceiling.

"Nothing risky merges without your sign-off" has two halves: an AI half that catches what a human would miss on a fast-moving fleet, and a human half that keeps you the final gate. Here's how the AI half decides.

Risk is a path, not a vibe

Before any model reads a diff, a fast mechanical pass reads its shape — how much changed, whether whole files were rewritten, whether anything matches a dangerous pattern (an eval, an injection-flavored string, a mass deletion). That's triage, not the verdict.

Then risk is decided by what the diff touches:

The diff touches…RiskWhat it gets
Schema, migrations, the lane state machine, the merge gateHigha blind second review
Whole-file rewrites or dangerous patternsHigha blind second review
Ordinary feature and UI codeStandardone review, then merge

The logic: a subtle bug in a button color breaks one screen; a subtle bug in schema or the merge gate breaks the system every other agent depends on. So the dangerous diffs earn a second look, and the ordinary ones don't waste one.

The blind second reviewer

For a standard diff, a passing first review is enough — it clears the merge. For a high-risk diff, the first approval is deliberately not enough: it can only nominate the change. The merge stays blocked until a second, independent reviewer agrees.

And that reviewer is blind by design. It's handed only the diff and the checks it must produce — never the first reviewer's verdict, score, or reasoning. There is nothing to rubber-stamp. It has to satisfy the protocol on its own: every guard live, every write partitioned correctly, every sub-requirement covered, and the execution path actually reaching the changed code. It returns one of a fixed set of verdicts — agree, disagree, or inconclusive — and only an independent agree turns the nomination into a cleared merge. Anything else sends the change back up the chain.

On the dangerous diffs, one model saying "looks good" doesn't open the gate. It opens a second, independent review.

When a merge fails: the escalation ladder

A branch can be green when it's written and still fail at merge time — main moved underneath it. o8 rebases onto current main and re-runs the typecheck before landing; if that fails, the lane doesn't stall and it doesn't loop forever. It climbs a fixed five-layer ladder — cheap and automatic at the bottom, you at the top — only as far as it has to:

LayerWhat happensWho decides
1 — Auto-rerunone automatic retry, handing the worker the full typecheck output to fix its own branchthe system
2 — Escalatelayer 1 failed → hand the lane to the orchestrator with the reason attachedthe system
3 — Steernudge the still-warm session to fix it in place — it already has full contextthe orchestrator
4 — Redispatchthe session's dead or the diff's wrong at the root → a fresh worker, with feedbackthe orchestrator
5 — Human cardthe orchestrator tried 1–4 and it's still wrong → an explicit handoff to youyou

Two things make this a budget instead of a loop:

  • Layer 1 means one. Exactly one free automatic retry, counted since the lane's most recent dispatch — so a deliberate re-dispatch starts fresh, but a single failing run never spirals.
  • Warm before cold. The orchestrator prefers steering the warm session (cheap — the worker still has everything loaded) over a fresh worker, and only escalates to a human when both are exhausted. The order is the point.

Most tools answer a failed merge by retrying until it works or until you notice — a runaway bill, a silent stall, or both. o8's answer is bounded: one automatic turn, then bounded attention, then you. Recovery is a budget, not a loop.

o8 v0.1.431 · updated 2026-06-25 · stable
tracks: src/lib/lane/blind-second-pass-review.ts · src/lib/lane/review-risk.ts · CLAUDE.md