AI-assisted code review
Lesson 9 of 12
9AI-assisted code review
The big pictureA good review catches the bug before it reaches the user. The assistant adds a second pair of eyes that never tires, but it sometimes invents a problem or misses the main one. You are the judge; it is the witness.
What the picture shows: The assisted review loop: no note is accepted until you have checked it yourself.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
It is like asking a clever friend to read your message before you send it. Say "have a look" and they will say "nice". Say "this goes to my manager; check the numbers, the tone and that the ask is clear" and you get real notes. Still, you decide which ones are right.
An effective review gives the model: only the diff, not the whole repository; the purpose of the change; the constraints (version, performance, security); an explicit checklist (correctness, edge cases, unhandled errors, injection, secrets, N+1 performance, naming); and an output format (file:line, severity, reason, failure scenario). Ask for "a concrete failure scenario" per note to cut hallucination. Then combine it with deterministic static tools (ruff, mypy, eslint, semgrep), which never hallucinate, and with tests.
Before You Start
🤖The assistant in the editor
This track's first lessons: completion and chat.
🔀Git
You know git diff and pull requests.
The Core Idea
1A review request that delivers
Compare the two requests. The first gets generic praise; the second gets notes you can test:
Bad: "Review this code." Good: Context: Flask API, Python 3.12, PostgreSQL. This diff adds an endpoint that lets a user download their own invoices. Check, in order: 1. Can a user reach another user's invoice? 2. Unhandled errors and missing input validation. 3. SQL built from strings. 4. Edge cases: empty list, very large list, missing id. For each finding give: file:line, severity (high/medium/low), a concrete request that triggers it, and the smallest fix. If you find nothing for an item, say so. Do not comment on style. <diff here>
2Sorting the notes
Every note falls into one of three: right (reproduce it with a test, then fix it), overstated (true in theory but cannot happen in your context, so write down why), wrong (the assistant misread, so ignore it). The rule: no fix without a test that fails before and passes after.
3A small automatic reviewer
Static tools are deterministic: the same input always gives the same result. Here is a tiny reviewer with the ast module that flags two risky patterns, a bare except: and a mutable default argument:
import ast
source = """
def add_item(item, basket=[]):
basket.append(item)
return basket
def load(path):
try:
return open(path).read()
except:
return None
"""
for node in ast.walk(ast.parse(source)):
if isinstance(node, ast.ExceptHandler) and node.type is None:
print(f"line {node.lineno}: bare except hides every error")
if isinstance(node, ast.FunctionDef):
for default in node.args.defaults:
if isinstance(default, (ast.List, ast.Dict, ast.Set)):
print(f"line {node.lineno}: mutable default in {node.name}()")Worked example
Problem: the assistant said "line 14 is open to SQL injection". Check: the line uses cursor.execute("... WHERE id = %s", (user_id,)), a parameterised query. Label: wrong, parameters prevent injection. In the same reply it said "it does not check the invoice belongs to the user". Check: requesting /invoices/7 as another user returned 200. Label: right and serious, so write the test and add AND owner_id = %s.
Myth vs Reality
| Myth | Reality |
|---|---|
| AI review replaces the human reviewer. | It speeds up the human reviewer and catches the obvious, but understanding the purpose and context stays with people. |
| If the assistant finds nothing, the code is sound. | It can miss logic bugs specific to your domain. Tests are the evidence. |
Test your understanding
What is the most useful thing to ask for with each note to cut hallucination?
A failure scenario can be tried, so it is immediately clear whether the note is real.
A note is true in theory but impossible in your context. What do you do?
Writing the reason down saves re-arguing it later.
Why pair the assistant with static tools?
A static tool always gives the same result for the same code.
Quick review cards
Check Your Understanding
Why not send the whole repository for review?
A huge context distracts the model from the change and may expose secrets.
When do you accept a note?
When you reproduce it with a failing test.
What should you not ask the assistant to review?
What tools settle automatically, like formatting; it is noise in the reply.