Skip to content

feat(health): show per-file bug-fix history in the drawer, panel and hover - #948

Merged
RaghavChamadiya merged 1 commit into
mainfrom
feat/health-bug-history-ui
Jul 20, 2026
Merged

feat(health): show per-file bug-fix history in the drawer, panel and hover#948
RaghavChamadiya merged 1 commit into
mainfrom
feat/health-bug-history-ui

Conversation

@RaghavChamadiya

Copy link
Copy Markdown
Member

The fix-event rollup has been computed and stored since #940, and the FileSignals contract has carried bug_magnet / last_fix_at / fix_symbol_counts since then too. Nothing rendered any of it. Three surfaces now do.

  • FileSignalsPanel bug-fix tile gains a "Bug magnet" badge and folds the last-fix age into its caption.
  • Health file drawer gains a collapsed "Bug history" section listing which symbols the fixes landed in, with the last-fix age on the toggle so "is this still happening?" is answered without expanding. Reuses the shared CollapsibleSection rather than the drawer-local group component.
  • VS Code file hover gains one line off the same contract. No new API: packages/vscode already pulls @repowise-dev/types, so the contract reached it for free.

The magnet badge never renders alone

types/health.ts states it plainly: bug_magnet is a recency claim, so any copy showing it must show last_fix_at too. Unanchored, the badge would describe a file fixed four times last month and one fixed four times two years ago identically. All three surfaces now drop the flag rather than show it bare.

Pre-merge review caught that all three were getting this wrong, and that no test covered the null-timestamp path. There is one now.

A real serialization bug, fixed upstream

SQLite's DATETIME bind processor drops tzinfo, so last_fix_at reads back naive even though the rollup writes it aware-UTC, and .isoformat() on a naive datetime produces a string with no offset. Per the ES spec, JS parses that as local time.

Concretely, for a viewer at UTC-8: a fix committed two hours ago is stored T-2h UTC, read as T-2h local, which is T+6h absolute. formatRelativeTimeOrNull's future-guard catches it and returns the empty fallback, so the age disappears from the caption, the drawer hint and the hover, and with the guard above the magnet badge disappears with it. Worst for the newest fixes, which are exactly the ones worth showing. East of UTC the age is simply wrong by the offset.

Fixed once in signals.iso_utc (renamed from _iso now that a second module reads it) rather than patching four consumers, with a regression test.

Hedging

Per-symbol counts are labelled approximate wherever shown: fixes are matched to symbols by line range against current-tree spans, so the mapping is a best effort on any file that has moved since. Nothing here names an inducing commit.

Tests

npm run type-check clean, UI health suites 42 passed, Python health suite 989 passed, all in isolation on this branch.

…hover

The fix-event rollup has been computed and stored since #940 but nothing
rendered it. Three surfaces now do:

- FileSignalsPanel's bug-fix tile gains a "Bug magnet" badge and folds the
  last-fix age into its caption.
- The health file drawer gains a collapsed "Bug history" section listing which
  symbols the fixes landed in, with the last-fix age on the toggle so the
  "is this still happening?" question is answered without expanding.
- The VS Code file hover gains one line off the same contract, no new API.

The magnet badge never renders without the last-fix age beside it. It is a
claim about recent fix pressure, so unanchored it would describe a file fixed
four times last month and one fixed four times two years ago identically. All
three surfaces drop the flag rather than show it bare, and the per-symbol
counts are labelled approximate because fixes are matched to symbols by line
range and lines move.

Also fixes a real serialization bug behind all of this. SQLite's DATETIME bind
processor drops tzinfo, so last_fix_at read back naive and isoformat() produced
a string with no offset. JS parses that as local time, so west of UTC a fix
committed two hours ago landed in the future, tripped formatRelativeTimeOrNull's
future-guard, and the age silently vanished from copy required to carry it,
worst for the freshest fixes. Fixed once in signals.iso_utc rather than in each
consumer.
@repowise-bot

repowise-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

✅ Health: 7.5 (unchanged)

📋 At a glance
1 file changed health · 5 hotspots touched · 1 new finding introduced · 5 files with recent fix history.

Files & modules (2)
  • packages (4 files)
    • .../health/file-signals-panel.test.tsx
    • .../health/health-file-drawer.tsx
    • .../health/health-file-drawer.test.tsx
    • .../health/signals.py
  • tests (1 file)
    • .../health/test_signals.py

