A few weeks back I wrote Vibe Coding Isn’t the Problem. Your Code Review Is. The argument was simple. AI is a tool, a tool cannot be held accountable, and the accountability lives in the review step. I still believe that.
What I got wrong was the size of the review step. I treated it like a gate that just needed more discipline. Spend more time on the diff, make juniors self review before raising a PR, plug an AI reviewer in for the parts no human can realistically read. Since then I have watched what actually happens on real teams, mine included, and I have to update the position. Careful manual review is still necessary. It has quietly stopped being sufficient.
The arithmetic stopped working
You cannot fix a throughput problem with a discipline problem.
Addy Osmani lays the numbers out in Code Review in the Age of AI. Pull requests are getting bigger as AI adoption goes up, incidents per PR are up, and change failure rates are up with them. His framing is the one that stuck with me: when output grows faster than your ability to verify it, review becomes the rate limiter for the whole team.
Everyone has felt this. A PR lands at 5 PM, it is 2000 lines, the author generated it in forty minutes, and you are expected to have an opinion by standup. So you skim it. You leave three comments on naming, you approve, and both of you pretend that was a review. The OCaml maintainers were more honest about it than most of us. When someone dropped a 13,000 line AI generated PR on them, they rejected it outright, not because it was necessarily wrong but because nobody had the bandwidth to establish whether it was right.
Asking people to try harder does not fix this. The generation side got ten times faster and the reading side did not get faster at all. That is an arithmetic problem, and no amount of “please review carefully” is going to close it.
Reviewing it yourself is the floor, not the ceiling
Before I go further I want to be clear that the base rule has not changed. Simon Willison lists it as a straight up anti pattern: do not file pull requests with code you have not reviewed yourself. Shipping something you have not read and putting your teammate in the position of being the first layer of quality control instead of the last is, to put it plainly, rude.
That rule is the floor. If you cannot explain your own diff, you are not ready to ask anyone else to look at it. But the floor is not the ceiling, and the mistake I made in the last post was treating it like one.
Code review is doing four jobs, not one
The thing that reframed this for me was Charity Majors on The Pragmatic Engineer. Her point is that we treat code review as one sacred activity when it is really a bundle of four different jobs stapled together, and those four jobs deserve very different fates.
The first is deciding whether we want this change in the product at all. The second is API design, architecture direction, and keeping the mental model of the system coherent. The third is mentoring, which mostly happens because nothing was written down. The fourth is reading for syntax, style, obvious bugs, and regression risk.
Only the fourth one is a validation task, and human brains are genuinely bad at validation. That is machine work. The first two are the valuable conversations and they are best had before the code exists, not after a agent has already produced 2000 lines in a direction nobody agreed to. The third one is real but it is a weak substitute for docs, lint rules, and guardrails.
Once you separate those out, the panic about the review bottleneck starts to look different. We are not short on review capacity. We are spending our scarce human review capacity on the one part of the job a machine should be doing.
The trust ledger
If you are debiting from the trust account when the code is created, it has to be credited back somewhere else.
This is the idea from that episode I keep coming back to, and it is the actual thesis of this post.
Every line of code you merge carries some amount of accumulated trust. Historically that trust was built at the moment of creation. A human wrote it, a human understood it, another human read it and signed off. Three humans deep, all with a working mental model of the system.
AI removes most of that at the source. The code appears, it looks reasonable, and no human ever held the full model in their head. You have debited the trust account. Manual review, on its own, cannot credit it back, because the reviewer never had that model either and now has ten times more code to build one from.
So you pay it back elsewhere. Tests and evals. Conformance testing, which is the boring but underrated question of whether the new code stays inside the performance and behaviour boundaries of what it replaced. Harness validation for every generated change. Small stackable commits instead of one giant drop. AI review as the first pass and a human as the final signature. And then telemetry, because production is where you find out what the code actually does.
That last one deserves its own line. We keep saying the source of truth is the code. It is not. The source of truth is production behaviour, and if you cannot see production clearly then you have no idea whether any of this is working. Observability stopped being an ops concern the moment we started shipping code that nobody fully read.
Proof, not promises
The practical version of all this is small. Addy calls it the PR contract, and I have started using a stripped down version of it.
What and why, in two sentences. Proof that it works, meaning tests that pass or a screenshot or a log, not the phrase “tested locally”. Which parts were AI generated and how risky the blast radius is, because a copy change and a payments change should not get the same treatment. And one or two specific things you actually want a human to look at.
If you cannot fill that in, you do not understand your own change well enough to ask somebody else to approve it. That is not bureaucracy, it is respect for the reviewer’s time, and it flips the default from “prove this is broken” to “prove this works”.
There is a routing decision hiding in there too. Anything touching auth, money, permissions, or irreversible data gets read line by line by a human, every time, no exceptions. Critical path code gets human eyes with agent assistance. Low risk, well scoped, boring stuff gets decomposed into atomic PRs and validated by machine with humans auditing the system rather than the diff. The skill worth building is not “read more code”. It is knowing which code to read.
Where this leaves my last post
I would not retract it. Vibe coding still is not the problem and your review process still is. But I would extend it.
Manual review was the answer when a human wrote every line and the reviewer’s job was to catch what the author missed. Now the author might have missed all of it, and the volume makes thorough reading physically impossible. Review has to move up a layer, from line by line gatekeeping to deciding intent, owning risk, and designing the system that does the validating.
The bottleneck moved from writing code to proving it works. Somebody still has to be accountable for what ships, and that somebody is still you.
I promised in the last post that I would share the AI workflow I use day to day. That one is coming next, along with what my PR contract and review agent setup actually look like in practice. Stay tuned!