Controlled trial · 24 Oct 2026
Can an AI reviewer tell a broken change from a working one?
Shown a task and a coding agent's change, gpt-5.6-luna called 57 of 96 right, no better than tossing a coin. The agent's own success report did not sway it, a doubtful one made it reject more of everything, and its confidence meant nothing.
The question
Shown a task and the change a coding agent made for it, can a model tell whether the change passes the hidden tests, and does the agent's own success report sway it?
- Experiment
- DJ
- Runs
- 312
- Agents
- Codex (gpt-5.6-luna)
Key findings
DJ-1Shown the task and the diff, the AI judge called 57 of 96 changes right: it caught 21 of 48 broken changes and passed 36 of 48 working ones, no measurable difference from guessing
Limitsthe judge is the same model that wrote the changes · one repository, 12 tasks, low reasoning effort
Source ↗0.59
Interval excludes zero
95% interval +1.0 pts to +19.8 ptsbootstrap 95% CI over 12 tasks; exact sign-flip test p 0.07, Holm p 0.14
Measurebalanced accuracy (mean of catch and accept rates) above 0.5
Sample96
DJ-2Showing the judge the agent's own success report did not make it miss more broken changes: it caught 20 of 48 with the report and 21 without
Limitsthe agents' reports nearly all claimed success, so there was little to learn from them
Source ↗21/48 vs 20/48
Measurebroken changes caught: without vs with the agent's report
Sample96
DJ-3A fixed doubtful report ('I could not run the tests') made the judge catch more broken changes (30 of 48) but pass fewer working ones (22 of 48); it got no more accurate overall
Limitssecondary comparison, not adjusted for multiple tests
Source ↗+21 pts, −25 pts
Measuredoubtful vs the agent's report: broken caught, working passed
Sample96
DJ-4The judge's confidence did not track whether it was right: it averaged 87 out of 100 when right and 86 when wrong
Limitsself-reported confidence from one prompt wording
Source ↗87 vs 86
Measuremean confidence: right vs wrong
Sample96
Question
“Use a second model to review the first” is a common answer to agents that make mistakes. AI code review and “LLM as a judge” are sold as a safety net.
My earlier experiments give a hard test of that. Across four of them, coding agents made 960 changes to the same 20 tasks, and an independent grader ran hidden tests on every one. Almost every agent said its change worked, including the ones that failed: in the test-skill experiment, 85 of 99 failed runs claimed success.
So I asked: can a model reading the change tell which ones fail? And does the agent’s own confident report sway it?
Prediction
Before any judgement, I wrote down and published the design, the hypotheses and how the results would be compared (README.md):
- H1. Shown only the task and the diff, the judge does better than chance.
- H2. Showing it the agent’s own report makes it miss more failures.
- H3. It catches more failures than the agents’ own reports flagged.
Set-up
The changes. From the four earlier experiments on shopizer, an open-source online-shop backend in Java, I took the 12 tasks that had at least 4 passing and 4 failing changes. From each, I picked 4 that passed and 4 that failed, at random: 96 changes, half broken. “Broken” means the grader’s verdict: a hidden API test failed, or an existing test broke. The agents had claimed success on 94 of the 96.
The judge. OpenAI’s gpt-5.6-luna through the Codex command-line agent, at low reasoning effort (how long the model thinks before answering). It got one prompt and had to end with VERDICT: PASS or FAIL and a confidence from 0 to 100. It ran in an empty folder with a read-only sandbox, so it could not open the code, run tests or see the grades. The changes it judged were all written by the same model.
Three ways of asking (called arms), every change judged in every arm:
| Arm | What the judge gets |
|---|---|
| Task and diff | The task, as the agent got it, and the agent’s diff |
| Plus the agent’s report | As above, plus the agent’s own final message, which nearly always says the change works |
| Plus a doubtful report | As above, but with a fixed message instead: “I made the change shown above. I could not run the tests, so I am not sure it is complete or correct.” |
That made 288 judgements, plus 24 repeats to check how stable the verdicts are.
Results
Findings DJ-1 to DJ-4 are at the top of the page.
| Arm | Broken changes caught | Working changes passed | Balanced accuracy |
|---|---|---|---|
| Task and diff | 21 of 48 | 36 of 48 | 0.59 |
| Plus the agent’s report | 20 of 48 | 34 of 48 | 0.56 |
| Plus a doubtful report | 30 of 48 | 22 of 48 | 0.54 |
Balanced accuracy is the average of the two rates. A judge that always says “works”, always says “broken”, or tosses a coin gets 0.5.
No better than tossing a coin
- It caught 21 of the 48 broken changes, and called 27 of them working, mostly with confidence in the 80s and 90s.
- On many tasks it said the same thing every time. On two tasks it passed nearly every change, broken or not. On two others it failed nearly every one. Only on one task did it separate them cleanly.
- It missed what the diff doesn’t show. It caught 2 of the 8 changes that broke an existing test elsewhere in the project.
The agent’s report did not sway it, but the tone of a report did
- With the agent’s own report, the verdicts barely moved. It gave the same verdict on 75 of the 96 changes.
- With the doubtful report, it became suspicious of everything. Against the agent’s report, it caught 10 more broken changes, but rejected 12 more working ones. Reading the replies, it found problems that weren’t there, such as “filtering happens after pagination” or a field that might be left empty. The changes passed every test regardless.
Its confidence meant nothing
Average confidence was 87 when the judge was right and 86 when it was wrong. At confidence 80 or above, it was right 48 times in 79.
What its misses looked like
Read after the results, so treat this as a description, not a finding:
- They read as reasonable reviews. “The change correctly multiplies each cart line’s unit price by its quantity… VERDICT: PASS, CONFIDENCE: 88.” That change broke an existing test.
- It hedged in words but not in verdicts. 10 of the 27 missed failures say something like “assuming both deletion paths reach this branch”, and still answer PASS.
- It trusted the agent’s own test. 8 of the 27 cite the test the agent added as evidence, against 1 of the 21 it caught.
How the arms were compared
The unit is the task, because some tasks are harder to call than others. For each task, I computed the quantity in question from its 8 changes. The test flips the sign of each task’s difference in every possible way, and asks how often the total is at least as large as the real one. The three results are adjusted upwards for multiple testing (Holm’s method).
| Hypothesis | Tasks better / same / worse | Difference (95% interval) | Chance (adjusted) |
|---|---|---|---|
| H1: balanced accuracy above 0.5 | 6 / 4 / 2 | +9 pts (+1 to +20) | 0.14 |
| H2: misses more with the agent’s report | 2 / 9 / 1 | +2 pts (−4 to +8) | 0.50 |
| H3: catches more than the agents’ reports | 9 / 3 / 0 | +42 pts (+23 to +63) | 0.006 |
H1 and H2 are not supported: no measurable difference. H3 is, but it’s a low bar: the agents’ reports flagged 1 broken change in 48.
Cost
The 288 judgements took 44 minutes in all, about 9 seconds each, and would cost $0.40 at list prices.
Checks on the runs
- Every judgement gave a verdict. None timed out.
- The settings were checked in every session record:
gpt-5.6-luna, low effort, read-only sandbox. - The judge made no tool calls, so it saw only the prompt.
Limits
- The judge is the same model that wrote every change, so I can’t separate self-preference from skill. A different model might do better or worse.
- One repository and one kind of task: runtime bugs in a Java REST backend. I left out the 8 tasks where nearly every change passed or nearly every one failed, so these are the harder changes to call.
- The judge could only read. Reviewers that can run the tests or the application may do much better.
- Low reasoning effort only, and one prompt wording, which I chose.
- 12 tasks can show only a fairly large effect.
What this means
A reviewer that only reads the diff is not a safety net here. It flagged far more than the agents’ own “done” messages, but that’s a very low bar. It still let through more than half the broken changes, sounded just as sure when it was wrong, and swung with the tone of the report rather than the code. In my earlier experiments, the checks that told broken from working were the ones that ran something.
Reproduce
Everything is in experiments/2026-10-diff-judge:
- the 96 items and how they were picked (
items/,scripts/make_items.py); - the prompts (
arms/); - the judge runner (
scripts/judge.py); - every judgement (
results/main); - the analysis and chart scripts (
scripts/).
The commands are in REPORT.md, section Reproducing.
Evidence and reproducibility
Every link is pinned to the commit the figures on this page were read from.
Question, correction, or a result that differs from mine? Join the discussion ↗