The Most Expensive Bug Isn't in Your Code
gstack's investigate skill enforces a root-cause-first debugging protocol. The real insight is about the mental habit it builds — and why most developers never develop it.
Every experienced engineer has a version of this story.
A bug surfaces in production. You look at the error message, recognize a pattern you've seen before, and apply the fix you remember. The tests pass. You ship it. Two weeks later, the same bug is back — wearing different clothes.
You didn't fix the bug. You fixed the symptom.
The actual bug — the architectural decision, the state mutation, the assumption that was never validated — is still there. You just bought yourself a few weeks of quiet.
gstack's investigate skill is built around one idea: you are not allowed to touch the code until you understand why it's broken.
That constraint is more valuable than the skill itself.
The Protocol
The /investigate workflow enforces a four-phase loop:
- Gather symptoms — reproduce the bug reliably, document what you observe
- Form hypotheses — generate at least three plausible explanations before testing any
- Test systematically — eliminate one hypothesis at a time with minimal code changes
- Implement the minimal fix — touch only what the root cause requires
The three-hypothesis rule is the one that changes behavior. It sounds like overhead. It isn't.
When you force yourself to generate three explanations before testing the first one, you discover something uncomfortable: most of your "obvious" explanations are actually guesses dressed up as confidence. The second and third hypotheses are where the real thinking happens.
There's also a three-strike rule. If three consecutive hypotheses are wrong, you stop and go back to symptom gathering. You haven't understood the problem yet. More debugging in the wrong direction just adds noise.
This feels slow when you're under pressure. It isn't. Undirected debugging — the frantic kind where you're changing things and hoping something helps — compounds time debt. You make the codebase harder to understand while solving nothing.
The Mental Habit Behind the Tool
The more interesting thing about investigate is the thinking pattern it trains.
Good debuggers don't think in terms of "what do I change to make this error go away?" They think in terms of "what is the system's model of reality, and where does that model diverge from what actually happened?"
These are very different questions.
The first question produces patches. The second question produces understanding.
Once you have understanding, the fix is usually obvious and small. Without understanding, you're playing whack-a-mole — and every fix you make without understanding the cause leaves a landmine for the next engineer.
Garry Tan's Iron Law of debugging is embedded in the skill's design: no fixes without root cause. It's not a suggestion. It's a gate. The skill won't let you implement anything until you've articulated what caused the problem at its source.
Forcing that articulation out loud — even to an AI — is surprisingly effective. Explaining a bug often reveals the answer before you finish the explanation. The skill gives you a structured audience for that process.
Where This Matters Most
The discipline matters most in complex systems — distributed services, stateful UIs, concurrent processes, legacy code with implicit dependencies.
In simple systems, the wrong approach still works most of the time. You poke around, you find something, you fix it, and you got lucky. That luck trains bad habits.
In complex systems, luck runs out. The systems are too interconnected for random probing. A fix in one place breaks three things in another. The only reliable path is understanding.
Most engineers know this intellectually. The hard part is doing it under pressure, when a customer is waiting and your first instinct is to console.log your way to a solution.
investigate builds the habit of slowing down precisely when your instinct is to speed up. That's what makes it useful beyond the tool itself.
The Question That Changes Everything
The question investigate trains you to ask first isn't "what's broken?"
It's "what has to be true for this behavior to make sense?"
A system doing something unexpected isn't behaving randomly. It's behaving consistently with its model of the world. The bug is the gap between your model and the system's model. Finding that gap is the whole job.
When you internalize that framing, debugging stops feeling like hunting and starts feeling like reasoning. You're not looking for the broken thing. You're reconstructing the system's logic until the unexpected behavior becomes inevitable.
At that point, you already know the fix.
AI Skill Daily 003. Part of the gstack series — 35 specialist skills from garrytan/gstack.