Let’s do arithmetic instead of philosophy.
Take a ten-engineer team. Assume each engineer can give genuinely careful review — the kind where they actually understand the change, not the kind where they scan and approve — to about 400 lines of unfamiliar code per hour. Generous. Assume they can spend two hours a day on review before it eats the work they’re accountable for. That’s 800 lines per engineer per day, 8,000 for the team.
Now look at what arrives. Faros telemetry on agent-heavy teams: 98% more PRs, 154% larger. The Pragmatic Engineer’s numbers over a two-year window are steeper — teams running agents ship five times more pull requests at triple the size. Whatever your baseline was, multiply it by something between 3x and 15x.
Your review capacity did not multiply by anything. It’s the same ten people with the same brains and the same two hours.
So one of two things is happening on your team right now, and it isn’t a third thing. Either work is queuing — Plandek’s 2026 benchmarks across more than 2,000 teams show bottom-quartile teams taking 35+ hours just to merge a PR, and Faros clocks a 4.6x increase in time-to-first-review-pickup — or your reviews stopped being reviews. They became approvals.
Nobody announces the second one. There’s no meeting where a team decides to start rubber-stamping. It just happens, PR by PR, at 6 PM, when the diff is 900 lines and the sprint ends Thursday.
Line-by-line human review of every change was never a principle. It was an affordable habit, made affordable by code being expensive to produce. The habit outlived its economics and turned into theater.
This is part four of Rethinking the SDLC. I’ve argued before that we should stop reviewing code and start reviewing evidence — that the gate should demand machine-verified proof and reserve humans for intent and architecture. This piece is the operational layer under that: how you actually route changes, what the machine floor must contain, when an AI reviewer is worth anything, and how to spend a review budget you can finally see.
The failure mode isn’t slowness. It’s silent approval.#
I want to be precise about why queue length is the less dangerous symptom.
A 35-hour merge time is visible. It shows up in dashboards, people complain, leadership eventually funds something. Painful, but self-correcting.
Approval theater is invisible and it corrupts the data. A rubber-stamped PR looks identical to a rigorously reviewed one in every system you own — same approval, same merge, same lead-time contribution, same green check. Your metrics get better as your review quality collapses, because the queue drains. That’s the worst possible property for a control to have.
And the consequences surface later, wearing a different name. Apiiro tracked more than 7,000 developers across 62,000 repositories and found roughly 4x velocity arriving with 10x the vulnerabilities. The asymmetry is the finding — ten times the security debt for four times the output is what a gate looks like when it stops working as a filter and keeps working as a signature.
Martin Fowler’s framing of the human as the Global Interpreter Lock for agents is the right diagnosis. The arithmetic consequence is harsher than the metaphor suggests.
A lock has a throughput, and ours is the number at the top of this article: 8,000 understood lines a week for a ten-person team, and it does not move. So serialization isn’t a slowdown you can optimize away. It’s a permanent ceiling on how much change your organization can absorb, wholly independent of how much it can produce.
Which leaves two outcomes, if review stays one undifferentiated activity applied to every change. Throttle production to fit the ceiling and accept that reviewers’ calendars set your capacity forever. Or breach it silently, with approvals that aren’t reviews — the case Charity Majors describes, where shipping past the reading rate means “reliability degrades, institutional knowledge evaporates.”
Neither is acceptable. So stop applying review uniformly.
Review isn’t one thing. It’s four different jobs stapled together.#
Here’s what actually happens in a good code review, and the reason it doesn’t scale is that we bundled four unrelated activities into one ritual and gave them all to the same person at the same time.
Job 1 — Conformance. Style, patterns, dependency rules, naming, secrets, banned APIs, scope sprawl. Entirely mechanical — and still where most review comments go.
Job 2 — Correctness. Does it do what it claims, and nothing else? Mostly provable: tests that fail before and pass after, property checks, regression runs, blast-radius analysis. Partly not provable, which is the interesting part.
Job 3 — Consequence. What breaks if this is subtly wrong? Who gets paged, which customer notices, is it reversible? Risk assessment, informed by scar tissue.
Job 4 — Intent and architecture. Should this change exist? Is it shaped right? Is it the third solution to a problem we should have solved once? No machine answers these, because they require knowing things that aren’t in the codebase.
Jobs 1 and 2 are where nearly all the volume is. Jobs 3 and 4 are where all the value is. A traditional review asks one human to do all four at once, on every change, which means their attention gets consumed by the volume before it reaches the value.
Unbundle them and the capacity problem changes shape entirely.
The routing model#
Stop asking “who reviews this PR.” Start asking “what does this change class require, and which of those requirements need a human.”
Layer 0 — The machine floor. Non-negotiable, applied to every change, no exceptions.
This is Job 1 in full, plus the mechanical parts of Job 2. Nothing reaches a human until it passes:
- Style, lint, types, build.
- Dependency and boundary rules — the architectural constraints from your intent packages, enforced.
- Secret detection. GitGuardian found 28.6 million new secrets in public commits in 2025, up 34%, with AI-assisted commits leaking at roughly twice the baseline rate. This one is not optional and it is not a human’s job.
- SAST and dependency-vulnerability scanning.
- Scope check. Does the diff touch only the surface the intent package declared? Unrequested tidying in adjacent modules is the most common way an agent change exceeds its brief, and it’s invisible to every other gate on this list — the additions compile, pass, and lint clean. Comparing declared scope against actual scope is cheap, mechanical, and catches a class of risk that no amount of careful reading reliably does.
- Test evidence: a repro that failed before and passes after, for anything claiming to be a fix.
If a change can’t clear Layer 0, it isn’t “awaiting review.” It’s not done. Nobody should ever see it.
Layer 1 — Adjudication. An adversarial reviewer whose job is to attack the evidence.
This is where AI-reviewing-AI belongs, and where most implementations of it are worthless. I’ll be specific about the difference in a moment.
The adjudicator is not asking whether the code is good. It’s asking one question — does the evidence actually establish the claim? — and it’s looking for four specific ways evidence lies.
The proof proves something else. The test passes for a reason unrelated to the fix; the assertion holds whether or not the change is correct.
The proof is unfalsifiable. Assertions loose enough to survive a wrong implementation, or mocks standing exactly where the real interaction risk was.
The claim and the diff disagree. The change does what it says and three things nobody asked for.
It’s internally consistent and externally wrong. Everything agrees with the code; nothing agrees with the stated intent. Human reviewers miss this one too, because coherence is persuasive.
Anthropic shipped a Code Review product aimed squarely at this problem, and the fact that vendors are building it as a category is a signal, not an endorsement — you still have to make it independent, which is the hard part.
Layer 2 — Human judgment, routed by risk. Jobs 3 and 4, and only those.
Now the arithmetic works, because the human isn’t reading 8,000 lines. They’re ruling on consequence and intent for the subset of changes where consequence and intent are actually in question.
Classify by consequence, not by size#
The routing decision needs to be made once per change class and then applied automatically. Here’s the classification I’d defend.
Class A — Reversible, bounded, machine-verifiable. Dependency bumps, codemods, framework migrations, generated client updates, test additions, formatting, config in a non-production path. A machine can prove the end state and a bad outcome is cheap to undo.
Route: Layer 0 + Layer 1. No human review. Sampled audit — pull 5% at random, weekly, and review those properly to detect gate drift.
This is the part that makes people uncomfortable, and I’d push back hard on the discomfort. Hand-reviewing a lockfile diff isn’t rigor, it’s ceremony. If a test can prove it, a human babysitting it adds latency and nothing else — and the attention you spend there is attention stolen from the changes that need it.
Class B — Business logic in a bounded blast radius. A feature in one service, behind a flag, with defined verification, no schema or contract change, reversible in minutes.
Route: Layer 0 + Layer 1 + human review of the evidence summary and the intent, not the diff. The reviewer reads: what was the intent, what proof arrived, what’s the blast radius, does this change deserve to exist. Ten minutes, not ninety. They can drill into the diff if the evidence smells wrong — and the drill-down being optional is the whole point.
Class C — Consequential and hard to reverse. Schema migrations, auth and authorization, quota and entitlement paths, public API contracts, data deletion, permission and IAM changes, cryptography, anything touching customer data, anything a partner integrates against.
Route: everything above, plus a named human who reads the code, plus a second human for the irreversible subset. Class C is where the old model was right and stays right. It should be a small percentage of your volume — and if it isn’t, that’s an architecture finding: your blast radiuses are too wide and too entangled, and no review policy will save you from that.
Class D — Architectural. New service, new boundary, new data ownership, new external dependency, a pattern that will be copied fifty times.
Route: this was never a PR review. It’s a design decision that arrived as a diff, which means it arrived too late. Class D belongs upstream, as a constraint in the intent package, decided before an agent writes anything.
Two rules keep the classification honest.
What separates real AI adjudication from theater#
Layer 1 is where most teams will either get enormous leverage or install a very expensive rubber stamp. Four properties decide which.
1. Independence. The reviewer must not be the author. Same model family is fine; the same session is not. An agent reviewing its own output isn’t reviewing — it’s rationalizing, and it will confidently confirm its own mistakes. I’ve written about AI reviewing AI’s code before, and independence is the entire ballgame.
2. Adversarial framing. “Review this change” produces compliments. “Find the input that breaks this, and default to rejecting if you can’t verify the claim” produces findings. If your AI reviewer approves more than it questions, it’s decoration.
3. Different context, deliberately. Give the adjudicator what the author didn’t have: incident history for this module, ownership metadata, the SLOs, the last three postmortems on this path. A second reviewer’s value has always come from a second perspective, and perspective is a function of context.
4. It must be able to say no, and that no must stick. A reviewer whose findings are advisory is a linter with better prose. If Layer 1 bounces a change it goes back, with no override absent a recorded reason. The moment “the AI reviewer complained” becomes something you click past, you’ve built theater with a compute bill.
And be honest about the ceiling. Cognition’s FrontierCode benchmark scores agent PRs on whether a senior maintainer would actually merge them, and every frontier model passes fewer than half the hard tasks. Two conclusions, both important: agents have not earned unsupervised trust, so the layers stay — and merge-worthiness is machine-gradeable, which means your pipeline can demand correctness, test quality, and scope discipline rather than hoping for them.
Make the review budget visible#
You can’t manage a scarce resource you don’t measure. Four numbers, on the same wall as your delivery metrics.
| Number | What it tells you |
|---|---|
| Review capacity, stated in advance | Hours per week, decided deliberately like an on-call budget — not “whatever’s left.” Once it’s stated, exceeding it is a visible event instead of a quiet degradation. |
| Class mix | If Class C is 40% of volume, your problem is coupling, not review. If Class A is 80% and humans are still drowning, your machine floor has holes. |
| Time-to-decision by class | Not overall merge time, which averages the signal away. Class A in minutes. Class C being slow is correct. |
| Escaped defects and gate-catch rate, by class | Which class produces incidents, and which layer caught what. |
That last row is what makes this a system rather than an opinion, so it’s worth being explicit about the loop it drives: sampled audits on Class A feed it directly. Two quarters of clean audits earns you a wider Class A. One bad finding fixes the gate — not the policy. Autonomy gets granted by evidence and revoked by incident, and this is the number that decides both.
What to do this month#
- Classify your last 200 merged changes into A/B/C/D, by hand, once. An afternoon, and it resets the conversation. Most teams find 70%+ is Class A and has been getting the same ceremony as a migration.
- Build Layer 0 until it’s genuinely trustworthy. Especially the scope check and secret detection. Every gap here is a human minute you’ll spend forever.
- Stand up one adversarial adjudicator on one repo. Independent session, refutation prompt, extra context, binding verdict. Then measure it both ways — what it caught that humans missed, and what humans caught that it missed. That comparison is the only way to find where the line sits in your codebase.
- Kill human review on Class A, with sampled audits. This is the move that frees the capacity for everything else. Announce it, publish the audit results, let the data defend it.
- Move your Class D findings upstream, and track the budget publicly. Every architectural objection raised in review this quarter was a constraint that belonged in the intent package. And when capacity, class mix, and escapes are all visible, “let’s launch four more agent lanes” becomes an arithmetic conversation instead of an enthusiasm one.
Reviewing is being promoted, not eliminated#
The version of this argument I don’t accept is “AI writes it, AI reviews it, humans get out of the way.” That’s a wish, not a system. Every layer above exists because agents are demonstrably fallible in exactly the ways the benchmarks show.
But the version I hear more often from good engineers is also wrong: that reading every line is what integrity looks like. It was, when a human wrote every line and there were few enough to read. Integrity is a property of outcomes, not of the ritual — and a team where 70% of changes are machine-proven and 30% get real human judgment has more of it than a team where 100% get a scan and a thumbs-up.
The reviewer role isn’t shrinking. It’s moving from fact-checker to judge.
Which brings me to the question worth asking in your next retro. Of the last ten PRs you approved, how many did you genuinely understand? Not scanned. Understood.
If the honest number is under five, you don’t have a diligence problem. You have a routing problem — and you’ve been paying for it with your own credibility.
I lead AI transformation for a global SaaS platform, and the routing model above is roughly how my agent lanes actually merge. If you’ve built a review classifier, or you think Class A can’t safely skip humans, come argue — this is the one I most want to be tested on. Find me on X, LinkedIn, or Telegram.
