PR review checklist for AI-generated code

Table of Contents
Table of Contents
People merge a Cursor Composer (or Agent) PR because the summary sounded right.
Then a teammate finds a new utils/ folder, a helper that already existed, and no test on the write path. That is not a smarter model problem. That is the ai coding workflow step people skip: review.
I’m Aris Setiawan. Senior full-stack, first Cursor Ambassador in Indonesia. I ship client work in Cursor every week. Treat the model like a junior. Read the diff, not the summary.
The production loop is How to use Cursor AI to ship faster without wrecking the codebase. The messy-repo version is How to use Cursor AI effectively on a real repo. This post is the review gate: a checklist you can run on AI-generated code before merge.
Why AI PRs fail review
Composer is confident. Confident is not correct.
Five things I still see:
The summary sold the ticket. “Added CSV export on invoices.” The diff also renamed a shared type, touched billing, and opened a file nobody asked for. Summaries are marketing. The diff is the work.
Extra files. A new top-level folder. A new package. A second button next to the one in components/ui. The ticket was one list page.
Duplicate helpers. lib/format-date.ts already exists. Composer wrote utils/date.ts because it did not look at the sibling. Classic miss when you review AI generated code: the new file looks clean.
Skipped tests. The happy path looks done in the browser. The existing *.test.ts next to the module never got a case. AI code review that never runs the old tests is a demo, not a review.
Scope creep. “While we are here” from a model is still scope creep. Auth. Payments. A rename. A drive-by refactor. Same as a junior who cannot stop helping.
If you cannot explain every file in the PR, you are not reviewing. You are trusting a recap.
The checklist I run before merge
I run this on every Composer or Agent diff, including my own. This is the cursor pr review I actually use.

- Blast radius. Does every touched file belong on this ticket? If Composer opened a stranger, stop. Do not “fix it in this PR.”
- New folders or packages. No new top-level folder. No new package I did not ask for. No
utils/next tolib/. Project rules should have blocked this. Still look. - Types. No
anywhere siblings use a real type. Error shape matches the nearby route, not a shape the model invented. - Names match siblings. Kebab-case files if that is what this folder uses. PascalCase components. The new helper is not
formatDate2. - Tests that already existed. Did it update the colocated test? Did it skip the failing case? Run
pnpm teston the files it touched. The demo is not the test. - Secrets, auth, payments. Did it touch session, cookies, or a payment provider? If the ticket did not name those files, revert that hunk. Same for env files and secrets.
- “While we are here.” A rename, a lint sweep, a cleanup in a file the ticket never mentioned. Cut it.
That is the whole list. If a box fails, the PR is not ready. I do not merge on a green CI and a nice summary.
When the diff is too big
A 30-file “CSV export” is not a PR. It is a dump.
I do not nitpick 30 files. I shrink the work.

Revert the extra. Keep the files the ticket named. Throw away the stranger folders, the new package, the drive-by rename.
Split. Two Composer jobs beat one “while we are here” job. Export helper first. Wire the button second. Same split I use when I build an app without a mess: one slice, then the next.
Run once more. Tighten the prompt. Name the paths. Name what is off-limits. Run Composer again on the smaller blast radius. Then review that diff, not the original monster.
If I cannot finish the review in one sitting, the change was too big.
How this sits with Chat, Composer, and project rules
Review is not a fourth tool. It is the last box in the same ai coding workflow.
Project rules are the standing fence: stack, folder map, do not create packages, error shape, test command. They cut invented architecture. They do not catch a wrong business rule. You still read the PR.
Chat vs Composer: Chat plans. Composer (or Agent) ships a scoped diff. You review like a senior reading a junior. If you skip review because Chat already “checked it,” you asked the author to approve their own homework.
I do not paste the whole diff into Chat and ask “is this good?” Chat will agree with the summary. I use Chat to trace a weird hunk: “Where does invoice status get set? Do not rewrite it.” Then I decide.
Composer without a plan is Chat with write access. Review without a checklist is hope. Rules, Chat, Composer, then this list.
A bad review comment vs a good one
Generic invoices list. Composer added CSV export and, while it was there, a new utils/csv.ts next to the real helper.
Bad:
Looks good. Nice work. Let’s ship it.
That comment reviews the summary. It does not review the code.
Good:
Export on the list is the ticket. Revert
utils/csv.tsand reuselib/export/csv.ts. Do not add a new top-levelutils/. Keep the change inapp/invoicesandlib/export. Add a case to the existinginvoices.test.tsfor an empty list. Do not touch billing.
The good comment names the extra file, the real helper, the folder fence, and the test that already existed. That is how you review AI generated code without being rude or vague. The person who ran Composer can act on it.
I leave the same comment on my own Composer PRs.
What I tell mentees
The ai coding workflow is not Chat, then Composer, then merge. The last step is this checklist.
I coach it in Cursor mentoring when a team keeps merging confident diffs they cannot explain. The fix is almost never “use a smarter model.” It is read the diff, cut the extra, split the work.
Most people who ask me about AI code review just need the list above, on their actual PR, once. If the team needs that workflow installed, that is the Level up lane. I sit with the real repo, not a toy app.
If you need the product built, not the review habit installed, that is the Build path. Most teams do not. They need to stop merging the summary.
Read the diff. Leave the extra files out.



