Code review has always done several jobs at once, and it is worth separating them before asking what changes. It catches defects. It spreads knowledge, so more than one person understands each part of the system. It enforces consistency. And it creates accountability: somebody other than the author put their name to this going in.
Only the first of those is about finding bugs, and it was never the one review was best at. Studies have said for decades that review catches a modest share of defects. Teams kept doing it anyway, correctly, because the other three jobs were worth the time on their own.
Review survived not because it was an efficient bug filter, but because it distributed understanding and assigned responsibility. Machine-written code strains the first job and quietly removes the conditions the other three depended on.
The assumptions that broke
The old process assumed the author understood the change. When a person wrote a function, they had held the problem in their head, considered alternatives, and could answer "why did you do it this way." A reviewer could lean on that: ask the question, get a real answer, and calibrate trust accordingly.
When the diff came out of a model, the author is a person who read it and thought it looked right. They may be an excellent engineer with genuine understanding, or they may have skimmed it. From the reviewer's side these are indistinguishable, and the usual signal, asking why, now returns an answer that was reconstructed after the fact rather than one that drove the decision.
The process also assumed volume was bounded by writing speed. A senior could review everything because a team could only produce so much. That constraint is gone, and the reviewing capacity it protected did not grow to match. We described the general form of this in the AI-native team: generation got cheap, verification became the bottleneck, and verification is fatiguing in a way generation is not.
Plausible is the new dangerous
The defects are also shaped differently, and this is the part that matters most for how you read a diff. Human bugs tend to look like human bugs: an off-by-one, a forgotten case, a misunderstanding visible in awkward code. There is often surface evidence that the author was struggling, and reviewers are well trained to notice it.
Machine-written defects arrive in fluent, idiomatic, well-formatted code that reads as though somebody confident wrote it. The error is usually semantic: a plausible-looking API used slightly wrong, an edge case handled in a way that is reasonable but not what this system requires, an assumption about the data that happens to be false here. Nothing looks wrong. The code looks like the code around it. This is why the vulnerability numbers move in the wrong direction even as readability improves.
Review the diff, or review the spec?
The most useful shift we made was moving part of the review earlier. If a change is going to be generated from a description, then the description is the artefact that determines whether the result is correct, and reviewing it costs a fraction of reviewing the output.
Concretely: for anything non-trivial, we agree the approach before generating, not after. What is this supposed to do, what are the edge cases, what should it explicitly not do, how will we know it works. That conversation takes a few minutes and catches the class of error that is most expensive to find in a diff, namely the change that is well-implemented and solving the wrong problem. This is the same instinct as the eval-side argument in reading the route rather than the score: judge the intent, not only the artefact.
Diff review still happens, but with the specification settled it becomes a narrower question: does this implement what we agreed, and does it do anything we did not ask for. That second half is worth stating explicitly, because unrequested extras, defensive handling for impossible cases, speculative abstractions, are a characteristic pattern in generated code and they are easy to wave through since each one individually looks harmless.
What we changed
The author states what they verified. Not "please review" but "I ran these cases, I checked this edge, I am unsure about this part." It re-establishes the signal the process lost, and it is honest about the difference between reading a diff and understanding it. When somebody writes "I have not verified the concurrency behaviour," that is the most useful sentence in the pull request.
We size review by risk, not by lines. A four-hundred-line generated change to an internal tool gets a lighter pass than a thirty-line change to auth. That was always sensible; it is now necessary, because volume made uniform scrutiny arithmetically impossible.
We treat reviewing capacity as the scarce resource it is. A senior who has read twelve generated diffs is not the reviewer they were on the first one. We cap how much review one person does in a day and we schedule the consequential reviews when people are fresh, which sounds fussy and has caught real bugs.
Using AI to review AI
The obvious response to more machine-written code is more machine review, and it does help, with a caveat worth knowing. Automated review is good at breadth: it will read every line of a large diff without fatigue, which no human does. It is weaker at the thing that matters most here, which is knowing what this system is actually supposed to do.
The practical caveat is that review harnesses are unusually sensitive to how you ask. A prompt that says "only report high-severity issues" or "be conservative" gets taken literally by current models: they investigate thoroughly, find the problems, and then decline to report what they judge below the bar. Precision goes up and measured recall goes down, which reads as the tool getting worse when it has actually got more obedient. Ask for everything with a confidence and severity attached, and filter afterwards.
The other caveat is not to let it become the whole process. If a generated change is reviewed only by a machine and merged, nobody on the team understands that code, and you have quietly traded away the knowledge-distribution job that was review's real value. That is a debt with a compound curve, of exactly the kind we described in the real cost of technical debt.
The bottom line
The honest position is that review is doing a harder job with the same budget, and pretending otherwise is how teams end up with a rubber stamp. Move the judgement earlier, to the specification, where it is cheapest. Make authors say what they actually verified. Spend scrutiny in proportion to risk rather than uniformly across a volume that no longer has a natural ceiling. Use automated review for breadth and keep a human on the parts that require knowing what the system is for. And keep at least one person other than the model understanding each important piece of the codebase, because that was always the point.