feat(mcp): surface counted bug-fix history on get_risk and get_change_risk#946
Merged
Conversation
…_risk get_risk gains a per-file `defect_profile`: how many bug fixes landed in the trailing 6 months, how long ago the last one was, a `bug_magnet` flag for sustained recent fix pressure, and the symbols the fixes clustered in. Built from the GitMetadata row the assessment already loads, so no extra query. get_change_risk gains `prior_fixes`: per changed file, how many past bug-fix commits touched it and how many of the change's lines fall inside the ranges one of those fixes replaced. `changed_lines` is now read once and shared with `impacted_tests` instead of shelling out to git twice. Both blocks are aggregate and neither names an inducing commit. File-level SZZ measured 74.5% precision against the frozen judgments, which counts fixes honestly and accuses a commit dishonestly. Both are silent on a repo with no fix history, so nothing grows a noise block. `risk_type="bug-prone"` now reads that counted history instead of scanning commit subjects for "fix". The old regex matched doc and test commits, had no recency, and disagreed with the count every other surface shows. Note this reclassifies: bug-prone returns first, so a file with 3 fixes in 200 commits now reports bug-prone where it reported churn-heavy. `bug_magnet` only renders alongside the last-fix age. It is a claim about recent pressure, so without a timestamp it would describe a file fixed four times last month and one fixed four times two years ago identically. The defect_profile block measures at 80 tokens worst case over the 803 dogfood files with a counted fix, against a 150-token budget. The approximation caveat on top_symbols lives in the tool docstring rather than repeating on every row.
|
✅ Health: 7.5 (unchanged) 📋 At a glance 📌 Before you merge
🗺️ Change map flowchart LR
subgraph PR ["Changed in this PR (3 with dependents)"]
f_packages_server_src_repowise_server_mcp_server_tool_change_risk_py[".../mcp_server/tool_change_risk.py 🔥"]:::changed
f_packages_server_src_repowise_server_mcp_server_tool_risk_assessment_py[".../tool_risk/assessment.py 🔥"]:::changed
f_packages_server_src_repowise_server_mcp_server_tool_risk_get_risk_py[".../tool_risk/get_risk.py 🔥"]:::changed
end
f_packages_server_src_repowise_server_mcp_server___init___py[".../mcp_server/__init__.py"]
f_packages_server_src_repowise_server_mcp_server_tool_change_risk_py --> f_packages_server_src_repowise_server_mcp_server___init___py
f_packages_server_src_repowise_server_mcp_server_tool_risk___init___py[".../tool_risk/__init__.py"]
f_packages_server_src_repowise_server_mcp_server_tool_risk_assessment_py --> f_packages_server_src_repowise_server_mcp_server_tool_risk___init___py
f_packages_server_src_repowise_server_mcp_server_tool_risk_get_risk_py --> f_packages_server_src_repowise_server_mcp_server___init___py
f_packages_server_src_repowise_server_mcp_server_tool_risk_get_risk_py --> f_packages_server_src_repowise_server_mcp_server_tool_risk___init___py
t_tests_unit_server_mcp_test_change_risk_py(["✅ .../mcp/test_change_risk.py"]):::guard
t_tests_unit_server_mcp_test_change_risk_py -.-> f_packages_server_src_repowise_server_mcp_server_tool_change_risk_py
classDef changed fill:#dbeafe,stroke:#1d4ed8,color:#1e3a5f
classDef warn fill:#fef3c7,stroke:#b45309,color:#78350f
classDef guard fill:#dcfce7,stroke:#15803d,color:#14532d
Solid arrows: code that imports the changed files (2 direct dependents, from the last indexed snapshot). Dashed: history/tests. 🚨 Change risk: high (riskier than 68% of this repo's commits)
🩹 Review priority (files here with the most recent bug-fix history — defects cluster, so review these first)
🔎 More signals (1)🔥 Hotspots touched (3)
📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-20 05:25 UTC |
swati510
approved these changes
Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The fix-event data layer has been computed and stored since #939/#940, and until now nothing read it. This is the agent-facing half.
get_risk:
defect_profilePer file, when it has counted fixes: how many landed in the trailing 6 months, how long ago the last one was, a
bug_magnetflag for sustained recent pressure, and the top symbols the fixes clustered in. Built from theGitMetadatarow_assess_one_targetalready loads, so no second query.get_change_risk:
prior_fixesPer changed file: how many past bug-fix commits touched it, and how many of the change's lines fall inside the ranges one of those fixes replaced.
changed_linesis now read once and shared withimpacted_testsrather than shelling out to git twice.Neither block names a commit
File-level SZZ measured 74.5% precision against the frozen judgments. That is enough to count fixes honestly and not enough to accuse one commit of causing them. Both blocks are aggregate, and both are absent entirely on a repo with no fix history, so nothing grows a noise block.
Behaviour change worth flagging in review
risk_type="bug-prone"now reads counted fix history instead of scanning commit subjects forfix|bug|patch|.... The old regex matched doc and test commits, had no recency at all, and disagreed with the count every other surface shows.Because
bug-pronereturns before the other classifications, this reclassifies some files: one with 3 fixes across 200 commits now readsbug-pronewhere it readchurn-heavy, and a sole-maintainer hotspot with 3 fixes stops readingbus-factor-risk. That is the intended direction, but it is a silent change to existing output.Token budget
Measured over all 803 dogfood files with a counted fix: mean 46 tokens, max 80, against a 150-token ceiling. The measurement changed the design once. The first draft carried an
approximate, symbol spans are current-treestring on every row, ~13 tokens per target of identical text. That caveat now lives in the tool docstring, and the fuller explanation indocs/MCP_TOOLS.md.Tests
test_defect_profile.pyandtest_prior_fixes.py. Both blocks are asserted silent without fix data. Theprior_fixestest seeds events across two files and asserts aggregation, overlap ranking, most-recent-wins age, and thecode_fixshape filter.Pre-merge review caught three things fixed here:
total_fixescounted rows rather than distinct commits (one commit touching three changed files reported "3 fixes"),bug_magnetcould render without the age that anchors it, and_overlap_counthad anint()outside its guard.