Short answer
Adding a reviewer at the end of an agent's run halved the bugs but made the run longer. Having two models write independent positions before any code existed cut the same task from 3.7 hours to 1.5 and from 389 M tokens to 34 M.
Every coding agent I have used has the same habit. It gets a third of the way into a task, writes a confident summary, and asks whether you’d like it to continue. You say yes. It does a bit more and asks again. Supervising that is a job, and I wanted it to stop being mine.
The fix I ended up with is not a smarter prompt. It is a second model whose only job is to disagree.
The setup
Bulava runs Claude Code and the Codex CLI side by side on one Mac. Claude does the work. When Claude stops, a hook hands Codex the real diff, the evidence the engine collected itself (build output, tests, any checks registered as commands) and the acceptance criteria. Codex either accepts the work or returns findings, and the findings go straight back to Claude. Nobody presses “continue”.
The loop, with nobody pressing "continue"
- Agent
- Automated check
Steps as text
| Step | What happens |
|---|---|
| 1. Two positions | Agent — Claude and Codex plan separately |
| 2. Claude builds | Agent — code and tests |
| 3. Engine checks | Automated check — build, tests, registered commands |
| 4. Codex reviews | Agent — diff + evidence + criteria |
| 5. Accepted | Automated check |
| Loop | findings go back to Claude: back from step 4 to step 2 |
Three details turned out to matter more than the models themselves:
- Two independent positions before any code. Claude and Codex read the same context file and each write an approach without seeing the other’s. Codex then lists only the material disagreements. Claude decides. Most bad starts die here, before they cost an hour.
- The reviewer judges evidence, not claims. “All tests pass” means nothing unless the engine ran the tests. If a claim can’t be proven by the build, the agent registers a command that exits 0 only when the claim is true, and the engine runs it and records the exit code.
- Hard limits. Three rounds of patience, two rounds without progress parks the run for a person, twelve rounds is a ceiling. A loop with no exit is just a more expensive way to waste a night.
The benchmark
To see whether any of this was worth it, I gave one task to three setups on 7–8 September 2026: rebuild a mobile game from a video of someone playing it. No hints afterwards, no second prompt.
| Measure | Claude Code alone | Claude + one review | Two independent positions |
|---|---|---|---|
| Time | 3.7 h | 4.2 h | 1.5 h |
| Tokens processed | 389.0 M | 155.6 M | 34.3 M |
| Bugs, counted by hand | ≈13 | ≈7 | 0 broken mechanics |
| The agent’s own tests | 12 / 12 | verify.sh PASS | 57 / 57 |
The middle column is the interesting one. Adding a reviewer to the end of an otherwise unchanged run halved the bugs but made the run longer. A likely reason: Claude had already committed to a plan before the reviewer saw anything, and the review rounds went into pulling it back. Moving the disagreement to the start, before code existed, is what cut both the time and the tokens.
What the numbers don’t say
I want to be careful here, because benchmarks like this are easy to oversell.
- The bug counts are mine, made by playing each game. They are not a test suite’s verdict.
- The first run used a higher reasoning effort than the other two, so it isn’t a like-for-like comparison of settings.
- 97% of all tokens were cache reads. The headline numbers are mostly re-reading the same files, so they say more about how long a run went on than about how much new work it did.
- It is one task. A different task could tell a different story.
The prompt, the file digests and the procedure are published at bulava.app/benchmark.json, so anyone can rerun it.
Where a person still belongs
The loop doesn’t replace a human. It moves the human to the decisions only a human can make. When the agent hits something it can’t settle from the code or the request (an account it needs, a product decision, a criterion that turns out to be impossible), it stops and asks. It doesn’t guess.
I’m also building a dark factory at Raccoon Gang on the same ideas. People there still decide what ships. They just stopped being the loop.
Related reading: why the writer can’t be the reviewer and how to take people out of code review step by step.
Questions
Is Codex better than Claude Code at reviewing code?
Not in general. What matters is that the reviewer is a different model from the writer, so their mistakes are less likely to overlap, and that it judges evidence the engine collected rather than the writer’s summary.
Why did adding one review at the end make the run longer?
The writer had already committed to a plan before the reviewer saw anything, so review rounds went into pulling that plan back. Putting the disagreement before any code existed avoided that.
Can I rerun this benchmark?
Yes. The prompt, the file digests and the procedure are published at bulava.app/benchmark.json.