Read time: 5 minutes
These days I fix a lot of bugs with Claude Code, and I’ve learned to keep an eye on a common trap.
You fix a bug, run your tests, and they all pass. Naturally, you think you’re done, ready to commit and push.
But you just reviewed your own work, and you were never going to be hard on it. You wrote the fix, so when you re-read it you’re checking that it does what you meant, not hunting for what you missed.
A coding agent does the same thing. Ask it to review the fix it just wrote, and it re-reads its own reasoning instead of questioning it.
Today I’ll show you how to catch what your own review misses, using Claude Code to both write a fix and act as its adversary.
Let’s start.
The bug report
I’ve been working on a new project to make interview preparation more engaging and fun. It’s gamified, so you earn XP and build a daily streak as you solve scenarios.
But as I was running a few manual tests I noticed you could farm XP: redo a scenario you already solved, and you’d get the XP again. Every time.
So I opened Claude Code and started working on it:

I think there’s a bug in the interview trainer: if you redo a scenario you already solved, you get XP again. Can you check @project/Api/Features/Scenarios/SubmitAnswer.cs and fix it? Write a failing test first so we know we go a repro before fixing.
That last instruction, asking for a failing test first, is part of the “red before green” philosophy in test-driven development.
Let me explain.
Red before green
Red before green means you write a failing test first, before touching any product code. You see the bug in action, and only then do you make the code changes necessary to make the test pass.
I find this especially useful with coding agents like Claude, because a test written first can’t be quietly shaped to confirm the fix that comes later.
Here, Claude started by writing a test that answers a scenario correctly, then answers it again, and finally asserts the second submission awards 0 XP and the total stays at 50.

Then it ran that test on the current code, and it failed exactly as expected:

Expected: 0, Actual: 50. The bug is now proven to exist, before anyone (even Claude) tries to fix it. If the test had passed here, there’d be nothing to fix.
The fix
The bug was one line. SubmitAnswer.cs computed the XP award straight from correct, with no check for whether the scenario had already been solved.
So it looked up the existing progress first, computed alreadySolved, and only awarded XP when the answer was correct and the scenario wasn’t already solved:

Then it ran the full suite: 16 tests, all green, including the new one.

Bug reported, reproduced, fixed and all tests green. This is the point where you usually merge and move on.
But wait, not so fast.
Bringing in an adversarial reviewer
AI models can be very confident in their assessments, so it never hurts to get a second pair of eyes that has not seen any of the previous conclusions.
So I started by switching from Sonnet 5 to Opus 4.8 for the review step. A smaller model can review code just fine. But finding problems in code that already looks correct is a harder, more open-ended job than fixing a bug you’ve already located, so I wanted the stronger reasoning for it.
Then I asked for a fresh subagent that had seen none of the work I’d just done:

Before I merge this, spin up a fresh subagent that hasn’t seen any of this conversation and have it review @..\..\Api\Features\Scenarios\ for anything else that looks like it could let someone get credit or progress they didn’t earn.
The subagent gets a self-contained prompt and the folder. It doesn’t get the story of the XP fix, my reasoning, or the fact that I already think the job is done.
It can’t rationalize a decision it never made. It just reads the code.
You hand the change to a reviewer whose only job is to find what’s wrong with it, with none of the context that would tempt it to agree with you.
What the fresh eyes caught
The subagent confirmed the XP fix was correct and complete. No replay-farming avenue left.
Then it found a second bug. One I never asked about, in the same file:

The streak counter advanced on any submission. StreakCalculator.Apply ran before the code even checked whether the answer was correct. So you could submit one wrong answer a day, never solve a thing, and still watch your streak climb.
That’s what self-review misses. Mid-fix I was focused on XP, so it never occurred to me to check the streak. The fresh reviewer wasn’t locked onto XP, so it looked at everything.
It also flagged two smaller notes I’ll come back to: a race condition on the first solve, and an unvalidated input that’s harmless today.
The catch
There’s a catch worth knowing about.
The subagent found the streak bug because of how I worded the ask. I told it to look for ways someone could “get credit or progress they didn’t earn,” which points straight at XP and streaks. Word the ask differently and you get different findings.
Adversarial review removes your bias as the implementer, but the reviewer can still only look for what you point it at.
So don’t treat one clean pass as proof there’s nothing left. It only means nothing turned up for the question you asked.
Deciding what to fix now
I concluded that the streak bug was important enough to fix immediately, while the other two findings could be deferred and documented for later.

Let’s fix the streak one now. Same pattern as before, failing test first. The other two I don’t think are worth touching right now, just note them somewhere so we don’t lose track.
Same red-green cycle as before: a failing test that submits a wrong answer and asserts the streak stays at 0, which fails as expected before the fix.

Then the fix to gate the streak update behind correct, and all 17 tests pass.

We now get all 17 tests passing. Claude also wrote the other two findings into a KNOWN-ISSUES.md file, with a pointer from CLAUDE.md, so a future session sees them instead of losing them when this conversation ends.
Wrapping up
The code you just fixed is the code you’re least equipped to review. You’re too close to it, and you already believe it’s right.
A reviewer with no memory of the fix (a person, or a fresh agent in a clean context) doesn’t carry that belief. It reads the code as it stands and questions things you stopped questioning the moment you felt done. In this session, that’s what turned one known bug into two fixed bugs and two documented ones.
Try it on your next fix. Get the tests green, then hand the change to something that never saw you write it.
And that’s it for today.
See you next Saturday.
Whenever you’re ready, here’s how I can help:
The .NET Developer Bootcamp: A complete path from ASP.NET Core fundamentals to building, containerizing, and deploying production-ready, cloud-native apps on Azure.