How to Review AI-Generated Code: A Four-Layer Checklist
Do not start by reading a generated diff from top to bottom. Establish what the change must prove, automate the repeatable checks, and spend human judgment where it matters.
Generated code creates a review trap. It is formatted, confident, and often much larger than a human would have written in the same time. That surface fluency encourages a reviewer to skim. The size encourages them to trust the tests. Neither is enough.
GitHub's own guidance starts with automated tests and static analysis, then asks reviewers to verify intent, code quality, dependencies, and AI-specific failure modes. That ordering is useful because it separates evidence from judgment.
The goal is not to prove a person read every line. It is to build a chain of evidence strong enough to justify the merge.
Before the diff: write the contract
Pull the acceptance criteria out of the issue, incident, or design note. State the behavior in observable terms. “Improve authentication” is not a contract. “After five failed attempts, reject login for 15 minutes and emit one audit event” is.
Then record four pieces of evidence:
- The user or system behavior that must change.
- The behavior that must remain unchanged.
- The test, trace, screenshot, or reproduction that proves both.
- The highest-risk boundary touched by the patch.
If the author cannot explain the contract, the review is premature. Asking the reviewer to infer it from generated code reverses the responsibility.
Layer 1: functional correctness
Run the repository's build, type checker, linter, tests, and static analysis before detailed review. Do not accept a screenshot of a green terminal when CI can produce the evidence.
- Does a test fail when the implementation is reverted?
- Do tests cover failure, timeout, empty, duplicate, and permission-denied paths?
- Did the patch delete, skip, loosen, or snapshot over a failing test?
- Are migrations reversible and compatible with the running version during deployment?
- Do user-facing flows work outside the happy path on a real render or environment?
A generated test can repeat the implementation's mistaken assumption. Read assertions as carefully as production code. Prefer observable outcomes over assertions about private helper calls.
Layer 2: intent and architecture
Correct code can solve the wrong problem. Compare the patch with the contract, established patterns, and recent similar changes. Ask why each changed file is necessary.
- Does the change use the repository's existing boundary, or create a parallel one?
- Is business logic located with the current domain owner?
- Did the agent add an abstraction for a single call site?
- Are configuration and defaults consistent across development, CI, and production?
- Can unrelated cleanup be removed into a separate change?
This is where repository instructions help. An AGENTS.md,
architecture decision record, or path-specific rule gives both author and reviewer a shared
standard. It guides the agent; it does not prove compliance.
Layer 3: security and supply chain
Start with trust boundaries: authentication, authorization, secrets, user input, file paths, network calls, data serialization, and third-party packages. Treat new dependencies as code you are choosing to run, not as harmless imports.
- Is authorization enforced server-side at the resource boundary?
- Is untrusted input parsed into a constrained type before domain logic?
- Can errors expose tokens, personal data, stack traces, or internal paths?
- Does every proposed package exist, have credible provenance, and use a compatible license?
- Are network calls bounded by timeouts, cancellation, retries, and safe redirect behavior?
- Did the patch weaken a scanner, permission, CSP, signature check, or audit trail to make tests pass?
OWASP's Secure Coding with AI guidance specifically warns against hallucinated dependencies and recommends independently verifying registry history, maintainers, age, and activity before installation.
Layer 4: maintainability and minimum change
Once behavior and risk are acceptable, remove the cost the patch does not need to carry. Check names, boundaries, error handling, complexity, comments, dead paths, duplicate logic, and the size of the change.
- Can a future engineer explain the code without reconstructing the prompt?
- Are errors preserved or converted deliberately rather than swallowed?
- Do comments explain a non-obvious constraint instead of narrating syntax?
- Can any changed line be reverted without breaking the contract?
- Does the patch leave the repository easier to modify than it found it?
This layer should not become a debate over personal taste. Automate the repeatable standards and reserve comments for consequential design or comprehension problems.
The copyable merge checklist
- □ The PR states a testable behavioral contract.
- □ Build, types, lint, tests, security, dependencies, and quality gates pass.
- □ At least one test would fail if the implementation were reverted.
- □ Failure and permission paths were exercised.
- □ The patch follows an existing architecture or documents the decision to change it.
- □ Every new package and external API was independently verified.
- □ No test, control, or warning was weakened to obtain a green result.
- □ Unrelated and functionally unnecessary edits were removed.
- □ A human owner accepts the remaining risk and can explain the change.
Use automation to buy back reviewer attention
aislop covers one part of this checklist: deterministic generated-code patterns that do not need a model or a human to reinterpret them on every pull request. Run it beside your compiler, tests, security scanner, and dependency checks—not in place of them.
npx aislop@latest scan --changesHumans still own the contract, architecture, exceptions, and merge. The value proposition is fewer predictable findings consuming that human judgment.
Sources
Frequently asked questions
What is the best way to review AI-generated code?
Review in four layers: functional correctness, alignment with intent and architecture, security and dependency risk, then maintainability. Run automated checks first, inspect the highest-risk boundaries, and require evidence for every consequential claim.
Can AI review AI-generated code?
AI can help find contextual issues and propose tests, but its output also needs verification. Use deterministic checks for repeatable rules, AI review for hypotheses that require context, and humans for product intent, risk acceptance, and the final merge decision.
What AI-specific mistakes should reviewers look for?
Look for hallucinated APIs and packages, deleted or weakened tests, fabricated configuration, silent fallback behavior, duplicated validation, unrelated edits, type-system escape hatches, and code that satisfies the prompt while violating the repository's architecture.