Series: AI-Assisted Engineering · Part 11 of 11
- A Year of AI Coding Assistants: What I've Learned Rolling Them Out in 2024
- Model Context Protocol Explained for Engineering Leaders
- From Autocomplete to Agents: How Agentic Coding Changed Our Workflow in 2025
- AI Adoption Strategy for Engineering Teams: How to Do It Without Losing Quality
- AI Editor Wars (Cursor vs Claude Code vs Kiro): An Honest CTO's Comparison
- Spec-First AI Development in Practice: Kiro, Plan Modes and Spec Kit Compared
- Deploying an LLM Gateway with LiteLLM: Virtual Keys, Budgets and Routing Claude Code Through It
- Claude Fable 5.1 vs GPT-5.6: My Take as a CTO Who Still Ships Code
- AI Coding Accuracy and Spec-Driven Development: What Works at Startup, Scaleup and Enterprise
- Running an LLM Gateway in Your Business: Keeping Context and Code In-House (and How It Differs from Bedrock)
- When AI Writes Most of the Code, Review Becomes the Bottleneck
Contents
- The Constraint Has Moved
- Why Review Got Harder, Not Just Busier
- Make PRs Small Again
- What to Delegate to AI Reviewers, and What Not To
- The Author Still Owns the Code
- Risk-Tier Your Pull Requests
- Tests, Specs and CI Are the Real Safety Net
- Metrics That Show Quality Drift
- Practical Team Policies
- A Short Decision Checklist
- The Takeaway
The Constraint Has Moved
For most of my career, the slow part of shipping software was writing it. Review was a check at the end.
That model is broken. With agentic coding tools, an engineer can produce in an afternoon what used to take a week. In recent consulting work, the pattern I see repeatedly is a queue of open pull requests that grows faster than anyone can read them. Engineers are not short of code. They are short of reviewers who understand the code well enough to say yes with a straight face.
Speed up one stage of a pipeline and leave the next alone, and you have not made the system faster; you have built inventory. Unreviewed PRs go stale, conflict, and push people towards approving things they have not really read.
AI made the cheap part cheaper and left the expensive part where it was. Reading code, understanding intent and spotting the missing edge case are still human work.
Why Review Got Harder, Not Just Busier
It is not only volume. AI-generated changes have a different shape from human ones, and that shape is harder to review.
- Plausibility is high. Generated code looks idiomatic, is well named and often has comments. Human code with a bug usually looks a bit wrong somewhere. AI code with a bug often looks completely fine.
- Diffs are larger. An agent asked to "add a field" will happily update the model, the migration, three serialisers, the admin view and twelve tests. Each change is reasonable. Together they are a 900-line PR.
- The author knows less. When an engineer wrote every line, they could answer "why did you do it this way?". When an agent wrote it, the honest answer is sometimes "I'm not sure, it passed the tests".
- Incidental changes creep in. Reformatting and "helpful" refactors that hide the signal.
When I was CTO of a subscription e-commerce business, the bugs that hurt us most were rarely syntax or style. They were business logic: a charge date that moved when it should not, a discount that stacked when it should not, an idempotency key that was not quite unique. Exactly the bugs that slip through when the code looks tidy.
Make PRs Small Again
The single most effective lever is PR size. It was true before AI and it is more true now, because generating a large diff costs nothing.
My working rule for teams I advise: a PR should be reviewable properly in under 30 minutes by someone who did not write it. For most codebases that means a few hundred lines of meaningful change, excluding generated files and lockfiles. If an agent produces more than that, the engineer's job is to split it before asking for review, not after.
Stacking
Stacked PRs are the practical answer to "but the feature is big". Instead of one large branch, you build a chain of small, dependent PRs, each of which makes sense on its own:
- Add the database column and migration (no behaviour change).
- Add the domain logic behind a feature flag, with tests.
- Wire the API endpoint.
- Add the UI.
- Remove the flag once it is rolled out.
Each step is small and independently revertible. Tools such as Graphite or git-branchless help, but plain Git and a team convention work too. Feature flags make this much easier, because half-built features can merge safely; I wrote about that in Feature Flags: Enabling Safe and Reliable Deployments.
AI agents are good at helping here: asking one to "split this branch into a stack, schema first, then logic, API and UI" works well, and is a better use of the tool than generating yet more code.
What to Delegate to AI Reviewers, and What Not To
AI review bots are now standard: GitHub Copilot code review, CodeRabbit, and agents such as Claude Code run in CI on every PR, plus plenty of in-house setups calling a model through a gateway. They are useful. They are also the easiest way to create a false sense of safety.
Here is how I split the work:
| Review concern | AI reviewer | Human reviewer | Notes |
|---|---|---|---|
| Style, naming, obvious smells | Good | Should not spend time here | Linters and formatters should catch most of this first |
| Common bug patterns (nulls, off-by-one, unhandled errors) | Good | Spot check | Fast and tireless |
| Security patterns (injection, secrets, unsafe deserialisation) | Useful first pass | Required for sensitive areas | Pair with SAST and secret scanning, not instead of |
| Does this match the spec / acceptance criteria? | Partial, if the spec is in the repo | Required | AI cannot judge intent it has not been given |
| Business rules (money, tax, dates, entitlements) | Weak | Required | Plausible but wrong is the danger zone |
| Architecture and fit with the wider system | Weak | Required | Needs context that rarely fits in a diff |
| Operational risk (migrations, locking, rollback, load) | Partial | Required | Humans who have been paged know what to look for |
The failure modes
Noise. A bot that leaves fifteen comments per PR, twelve of them trivial, trains everyone to ignore it within a fortnight. Once engineers stop reading bot comments, the three useful ones get ignored too. Tune aggressively: drop style comments your linter covers, ask for high-confidence findings only, and cap the count.
False confidence. This is the more dangerous one. A green tick from an AI reviewer feels like a review. It is not. The bot does not know that this endpoint is called by the warehouse integration at 3am, or that finance reconciles against this table. Seeing "AI review: no issues", human reviewers read less carefully, even in teams with otherwise excellent habits.
Correlated blind spots. A model that misunderstands an API when writing code will often misunderstand it the same way when reviewing. A different model helps a little; it does not replace an independent human.
My rule: AI review is a pre-filter that makes human review cheaper. It runs first, the author resolves or dismisses its comments, and then a human reviews. It never counts as an approval on its own, and branch protection should enforce that.
The Author Still Owns the Code
This needs saying plainly, because I still hear "the AI wrote that bit".
If your name is on the PR, you own every line of it. You should be able to explain any part of it in review, and you should be the person who gets paged when it breaks. The agent is a tool, and nobody ever blamed a compiler for a bug in their logic.
In practice, I ask teams to adopt an author checklist that goes in the PR template:
## Author checklist
- [ ] I have read every line of this diff, including AI-generated code
- [ ] I can explain why each non-trivial change is needed
- [ ] Incidental changes (formatting, unrelated refactors) are removed or split out
- [ ] Tests cover the behaviour in the spec, not just the lines changed
- [ ] Risk tier: [ ] Low [ ] Medium [ ] High (see REVIEW.md)
- [ ] Rollback plan (Medium/High only):The first box matters most. Self-review is the cheapest quality gate there is, and AI made it optional in a way hand-written code never did.
Risk-Tier Your Pull Requests
Not every change deserves the same scrutiny. Treating a copy change and a payments migration identically means either the copy change waits too long or the migration gets too little attention.
I use three tiers. The exact boundaries vary by business, but the shape is consistent:
| Tier | Examples | Review required | Merge path |
|---|---|---|---|
| Low | Copy, styling, internal tooling, tests only, docs, isolated behind an off flag | AI review plus one human, light touch | Can merge same day, auto-merge on green allowed |
| Medium | New features in existing patterns, non-critical API changes, dependency upgrades | AI review plus one human who knows the area | Normal flow, flag for anything user-facing |
| High | Payments, auth and permissions, data migrations, PII handling, pricing, infrastructure, anything irreversible | AI review plus code owner, ideally two humans; spec linked | Deliberate deploy window, rollback plan, staged rollout |
You can automate part of the tiering with path-based rules. GitHub's CODEOWNERS file is the simplest tool for this:
# CODEOWNERS
/src/billing/ @org/payments-owners
/src/auth/ @org/security-owners
/migrations/ @org/data-owners @org/platform
/infra/ @org/platformCombined with branch protection requiring code owner approval, this ensures high-risk paths always get a human who understands them.
The point of tiering is not bureaucracy. It is to free reviewer attention for the changes that can actually hurt you.
Tests, Specs and CI Are the Real Safety Net
Human review was never a very reliable bug catcher; much of its value is knowledge sharing and design feedback. At AI-generated volume, relying on it to catch bugs is a losing strategy.
The safety net has to be automated and has to sit in front of review:
- A spec in the repo. If the acceptance criteria are written down, both the agent and the reviewer can check the change against them. Without a spec, the reviewer is reverse-engineering intent from a diff. I covered how to do this without drowning in process in AI Coding Accuracy and Spec-Driven Development.
- Tests that encode behaviour, not lines. Agents write tests that pass; fewer of them would fail if the behaviour were wrong. Reviewers should spend more time on the tests than the implementation.
- Types, linters and static analysis as hard gates. Anything a machine can check, a machine should check, and the PR should not reach a human until it passes.
- Progressive delivery. Feature flags, canaries and fast rollback reduce the cost of the bugs that do get through. When review is the bottleneck, making mistakes cheaper is as valuable as making them rarer.
The mental shift for reviewers: you are not checking correctness line by line. You are checking whether the tests would catch it if it were wrong, and whether the change does what the spec says.
Metrics That Show Quality Drift
The risk with a review bottleneck is that teams "solve" it by reviewing less, and quality erodes slowly enough that nobody notices for a quarter. You need leading indicators. These are the ones I watch:
- Change failure rate. The DORA metric: the share of deployments that cause a failure needing remediation. If it rises after AI adoption, review or testing is not keeping up.
- Revert rate. Reverts per week, or as a share of merged PRs. Cheap to measure from Git history and a very honest signal.
- Review latency. Time from "ready for review" to first human review, and to merge. Falling latency with a rising failure rate means rubber-stamping.
- Rework. Code changed again within a few weeks of merging. Some tools call this churn. A spike in rework on AI-heavy changes suggests things are merging before they are understood.
- Review depth. A steady stream of zero-comment approvals on large PRs is a warning sign.
- Escaped defects by tier. Incidents traced back to a change, broken down by the risk tier of that change. If high-tier changes are failing, your deep review is not deep enough.
None of these should become individual targets. The moment review latency is on someone's objectives, you will get fast, shallow reviews. Use them at team level to spot trends, as I argued in Measuring Engineering Productivity in 2025.
Practical Team Policies
For a team where most code is AI-assisted, I would start with:
- AI review runs first and never counts as approval. Enforced by branch protection, not convention.
- Authors self-review every line before requesting review. The PR template says so, and reviewers are entitled to bounce PRs where it is obvious nobody did.
- Soft size limit with a warning in CI. Large PRs need a sentence explaining why they could not be split.
- Risk tier on every PR. Path-based defaults, author can raise but not lower.
- Code owners on high-risk paths. Payments, auth, migrations, infrastructure, PII.
- Specs linked on Medium and High tier changes. Reviewers check against the spec, not their guess at intent.
- Review time is protected. Explicit review slots each day, and review counts as real work in planning. If you budget 100 per cent of capacity to building, nobody has time to review what was built.
- Reviewers can say "I don't understand this" and that blocks the merge. If the reviewer cannot follow it, the next engineer to debug it at 2am will not either.
- A monthly team look at the quality metrics, changing process rather than blaming people.
The seventh point is where leadership matters most. If AI has made each engineer, say, twice as productive at writing code, a meaningful chunk of that gain has to be reinvested in review, or you have just moved the risk downstream to production. The CTO has to make that trade-off visible, because no individual engineer will choose to slow down.
A Short Decision Checklist
Before you conclude that your team needs more reviewers or a better AI review tool, check:
- Is the median PR reviewable in under 30 minutes?
- Do engineers stack or split large AI-generated changes before review?
- Is AI review tuned to a handful of high-signal comments, and is it barred from counting as approval?
- Does every PR have a risk tier, with code owners on the high-risk paths?
- Are specs and tests strong enough that a reviewer can trust them as the definition of correct?
- Do you track change failure rate, reverts, review latency and rework at team level?
- Is review time explicitly planned rather than squeezed in around delivery?
If you answer no to more than two or three, the problem is not a lack of reviewers. Review has not been redesigned for AI volume.
The Takeaway
AI has turned code generation from the expensive part of software delivery into the cheap part. Understanding, verifying and owning that code has not got any cheaper, so review is now where the constraint lives. Teams that ignore this end up with long PR queues, or with fast approvals and a slow rise in incidents.
The answer is not to review harder. It is to make each review smaller, to spend human attention where the risk is, to let machines (tests, types, CI and AI pre-review) catch what machines can catch, and to keep the author fully accountable for what they ship. Measure change failure rate, reverts, latency and rework so you can see drift before your customers do.
Treat review as a first-class part of the system, with its own capacity, tooling and metrics, not as the step after the real work is done.
