AI Code Review vs Verification: Why Reading Code Is Not Enough
Shiplight AI Team
Updated on July 15, 2026
Shiplight AI Team
Updated on July 15, 2026

Code review and verification answer two different questions about a change. Code review asks whether the code, as written, looks correct: is it readable, does it follow conventions, does the logic appear sound to a reader. Verification asks whether the running software actually behaves correctly: does the feature work, do the existing flows still pass, does the change do what it claims. A reviewer reasons about the code. Verification proves the behavior.
For most of software history these two questions overlapped enough that a careful review caught most defects. AI coding agents break that overlap. They generate code faster than any reviewer can read it, and the code they produce is optimized to read well: consistent style, plausible structure, sensible names. The output passes the "does this look right" test almost by construction. Whether it also passes the "does this work" test is a separate fact that only running the software can establish.
This page draws the line between review and verification, explains why AI-generated code defeats review specifically, and shows where each belongs. The short version: review is necessary and not sufficient, and the sufficiency gap is verification.
Code review operates on the diff. A reviewer, whether a human or an AI reviewer bot, reads the changed lines and reasons about them: control flow, naming, structure, adherence to the codebase's conventions, obvious logic errors, and known anti-patterns. This is static reasoning. Nothing is executed. The reviewer builds a mental model of what the code will do and checks that model against what the change is supposed to accomplish.
Review is genuinely good at a specific set of catches. It flags unreadable code before it compounds, enforces conventions that keep a codebase navigable, spots obvious slips like an unchecked return, and surfaces design concerns a test would never raise. AI reviewers extend this reach: they scan every diff consistently, never tire on the four hundredth file, and catch standard errors at a scale humans cannot sustain. As the engineering guide from Graphite notes, AI code review is strong at routine checks and consistency enforcement.
The limit is structural, not a matter of tool quality. Review reasons about code paths without executing them, so it cannot observe what the software does when a real user clicks through the feature, when the change interacts with authentication and session state, or when the same code runs in Safari instead of Chrome. Those facts do not exist in the diff. They exist only at runtime.
Verification operates on the running software. It builds the change, exercises the affected behavior in a real environment, and observes the result: the feature works or it does not, the existing flows still pass or they regressed. This is dynamic evidence. The distinction is the same one the testing literature draws between static and dynamic analysis: static reasoning tells you what the code could do wrong, and dynamic execution shows you what it actually does wrong when it runs.
Verification catches the categories review structurally cannot: broken user flows, integration failures between components that each looked fine in isolation, cross-browser inconsistencies, and regressions in code the change never explicitly touched. These are exactly the bugs that survive review, because they are invisible in the diff and only appear when the application executes end to end. For a fuller catalogue of what runtime checks catch that reading does not, see how to detect hidden bugs in AI-generated code.
Verification also leaves behind something review does not: a repeatable artifact. A good review ends in an approval and some comments, both of which expire the moment the code changes again. A verification captured as a test reproves the behavior on every future change. Martin Fowler calls this self-testing code: "you have self-testing code when you can run a series of automated tests against the code base and be confident that, should the tests pass, your code is free of any substantial defects." Review confidence is point-in-time; verification confidence is durable and re-runnable.
Review has always had this runtime blind spot. What changed is that AI-generated code aims directly at it. A model trained to produce code that looks like the code humans approve is, in effect, trained to pass review. The output is syntactically clean, stylistically consistent, and structurally plausible, and it can still be wrong in edge cases or missing a domain assumption entirely. Codacy's argument in Code Review Is Dead is blunt about the consequence: teams approve AI-generated changes based on readability and perceived correctness rather than on demonstrated behavior.
Two forces make this worse. The first is volume: an agent implementing a feature across five files produces a five-hundred-line diff in minutes, and a reviewer can approve it in seconds without verifying any behavior. The second is automation bias. As Addy Osmani documents in Code Review in the Age of AI, the less familiar a reviewer is with a domain, the more they trust plausible-looking machine output, and AI makes unfamiliar domains accessible faster than it makes them verifiable. The signal a reviewer relies on, "does this look like someone who understood the problem wrote it," is precisely the signal the model has learned to fake.
This is why "is AI code review enough" has a clear answer: no, because the thing AI code most reliably produces is the appearance of correctness, and appearance is all review can inspect. The question of whether the code should be trusted by a peer coding agent instead of a human is the same question from a different angle, which we cover in can coding agents test their own code.
The two are complementary, not competing. This table separates them on the axes that matter when you decide which one covers a given risk.
| Axis | Code review (human or AI reviewer) | Verification |
|---|---|---|
| What it inspects | The code as written: the diff, structure, and style | The software as it runs: actual behavior in a real environment |
| What it catches well | Readability, convention violations, obvious logic slips, known anti-patterns, design concerns | Broken flows, integration failures, cross-browser bugs, regressions in untouched code |
| What it structurally misses | Runtime behavior, integration effects, edge cases that only appear on execution | Nothing about code aesthetics or maintainability, which is not its job |
| When it runs | Before merge, reading the diff | After the change is built, exercising the running app |
| What artifact it leaves | An approval and comments that expire when the code changes | A repeatable test that reproves the behavior on every future change |
Read across any row and the pattern holds: review is about the code, verification is about the software. Neither substitutes for the other. A change that passes review and fails verification is broken. A change that passes verification and fails review works but will be painful to maintain.
None of this argues against AI code review. Consistency, style, and structural feedback at scale are real value, and an AI reviewer that flags a convention violation on every PR does work no human has the patience to do reliably. The framing is layered: AI review handles the "as written" layer, verification handles the "as run" layer, and problems arise only when a team treats review as the whole gate and ships on approval alone.
The practical failure is easy to spot. If your merge gate is "a reviewer, human or AI, said this looks good," you are gating on appearance. If it also requires that the change was exercised in a real environment and the affected flows passed, you are gating on behavior. The second is what a quality gate for AI pull requests needs to enforce: the difference between catching a plausible-but-broken change before merge and catching it in production.
Shiplight supplies the verification half of this pair. It plugs into your coding agent as an MCP server and gives the agent eyes and hands in a real browser, so after the agent writes a change it can run the affected flow and observe what actually happens instead of reasoning about what should happen. The /shiplight verify command confirms a UI change behaves right after an edit; /shiplight create-yaml-tests has the agent walk the app and author E2E tests from intent; /shiplight fix reproduces failures and, if the application is genuinely broken rather than the test, reports the bug instead of quietly rewriting the test to pass.
That last property turns verification into a durable artifact rather than a one-time check. The tests are readable YAML written from intent, not brittle selectors, and they live in your own git repository, so a behavior verified once is reproved on every subsequent change. This is the mechanism behind verification-driven development: instead of trusting that reviewed code works, you prove it and keep the proof. For the step-by-step version applied to agent output, see how to verify AI-generated code. Verification here is a bounded capability the coding agent calls, a narrower shape than a standalone QA agent, a distinction laid out in QA agent vs verification tool.
AI code review inspects the code as written: it reads the diff and reasons about style, structure, conventions, and obvious logic errors without executing anything. Verification inspects the software as it runs: it builds the change, exercises the behavior in a real environment, and observes whether the feature works and existing flows still pass. Review reasons about code; verification proves behavior.
No. AI-generated code is engineered to look plausible, which is precisely the signal review depends on. A change can be syntactically clean, stylistically consistent, and structurally sensible while still being broken in edge cases or integration paths that only appear at runtime. Review is necessary but not sufficient; the sufficiency gap is verification.
Because a model trained to produce code that looks like the code humans approve is effectively trained to pass review. The output passes the "does this look right" test by construction, while whether it works is a separate fact only execution establishes. Volume and automation bias compound it: reviewers approve large, plausible diffs quickly and trust machine output most in domains they know least.
No, they are complementary layers. Review handles the "as written" concerns: readability, maintainability, conventions, and design, which no test can evaluate. Verification handles the "as run" concern: does the software actually behave correctly. A mature gate uses both and merges only when a change passes review and is proven at runtime.
A repeatable test. A review ends in an approval and comments that expire the next time the code changes. A verification captured as a test reproves the behavior on every future change, which is what Martin Fowler calls self-testing code. Shiplight authors these as readable YAML tests that live in your own git repository and re-run in a real browser.