Home Reviews, Tests & Docs Code Review With AI That Finds Logic Bugs, Not Just Missing Semicolons

Code Review With AI That Finds Logic Bugs, Not Just Missing Semicolons

How to prompt AI reviewers so they catch concurrency races, off-by-one errors, and broken invariants instead of restyling your braces.

By Jordan Boyd, a backend engineer · Published 3 June 2026 · 8 min read · Reviewed against our editorial standards

ADVERTISEMENT

Most AI code review out of the box is a linter with a thesaurus. Point Copilot's PR review or a stock Cursor prompt at a diff and you get a wall of “consider extracting this into a helper” and “this variable could be const.” None of it is wrong. Almost none of it is the reason your service paged someone at 3 a.m. The bugs that matter live in the space between two functions that each look fine on their own, and that is exactly the space a generic reviewer skips.

After a year of running AI review on a payments backend, I've settled on a set of habits that shift the output from cosmetic to consequential. The short version: give the model the invariants, give it the diff and the surrounding call sites, and force it to reason about failure before it reasons about taste.

Style nits are a symptom of a lazy prompt

When you paste a diff and say “review this,” the model has no idea what the code is supposed to guarantee, so it falls back to the only thing it can assess from syntax alone: style. You have to tell it what correctness means here. Compare a bare request with one that front-loads the contract:

Review this diff for correctness. The system guarantees:
- charge() is idempotent per idempotency_key
- balances never go negative
- every state transition is logged before it commits

Ignore style and formatting entirely. For each issue, give me:
1. the exact line
2. a concrete input or interleaving that breaks it
3. severity (data-loss / wrong-result / crash / none)

If you cannot construct a failing case, say the code is fine.

That last line does a lot of work. Models love to manufacture concern to seem useful. Requiring a concrete failing input forces the difference between “this feels risky” and “here is the interleaving where two requests with the same key both pass the check and double-charge.” The second is a bug report. The first is noise.

Give it the call sites, not just the diff

The single biggest quality jump comes from context width. A diff shows you what changed; it doesn't show you what assumes the old behavior. If a function used to return null on miss and now throws, the diff looks clean and correct. The bug is in the three callers that still do if (x == null).

With Claude Code or Cursor's agent mode, don't hand over a patch file. Point the tool at the repo and let it pull the callers itself:

The change is in src/ledger/balance.rs. Before reviewing,
grep for every caller of settle() across the repo and read
them. I care specifically about callers that assume the old
return contract. List call sites that need to change but
aren't in this diff.

This is where agentic tools genuinely beat a chat window. The model can run rg 'settle\(', open each file, and check the assumptions. A pasted snippet can't do that, and a human reviewer skimming a 400-line PR usually won't either.

The bug classes AI is actually good at

Calibrate your expectations by category. In my experience the hit rate is high on:

It is mediocre-to-bad at:

Make it argue against itself

A second pass that only asks “which of your findings are false positives?” measurably cleans up the output. The model is often right that something looks suspicious and wrong that it's a bug, and it can usually tell the difference when you ask directly:

Here are the 6 issues you just reported. For each, try hard
to prove it is NOT a bug using the actual code. Keep only the
ones you cannot dismiss. I would rather have 2 real bugs than
6 maybes.

This trades recall for precision, which is the right trade for review. A review tool that cries wolf gets muted within a week; developers start rubber-stamping the AI comments the same way they rubber-stamp a flaky lint rule.

Where it fits in the pipeline

Two placements have earned their keep. First, a pre-commit local pass in Claude Code or Cursor before you even open the PR — catches the dumb stuff while context is fresh and nobody else has to see it. Second, a CI-triggered review on the PR diff that posts as a comment, gated so it only flags data-loss and wrong-result severities to avoid drowning the thread.

A minimal GitHub Actions shape, using a CLI agent in non-interactive mode:

- name: AI correctness review
  run: |
    git diff origin/main...HEAD > /tmp/pr.diff
    claude -p "Review /tmp/pr.diff for correctness only.
      Report only data-loss or wrong-result severity issues,
      each with a concrete failing input. Repo context is
      available. Output empty if none." \
      --output-format text > review.txt
    gh pr comment $PR --body-file review.txt

Keep the severity gate. The version that posted every observation got turned off by the team in three days. The version that stays quiet unless it can name a concrete data-loss path still gets read six months later, because when it comments, people have learned it usually means it.

The honest limits

AI review does not replace a human who understands the system. It replaces the first human pass, the mechanical sweep for boundary cases and leaked resources that a senior engineer resents doing. What it cannot do is tell you the feature is wrong, that the requirement was misread, or that this whole approach will fall over at 10x traffic. It reviews the code you wrote against the contract you gave it. If the contract in your head never made it into the prompt, the model will happily approve a correct implementation of the wrong thing.

Treat it as a tireless junior reviewer with perfect edge-case stamina and zero product context. Feed it the invariants, feed it the call sites, make it prove its bugs with inputs, and make it kill its own false positives. Do that and the ratio flips: fewer comments, but the comments are the ones you'd have been embarrassed to ship.

code-reviewdebuggingworkflowclaude-code

A note on shelf life. AI products change fast. This guide deliberately focuses on the parts that stay true — how to judge a tool, what the trade-offs are — rather than ranking products that will have changed by the time you read it. Prices and feature claims should always be checked against the provider before you rely on them.