Skip to content

fix(mcp): rank get_risk's attention list and get_context's triage on fix history#956

Merged
RaghavChamadiya merged 1 commit into
mainfrom
fix/risk-context-fix-history
Jul 20, 2026
Merged

fix(mcp): rank get_risk's attention list and get_context's triage on fix history#956
RaghavChamadiya merged 1 commit into
mainfrom
fix/risk-context-fix-history

Conversation

@RaghavChamadiya

Copy link
Copy Markdown
Member

get_risk classified a target bug-prone from 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_type printed later on the same line:

src/pipeline.py — 5 bug fixes in 6mo, last 14d ago (bug magnet), hotspot score 92% (stable), 12 dependents, bug-prone, ...

Files with no counted fixes keep the summary they already had, byte for byte.

get_context triage

Gains a fix_history pointer (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 in get_risk: no symbols, no findings, just the cue to call it.

One place owns the recency rule

fix_annotation is now the single function that refuses to emit bug_magnet without an age to anchor it, and _defect_profile is 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_score deliberately 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_risk response with all five rows carrying fix data, 19 per get_context file 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_risk docstring-budget failure until that lands. It is unrelated to this change.

…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.
@repowise-bot

repowise-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

✅ Health: 7.5 (unchanged)

📋 At a glance
5 hotspots touched · 3 new findings introduced · 5 files with recent fix history.

Files & modules (2)
  • packages (4 files)
    • .../tool_risk/assessment.py
    • .../tool_risk/get_risk.py
    • .../tool_context/targets.py
    • .../tool_context/context.py
  • tests (1 file)
    • .../mcp/test_defect_profile.py

📌 Before you merge

  • Run .../mcp/conftest.py: they depend on the changed files

🗺️ 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
Loading

Solid arrows: code that imports the changed files (4 direct dependents, from the last indexed snapshot). Dashed: history/tests.

⚠️ Change risk: moderate (riskier than 55% of this repo's commits)
This change's risk is driven by:

  • more lines added than baseline
  • more scattered than baseline

🩹 Review priority (files here with the most recent bug-fix history — defects cluster, so review these first)

🔎 More signals (1)

🔥 Hotspots touched (5)

  • .../mcp/test_defect_profile.py — 1 commits/90d, 1 dependents
  • .../tool_risk/assessment.py — 3 commits/90d, 3 dependents
  • .../tool_risk/get_risk.py — 6 commits/90d, 2 dependents
2 more
  • .../tool_context/targets.py — 10 commits/90d, 2 dependents · primary owner: Swati Ahuja (80%)
  • .../tool_context/context.py — 8 commits/90d, 1 dependents · primary owner: Swati Ahuja (88%)

📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-20 08:40 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

@RaghavChamadiya
RaghavChamadiya merged commit faa8042 into main Jul 20, 2026
5 of 7 checks passed
@RaghavChamadiya
RaghavChamadiya deleted the fix/risk-context-fix-history branch July 20, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants