Four AI reviewers, one schema, and a fix I reverted
I had four models audit the same Prisma schema twice each, verified every claim by script, and still implemented a critical finding the application had already solved. What eight AI reviews are good for, and what they are not.
26 Jul 2026 · 6 min read
I write most of my code with AI now, and I review most of it with AI too, and the more of that I do, the less I trust any single review, no matter how confident it sounds. This is the story of how I stopped trusting even four of them at once.
In July I had a Prisma schema to harden before a migration, a few dozen models and about a hundred relations with two layers of history in it: a newer part in decent shape, and a legacy part with no explicit indexes on foreign keys, nullable timestamps, decimals without precision, and delete behaviour that worked by accident of ORM defaults. I wanted an audit before writing migrations against a live database.
I ran that audit with four models, Claude, GPT, Grok and Qwen, each of them twice with a different set of database-review skills loaded, and each pass in a planning mode with no shared context, so I ended up with eight independent audits. Then there was one merge session, where every claim from all eight was re-checked by a script against the actual schema file before anything was acted on.
The fix I reverted
Here is the finding that mattered most, on an example with the names changed.
Picture a small price list with one row per vehicle type, a price, and a version number, where orders point at a row and store the version they saw. The audit read it like this: a price change is an update over the same row, so the version an order stored now refers to a row that no longer looks like that, which means the snapshot pattern is declared but the history it points to gets destroyed. All eight passes flagged it, and the merged review carried it as critical.
The fix that came with it was versioned rows, one per vehicle type per version, an is-active flag, and a partial unique index in raw SQL, because the ORM cannot express “unique among active rows”, and I implemented it, wrote the migration and applied it.
Then, doing the implementation, I read the order side properly, and the orders already stored the full price payload at order time: the type, the direction, the base price, the final price, and the version. So the history lived on the order, and the version on the price row was never a key into history at all, it was a freshness label, bumped on every price change and used for exactly one thing, which is rejecting a stale submit with a 409.
So the versioned rows duplicated a guarantee the application already had, at the price of three new constraints, one of which the schema file could not even declare. That had a second cost I only saw then: the schema stopped being a complete description of the database, because part of the truth now lived in a hand-written index inside a migration.
I reverted it the same day, so the versioned model only ever lived between two migrations, and zero rows were written with it.
The snapshot columns were in the schema the whole time, and the review did not check them, and neither did I before implementing.
The lesson as I wrote it down that day was to check, before adding a database mechanism for an integrity concern, whether the application or a data snapshot already provides the invariant, and in general to prefer removing mechanism over adding it, because a tiny price table does not need enterprise versioning.
What four models were good for
They were good for coverage, not for deciding.
By my count, roughly 80% of the findings overlapped across the eight passes, and that is an estimate from reading them side by side, not a measurement, and it does not mean the findings were right. What it meant was that the debt was real rather than one model’s taste, because eight passes from four different models had the same complaints about the same foreign keys.
And every model found something the others did not. The GPT passes brought the process layer, a safe migration order (additive first, then backfill, then validate, then constrain), and the exact counts: more than half of the foreign keys with no covering index, nearly three quarters of the relations with no explicit delete rule. One pass alone raised the token and PII security points, so if you drop any one of the four models, something real goes missing.
The price versioning finding, the one I reverted, was in all eight passes, which is exactly why agreement between reviews is not the same thing as being right: eight readers with the same blind spot still have the blind spot.
I saw the same shape a month later on a much cheaper version: the same review prompt for one ticket, through three models, then one model adjudicating the others’ findings claim by claim. Of the ten or so findings, exactly one overlapped, which is the same conclusion from the cheap end: three models are three reviewers, not one reviewer three times.
The gate that held
The merge step re-checked every number and every claim by script against the schema file, and every count matched. The same script also falsified one claim the audits had made in the other direction, that the new layer was fully indexed, because the audit-actor foreign keys, created-by and updated-by, had no indexes either. A script that only confirms things is not a gate.
So should I trust four models more than one? For coverage yes, for decisions no, because a finding from a review is a hypothesis about the code, and the engineer still decides the blast radius, meaning what a change can break and whether the evidence covers that. In practice that means small diffs, the invariants named before the code is written, tests before trust, and the risky zones first, auth, data writes and migrations. None of that got looser because the reviewers got better, it got stricter, because they got faster.
Four heads are better than one, the saying goes, and for finding things that turned out to be true, because four models over eight passes found more real debt in that schema than I would have found on my own. But all eight of them also agreed on a fix I had to revert the same day, so the saying needs a footnote: the heads are for finding, and one engineer with a script and enough patience to read the order table is still the one who decides.
It cost me eight audit sessions plus a merge for a single schema, which is fine for a change I really did not want to get wrong and far too much for an everyday pull request, and I am still not sure where the line between those two sits. If you run reviews like this at a different scale, I would like to hear where you draw it, and the easiest place to find me is LinkedIn.