skills/debugging/bug-localization/SKILL.md
Pinpoints the exact file, function, or line in a codebase responsible for a reported bug using static and dynamic analysis signals. Use when a bug is reported but the fault location is unknown, when narrowing down a failure to a specific code region, when triaging an issue tracker ticket, or when the user asks to locate where a bug originates.
npx skillsauth add santosomar/general-secure-coding-agent-skills bug-localizationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pinpoint the fault location — the code that must change to fix the bug — not merely where the symptom surfaces. A NullPointerException at line 400 is a symptom; the fault is wherever the null was introduced or wherever the null-check was forgotten.
Different signals demand different first moves. Pick the row that matches:
| Signal available | First move | Then |
| ---------------------------------- | -------------------------------------------------- | --------------------------------------- |
| Stack trace / crash dump | Extract top frame that belongs to project code | Backward slice from that variable |
| Failing test, no trace | Read the failing assertion | Find producer of the asserted value |
| Wrong output, no test | Diff actual vs expected — identify which field(s) | Trace producer of divergent field |
| "Broke after upgrading X" | Search for callsites into X | → regression-root-cause-analyzer |
| "Broke in commit range A..B" | Don't read code first — bisect | → regression-root-cause-analyzer |
| Log shows error | grep for the error string literal | Find the condition that triggers it |
| Intermittent / "sometimes" | Do not stare at code; reproduce first | → bug-reproduction-test-generator |
If more than one signal is available, prefer stack traces > failing tests > logs > prose — in that order of precision.
The anchor is one concrete code location you are certain is involved. You cannot localize without one.
assertEqual(result.total, 100), the anchor is whatever produces result.total.grep -rn "exact log message" → the logger callsite is the anchor.The anchor is where the bad value arrives. The fault is where the bad value is born.
Stop when you reach one of:
Cap backward tracing at ~5 hops. If still ambiguous at 5 hops, the static picture alone is insufficient — jump to Step 4.
You have N candidates and can't distinguish them by reading. Make the code tell you.
bug-reproduction-test-generator). Localization without reproduction is speculation.Before reporting, apply this sanity check to your top candidate:
"If I correct the value at this exact line, does the symptom disappear and every caller still receives a correct value?"
If two candidates both pass this check (both are valid fix points), prefer the upstream one — it fixes more paths.
PRIMARY: src/billing/invoice.py:142 — compute_tax()
Rationale: rate field read from config as string, multiplied without
float conversion → "0.08" * qty produces string repetition, not
arithmetic. Fault is missing float() cast at config load.
Confidence: High — reproduced with qty=3, rate="0.08" yielding "0.080.080.08"
ALTERNATIVE: src/config/loader.py:31 — load_tax_config()
Rationale: upstream fix point. Config loader returns string; coercing
to float here fixes all consumers, not just compute_tax.
Confidence: Medium — would need to verify no consumer expects string
NEXT: → bug-to-patch-generator with PRIMARY location
State confidence as High (reproduced and confirmed), Medium (strong static trace but not executed), or Low (best guess, list what would confirm it).
Input: "POST /orders returns 500. Stack trace shows KeyError: 'discount' at order_service.py:88."
order_service.py:88.total -= payload["discount"]. Faulty value is payload, missing key "discount".payload is the parsed HTTP body. Origin is external input.discount required or optional per the API spec?
payload.get("discount", 0).Output: order_service.py:88 — missing default for optional field. Confidence: High. Alternative fix point: request schema validator (if discount should be required).
< vs <=, len-1 vs len), not the loop body.bug-to-patch-generator. Fixing-while-finding biases you toward the first plausible candidate.development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.