Blog · ← All posts
A Practical Checklist for Reviewing AI-Written Pull Requests
Last updated: October 2026 · 7 min read
Reviewing AI-generated code is a different skill from reviewing a teammate's PR. A teammate's diff is shaped by judgment you can interrogate, you can ask why they chose something. An AI diff is shaped by probability. There's no "why" behind a model's choice, only "what was most likely." That changes how you review it.
This is the checklist we use when auditing AI-written code, ordered the way we actually work through a PR. It's built for the defects AI code actually has, not the ones textbooks describe.
Before you read a line: context checks (5 minutes)
Don't start with the code. Start with the circumstances.
- Read the original prompt. Ask the author what they asked the model. The prompt is the spec the code was written against, which tells you where the blind spots are. Everything the prompt didn't mention is where the bugs live.
- Check the diff size. A 1,500-line AI-generated PR is not reviewed; it's skimmed. Ask for it split. We draw the line at about 400 lines per review; beyond that, reviewers stop reading and start approving.
- Look for iteration residue. Scroll the diff for dead functions, commented-out blocks, and TODO comments the model left behind. AI code frequently ships its own drafts. If you see residue, the author didn't clean up. Cleanup is where they would have caught other things.
Pass 1: The seams (15 minutes)
Read only the boundaries first: function signatures, API calls, database queries, imports. Ignore the logic inside the functions for now.
- Every external call gets scrutiny. Database, network, filesystem, third-party APIs. AI code is weakest at boundaries: wrong endpoints, missing timeouts, unhandled failures. One audit found a generated payment flow that called the sandbox API in production config. The signature looked right. The URL was wrong.
- Check what comes in and what goes out. Validate inputs at every boundary. Models routinely skip input validation because the prompt described the happy path and never mentioned malicious input.
- Trace the data flow. Pick the most important piece of data in the PR and follow it from entry to storage. Check whether it gets validated, transformed, or logged anywhere it shouldn't be. This one exercise catches more real bugs than any other single review step.
Pass 2: Error handling (10 minutes)
This is the defect class that shows up in 29 out of 30 codebases we've audited, so it gets its own pass.
- Every catch block must do something real. Retry, raise, return an error, degrade gracefully. If it only logs and continues, flag it. Logging is not handling.
- Check the failure you're most afraid of. For this PR, name the worst realistic failure (payment double-charge, data loss, auth bypass) and trace it specifically. Generic error-handling review misses specific disasters.
- Look for the empty else. Models write conditionals for the cases they thought of. The missing branch, the one with no code at all, is where the unhandled state hides.
Pass 3: The logic itself (20 minutes)
Now read the internals. But read them skeptically, because this is where AI code looks most convincing while being wrong.
- Verify, don't vibe. AI-generated code reads well. Clean formatting and confident comments create a false sense of correctness. We once reviewed a date calculation with a perfectly written comment explaining the logic. The logic was wrong. The comment described what the code should do. Read the code, not the comments.
- Check every loop boundary and conditional. Off-by-one errors, wrong comparison operators, conditions that can never be true. Models are fluent in syntax and sloppy in logic. The `<` vs `<=` mistakes are where the bugs are.
- Test empty, null, and zero. For every collection, string, and number, check the empty case. AI code handles the populated case beautifully and the empty case never.
- Look for duplicated logic. Search the diff for repeated blocks. If the same 10 lines appear twice, they should be one function. Duplication in a fresh PR becomes triplication by next quarter.
Pass 4: Fit with the codebase (10 minutes)
AI code is written in isolation. Your codebase isn't.
- Check reuse of existing utilities. If the codebase has a date formatter and the PR defines a new one, that's a review comment. Every time.
- Check the project's conventions. Error types, logging patterns, naming, file placement. AI code defaults to generic patterns; your project has specific ones.
- Check for new dependencies. Every new package is a supply-chain decision. Verify it exists in the real registry, check it's not brand-new or suspicious, and make sure it's actually needed.
Pass 5: read the tests adversarially (10 minutes)
AI-generated PRs often include AI-generated tests. Those tests verify the implementation's actual behavior, including its bugs. So:
- Check whether the tests could fail. A test that can't fail is decoration. Look for assertions on real behavior, not just "doesn't throw."
- Write one test the model didn't. Pick the edge case from Pass 2, the failure you're most afraid of, and check whether a test covers it. If not, require one before merge.
- Run the suite yourself. Don't trust the green checkmark on code you haven't verified. It takes two minutes.
A review, narrated
To make this concrete, here's what the checklist looks like on a real-shaped PR: 340 lines of AI-generated code adding password reset to a Node/Express app. The diff is clean, the comments are articulate, the tests pass.
Context check first. The prompt was "add password reset with email." Five words of spec for a security-sensitive feature. Already I know the blind spots: token expiry, token reuse, rate limiting, and whether reset emails leak account existence were all unmentioned, which means they're all unhandled until proven otherwise.
Pass 1, the seams: the reset endpoint takes an email, looks up the user, generates a token, and sends a link. Two findings in ten minutes. First, the token is a UUID stored in plaintext in the database; anyone with read access to that table can reset any account. Second, the lookup responds differently for existing vs. nonexistent emails ("If an account exists, we've sent a link" vs. a silent 200), which lets an attacker enumerate registered addresses. Both are textbook. Both passed the tests, because the tests only checked the happy path.
Pass 2, error handling: the email-sending call is wrapped in try/catch, and the catch logs "email failed" and continues, returning success to the user. The user sees "check your inbox." No email is coming. This is defect number one from our 30-codebase audit, wearing a new outfit.
None of this required brilliance. It required the checklist, an hour, and the discipline to start from the prompt instead of the code. The PR was rewritten, not patched: tokens hashed with an expiry, uniform responses, failures surfaced. The second review took twenty minutes.
What this checklist won't do
Honest limits: this catches defects, not design mistakes. If the PR builds the wrong feature well, no checklist finds that, only someone who understands the product. And a reviewer who doesn't understand the domain will rubber-stamp AI code no matter the checklist, because the code looks right. The checklist is a floor, not a ceiling.
Also: this takes about an hour per PR. That's the real cost of AI-generated code that nobody talks about: generation is fast, review is not. If your team is merging AI PRs in five minutes, you're not reviewing them. You're approving them.
Make it a habit, not a hero effort
The teams that do this well don't rely on heroic reviewers. They put the checklist in their PR template, require the prompt in the PR description, and block merges over 400 lines of generated code. Boring process beats brilliant review, because brilliant review doesn't scale and boring process does.