Every AI reviewer claims it finds real bugs. Almost none of them publish the times it was wrong. This page is our scoreboard, false-positive column included, and an account of the things we still cannot honestly measure.
After a review lands, a human reads it against the code and writes a verdict for every finding:
confirmed (a real problem), false positive (it is not a problem, or the diagnosis is
wrong), out of scope (real, but not something this PR should be asked about), or missed
(a problem someone found later that the reviewer said nothing about). Precision is
confirmed / (confirmed + false positives). Nothing is scored by a model, and nothing
is scored by the reviewer itself.
There is no recall number on this page, and that is deliberate. A miss only enters the table when a human later found the bug and remembered to write it down, so the “missed” column is a floor, never a rate. We had a recall figure once; auditing it showed it was an artefact of how the corpus recorded line numbers, and a shuffled control scored higher than the real reviewer. We deleted it rather than quote it. Until the measurement is sound, the honest answer to “what is your recall?” is that we do not know.
One row per review. r1, r2… are re-reviews of the same pull request after the
author pushed fixes. Most of these repositories are private, so they appear by letter — the counts are
what matters, and inventing public rows to look better would defeat the purpose of the page.
| date | repository | PR | round | confirmed | false pos | worst FP | out of scope | missed | precision |
|---|---|---|---|---|---|---|---|---|---|
| 2026-07-27 | private A | #102 | — | 0 | 0 | — | 0 | 1 | — |
| 2026-07-27 | private A | #103 | — | 3 | 0 | — | 0 | 0 | 100% |
| 2026-07-27 | private A | #104 | — | 2 | 0 | — | 0 | 0 | 100% |
| 2026-07-27 | private A | #105 | — | 1 | 0 | — | 0 | 0 | 100% |
| 2026-07-27 | private A | #106 | — | 2 | 1 | — | 0 | 0 | 67% |
| 2026-07-30 | private B | #2628 | — | 2 | 1 | — | 1 | 1 | 67% |
| 2026-07-30 | VinaText | #10 | r1 | 0 | 2 | BLOCKING | 0 | 0 | 0% |
| 2026-07-30 | VinaText | #10 | r2 | 2 | 0 | — | 0 | 0 | 100% |
| 2026-07-30 | VinaText | #20 | r1 | 0 | 5 | MEDIUM | 0 | 0 | 0% |
| 2026-07-30 | VinaText | #20 | r2 | 0 | 0 | — | 7 | 0 | — |
| 2026-07-31 | pr-review-core | #28 | r1 | 0 | 1 | BLOCKING | 0 | 0 | 0% |
| 2026-07-31 | pr-review-core | #28 | r2 | 0 | 1 | MEDIUM | 0 | 0 | 0% |
| 2026-07-31 | pr-review-core | #31 | — | 2 | 0 | — | 0 | 2 | 100% |
| 2026-08-02 | private C | #10 | — | 0 | 0 | — | 0 | 1 | — |
| 2026-08-02 | VinaText | #35 | — | 8 | 0 | — | 0 | 1 | 100% |
| 2026-08-02 | private D | #25 | r1 | 2 | 0 | — | 1 | 1 | 100% |
| 2026-08-02 | private D | #25 | r2 | 2 | 0 | — | 0 | 0 | 100% |
| 2026-08-02 | private D | #27 | — | 2 | 0 | — | 0 | 3 | 100% |
| 2026-08-02 | private D | #29 | r1 | 2 | 0 | — | 0 | 0 | 100% |
| 2026-08-02 | private D | #29 | r2 | 1 | 0 | — | 0 | 0 | 100% |
| 2026-08-04 | private C | #16 | r1 | 1 | 0 | — | 0 | 3 | 100% |
| 2026-08-04 | private C | #16 | r2 | 1 | 0 | — | 0 | 2 | 100% |
| 2026-08-04 | private C | #16 | r3 | 1 | 0 | — | 0 | 1 | 100% |
| 2026-08-04 | private C | #16 | r4 | 1 | 0 | — | 0 | 0 | 100% |
| 2026-08-04 | private C | #16 | r5 | 0 | 0 | — | 0 | 0 | — |
| 2026-08-05 | private C | #19 | — | 1 | 0 | — | 0 | 0 | 100% |
| 2026-08-05 | kaniscope-action | #6 | — | 0 | 1 | — | 0 | 0 | 0% |
| 2026-08-05 | private D | #35 | — | 0 | 0 | — | 0 | 1 | — |
| 2026-08-05 | pr-review-core | #35 | — | 1 | 0 | — | 0 | 0 | 100% |
| 2026-08-15 | private E | #63 | r1 | 2 | 0 | — | 1 | 4 | 100% |
| 2026-08-15 | private E | #63 | r2 | 2 | 0 | — | 1 | 3 | 100% |
| 2026-08-15 | private E | #63 | r3 | 1 | 0 | — | 1 | 2 | 100% |
| 2026-08-15 | private E | #63 | r4 | 3 | 0 | — | 0 | 2 | 100% |
| 2026-08-15 | private E | #63 | r5 | 3 | 0 | — | 0 | 1 | 100% |
| 2026-08-18 | private F | #1 | — | 6 | 0 | — | 0 | 1 | 100% |
| 2026-08-26 | private G | #1 | — | 4 | 1 | LOW | 0 | 1 | 80% |
| 2026-08-27 | wincrust | #13 | — | 1 | 1 | BLOCKING | 0 | 1 | 50% |
| 37 rounds | 59 | 14 | 12 | 32 | 81% | ||||
Not all wrong findings cost the same. A wrong LOW is noise you scroll past. A wrong
BLOCKING tells someone to stop shipping over a bug that is not there, and it is the one
that makes people uninstall a reviewer. Four of ours were BLOCKING, and they are the reason severity
calibration is a standing piece of work rather than a solved problem.
| severity of the false positive | count |
|---|---|
| BLOCKING | 4 |
| MEDIUM | 6 |
| LOW | 1 |
| unlabelled | 3 |
The pattern in the table above is worth noticing too: on the pull requests that got a second round
(r1 → r2), precision usually goes up. The first pass on an unfamiliar
codebase is the noisy one.
We ran Kaniscope over 30 public pull requests that CodeRabbit had already reviewed, and lined the findings up by file and line (within ±8 lines counts as the same place). 263 findings across both.
| bucket | findings | share |
|---|---|---|
| both reviewers, same place | 28 | 11% |
| theirs only | 124 | 47% |
| ours only | 111 | 42% |
This is not a scoreboard, and we will not present it as one. Neither column is ground truth. A CodeRabbit finding is another model’s opinion, not a verified defect — so “theirs only” is a list of candidates, not a list of our misses, and “ours only” is as likely to be our false positive as their miss. Even the overlap proves little: two models share false positives routinely. The only thing here that was graded by a human is the table further up this page.
One signal in it does not depend on ground truth, though, and it does not flatter us: the shape of what each reviewer raised alone. By their own labels their 124 unique findings were 68 Major and 11 Critical. By ours, our 111 were 61 LOW and 7 HIGH. Whatever the truth of the individual findings, we are producing more low-severity material on the side where we are alone, and their unique findings cluster in functional correctness, data integrity and stability. That is the gap we are working on, and it is why this page exists in the state it is in rather than a tidier one.
examples/bench.rs in the engine scores the reviewer against a corpus of pull requests
with known issues and reports precision, recall, F1 and token cost, so a feature can be A/B’d by
re-running with the flag flipped. It is a dry run — it posts nothing — and it needs your own model
key. Blast radius, complexity metrics and the choice of backend were all measured this way. Blast
radius, for the record, showed no recall improvement on well-named repositories; it stays on
because it may still help on large monorepos, not because we measured it helping.