- Three AI failure modes no test catches: duplication instead of reuse, style drift, and tests that mock the hard part.
- A 20-minute review pass: find what should have been reused (3 min), read the tests and ignore the impl (7 min), run it on a device (5 min), ask the "six months from now" question (5 min).
- The bar for AI-generated code should be higher than for human code — a human is committing their reputation to what they wrote. The AI isn't.
- Rewrite when the pattern would set a precedent. Accept when the failure is small and isolated.
Claude Code will produce a working React Native feature in 20 minutes that would have taken you four hours. Tests pass. Typecheck passes. You ship it.
Six weeks later you're wondering why the codebase feels harder to work in than it should.
What happened: the AI made choices that were locally correct and globally corrosive, and no automated check caught them.
Here's how to catch them yourself.
The three failure modes
1. Duplication instead of reuse. The AI didn't know useUser() existed, so it wrote its own version. Or it wrote three functions that all normalise a phone number, none of them quite the same.
2. Style drift. Your codebase uses styled-components. The AI generated a screen with inline StyleSheet.create because that's more common in its training data. Both work. Now your codebase has two styling systems.
3. Test-driven wishful thinking. The AI wrote a test that mocks the tricky part. Test passes. The tricky part still doesn't work in production.
None of these are caught by tests, typecheck, or linting.
The 20-minute review pass
For every AI-generated PR:
Minutes 1–3: Find the smallest new thing that should have been reused
- Search the codebase for the function name. If two exist, decide which one stays.
- Check the imports. Did the AI pull in a new library when an existing one would work?
Minutes 4–10: Read the tests, ignore the implementation
- What are the assertions actually checking — the important behaviour, or the easy behaviour?
- Are the mocks hiding the hard part?
- Would this test still pass if the implementation was
return truefor the happy path?
Minutes 11–15: Run the feature end-to-end on a device
- Don't trust "tests pass." Open the app and do the flow.
- Empty state? Error state? Slow network?
Minutes 16–20: The "six months from now" question
- If someone joined the team in six months, would they know why this exists?
- Will the naming still make sense when the product has changed?
- Would you be embarrassed if this was on your GitHub?
Reject the PR if any of the above smells. The AI can rewrite it in five minutes; you save yourself weeks of drag.
What good AI-generated code looks like
- Reuses existing helpers instead of inventing new ones.
- Follows existing patterns — styling, error handling, state management — without being told to.
- Tests assert on user-visible behaviour, not implementation details.
- Function and variable names match the codebase's conventions.
- Comments explain why, not what.
If your CLAUDE.md is doing its job, most of these are automatic. If it isn't, you'll see the failure modes above in every PR.
When to accept vs. rewrite
Accept when: the failure is small (one duplicate helper), the risk is low (isolated feature), and the fix cost is high (refactoring would take longer than the value it returns).
Rewrite when: the pattern would set a precedent (the next five features would follow it), the risk is high (it touches shared code), or the code just feels foreign in the codebase.
The bar for AI-generated code should be higher than for human-generated code, not lower. A human is committing their reputation to what they wrote. The AI isn't.
Setting up guardrails past one dev
If you're on a team using AI heavily:
-
Require a
CLAUDE.mdin every repo. Update it every time you catch the AI going in a wrong direction. - Shift the code review focus. Human reviewers should focus on the failure modes above, not on "does this work" — the AI will make it work.
-
Run a weekly AI code-quality review. Grep for patterns the AI introduced, refactor duplicates, and update
CLAUDE.mdso the next PRs don't repeat them.
The takeaway
AI code that you don't review will make your codebase worse over time. AI code that you review carefully will make you 3× faster without the tax.
The difference is entirely in your review discipline.
One thing that reduces the failure modes at the source: pointing the agent at a codebase that already has conventions rather than an empty folder. Applighter ships Expo + Supabase templates with the patterns and agent docs already in place, so there's less for the AI to invent.
What's the worst thing an AI has quietly done to your codebase? Mine wrote a third phone-number formatter.
Top comments (0)