# How to review AI-generated code

> What to look at in changes from an assistant, which signs should worry you, and how to keep review from becoming a formality.

Published: 2026-03-29 · Source: https://subxcat.com/articles/reviewing-ai-code · Author: SUBXCAT

Code from an assistant reads easily. Tidy names, comments in place, a familiar structure. That's exactly why it's risky to review out of habit. Habitual review looks for signs of haste and sloppiness, and there aren't any. AI mistakes look different: confidently written code that does almost, but not quite, the right thing.

## Size first

Assistants happily touch twenty files where two would do. They rename things while they're there, "improve" things while they're there, reformat while they're there. A diff like that can't be read carefully, so it isn't read. It's scrolled.

The first rule of review: a change must be small enough to understand as a whole. If it isn't, send it back and ask for it to be split. That's not nitpicking. Without it, nothing else in this list works.

## Read beyond the diff

A diff shows the changed lines, not who calls them. The assistant may have changed a function signature and updated two of the five call sites. It may have added a new handler without the permission check its neighbors have. Open the call sites and the adjacent files. That's often where the bug is.

## Red flags

What we look for first:

- **Duplicates.** A new `formatPrice` function when the project already has `formatMoney`. Assistants don't always see the whole codebase and solve the problem again. Six months later there are three ways to do one thing, and they disagree.
- **Swallowed errors.** A `try/catch` that returns `null` or an empty array. The app doesn't crash; it quietly shows nothing, and nobody knows why.
- **Disabled checks.** `any`, `@ts-ignore`, `eslint-disable`, `--no-verify`. The assistant removes the obstacle by the shortest route.
- **Edited tests.** A test was failing, so it was "fixed" by changing the expected value. Every change to a test needs an explanation of why the old expectation was wrong.
- **Invented APIs and packages.** A library method that doesn't exist in your installed version, or a package with a plausible name that doesn't exist. Or worse, does exist, published by someone other than who you assume.
- **Stubs in production code.** Demo data "in case the API doesn't respond", a hardcoded user, `TODO: add check`.
- **Trusting the client.** Price, role or owner ID taken from the request body.
- **Unbounded queries.** A fetch with no pagination or limit, a database query inside a loop.
- **Comments that don't match the code.** The comment says "check permissions" and the lines below don't. Assistants describe the intent, not the result.

## An order that works

- **Start with the task.** Read what was asked for, then check whether exactly that was done. No more, no less.
- **Then the tests.** They show what the author considers correct behavior. If there are none and the change touches money or access, that's your first comment.
- **Run it.** Five minutes of clicking through the flow catches what the text hides.
- **Ask the author.** "Why is it like this?" If the person who submitted the change can't explain a line, it shouldn't reach production, whoever wrote it.

## Who's responsible

The most important rule isn't technical. Code an assistant generated belongs to whoever submitted it for review. "The AI wrote it" isn't an explanation; it's an admission that the author didn't read it. The reviewer, in turn, owns what they approved.

If review has turned into pressing Approve, it's better to admit it and agree on smaller changes than to pretend someone checked the code.

SUBXCAT can review a codebase built with an assistant and help set up a process that catches these mistakes before production does.
