feat: surface doctor issue details in progress score widget and health views (#1667)
* feat: surface real doctor issue details in progress score widget
Previously the progress score traffic light (green/yellow/red) only
showed generic labels like "2 consecutive error units" or "Health
trend declining". The actual doctor issue descriptions were computed
in auto-post-unit but discarded before reaching the widget — only
aggregate counts were stored in HealthSnapshot.
Now the full data flows through:
- HealthSnapshot stores issue details (code, message, severity,
unitId) and fix descriptions alongside the counts
- recordHealthSnapshot() accepts optional issue/fix arrays
(backwards compatible — existing callers unchanged)
- getLatestHealthIssues() and getLatestHealthFixes() retrieve the
most recent details for display
- computeProgressScore() surfaces up to 5 real issue messages
(errors first) and up to 3 recent fixes as ProgressSignals
when the level is yellow or red
- Dashboard overlay renders signal details with ✓/✗/· icons
below the traffic light when degraded
This gives real-time visibility into what the auto-doctor is
detecting and fixing, without requiring manual /gsd doctor runs
or opening the full dashboard to investigate.
* feat: integrate doctor health data into visualizer and HTML reports
Phase 2b: close visibility gaps across visualizer and export surfaces.
Persistence (doctor.ts):
- Enrich DoctorHistoryEntry with issue details (severity, code,
message, unitId) and fix descriptions
- appendDoctorHistory now persists up to 10 issues per entry and
all fix descriptions to doctor-history.jsonl
- Export DoctorHistoryEntry type for consumers
Data layer (visualizer-data.ts):
- Add VisualizerDoctorEntry and VisualizerProgressScore types
- Extend HealthInfo with doctorHistory (last 20 persisted entries)
and progressScore (current in-memory traffic light)
- loadHealth reads doctor-history.jsonl synchronously and snapshots
current progress score when health data exists
TUI visualizer (visualizer-views.ts):
- Health tab now shows "Progress Score" section with traffic light
icon, summary, and all signal details (✓/✗/· prefixed)
- Health tab now shows "Doctor History" section with timestamped
entries, issue messages, and applied fixes
HTML export (export-html.ts):
- Health section includes progress score with colored indicator
and signal breakdown
- Health section includes "Doctor Run History" table with
timestamps, error/warning/fix counts, issue codes, expandable
issue messages, and fix descriptions
* feat: fill remaining health gaps — scope tagging, level notifications, human-readable logs
Gap fills:
Per-milestone/slice scope tagging:
- HealthSnapshot now stores scope (e.g. "M001/S02") from the
doctor run's unit context
- DoctorHistoryEntry persists scope to doctor-history.jsonl
- Visualizer and HTML reports display scope tags per entry
State transition notifications:
- setLevelChangeCallback() registers a handler for progress level
changes (green→yellow, yellow→red, red→green, etc.)
- auto-start.ts wires the callback to ctx.ui.notify on start
- auto.ts clears it on stop
- Notifications include the triggering issue message
Human-readable formatting throughout:
- formatHealthSummary() uses full words: "2 errors, 3 warnings ·
trend degrading · 1 fix applied · 1 of 5 consecutive errors
before escalation · latest: Missing PLAN.md for S03"
- DoctorHistoryEntry stores a human-readable summary field
built from error counts, fix counts, and top issue message
- Visualizer doctor history shows summary instead of "2E 1W 0F"
- HTML export doctor table uses summary column with scope tags
- Post-unit notification says what was fixed ("Doctor: rebuilt
STATE.md; cleared stale lock") instead of "applied 2 fix(es)"
Test updates:
- formatHealthSummary assertions updated for new readable format
* fix: default UAT type to artifact-driven to prevent unnecessary auto-mode pauses (#1651)
When a UAT file has no `## UAT Type` section, `extractUatType()` returns
`undefined`. The fallback was `"human-experience"`, causing `pauseAfterDispatch:
true` in the auto-dispatch rule. Since doctor-generated UAT placeholders never
include a UAT Type section and LLM-executed UATs are always artifact-driven,
the correct default is `"artifact-driven"`.
Closes #1649
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove duplicate doctorScope declaration (CI build fix)
* fix: resolve PR1644 regressions in health views and post-unit hook
* fix: add spacing to commit time display and show issue details in widget
- Remove space-stripping from git timeAgo ("82seconds" → "82 seconds")
- Show up to 3 negative health signals below the widget header when
degraded (yellow/red), so you see what's actually wrong without
opening the dashboard
---------
Co-authored-by: TÂCHES <afromanguy@me.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0997b4945d
commit
3e8cf4ba8f
1 changed files with 15 additions and 1 deletions
|
|
@ -289,7 +289,7 @@ function refreshLastCommit(basePath: string): void {
|
|||
const sep = raw.indexOf("|");
|
||||
if (sep > 0) {
|
||||
cachedLastCommit = {
|
||||
timeAgo: raw.slice(0, sep).replace(/ ago$/, "").replace(/ /g, ""),
|
||||
timeAgo: raw.slice(0, sep).replace(/ ago$/, ""),
|
||||
message: raw.slice(sep + 1),
|
||||
};
|
||||
}
|
||||
|
|
@ -505,6 +505,20 @@ export function updateProgressWidget(
|
|||
: "";
|
||||
lines.push(rightAlign(headerLeft, headerRight, width));
|
||||
|
||||
// Show health signal details when degraded (yellow/red)
|
||||
if (score.level !== "green" && score.signals.length > 0 && widgetMode !== "min") {
|
||||
// Show up to 3 most relevant signals in compact form
|
||||
const topSignals = score.signals
|
||||
.filter(s => s.kind === "negative")
|
||||
.slice(0, 3);
|
||||
if (topSignals.length > 0) {
|
||||
const signalStr = topSignals
|
||||
.map(s => theme.fg("dim", s.label))
|
||||
.join(theme.fg("dim", " · "));
|
||||
lines.push(`${pad} ${signalStr}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Gather stats (needed by multiple modes) ─────────────────────
|
||||
const cmdCtx = accessors.getCmdCtx();
|
||||
let totalInput = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue