Bug Predict¶
Overview¶
Bug-predict scans a codebase and predicts where bugs are most
likely to hide. It is SDK-native: BugPredictionWorkflow
delegates the analysis to three specialized Claude Agent SDK
subagents and synthesizes their findings into a single report
with an overall risk score, per-finding file/line locations, and
prioritized prevention advice.
It predicts — it does not prove. The three subagents apply LLM judgment over the code (via Read / Glob / Grep), so findings are risk hypotheses to triage, not the deterministic output of a linter. Treat a HIGH finding as "look here first," not "this line is definitely broken."
You reach bug-predict four ways, all of which run the same workflow:
- the
/bug-predictskill, inside a Claude Code conversation; - the CLI —
attune workflow run bug-predict; - the
bug_predictMCP tool (one requiredpathargument); - the Python API —
await BugPredictionWorkflow().execute(...), documented here for wiring bug-predict into a hook, a CI step, or a custom tool.
A separate set of regex/string pattern helpers also lives in the
module (bug_predict_patterns.py). They are an internal,
lower-level utility layer — not what the live workflow runs.
The "Notes & tips" and "Design & extension" sections below say
exactly what they do and do not affect.
Concepts¶
Three subagents, one synthesized report¶
BugPredictionWorkflow.execute issues a single
claude_agent_sdk.query whose options define three subagents,
each scoped to Read / Glob / Grep:
| Subagent | What it looks for |
|---|---|
pattern-scanner |
Null references, type mismatches, race conditions, eval/exec usage, broad exception handlers, resource leaks, off-by-one errors. Reports file path, line number, pattern type, and severity. |
risk-correlator |
Correlates the scanner's findings with file complexity, change frequency, and historical bug density; assigns a per-file risk score and names the highest-risk modules. |
prevention-advisor |
Reviews the correlated risks, ranks them by impact, and proposes specific fixes: refactoring, added tests, type annotations, error-handling, and architectural changes. |
The orchestrator then synthesizes all three into one report with three sections — Summary (an overall 0–100 risk score plus a 2–3 sentence executive summary), Bugs (grouped HIGH / MEDIUM / LOW, each with file, line, pattern, and description), and Suggestions (prioritized prevention strategies).
Depth controls the agent-turn budget¶
execute takes a depth of "quick", "standard" (default),
or "deep". Depth maps to the maximum number of agent turns the
SDK query may take, and to a per-run cost cap:
| Depth | Max agent turns |
|---|---|
quick |
10 |
standard |
20 |
deep |
40 |
An unrecognized depth falls back to the standard budget (20
turns). Deeper scans let the subagents read more files and reason
longer, at higher cost — the run is bounded by a max_budget_usd
derived from the depth.
execute is async, and honors only path and depth¶
execute is a coroutine — await it (or drive it with
asyncio.run). Calling it without awaiting is the most common
bug-predict mistake.
It reads exactly two keyword arguments from **kwargs: path
(required) and depth (default "standard"). Any other keyword
is silently ignored — there is no file_types, exclude, or
depth=... shorthand beyond those two. An empty or missing
path returns a failed WorkflowResult rather than raising.
The result is a WorkflowResult¶
execute returns a WorkflowResult (from
attune.workflows). The synthesized report lands in
final_output — a serialized WorkflowReport when the findings
parse into categories, or the raw markdown text otherwise — with
a short summary, a suggestions list, the cost_report, the
provider, and a metadata dict echoing back path, depth,
and max_turns. On failure, success is False and error /
error_type carry the reason.
Design & extension¶
Design decisions¶
- SDK-native, three specialized subagents. Since v4.2.0,
bug-predict is a single
claude_agent_sdk.querywith three subagents —pattern-scanner(detection),risk-correlator(scoring), andprevention-advisor(advice). Splitting the work keeps each subagent's context focused and lets one be changed without touching the others; the cost is an extra synthesis step in the orchestrator. - Prediction, not deterministic scanning, is the contract. The workflow returns LLM-judged risk hypotheses, deliberately trading a linter's precision for breadth and prioritization. This is why findings are framed as hotspots to triage.
- The result is data, not print output.
executereturns aWorkflowResult(report infinal_output, plussummary,suggestions,cost_report, andmetadata); callers own presentation. The CLI, MCP, and skill surfaces all render that same result.
Extension points¶
- Steer a single run: pass
system_prompt_suffixto the constructor to append instructions to the orchestrator prompt without subclassing — the pattern discovery-sweep'sBugPredictSourceuses. - Change the budget: choose
depth(quick/standard/deep) to trade coverage against cost;--cheapon the CLI forces unpinned subagents onto Haiku. - The static pattern helpers are a separate layer.
bug_predict_patterns.pyexposes regex/string detectors (_is_dangerous_eval_usage,_has_problematic_exception_handlers, …) and_load_bug_predict_config, which reads the./attune.config.ymlbug_predictblock (risk_threshold,exclude_files,acceptable_exception_contexts)._should_exclude_fileis reused byworkflow_patterns/behavior.py; the eval/exception detectors are not wired into the live SDK workflow. Treat them as an internal utility, not a configuration surface for the prediction.