Back to posts
AINews

How to review an AI-generated PR

47 files changed, green CI, an AI-written description, and 30 seconds to approve. That's the failure mode. Here's a 12-point review checklist that catches what the AI got wrong — and how to scope the review so you'll use it.

47 files changed. Green CI. A description that says "add user notifications." Approve in 30 seconds. Bugs in prod by Tuesday.

The most predictable failure in AI-built codebases isn't bad code — it's bad review. Code review evolved for a world where a human wrote the code and could explain it. AI broke that assumption, and most teams haven't updated the process.

This post is a checklist for reviewing an AI-generated PR, and how to scope the review so you'll do it properly instead of skipping it.

Why traditional review fails for AI code

A few things change when AI is the author:

  • Diff size stops correlating with risk. AI generates a 600-line diff in 30 seconds. The cost of writing it tells you nothing about how careful you should be.
  • The author can't explain why. Whoever opened the PR didn't make most of the decisions in it. "Why is there a new utility file?" — they don't always know.
  • Tests pass for the wrong reasons. Mocks of the unit under test, assertions on calls instead of behavior, tautological tests that mirror the implementation. (Last week's post covered this in detail.)
  • Hallucinated code looks like real code. A function call to a method that doesn't exist will compile if TypeScript can find a near-match. pnpm install proves nothing about whether the API is real.
  • Comments lie. AI writes comments based on what it thinks the code does, not what it does.

You can't review this kind of PR by reading top-to-bottom and nodding. You have to actively look for what AI tends to get wrong.

The 12-point review checklist

Run through these on every AI-generated PR. Most take under 30 seconds.

1. Description vs. diff: are they the same change?

Read the PR description first. Then read the diff. If the description says "add notifications" and the diff also refactors auth middleware, the PR is too big or the description is misleading. Both are red flags.

2. Does every import resolve to a real version?

AI loves to import functions that don't exist in the version of the package you're using. findManyAndCount from Prisma. useFormState from React 18 codebase. The build will sometimes pass; the runtime will crash. Spot-check 3-4 imports against the actual package.

3. Were any unexpected files created?

Look at the new-files list. AI often spawns helper files, type files, index files, util folders. Each one is surface area. If you didn't expect it, ask why it exists. Half the time the answer is "the AI thought it would be cleaner."

4. What got renamed or moved?

AI is happy to refactor 20 unrelated files to make 1 change feel "consistent." Check the rename list. If it's there and you didn't ask for it, push back. Refactor PRs and feature PRs are different PRs.

5. Every error handler — what does it do?

The most expensive line of code in an AI PR is catch (e) { }. Empty catches, broad catch (Error e), catches that log without rethrowing — all of these turn loud failures into silent ones. Read every catch block. Ask: if this throws, do I want to know? If yes, the catch is wrong.

6. Async boundaries: missing awaits?

AI sometimes writes someAsyncFn() without await, sometimes does the opposite. Function signatures and call sites drift. Spot-check: every async function call should be awaited unless you want fire-and-forget. Every fire-and-forget should have a comment explaining why.

7. Are the tests testing the change?

The function added to the diff: is there a test that fails if the function is wrong? If the only tests check that the function was called, or assert on mocks, the test isn't worth merging. (See the post on AI-generated tests.)

8. Schema touched?

Migrations, validators, type definitions, API contract — they all need to stay aligned. AI updates one and forgets another more often than not. If the schema changed, verify all four layers match.

9. Any user input flowing into a query, path, or command unsanitized?

Look at every place external data crosses an interesting boundary. Database query: parameterized? File path: validated? Shell command: argv-style or string-concatenation? AI is great at making things work in the happy case and unintentionally building injection holes in the edge case.

10. New env vars, secrets, or feature flags?

Document them. If a new variable is required in prod and you don't know it, the deploy breaks silently. Check .env.example got updated. Check the deploy config has the new keys.

11. Config files: anything permissive?

CSP, CORS, allowed origins, rate limits, IP allowlists. AI's instinct when something doesn't work in dev is to widen the rule until it does. connect-src 'self' becomes connect-src *. Check every config diff for * or "any" or 0.0.0.0/0.

12. What's the rollback plan?

If this PR breaks prod at 2 a.m., what do you do? Revert the merge commit cleanly? Revert just one file? Run a down migration? If you can't answer this in one sentence, the PR isn't ready to merge.

How to scope the review so you'll do it

The checklist works only if you'll run it. To make sure you will:

Cap PR size. 200 lines of net change, max. Above that, the review gets skimmed. If the AI generates 800 lines, split it. The split itself is a useful exercise — most of the time it reveals the PR was doing too much.

One human reviewer per AI-generated PR, minimum. "AI-reviewed" is not review. Models are bad at flagging the things they themselves are most likely to write wrong.

Run the code locally. Not just CI. Pull the branch, install, run, click through. The number of bugs that reveal themselves in 30 seconds of manual use, and never reveal themselves in CI, is humbling.

For UI changes, click through the feature. Golden path and one edge case. If you can't run it, say so out loud — "I haven't tested this in a browser" — instead of approving anyway.

Treat every approval as a decision. The AI didn't make the architectural calls. You're making them at review time. The button is yours.

What this looks like in practice

A 150-line AI-generated PR I reviewed recently took 8 minutes to go through with this checklist. Items 5, 7, and 11 caught real issues:

  • An empty catch swallowing failed Stripe webhook calls (item 5)
  • A test that asserted mockSendEmail.toHaveBeenCalled() but never checked the email body (item 7)
  • A new next.config.ts line allowing unsafe-eval in production CSP because the AI couldn't get a library to load otherwise (item 11)

Without the checklist, all three would have shipped. With it, the review found them faster than the AI generated the original code.

That's the trade. AI writes faster than you can read. The checklist is what makes the read survive.

Get the next post when it ships

One email on Sunday with the new post and a short list of what shipped that week — new guides, tool updates, and a couple of links worth reading.