Skip to content

Part 03 / Review & Quality

Diff Review Loops

Avoiding the looks-fine trap in AI-generated code

Have you ever approved a diff that looked clean, only to find a subtle bug two days later?

On this page

The most dangerous moment in AI-assisted development: you're looking at a diff that looks correct. Code is clean, logic seems right, tests pass. You approve it. Two days later, bug in production.

AI-generated code has a specific failure mode — correct for the happy path, wrong for the edge cases. The code looks right because the structure is right. The bug is in the behavior.

The diff review mindset

Reviewing an AI diff requires a different mindset than reviewing a human-written one. With human code, you're checking for mistakes. With AI code, you're checking for plausible-looking mistakes — code that looks right but isn't.

A concrete example: you ask the model to add pagination to a list. It returns this:

const start = (page - 1) * pageSize;
const end = start + pageSize - 1;
return items.slice(start, end);

Looks right, but slice treats its end index as exclusive. Subtracting one means every page returns pageSize - 1 items. A test that only checks the first item or verifies that the result is non-empty can still pass while every page silently drops its final item.

The code is clean, the logic is almost right, and nothing in the diff signals the problem. That's the failure mode.

Questions I ask:

  • What edge cases does this not handle? The model tends to handle the cases it was asked about and miss the ones it wasn't.
  • Does this change the behavior in ways that aren't visible in the diff? Changing a function's return type, modifying shared state, altering execution order.
  • Are the tests testing the right things? AI-generated tests often test the happy path and miss the edge cases.
  • Does this introduce any implicit dependencies? New imports, global state, environment variables.

Ask the model to break it

After the model generates code, ask it to try to break it. "What inputs would cause this to fail? What edge cases does this miss?"

Works because the model is in a different mode — looking for problems rather than generating solutions. It often finds issues it missed during generation.

Patterns that indicate risky diffs

Patterns I've learned to scrutinize:

  • Simplified conditionals. The model often simplifies complex conditions. Sometimes correct, sometimes it removes an edge case handler.
  • Changed function signatures. Even small signature changes can break callers in non-obvious ways.
  • New async/await patterns. Async code is where subtle bugs hide. Any change here deserves extra attention.
  • Modified error handling. The model tends to add or remove error handling in ways that change behavior silently.

Scenario Lab

Curated task examples and current model cost comparisons

Paste a stack trace and get a plain-English explanation with a fix suggestion.

~0.8k in~0.5k outsignal: speed
→

Fast models handle this as well as expensive ones. The answer is either right or obviously wrong — no back-and-forth needed.

Current models: estimated cost for this task

These models have not been run against the local scenario checks. Costs use the same token assumptions; they do not predict quality or actual token use.

  • Mistral Large 4 · Not tested$0.0016
  • Gemini 3.8 Flash · Not tested$0.0025
  • Claude Fable 5.1 · Not tested$0.033
  • Claude Opus 5.5 · Not tested$0.013
  • Claude Sonnet 5.5 · Not tested$0.0066
  • GPT-6 Astra · Not tested$0.033
  • GPT-6.1 Sol · Not tested$0.0066
  • GPT-6 Luna · Not tested$0.0003
  • DeepSeek-V4.1-Flash · Not tested$0.0008
  • GLM-5.3 · Not tested$0.0033
  • Kimi K3 · Not tested$0.0099

DeepSeek uses peak rates. Gemini uses its current introductory rate. Older excerpts below keep their original model versions.

The excerpts below are curated examples, not a measured ranking. Original run logs are not included; validate the approach against your own task.

🌙
GPT-5.6 LunaBest pickrecommended

Fast, correct, no fluff

What it produced

The error occurs because `user` can be `undefined` when the component first renders. Add a null check: `if (!user) return null;` before accessing `user.name`.

What went right

  • ▸Identified root cause immediately
  • ▸Gave a one-line fix
  • ▸No unnecessary explanation

Cost note

The current GPT-5.6 fast default; negligible at normal volume

token cost

$0.0008/run

💎
Gemini 3 Flash PreviewGood fit

Correct but slightly verbose

✨
Claude Sonnet 5Use with care

Correct, but added unrequested refactor suggestions

🧠
Claude Opus 4.8 (superseded; historical example)Avoid

Thorough but massively over-engineered for this task

Scenario takeaway

Luna is fast, cheap, and more than capable for error explanation. Paying for Sol or Fable here is waste.

Existing excerpts are retained as qualitative examples; original run logs are not included. New models have no local results yet. Prices checked 2026-10-05; Mistral checked separately 2026-10-07, with its 50% launch offer interpreted as October 6–19 inclusive. Mistral · Anthropic · OpenAI · Google · DeepSeek · Moonshot AI · Z.ai · Cursor Standard uncached text-token estimates. Excludes cache writes/reads, tool fees, taxes, and platform-specific charges. Reasoning tokens count as output.