← Back to Blog

Who Reviews the AI's Code?

Paul Allington 21 August 2026 8 min read

I merged a pull request last month that I had not really read. Not properly. I'd scrolled it, nodded at the green tests, glanced at a diff that touched about fourteen files across Task Board, and clicked the button. The agent had been confident. The summary it wrote was tidy. The tests were passing. And three days later a user emailed me to ask why their archived boards kept reappearing.

The bug was right there in the diff I'd "reviewed". A filter that should have excluded archived records was checking the wrong flag. Obvious, once I actually looked. I'll be honest with you: the AI didn't fail me there. I failed me. The AI did exactly what AI does, which is produce something plausible at a speed I can no longer match. The part that broke was the bit that was supposed to be my job.

The bottleneck moved and nobody told me

For most of my career the slow, expensive, error-prone part of building software was writing it. You'd spend a day on a feature and ten minutes glancing over a teammate's PR. The ratio was wildly lopsided in favour of production. Review was the cheap bit you did at the end, the bit that got skipped when the sprint was tight.

That ratio has inverted, and it happened so quietly I didn't notice until it bit me. When the AI writes the code, writing becomes the cheap part and reviewing becomes the entire job. I can have three agents working at once now, one on TestPlan, one on CoSurf, one chewing through a refactor on the Forest School App, and the output arrives faster than I can possibly absorb it. The constraint on how much good software I ship is no longer how fast I type. It's how fast I can genuinely understand what's been written and decide whether I trust it.

Nobody writes about this part. There's endless content about how to prompt better, how to get the AI to write more code, faster. There's almost nothing about the boring, unglamorous reality that you are now a reviewer first and a writer second, and that you were probably never very good at reviewing because it was always the thing you rushed.

The confident diff is the dangerous one

Here's the thing though. Human pull requests come with social signals. You know your colleague was tired, or that they flagged a bit as "not sure about this, can you check". You know which developer over-engineers and which one ships duct tape. You read their code with that context.

AI code arrives with none of that. Every diff is delivered with the same calm, fluent confidence whether it's flawless or quietly catastrophic. The variable names are sensible. The comments are coherent. It reads like code written by someone who knew what they were doing. And that polish is precisely the problem, because my brain takes "looks competent" as a proxy for "is correct", and those two things have completely decoupled.

This is review fatigue, and it's a different beast from the old kind. The old fatigue was from slogging through messy code. The new fatigue is from the relentless plausibility of it all. After the eighth confident diff of the day, the ninth gets a nod instead of a read. The danger isn't that the AI writes bad code; it's that it writes convincing code, and conviction is contagious. I caught myself trusting the diff because it sounded sure of itself. That sounds a lot like good judgement. It is not. It's just pattern-matching on tone.

Reading for intent, not for lines

The instinct, when you realise you've been rubber-stamping, is to overcorrect and start reading every line like a compiler. I tried that for about a week. It doesn't scale and it doesn't even work, because line-by-line reading is exactly the kind of mechanical, attention-heavy task my tired brain is worst at. I'd read forty lines and retain none of it.

What actually works is changing the question I'm asking. Instead of "is this line correct?" I ask "does this change do what I intended, and does it belong here?". I read for intent and architecture. Did it put the business logic in the service layer or smear it across a Blazor component? Did it invent a new pattern for something we already had a pattern for? Does the shape of the change match the shape of the problem? Those are questions a human is genuinely good at and an AI is genuinely bad at, because they require knowing what the codebase is for, not just what it says.

The AI optimises for "make this work". I have to review for "does this fit". A function can be entirely correct and still be wrong, because it solves the problem in a way that'll make the next five features harder. That's the kind of judgement I can't delegate, and honestly it's the kind I find most interesting now. The grunt work left. The architecture stayed.

Review can't be the only safety net

The real lesson from that archived-boards bug wasn't "read your diffs more carefully". I mean, yes, obviously. But "try harder to be perfect" is a terrible engineering strategy, the same way "remember to free the memory" was a terrible strategy before garbage collection. If correctness depends on me being sharp at five o'clock on a Friday after my eighth review, correctness is already gone.

So the more important shift has been to stop treating human review as the safety net and start treating it as one layer among several. The best review is the one a machine performs every single time without getting tired. Tests catch behavioural regressions whether I'm paying attention or not. Types catch whole categories of nonsense before I ever see the diff. And I've become slightly obsessed with analyzers, because a compile error is a review comment that can never be ignored, never gets argued with, and never gets rubber-stamped at the end of a long day.

I wrote a Roslyn analyzer a while back that turns an unmapped property into a build failure. The AI cannot "forget" to map a field anymore, because the project won't compile if it does. That's not me being clever; that's me admitting I'm fallible and moving the check somewhere that isn't. Every guardrail I add is one fewer thing my fragile human attention has to catch. The goal isn't to review less. It's to make the review that's left small enough that I can actually do it properly.

Using AI to review AI (and not believing it)

The obvious move is to point a second AI at the first one's work. And I do this. I'll have one agent write a change and another review it cold, with no knowledge of how it was built. It's genuinely useful. It catches the silly stuff, the off-by-ones, the missed null checks, the test that asserts nothing.

But I do not, ever, treat a clean bill of health from an AI reviewer as "this is fine". Here's why. The same blind spots that produced the bug tend to produce a reviewer that can't see the bug. They share a worldview. If the writing model misunderstood the intent of the feature, the reviewing model will very cheerfully confirm that the wrong thing was implemented correctly. Two confident systems agreeing with each other is not the same as two independent checks, and it feels exactly the same, which is what makes it dangerous.

So I use AI review the way I'd use a spell-checker. Brilliant for catching the mechanical errors I'd miss. Completely useless for telling me whether I wrote the right essay. A green tick from the second agent means "no obvious mechanical faults". It does not mean "this is what the business needs", and I've trained myself to feel a small flicker of suspicion precisely when everything comes back clean. A clean result on a complex change is a prompt to look harder, not a permission slip.

What still genuinely needs my eyes

After a year of this I've got a fairly clear picture of where a human is still non-negotiable, and it's a shorter list than I'd have guessed.

Anything touching money. Anything touching auth or who-can-see-what. Anything that deletes data or that's expensive to reverse. Anything where the requirement was ambiguous and the AI had to guess what I meant, because that's where it confidently fills the gap with something reasonable that happens to be wrong. And anything architectural, where the cost of a bad decision isn't this PR but the next twenty. Those are the diffs that get read slowly, on a clear head, ideally not last thing on a Friday.

The rest, the genuinely mechanical changes with tests and types and analyzers standing guard, I'm comfortable reviewing for intent and trusting the guardrails for the details. That comfort had to be earned, layer by layer. It's not blind faith; it's that I've built enough automated checks that being wrong is loud rather than silent.

If you're taking one thing from this, take this: do not let your review process be the thing that scales worst as your output scales fastest. The day you start shipping three times more code is the day your reviewing has to get three times better, and it won't, because you're the same tired human you were last week. So spend the effort where it compounds. Write the test, tighten the type, add the analyzer. Read for intent and let machines read for syntax. And when the diff looks too clean and you're too sure, that's the one to slow down on. The AI doesn't get nervous before a big change. That's still my job, and I've decided it's a job worth keeping.

Want to talk?

If you're on a similar AI journey or want to discuss what I've learned, get in touch.

Get In Touch

Ready To Get To Work?

I'm ready to get stuck in whenever you are...it all starts with an email

...oh, and tea!

paul@thecodeguy.co.uk