Over part 1 and part 2 of this series, we made a team fast. A shared skill so everyone writes endpoints the same way. A plugin so everyone has the same subagents and hooks. Ten developers, all producing correct-shaped code at AI speed.

That’s the problem this post is about.

When code was slow to write, review kept up naturally — there simply wasn’t that much of it. Now your team opens twice as many pull requests, each one larger, each one written by an AI that is very good at producing code that looks right. The bottleneck moved. It’s no longer writing the code. It’s trusting it.

And there’s a quiet failure mode hiding in that speed: the AI writes it, a human clicks approve, and nobody actually understood it. The commit has a name on it, but the understanding it implies isn’t there.

The principle I keep coming back to is simple: AI is a tool; the developer is accountable. It’s the principle I wrote down in my team’s AI governance rules, and it’s the one thing in this series that isn’t negotiable. Fast AI doesn’t change it — it just makes it easier to pretend otherwise. Review gates are how you stop pretending.


The new bottleneck is review, not production

You can’t fix this by reviewing harder. A human skimming ten AI-written PRs a day will rubber-stamp them, because attention doesn’t scale the way generation does.

So you build two gates, and you’re deliberate about which does what:

  • an automated gate that catches the mechanical, the repetitive, the things a machine is genuinely better at spotting, and
  • a human gate for the small number of things a machine cannot be trusted to judge.

The goal isn’t more review. It’s putting each kind of review where it actually works.


Layer 1 — the automated gate

You already built most of this in part 2: the dotnet-reviewer subagent in your team plugin. Now you give it a job with teeth — it reviews the diff before the pull request is opened.

Point it at the changes and let it do the mechanical pass:

“Review the staged diff with the dotnet-reviewer subagent. List only issues you’re confident about, most severe first.”

This is the layer that reliably catches the AI’s own blind spots in C#:

// The kind of thing the automated gate should stop:

public async void ProcessTrip(Guid id)          // async void — unobserved exceptions
{
    var trips = await _db.Trips.ToListAsync();   // loads every trip to find one
    var trip = trips.First(t => t.Id == id);     // N+1 waiting to happen at scale
    trip.Complete();                             // no null check, throws
}

None of that is subtle, and that’s exactly why it belongs to the machine. async void, a query that pulls the whole table, a missing guard — a reviewer shouldn’t be spending human attention on these, and an AI reviewer catches them every time without getting bored on the ninth PR of the day.

Wire it into CI too, so it runs on every PR and not only when someone remembers to ask. The point of an automated gate is that it isn’t optional.

But notice what this gate can’t tell you: whether the endpoint should exist, whether it belongs in this service, whether returning that field to that caller is a data-leak. It’s checking the how. It has no opinion on the whether.


Layer 2 — the human gate

This is the layer you cannot delegate, and the whole series has been building toward it.

There are a handful of judgements a human has to make, precisely because they’re the ones the AI is worst at and the ones with the highest cost when they’re wrong:

  • Ownership. Does the person merging this actually understand it well enough to fix it at 2am when it breaks? If the honest answer is no, it’s not ready — no matter how green the checks are.
  • Architecture. The AI optimises the change in front of it. It won’t tell you that this is the fourth slightly-different TripService and they should be one.
  • Security and data intent. “Return the trip” and “return the trip including the driver’s home address to an unauthenticated caller” look almost identical in a diff. Intent isn’t in the syntax.
  • Domain correctness. The code can be flawless and still encode the wrong rule, because the AI took the requirement literally and the requirement was wrong.

The way to keep this gate honest is to make it explicit rather than hope for it. Two small artifacts do most of the work.

A CODEOWNERS file, so the right human is required — not requested — on the changes that matter:

# .github/CODEOWNERS
/src/Payments/    @acme/payments-leads
/src/Auth/        @acme/security
*.sql             @acme/data

And a pull-request template that asks the merger to claim the understanding the AI can’t:

## Human review checklist
- [ ] I understand this change well enough to debug it in production.
- [ ] I checked what data this exposes and to whom.
- [ ] This fits the existing architecture (or the deviation is intentional
      and noted below).
- [ ] The domain rule here is the one we actually want.

Those checkboxes aren’t ceremony. They’re the difference between a name on a commit and a person who stands behind it.


Where this gets dangerous

One honest warning, because this is the failure mode I worry about most.

A green gate is not understanding. The real risk of good automated review isn’t that it misses things — it’s that it’s reassuring. A passing dotnet-reviewer and a wall of green checks make it feel safe to approve without reading. That’s the exact moment accountability evaporates: everyone assumed the gate meant someone had looked, and no one had.

The automated gate exists to free up human attention for the judgements only a human can make — not to replace them. If your review gates make people read less carefully, you’ve built a faster way to ship code nobody owns. Watch for it.


Try it this week

Don’t start with tooling. Start with a sentence your team agrees on:

These three things, a human always checks before merge — no matter what the AI or the CI says.

Write down your three. Ownership is probably one. Pick the other two from what actually hurts in your domain. Then — and only then — turn them into a PR checklist and a CODEOWNERS entry so they’re required, not remembered.

What’s on your list? What should an AI never be allowed to tick off alone? I’d really like to read your three in the comments — this is the part every team has to answer for itself, and the answers are worth sharing.


That’s the series: a shared skill, a team plugin, and the review gates that keep a human accountable for what all that speed produces. If you’re trying to bring Claude Code to a whole .NET team and want a second pair of eyes on how to do it without losing the plot, schedule a call — it’s the kind of thing I like talking through.