Open source · in daily use on my own work

One model reviewing your code agrees with itself.So I made three of them argue instead.

Four models from four different vendors. Three review the same change without seeing each other's work, then have to defend or refute what the others found. Whatever is still contested goes to the fourth with the repository open, and to me after that. Only findings that survive the argument reach the report.

Working tool · runs on my own branches before they land · open source on GitHub

01 / The problem

One model reviewing code is a very confident intern.

Ask a language model to review a diff and you get a list. Some of it is real. Some of it is a plausible sentence about a vulnerability that cannot happen in this codebase, written in exactly the same tone as the findings that matter.

Asking the same model again does not help, because it agrees with itself. Asking it to be more critical does not help either: it becomes more critical about everything, including the things that were fine, and the signal gets worse rather than better. The failure is not that the model is stupid. It is that a single reviewer has nothing to disagree with.

So the review became a panel, and the panel was made to argue.

02 / The panel

Three vendors, one diff, no conferring.

Three models from three different companies review the same change at the same time, none of them able to see what the others found. They share one thing only: the brief. The fourth model is not on the panel: it arbitrates, and it is the one seat with the repository open.

Seat one Deepseek V4 Pro

Reasoning effort at maximum, over the raw diff. Independent API call, no repository access.

Seat two Kimi K3

Same brief, same diff, same maximum reasoning setting. A different vendor and a different training run, which is the entire point of it being there.

Seat three OpenAI Codex

Runs locally in read-only mode, so unlike the other two it can open repository files to check a claim before making it.

The shared brief is a single file, and it is doing more work than the model choice. It fixes the output as a strict schema, so findings can be compared mechanically rather than read as prose. It requires a category and a written exploit scenario for every finding, which is the cheapest filter there is: a model that cannot describe how something is exploited usually cannot, on inspection, explain why it is a finding. It carries an explicit exclusion list for the false positives these tools raise every single time. And it forces a calibrated confidence score, which the later rounds depend on.

If a seat is unavailable, the panel runs short-handed and says so in the report, naming which seat was empty. A three-model verdict and a one-model verdict should not look the same on the page.

03 / The argument

Findings have to survive people who did not make them.

This is a Delphi process wearing a code review costume: independent opinions first, then structured rebuttal, then convergence, with a rule that forces it to terminate.

Round one

Three independent reviews

All three panelists run concurrently against the same diff. Nobody sees anybody else's output. This is the only stage where a model is asked what it thinks unprompted.

Merge

Agreement is measured, not assumed

Findings are clustered by file and line proximity. Anything two or more panelists found independently is consensus. Anything exactly one panelist found is disputed, and disputed is the interesting pile. Then I read the clustering and correct it by hand, because two descriptions of one root cause in different files will not cluster mechanically and one line of shared code with two separate faults will cluster when it should not.

Round two

Rebuttal

Every disputed finding goes back to the panelists who did not raise it, and they have to take a position: agree, or refute and say specifically why the problem cannot occur. The brief tells them that being contrarian is as bad as being credulous, because a panel that refutes everything is exactly as useless as one that agrees with everything. A finding another seat backs at reasonable confidence is promoted. One that every other seat can explain away is dropped, and still listed, with the reason it died.

Termination

At most one more round

Rebuttals sometimes raise something genuinely new, and that goes into the pool. But the process is capped at two rounds and everything unresolved is escalated. A debate that can run forever is not a process, it is a bill.

Arbitration

A human reads the actual code

Whatever is still contested comes to me, with the repository open. Is the path reachable? Do the callers, the types and the auth layer make the scenario possible at all? Each one is ruled confirmed, refuted with the specific line that disproves it, or marked unverifiable, which is a real and permitted answer.

The rule that makes the whole thing work: a majority is not a verdict. Two models agreeing on a hallucination is still a hallucination, so a consensus finding that looks wrong to me gets pulled back and checked like a contested one.

04 / What comes out

A verdict, and the argument that produced it.

The report

One table. Every finding with its verdict, severity, how many seats raised it, category and location. For anything confirmed and critical, the exploit scenario and the fix. It ends on a single gate: fail if there is a confirmed critical finding, otherwise pass.

The debate log

One line per contested finding: who claimed it, who refuted it, how I ruled and why. Plus the appendix of everything that died, with its cause of death. The rejected findings are the part that tells you whether to trust the accepted ones.

The cost is three API calls and a few minutes of wall clock, and the panelists run concurrently so it is minutes rather than the sum of three reviews. It runs on my own branches before they land.

Where it has earned its keep is not the critical findings. It is the confident, well-written, entirely false ones that a single reviewer would have had me chasing, and that died in round two because another model could name the reason they were impossible.

05 / What it is not

The limits, before you ask about them.

A talk that only lists strengths gets picked apart in the questions. Same here.

  • It reviews a diff, not a system. An architectural flaw that spans files the change never touches is invisible to it, and no amount of arguing will surface it.
  • Three vendors is not statistical independence. These models share a great deal of training data and can absolutely be wrong in the same direction. Disagreement is evidence; agreement is weaker evidence than it looks.
  • Two of the three seats never see the repository. They reason from the diff alone, which is exactly why arbitration reads the real file before anything is called confirmed.
  • It does not replace a security review by someone accountable. It replaces the first pass, and it makes the human pass start from a much shorter and better argued list.
  • It is not a compliance artefact. It is a working tool that lives in my own toolchain. If you need something auditable, that is a different piece of work and I would say so.

All of which is easier to judge with the thing in front of you, so it is open source. The skill and the shared brief the panelists are given are both in the repository, and the brief is the part worth reading: it is doing more work than the choice of models.