Skip to content
Back to skills

Fix

ASecurity

Systematic debugging — investigate, hypothesize, fix, verify. No fixes without root cause.

  • 2 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 26, 2026
developmentrustgobashreacttestingdebuggingrefactoringgitapi

Works with

  • api
  • mcp

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add iamvonpasion/hashb --skill fix --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fix?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Fix
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iamvonpasion-fix/badge)](https://www.skillsdirectory.com/skills/iamvonpasion-fix)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
description: Systematic debugging — investigate, hypothesize, fix, verify. No fixes without root cause.
---

# Investigate

**Iron Law: NO FIXES WITHOUT ROOT CAUSE.**

Fixing symptoms creates whack-a-mole debugging. Every fix that doesn't
address root cause makes the next bug harder to find.

---

## Presentation Rules

Follow the shared formatting rules in `skills/shared/formatting.md`.

1. **Progress indicator** — every output starts with:

```
/fix ════════════════════════════════════════════════════════════

  ▸ Phase 0  Preflight & Tracker
  ○ Phase 1  Gather Evidence
  ○ Phase 2  Test Hypothesis
  ○ Phase 3  Fix
  ○ Phase 4  Verify & Report

════════════════════════════════════════════════════════════════
```

Update `▸` (current), `✓` (done), `○` (pending) as phases progress.
Completed phases show a status note (e.g., `✓ hypothesis confirmed`, `✓ 1 file changed`).

---

## Phase 0: Preflight & Tracker

Run `skills/shared/preflight.md` for branch/base detection.

Run `skills/shared/tracker.md` §Tracker Detection if `TRACKER_TYPE` is not yet
cached. Then run the §Issue Resolution Block to resolve `TASK_ISSUE` from the
user's invocation message, current branch name, or conversation context.

### Re-entry Detection

Before starting Phase 1, check for prior state — the user may be resuming
a bugfix from a prior session.

**Check 1 — Local state file:** Read `.fix-state-{branch}.json` if it exists.
If found, this is a resumed investigation. Report the prior state (strikes,
phase, bug description) and ask whether to continue or start fresh.

**Check 2 — Tracker labels (when `TASK_ISSUE` is resolved):** Query the
issue's labels to determine chain position:

```bash
if [ "$TRACKER_TYPE" = "github-issues" ] && [ -n "$TASK_ISSUE" ]; then
  LABELS=$(gh issue view "$TASK_ISSUE" --json labels --jq '.labels[].name' 2>/dev/null)
fi
```

| Labels found | Meaning | Action |
|---|---|---|
| `hashb:fix` present | Fix already completed in a prior session | Skip `/fix` — suggest `/review` or `/ship` as next chain step |
| `status:investigating` (no `hashb:fix`) | Investigation started but not finished | Resume from Phase 1 or 2 (check state file for strikes) |
| `status:dev` (no `hashb:fix`) | Fix implementation started but not verified | Resume from Phase 3 or 4 |
| `hashb:fix` + `hashb:review` (issue open) | Fix and review done, not shipped | Skip `/fix` and `/review` — suggest `/ship` |
| No hashb labels | Fresh bug — first run | Proceed normally to Phase 1 |

**Chain routing on re-entry:** When tracker labels show the fix is already done,
present the chain status and route forward instead of re-fixing:

```
▸ RE-ENTRY — issue #N already has [fix ✓] from prior session

  Chain status:
    ✓ /fix      {root cause summary from issue or commit}
    ○ /review   not yet run
    ○ /ship     not yet run

  Next: /hashb:review (recommended — resume chain)
```

If labels show no prior state, proceed with Status Swap to
`status:investigating` using `skills/shared/tracker.md` §Status Swap Block.

---

## Phase 1: Gather Evidence

Collect before hypothesizing. Do not guess. No file edits or code
changes until the root cause hypothesis is written — reading and
grepping are the only tools in Phase 1. If invoked mid-conversation
after prior fix attempts, discard those attempts as noise and start
evidence gathering fresh from the original symptom.

**Read the symptoms:** Error messages, stack traces, reproduction steps.
If the user hasn't provided enough context, ask ONE focused question.

**Trace the code path:** Follow execution from symptom back to potential
causes. Grep all references, read the logic.

**Check recent changes:**

```bash
git log --oneline -20 -- <affected-files>
```

Was this working before? If so, the root cause is in the diff.

**Design source first (if visual/UI bug):** When the symptom is a visual
mismatch — wrong color, spacing, layout, or appearance — the design file
is the primary evidence source, not a screenshot.

1. Locate the design spec: Figma link, design HTML export, token file,
   or reference in the spec/ticket. If the user provided only a
   screenshot, ask: "Is there a design file or Figma link for this?"
2. Read the design spec BEFORE reading the component code.
   Extract concrete values: colors, spacing, font sizes, radii, states.
3. A screenshot is a symptom report. A design file is the spec.
   Fix to the spec, not to the screenshot.

**Trace existing implementations (if visual/UI bug):** Before fixing a
visual element, find where the same treatment is already applied
correctly elsewhere in the codebase.

```bash
# Find components using the same visual pattern
grep -r "bg-heading\|variant.*primary" --include="*.tsx" --include="*.css"
```

If the same visual treatment (button style, avatar, badge, indicator)
exists elsewhere and looks correct, that implementation is your
reference — copy the approach, don't reinvent it.

**Check known issues:** Scan `TODOS.md` (root index + General section) and
every `specs/*.todos.md` referenced by the index, plus git log, for prior
fixes in the same area. Recurring bugs in the same files = architectural smell.

**Graph-Aware Tracing (if graphify MCP is available):**
If the consumer's Project Profile lists `graphify`, query it to
accelerate evidence gathering:
- Trace callers and dependents of the symptomatic function to find the
  full call chain from entry point to failure site
- Identify which tests cover the affected code paths — if they're passing,
  the bug may be in an untested path
- Map the blast radius of the suspected root cause before fixing

If graphify is not available, trace manually via grep and file reads.

**Reproduce:** Can you trigger it deterministically? If not, gather more
evidence before proceeding.

**Output:** "Root cause hypothesis: ..." — a specific, testable claim
about what is wrong and why.

---

## Phase 2: Test the Hypothesis

Before writing ANY fix, verify your hypothesis with instrumentation.

### Instrumentation Gate

Determine whether instrumentation is needed based on the bug type:

| Bug type | Instrument first? | Example |
|----------|-------------------|---------|
| **Obvious** — root cause visible in code | No — fix directly | Typo, missing import, wrong variable, config error |
| **Non-obvious** — hypothesis needs verification | **Yes — mandatory** | State bugs, race conditions, hydration, lifecycle, async timing, silent failures |

**If instrumentation is needed:**

1. Add `console.log` / `logger.debug` / breakpoint at the suspected root cause
2. Add logging at the entry and exit of the affected code path
3. Run the reproduction and **paste the diagnostic output**
4. Only proceed to a fix if the output confirms your hypothesis

If you cannot reproduce with instrumentation, say so and present options
to the user. Do not guess.

> **Why this matters:** Retro evidence shows that skipping instrumentation
> on non-obvious bugs leads to 3-6x fix attempts. Reading logs is faster
> than reading diffs.

**Confirm it:** Does the evidence (code reading or diagnostic output) match your hypothesis?

### 5 Whys Analysis

Once the immediate cause is identified, apply 5 Whys to reach the systemic
root cause. Shallow fixes ("the variable was null") create recurring bugs.
Deep fixes ("the schema allows null where it shouldn't") prevent entire classes
of bugs.

```
WHY #1:  Why did {symptom} happen?
         → {immediate cause}

WHY #2:  Why did {immediate cause} happen?
         → {deeper cause}

WHY #3:  Why did {deeper cause} happen?
         → {process/design cause}

WHY #4:  Why did {process/design cause} happen?
         → {systemic cause}

WHY #5:  Why did {systemic cause} happen?
         → {root cause — fix HERE}
```

**Rules:**
- Stop early if you reach a root cause before 5 — don't force it
- Each "why" must be supported by evidence, not speculation
- If a "why" has multiple answers, branch and investigate each
- The final "why" should point to something **preventable** — a missing
  validation, a design gap, a process failure. If it points to "human error,"
  go one level deeper: why did the system allow the error?

**Output:** State the root cause chain:
```
ROOT CAUSE CHAIN ────────────────────────────────────────────────

  Symptom      {what the user saw}
       │
  Why #1       {immediate cause}
       │
  Why #2       {deeper cause}
       │
  Root cause   {the thing to fix}
       │
  Fix target   {code/process/rule change that prevents recurrence}

─────────────────────────────────────────────────────────────────
```

**If wrong:** Return to Phase 1. Gather more evidence. Do not guess.

**Check if it matches a known pattern:**

| Pattern | Signature | Where to look |
|---------|-----------|---------------|
| Race condition | Intermittent, timing-dependent | Concurrent access to shared state |
| Nil propagation | NoMethodError, TypeError | Missing guards on optional values |
| State corruption | Inconsistent data, partial updates | Transactions, callbacks, hooks |
| Integration failure | Timeout, unexpected response | External API calls, service boundaries |
| Config drift | Works locally, fails elsewhere | Env vars, feature flags, DB state |
| Stale cache | Shows old data, fixes on clear | Redis, CDN, browser cache |
| Visual mismatch | Wrong color, size, spacing, layout vs. design | Design tokens, theme files, component variants, CSS override chain |
| Interaction mismatch | Wrong hover/focus/active/disabled state | Event handlers, CSS pseudo-classes, state-driven class logic |

**3-strike rule (HARD STOP — not a suggestion):**

If 3 hypotheses fail, you **MUST** stop. Do not attempt a 4th fix.
Do not continue investigating silently. Present this to the user and WAIT:

```
■ 3-STRIKE STOP ─────────────────────────────────────────────────

  Hypotheses tested:
  1. {hypothesis} — {why it failed}
  2. {hypothesis} — {why it failed}
  3. {hypothesis} — {why it failed}

  Options:
  A) New lead — {describe what's different this time}
  B) Escalate — this needs domain knowledge I don't have
  C) Instrument deeper — add more logging, reproduce again

─────────────────────────────────────────────────────────────────
```

> **Why this is a hard stop:** Retro evidence shows that blowing past
> 3 strikes leads to 6+ attempts, wasted commits, and trust erosion.
> Stopping at 3 and asking is always cheaper than guessing at 6.

### Strike Persistence

Persist strike state and chain context to disk so progress survives context
compaction and session boundaries:

**On each failed hypothesis**, write `.fix-state-{branch}.json`:

```json
{
  "branch": "{branch}",
  "bug": "{short description}",
  "task_issue": 50,
  "phase": "investigating",
  "strikes": [
    {"hypothesis": "...", "result": "disproved — ...", "timestamp": "..."}
  ],
  "root_cause": null,
  "status": "INVESTIGATING"
}
```

| Field | Purpose |
|-------|---------|
| `task_issue` | GitHub Issue number (or `null`) — enables re-entry without re-resolving |
| `phase` | Current phase: `investigating`, `hypothesis`, `fixing`, `verifying` |
| `root_cause` | Root cause summary once confirmed (or `null`) — carries context across sessions |
| `strikes` | Failed hypothesis chain |
| `status` | `INVESTIGATING`, `FIXING`, `HARD_STOP`, `DONE` |

**Update the file at each phase transition:**
- Phase 1 complete → set `phase: "hypothesis"`
- Phase 2 (hypothesis confirmed) → set `phase: "fixing"`, `root_cause: "..."`, `status: "FIXING"`
- Phase 3 complete → set `phase: "verifying"`
- Phase 4 (DONE) → set `status: "DONE"` (file cleaned after badge/handoff)

On 3rd strike, set `"status": "HARD_STOP"`.

**At Phase 0 or Phase 2 start**, read `.fix-state-{branch}.json` if it exists:
- If `status` is `HARD_STOP` — present the 3-strike stop immediately.
- If `status` is `INVESTIGATING` with strikes — resume from recorded position.
- If `status` is `FIXING` — root cause is already confirmed, resume from Phase 3.
- If `task_issue` is set — restore `TASK_ISSUE` without re-running Issue Resolution.

**On resolution:** `rm -f ".fix-state-${BRANCH}.json"`

---

## Phase 3: Fix

Once root cause is **confirmed** (not suspected — confirmed):

### Branch Guard

Before writing any code, ensure you're on a feature branch:

```bash
BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
  echo "⚠ ON PROTECTED BRANCH — creating fix branch"
  SLUG=$(echo "{short-bug-description}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]')
  if [ -n "$TASK_ISSUE" ]; then
    git checkout -b "fix/#${TASK_ISSUE}-${SLUG}"
  else
    git checkout -b "fix/$SLUG"
  fi
fi
```

> **Never write fixes directly on main/master.** If the user explicitly
> says to commit to main, warn them and proceed only with confirmation.

### Status Swap — Dev

When the fix implementation begins (after hypothesis confirmed), swap
the issue status to `status:dev` using `skills/shared/tracker.md`
§Status Swap Block. This distinguishes active coding from investigation.

1. **Write a regression test FIRST — before writing the fix.**
   The test must target the exact bug scenario from the root cause chain.

2. **RED: Run the test. It MUST fail.** Paste the failure output.
   If it passes without a fix, the test is wrong — it's not testing the bug.
   Rewrite it until it fails for the right reason.

3. **Fix the root cause from the 5 Whys chain, not the symptom.** Smallest
   change that eliminates the actual problem at the deepest actionable level.
   Minimal diff — fewest files, fewest lines. Resist refactoring adjacent
   code during a bug fix.

4. **GREEN: Run the test again. It MUST pass.** Paste the passing output.
   This is the proof the fix works. Without RED then GREEN on the same test,
   you have no proof — only a claim.

5. **Run the full test suite.** Paste output. No regressions.

**Blast radius check:** If fix touches >5 files, stop and ask:

```
This fix touches N files — large for a bug fix.
A) Proceed — root cause genuinely spans these files
B) Split — fix critical path now, defer the rest
C) Rethink — maybe a more targeted approach exists
```

---

## Phase 4: Verify & Report

**Reproduce the original bug and confirm it's fixed.** Not optional.

Run the test suite, paste output.

```
✓ DEBUG REPORT ──────────────────────────────────────────────────

  Symptom          {what the user observed}
  Root cause       {what was actually wrong}
  Fix              {what changed — file:line refs}
  Evidence         {test output or repro showing fix works}
  Regression test  {file:line of new test}
  Related          {TODOS, prior bugs, architectural notes}
  Task             #{TASK_ISSUE} (if resolved) | — (no tracker)
  Status           DONE | DONE_WITH_CONCERNS | BLOCKED

  Next:            /hashb:{recommended-per-status} (recommended — {status phrase})

─────────────────────────────────────────────────────────────────
```

**Tracker badge label** — if `TRACKER_TYPE=github-issues` (see
`skills/shared/tracker.md` §Badge Label Block), also add the `hashb:fix` label
to the issue on DONE or DONE_WITH_CONCERNS status. Skip on BLOCKED (no
verified fix to badge). The badge marks the fix as verified for cross-session
visibility.

**TODOS badge append** — if the task is tracked in a TODOS file (root
`TODOS.md` or `specs/*.todos.md`), append `[fix ✓]` on the continuation
line of the task entry:

```markdown
- [ ] P1 [M] #50 Dashboard shows stale data
      [fix ✓]
```

This enables `/decompose` re-entry to show fix completion in the progress
table, and new sessions to see which bugs have been verified.

**Handoff enrichment** — when `TASK_ISSUE` is resolved, include `Task: #N`
and `Refs: #N` in the handoff so downstream `/review` and `/ship` inherit
the issue reference. Commit messages for the fix should include `Refs: #N`
in the footer (per `rules/git.md` bug fix template).

**State file cleanup** — after badge and handoff are emitted, clean up the
transient state file: `rm -f ".fix-state-${BRANCH}.json"`.

### Next Step

| Status | Next Skill | Why |
|--------|-----------|-----|
| DONE | `/review` (if not yet reviewed) or `/ship` | Verify fix in context |
| DONE_WITH_CONCERNS | `/review` with concerns flagged | Verify, watch for edge cases |
| BLOCKED | Escalate to user | Root cause unclear after investigation |

**Autonomous mode:** If running inside a recipe chain:
- DONE → auto-proceed to `/review` if this is the first fix, or `/ship` if already reviewed
- DONE_WITH_CONCERNS → auto-proceed to `/review` with concerns flagged
- BLOCKED → stop the chain, present investigation to user

---

## Red Flags — Slow Down If You See These

- **"Quick fix for now"** — there is no "for now." Fix it right or escalate.
- **Proposing a fix before tracing data flow** — you're guessing.
- **Each fix reveals a new problem elsewhere** — wrong layer, not wrong code.
- **Can't reproduce** — don't ship a fix you can't verify.
- **3+ failed attempts** — question the architecture, not your luck.
- **Touching library persistence/lifecycle internals** — if the fix involves
  changing how a library manages state, storage, hydration, or lifecycle
  (Zustand persist, React Query cache, auth token storage, ORM hooks, etc.),
  **STOP and run `/research` first.** Read the library source code or query
  Context7 for the internal behavior before changing it. "Simple" storage
  swaps can cascade into complex bugs when the library's internal assumptions
  are violated.
- **Fixing visual appearance without a design reference** — if adjusting
  colors/spacing by eyeballing a screenshot, you're guessing. Get the
  design file or find an existing component that implements the treatment.
- **Same fix attempted twice with different values** — if you've tried
  two different colors/sizes and neither matches, you don't have the
  spec. Stop and ask for the design source.

---

## Completion Status

- **DONE** — root cause found, fix applied, regression test passes, suite green
- **DONE_WITH_CONCERNS** — fixed but can't fully verify (intermittent, needs staging)
- **BLOCKED** — root cause unclear after investigation, escalated

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.