fix(mcp): rank get_risk's attention list and get_context's triage on fix history#956
Merged
Merged
Conversation
…fix history get_risk classified a target "bug-prone" from counted fixes, then showed an attention list beside it ranked purely on churn, so the two halves of one response disagreed about what deserves attention. get_context's triage card had the churn bit alone and no defect signal at all. global_hotspots now admits bug magnets rather than filtering on is_hotspot, and orders by fix history before churn. The filter matters as much as the order: is_hotspot-only means a file fixed four times last month that is not busy can never appear, so no amount of re-sorting inside the churn set would reach it. Churn stays the fallback, and rows are annotated with the fix count and age only when there is fix history. These are full ORM rows, so no query is added. risk_summary leads with the fix history when a file has any, so the first thing read agrees with the risk_type printed on the same line. Files with no fixes keep the summary they had. get_context gains a fix_history triage pointer (count, age, magnet flag) from the same single row, widened from one column to four. Omitted entirely on files with no counted fixes, so a repo without fix history pays nothing. The recency contract now lives in one place: fix_annotation never emits the bug_magnet flag without an age to anchor it, and _defect_profile is built on it rather than repeating the rule. Cost: ~73 tokens worst case per get_risk response with all five rows carrying fix data, ~19 per get_context file target, zero without fix history.
|
✅ Health: 7.5 (unchanged) 📋 At a glance Files & modules (2)
📌 Before you merge
🗺️ Change map flowchart LR
subgraph PR ["Changed in this PR (5 with dependents)"]
f_packages_server_src_repowise_server_mcp_server_tool_context_context_py[".../tool_context/context.py 🔥"]:::changed
f_packages_server_src_repowise_server_mcp_server_tool_context_targets_py[".../tool_context/targets.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
f_tests_unit_server_mcp_test_defect_profile_py[".../mcp/test_defect_profile.py"]:::changed
end
f_packages_server_src_repowise_server_mcp_server_tool_context___init___py[".../tool_context/__init__.py"]
f_packages_server_src_repowise_server_mcp_server_tool_context_context_py --> f_packages_server_src_repowise_server_mcp_server_tool_context___init___py
f_packages_server_src_repowise_server_mcp_server_tool_symbol_py[".../mcp_server/tool_symbol.py"]
f_packages_server_src_repowise_server_mcp_server_tool_context_targets_py --> f_packages_server_src_repowise_server_mcp_server_tool_symbol_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___init___py[".../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___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_conftest_py(["✅ .../mcp/conftest.py"]):::guard
t_tests_unit_server_mcp_conftest_py -.-> f_tests_unit_server_mcp_test_defect_profile_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 (4 direct dependents, from the last indexed snapshot). Dashed: history/tests.
🩹 Review priority (files here with the most recent bug-fix history — defects cluster, so review these first)
🔎 More signals (1)🔥 Hotspots touched (5)
2 more
📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-20 08:40 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.
get_riskclassified a targetbug-pronefrom counted bug fixes, then showed an attention list beside it ranked purely on churn, so the two halves of one response disagreed about what deserves attention.get_context's triage card carried the churn bit alone and no defect signal at all.global_hotspots
Admits bug magnets instead of filtering on
is_hotspot, and orders by fix history before churn. The filter matters as much as the order:is_hotspot-only means a file fixed four times last month that simply is not busy can never appear, so no amount of re-sorting inside the churn set would reach it.Churn stays the fallback, so a repo whose commit messages carry no fix convention keeps exactly the list it had. Rows gain a fix count, an age and the magnet flag only when there is fix history. These were already full ORM rows, so the fix columns were in memory and no query is added.
risk_summary
Leads with the fix history when a file has any, so the first thing read agrees with the
risk_typeprinted later on the same line:Files with no counted fixes keep the summary they already had, byte for byte.
get_context triage
Gains a
fix_historypointer (count, age, magnet flag) from the same single row, widened from one selected column to four. Omitted entirely on files with no counted fixes, so a repo without fix history pays nothing for it. The full dossier stays inget_risk: no symbols, no findings, just the cue to call it.One place owns the recency rule
fix_annotationis now the single function that refuses to emitbug_magnetwithout an age to anchor it, and_defect_profileis built on it rather than restating the rule. A magnet claim with no timestamp would describe a file fixed four times last month and one fixed four times two years ago identically.hotspot_scoredeliberately still means churn. Blending fix mass into it would invent a composite metric nobody has calibrated; the honest fix is that the summary leads with defect evidence while the field keeps its accurate name.Cost
Measured on the added keys: about 73 tokens worst case per
get_riskresponse with all five rows carrying fix data, 19 perget_contextfile target, 11 for the summary clause, and zero without fix history. Tool docstrings stay inside the schema budget.Testing
1094 server tests and 573 MCP tests pass. Seven new tests cover the magnet union, fix-first ordering, the summary clause, the triage block, and silence on repos without fix data; the four behavioural ones were confirmed to fail against the previous code rather than pass vacuously.
Note: this branch was cut before #955, so CI here will also show the pre-existing
get_change_riskdocstring-budget failure until that lands. It is unrelated to this change.