📌 Before you merge

  • Run .../server/test_health_badge.py: they depend on the changed files
  • Docs that usually track this code: docs/CODE_HEALTH.md

🗺️ Change map

flowchart LR
  subgraph PR ["Changed in this PR (4 with dependents)"]
    f_packages_core_src_repowise_core_analysis_health_signals_py[".../health/signals.py 🔥"]:::changed
    f_packages_ui_src_health_health_file_drawer_tsx[".../health/health-file-drawer.tsx 🔥"]:::changed
    f_packages_ui_src_health_file_signals_panel_tsx[".../health/file-signals-panel.tsx"]:::changed
    f_packages_vscode_src_features_hovers_ts[".../features/hovers.ts"]:::changed
  end
  f_packages_server_src_repowise_server_mcp_server_tool_context_enrichment_py[".../tool_context/enrichment.py"]
  f_packages_core_src_repowise_core_analysis_health_signals_py --> f_packages_server_src_repowise_server_mcp_server_tool_context_enrichment_py
  f_packages_server_src_repowise_server_mcp_server_tool_health_py[".../mcp_server/tool_health.py"]
  f_packages_core_src_repowise_core_analysis_health_signals_py --> f_packages_server_src_repowise_server_mcp_server_tool_health_py
  f_packages_server_src_repowise_server_routers_code_health_loaders_py[".../code_health/loaders.py"]
  f_packages_core_src_repowise_core_analysis_health_signals_py --> f_packages_server_src_repowise_server_routers_code_health_loaders_py
  f_packages_server_src_repowise_server_routers_code_health_serializers_py[".../code_health/serializers.py"]
  f_packages_core_src_repowise_core_analysis_health_signals_py --> f_packages_server_src_repowise_server_routers_code_health_serializers_py
  f_packages_ui_src_health_health_file_drawer_tsx --> f_packages_server_src_repowise_server_mcp_server_tool_health_py
  f_packages_types_src_files_ts[".../src/files.ts"]
  f_packages_ui_src_health_health_file_drawer_tsx --> f_packages_types_src_files_ts
  f_packages_ui_src_files_file_health_tab_tsx[".../files/file-health-tab.tsx"]
  f_packages_ui_src_health_health_file_drawer_tsx --> f_packages_ui_src_files_file_health_tab_tsx
  f_packages_ui_src_health_biomarker_list_tsx[".../health/biomarker-list.tsx"]
  f_packages_ui_src_health_health_file_drawer_tsx --> f_packages_ui_src_health_biomarker_list_tsx
  f_packages_ui_src_health_file_signals_panel_tsx --> f_packages_ui_src_files_file_health_tab_tsx
  f_packages_ui_src_health_index_ts[".../health/index.ts"]
  f_packages_ui_src_health_file_signals_panel_tsx --> f_packages_ui_src_health_index_ts
  f_packages_vscode_src_extension_ts[".../src/extension.ts"]
  f_packages_vscode_src_features_hovers_ts --> f_packages_vscode_src_extension_ts
  more(["+1 more dependent"])
  PR --> more
  t_tests_unit_server_test_health_badge_py(["✅ .../server/test_health_badge.py"]):::guard
  t_tests_unit_server_test_health_badge_py -.-> f_packages_core_src_repowise_core_analysis_health_signals_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 (10 direct dependents, from the last indexed snapshot). Dashed: history/tests.

⚠️ Change risk: moderate (riskier than 52% 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)

File Score Δ Why
.../health/file-signals-panel.test.tsx 9.3 → 8.6 ▼ -0.7 🔻 introduced duplicated assertion block
🔎 More signals (1)

🔥 Hotspots touched (5)

  • .../health/health-file-drawer.tsx — 10 commits/90d, 6 dependents · primary owner: Swati Ahuja (59%)
  • .../health/test_signals.py — 2 commits/90d, 0 dependents
  • .../health/health-file-drawer.test.tsx — 2 commits/90d, 0 dependents · primary owner: Swati Ahuja (100%)
2 more
  • .../health/file-signals-panel.test.tsx — 2 commits/90d, 0 dependents
  • .../health/signals.py — 2 commits/90d, 7 dependents

📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-20 05:26 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 967dc2d into main Jul 20, 2026
7 checks passed
@RaghavChamadiya
RaghavChamadiya deleted the feat/health-bug-history-ui branch July 20, 2026 05:29
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