Reviewing AI-Generated Code

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Examples on this page target GitHub Copilot code review on github.com and Claude Code’s bundled /review (an alias for its code-review skill), both checked against GitHub Copilot’s documentation and Claude Code’s official docs as of 2026-09-28. The running example is the same DocsAssistant API Spring Boot + Python sample used throughout this sub-section, with its controller at src/main/java/com/example/docsassistant/DocsController.java and its tests under src/test/java/com/example/docsassistant/.

An AI agent’s own "verify" step — running tests, re-reading its diff — is not a substitute for a human review. It confirms the code does what the agent thinks it was asked to do, not that the request was the right one, or that the change is safe, minimal and maintainable. That gap is why the agentic loop and agent mode both end with a diff for a person to look at before it lands.

Review checklist for AI-generated diffs

The failure modes below are specific to AI-written code and rarely show up in a checklist written for human-authored diffs. Read every diff against all six before approving it:

Check What to look for

Intent match

Does the diff actually do what the prompt asked, not a plausible-looking neighbor of it? An agent that misreads "return 404 when missing" as "return an empty list when missing" produces code that compiles, passes an incomplete test suite, and is still wrong.

Off-by-one and boundary errors

Loop bounds, pagination offsets, and < vs ⇐ comparisons are a common source of subtly wrong but plausible-looking AI code, especially in code translated or extended from an existing pattern nearby.

Placeholders left in

// TODO: implement, throw new UnsupportedOperationException(), a hard-coded stub return value, or a config value copied verbatim from an example (localhost, a sample API key) that was never meant to ship.

Hallucinated APIs and packages

A method, class or package that does not exist, or that exists but not with that signature or in that library version. Check DocsController.java’s new imports against the project’s actual dependency versions in `pom.xml, and see slopsquatting on Securing AI-Assisted Development for checking a package name is real before it’s added.

Over-engineering

An abstraction, interface or configuration layer the task did not ask for and the codebase does not already use elsewhere — a common tendency when an agent tries to look thorough rather than minimal. Prefer the change that matches the surrounding code’s existing patterns.

Test quality

Not just that tests exist, but that they assert the right thing: a test that only calls the new code without asserting on its result, or one that asserts on a mock’s call count instead of the endpoint’s actual response, passes without proving anything. Compare against Testing & Debugging with AI's guidance on critiquing AI-generated tests.

Copilot code review on a pull request

On github.com, open the pull request and find Copilot in the Reviewers panel of the sidebar; selecting Request there queues a review, which typically posts inline comments on the diff within about half a minute. The panel also offers an effort level — Lite for a faster, more targeted pass or Balanced for a deeper one — before you request the review. The same request works from the GitHub CLI:

$ gh pr edit 42 --add-reviewer @copilot

A repository can also be configured to request Copilot automatically on every new pull request, and to re-review on each push, from the repository’s code review settings rather than requesting it pull request by pull request. See GitHub — Requesting a code review from Copilot.

Copilot’s comments land as ordinary PR review comments, so they read, get resolved and get replied to the same way a human reviewer’s comments do — covered in Pull Requests.

/review in Claude Code

Claude Code ships /review as an alias for its bundled code-review skill: running it reviews the current diff (or a pull request number, branch or path passed as an argument) for correctness bugs, at an effort level that trades off fewer high-confidence findings against broader, more speculative coverage.

$ claude
> /review high

Passing --comment posts the findings as inline comments on the pull request instead of only printing them in the session, and --fix applies them to the working tree after the review runs. Because it is a bundled skill rather than a fixed built-in command, a project-local skill named code-review replaces /code-review itself — but not its aliases: the bundled /review alias never runs the project skill, so in a repository with its own .claude/skills/code-review/ the two commands can behave differently. See Claude Code — Commands, Claude Code — Code Review and Claude Code — Skills.

Example review prompt and output

Reviewing the endpoint added on Getting Started with Claude Code before it is committed:

In Claude Code
$ claude "review the uncommitted diff in @src/main/java/com/example/docsassistant/DocsController.java
against the checklist: intent match, off-by-one errors, placeholders, hallucinated APIs, over-engineering,
test quality"
Findings (most severe first):

1. [test-coverage] DocsControllerTest has no case for a negative or zero id; only "found" and "missing"
   are covered, so a regression that returned 500 instead of 404 for id=-1 would pass the suite.
   File: src/test/java/com/example/docsassistant/DocsControllerTest.java
2. [placeholder/unused-import] The diff imports org.springframework.web.bind.annotation.ResponseStatus
   but never uses it -- leftover scaffolding that a linter will flag; use it or remove it.
   File: src/main/java/com/example/docsassistant/DocsController.java

That output shape — one finding per line with a file and a concrete failure scenario, most severe first — is the same one the iru-pr-review skill produces when reviewing a pull request end to end with the account’s own tooling instead of an ad hoc prompt.

AI as validator

Using a second AI review as one more check, on top of — never instead of — a human review, is the third of the three ways an assistant participates in a task, alongside drafting the first version and pair-programming through it: reviewing code someone else (a person or another agent) already wrote, against a checklist like the one above. Two things make an AI reviewer more useful in that role:

  • A different model or a fresh context reviewing the diff cold catches issues the model that wrote the code is less likely to flag, because it never built up the same assumptions about what the code "obviously" does. See Choosing Models in Your Assistant for running a second model deliberately.

  • A checklist prompt beats an open-ended "review this" — naming the specific failure modes above gives the reviewing model something concrete to check against, instead of a generic pass that tends to praise the code more than it questions it.

An AI reviewer, like the agent that wrote the code, can still miss a bug, invent one that isn’t there, or approve something it misunderstood — it narrows what a human reviewer has to look at, it does not remove the need for one.

Deterministic gates as the backstop

A linter, a static analyzer or a coverage threshold cannot be talked out of flagging something the way an AI reviewer occasionally can, and it runs the same way on every commit whether or not a human remembered to ask for a review. On DocsAssistant API’s Java side, mvn verify runs Checkstyle, SpotBugs and PMD plus a JaCoCo coverage check, all covered on Maven Quality Plugins:

$ mvn verify

For the Python ingestion script under ingest/, an equivalent gate is a linter and a type checker run in CI on every push. Neither AI review above should be treated as a replacement for these gates — they are the checks that still run, and still fail the build, on a diff no one reviewed carefully enough.