| name | bug-hunt |
| description | Find source of concrete failure — rank historically buggy code (high bugFixRate + churn) against symptom. Triggers on "debug X", "why does Y fail", "test fails", "stack trace says Z", "падает", "почему не работает". NOT for code health scanning without a specific symptom — use risk-assessment for that. |
| argument-hint | ["bug description or symptom"] |
Bug Hunt
Signal-driven root-cause investigation via TeaRAGs git signals.
Rules
- Execute YOURSELF — no subagents.
- No
git log, git diff, git blame — overlay has git signals.
- No built-in Search/Grep for code discovery — TeaRAGs + ripgrep MCP only.
- Search results contain code.
metaOnly=false (default) returns chunk
content + startLine/endLine. Evaluate checkpoint from results BEFORE any Read
or navigation.
- Partial reads only.
Read(path, offset=startLine, limit=endLine-startLine) using coordinates
from results. Never read full files.
- Labels are triage. bugFixRate "healthy" → SKIP. Trust it.
Loop
1. Search (search-cascade, rerank="bugHunt", limit=10).
2. CHECKPOINT — fill from ALL available info:
- Suspect file(s): ___
- Buggy line/method: ___
- Why it breaks: ___
All filled? → PRESENT. STOP.
"Not sure" ≠ "don't know" — present with confidence note.
3. ONLY IF checkpoint incomplete — ONE action for what's missing.
Search-cascade for tool selection. Go to step 2.
PRESENT
Ranked suspect list. Per suspect: file:line, signal labels (bugFixRate,
relativeChurn), one-sentence observation why it's the root cause.
Anti-patterns
- Parallel searches in discovery. ONE search finds the area. Returns
batch_create AND jobs/create — both suspects already found.
- Curiosity search. "How does the other path work?" → Read or LSP, not
search. You already know WHERE the code is.
- Confirmatory search. Checkpoint has a candidate — present it. Don't search
for "proof." Confirmatory searches almost never change the answer.
- Full file reads. Chunk coordinates exist. Use them.
pathPattern rules
Use exact relativePath values from search results joined with braces:
- GOOD:
{app/services/batch_create.rb,app/services/jobs/create.rb}
- BAD:
**/services/{batch_create,jobs/create}** (slashes inside braces =
broken glob)
Signal triage
rank_chunks returns overlay labels:
- file.bugFixRate "critical" → prime suspect
- file.bugFixRate "concerning" + relativeChurn high → secondary suspect
- file.bugFixRate "healthy" → SKIP
High bugFixRate + high imports/fanIn (fan-in): suspect may be a coupling
point propagating bugs from upstream, not the origin. Check callers before
fixing here — when codegraph on, get_callers (see Codegraph fault-chain
navigation below) names the exact upstream origins. See
signal-interpretation.md (bug attractor vs coupling; codegraph fanIn
supersedes the imports proxy).
Trace the chain between suspects
Signal triage gives a flat list — WHAT is historically buggy. trace_path
turns it into a causal chain — WHICH step on the route from an entry point
to a suspect is riskiest.
Requires codegraph (prime shows codegraph.symbols). Codegraph off →
trace_path not registered — skip the chain step, report the flat suspect list
only, noting call-chain ranking unavailable without codegraph.
Use when a suspect surfaced but the symptom enters elsewhere (handler,
controller, job) — you need the danger-ranked call path between them, not just
the endpoints.
trace_path(from=<entry point>, to=<suspect>, rerank="bugHunt")
Per-step dangerOverlay carries the same git signals as triage (bugFixRate,
relativeChurn) for every hop on the path. Read the response top-down:
dangerRanking[0] → inspect-first step — the riskiest hop on the route.
- each step's
dangerOverlay → triage that hop exactly like the flat list
(critical → prime, concerning + churn → secondary, healthy → SKIP).
aggregateDanger → ranks competing paths when maxPaths > 1; the
highest-danger route is the one to walk first.
- Empty result = no static call path from
from to to. Negative signal:
suspect not reachable from that entry — wrong entry, dynamic dispatch, or
wrong suspect. Re-pick before reading code.
Fresh-regression bisect: rerank="recent" instead of bugHunt ranks the
path by recency, surfacing the step that changed most recently — the likely
regression on a route that worked before.
Curated danger presets for trace_path (pass explicitly — no default; without
rerank the trace is lean, no danger ranking): bugHunt, dangerous,
hotspots, recent, ownership, blastRadius, securityAudit, techDebt,
codeReview. Use bugHunt for general fault-tracing. Bound the search with
maxDepth / maxPaths.
Codegraph fault-chain navigation
Requires codegraph (prime shows codegraph.symbols). Codegraph off → these
tools not registered — skip this section, stay with the flat suspect list +
manual reasoning; never read an absent tool as a fact.
- Upstream origin (
get_callers). Suspect looks like a victim (bad
input/state arrives from elsewhere) → get_callers symbolId=<suspect> names
who feeds it — bug may originate one hop up. Resolve the exact id with
find_symbol first (Class#method vs Class.method).
- Downstream blast (
get_callees). What the suspect calls — where corrupted
state propagates next, to pick the next checkpoint.
- Find the entry point (
entryPoint). Have a suspect but no from for
trace_path → semantic_search rerank="entryPoint" pathPattern=<scope>
surfaces flow entries (high fan-out / low fan-in drivers) — pick the entry
that reaches the suspect, then trace from it.
- State-loop / re-entrancy smell (
find_cycles). Symptom is an infinite
loop, runaway recursion, or repeated re-entry →
find_cycles scope=method pathPattern=<scope> surfaces circular call paths —
a cycle through the suspect is the structural form of that hypothesis.
These are ONE-hop / structural lookups; trace_path is the full danger-ranked
chain. Start with get_callers/get_callees (cheap), escalate to trace_path
only when the whole route matters.
After root cause found
Pattern found → find_similar from chunk ID for copy-paste bugs in other files.
Fix needed → /tea-rags:data-driven-generation.