Skip to main content
Corey Daley

How Much Review Is Too Much Review?

Ask a human to review a pull request and something quietly reasonable happens: they finish. They read the diff, poke at the risky parts, maybe leave two comments and a nit, and then they approve it. Not because the code is perfect, but because they’ve satisfied themselves it’s safe enough to ship. That internal “okay, I’m good” is the most underrated feature of human review. It’s a terminal point, and it arrives fast.

Ask an AI to review the same pull request and you get something else entirely. It returns fourteen findings on a three-line diff. It flags the function you didn’t touch. It questions a naming convention that predates the branch. It proposes a refactor of the module the change happens to live in. Every point is individually defensible, and collectively they’ve turned “approve this small change” into “reopen the design of the whole file.”

The AI didn’t do a worse job. It did a job with no stopping condition — and that’s a problem we handed it in the prompt.

Finding is not the same as deciding

Here’s the trap. We tell the reviewer to “find issues.” That sounds like the whole job. It isn’t even the point of the job.

A human reviewer is secretly answering a different question: should this merge? Finding issues is just how they gather evidence for that decision. Once they have enough evidence to answer — yes, with these two fixes — they stop looking. The decision is the terminal condition. Finding is subordinate to it.

An AI reviewer told to “find issues” has been handed the subordinate task as the whole task. So it optimizes the thing you actually measured it on: quantity of findings. An empty findings list doesn’t read as ship it. It reads as failure to do the assignment. No self-respecting bug-finder returns “I found nothing,” so it keeps looking, and if the diff is clean, it goes looking where the diff isn’t. I’ve watched a reviewer return a dozen findings on a whitespace-only change and, when pressed on the weakest one, fall back to “well, the surrounding code could be cleaner.”

That’s the mechanism behind the scope creep. It isn’t the model being pedantic. It’s the model being obedient to a goal we set badly.

The scope keeps leaking off the diff

Watch where an unbounded review actually goes and you’ll see a predictable drift:

  • It starts on the changed lines. Good.
  • It expands to the whole function the change sits in.
  • Then the file. Then the sibling files it imports.
  • Then it’s commenting on architecture, test strategy, and a variable name three functions away that the PR never so much as read.

Each hop feels justified in isolation — “well, while I’m here, this adjacent thing is also suboptimal.” But the pull request didn’t propose any of that. Those decisions were made in other commits, by other people, for reasons not in the diff. Re-litigating them isn’t review; it’s an uninvited architecture meeting stapled to someone’s two-line bug fix.

I wrote a while back about how the strongest model makes a maddening junior engineer : it improves the assignment instead of doing it. This is the same failure mode, just moved to the other end of the loop. On the implementation side it widens the patch. On the review side it widens the critique. Same restless capability, same missing restraint, same bill paid in your attention.

The end goal is a merge decision, not a defect list

The reframe that fixes this is simple: tell the reviewer what it’s actually for.

The review doesn’t exist to maximize findings. It exists to answer one question — is this change safe to merge? — and to surface only the things that bear on that answer. A defect list is a means. The merge decision is the end. When the prompt makes the end explicit, the terminal point comes back, because now there’s a condition that says “you’re done”: you can answer the question.

Building the terminal point into the prompt

That single shift — from “find problems” to “decide whether this ships, and justify it” — does most of the work. But you can make it concrete. Four things reliably pull an AI review back to human-shaped behavior:

1. Bound the scope to the diff. Say it outright: review only the lines this change adds or modifies, and the code directly required to judge them. Pre-existing code is context, not a target. If the reviewer wants to flag something outside the diff, it goes in a separate “out of scope, for later” bucket — not the blocking list.

2. Set a severity floor. Most manufactured findings live below the line where anyone would actually block a merge. So draw the line: report only what you would hold up the merge for — correctness, security, data loss, a real regression. Do not report style, taste, or “could be cleaner” unless it causes a defect. A nit that isn’t worth a comment isn’t worth generating.

3. Name the terminal state. Give it permission to finish. If the change is correct and safe within its scope, say so and stop. “No blocking issues found” is a complete, successful review. This is the sentence that breaks the reflex where an empty list feels like failure. You have to explicitly bless silence, or the model won’t believe it’s allowed.

4. State the goal, not just the task. Open with the why: the goal is a confident merge decision on this specific change, not an audit of the surrounding code. The task (“look for issues”) is subordinate to the goal (“decide if this ships”). Put the goal first and the task inherits its boundaries.

None of this makes the reviewer miss real bugs. A genuine correctness problem clears the severity floor easily — that’s the whole point of the floor. What it stops is the manufactured finding, the one that only exists because the model felt obligated to return something.

Right-sizing the review to the change

The review should be proportional to the diff. A three-line fix warrants a three-line-fix review. A new subsystem warrants a thorough one. The failure isn’t “too much rigor” in the abstract — it’s rigor decoupled from the size and risk of what actually changed. Humans calibrate this automatically; they spend their scrutiny where the change is. An AI won’t calibrate unless you tell it to, because from where it sits every review is a fresh mandate to find things, and a small diff just means it has to look harder to hit quota.

So the answer to “how much review is too much?” is: any review that keeps going after it can already answer whether the change should merge. Past that point you’re not buying safety. You’re buying scope creep, re-litigated decisions, and a punch list that costs more attention to triage than the change was worth in the first place.

The good news is that the terminal point isn’t something the model lacks the ability to find. It’s something we forgot to tell it exists. Give the review an end goal and a definition of done, and it’ll stop — right about where a good human would have.

What are you actually asking your reviewer to decide — and have you ever told it that it’s allowed to say “this is fine”?