Skip to content

fix(hud): session self-heal & stale state detection (Wave 1-B)#1469

Closed
JeremyDev87 wants to merge 2 commits into
feat/statusbar-wow-refactorfrom
feat/statusbar-wow-session
Closed

fix(hud): session self-heal & stale state detection (Wave 1-B)#1469
JeremyDev87 wants to merge 2 commits into
feat/statusbar-wow-refactorfrom
feat/statusbar-wow-session

Conversation

@JeremyDev87
Copy link
Copy Markdown
Owner

Closes #1468
Stacked on #1465 (Wave 0 refactor — must merge first)

Summary

Fixes the status bar "PLAN shown as ACT" bug by introducing a 4-signal staleness check and soft-reset healing that runs on every statusLine render.

Root Cause

hud-state.json is written at session-start and never invalidated. Real-world incident: the hud-state.json showed sessionId: \"manual-fix\", sessionStartTimestamp: 2026-03-29 (12 days old), currentMode: \"PLAN\", version: \"5.2.0\" — but the actual current session was on 2026-04-11 with plugin v5.5.0.

Design

New lib/hud_session.py module (replaces Wave 0 skeleton):

Function Purpose
detect_stale_session(state, *, now=None, stdin_session_id=\"\") Return True if state should be healed. 4 signals: (1) empty → False, (2) sessionId in {"", "manual-fix", "unknown", "none"}, (3) stdin_session_id mismatch, (4) timestamp > SESSION_STALE_SECONDS (4h) or unparseable
heal_stale_state(state) -> dict Return copy with cleared ephemeral fields. Preserves sessionId + sessionStartTimestamp. Does NOT mutate input. Does NOT write disk.
reset_stale_session(state_file) Durable variant: read, detect, heal, persist via hud_state.update_hud_state. Silent on all errors.
SESSION_STALE_SECONDS = 14400 Module constant (4h).

Integration

codingbuddy-hud.py::main() now calls:

```python
hud_state = read_state(state_file)
try:
from hud_session import detect_stale_session, heal_stale_state
stdin_session_id = (stdin_data.get("session_id") if stdin_data else "") or ""
if detect_stale_session(hud_state, stdin_session_id=stdin_session_id):
hud_state = heal_stale_state(hud_state)
except Exception:
pass # never block rendering on self-heal failure
```

Defensive try/except ensures a buggy self-heal never crashes the statusLine.

Tests

24 new tests in test_hud_session.py:

detect_stale_session (15 tests):

  • empty state / None state
  • 4 repair markers (manual-fix, "", unknown, none)
  • stdin mismatch / stdin match / empty stdin
  • old timestamp / recent timestamp / unparseable / naive tz
  • clock override for deterministic age check
  • repair marker beats fresh timestamp

heal_stale_state (5 tests):

  • clear semantics (6 ephemeral fields)
  • preserve semantics (sessionId, timestamp)
  • non-mutation of input
  • unknown field preservation
  • empty state healing

reset_stale_session (4 tests):

  • fresh state noop
  • repair marker healed persistently
  • missing file silent
  • malformed file silent

Test Results

179/179 tests pass (Golden Rule 133 + Wave 0 22 + Wave 1-B 24)

Backwards Compatibility

  • No public API changes to codingbuddy-hud.py
  • main() enhancement is defensive (try/except)
  • Existing callers unaffected

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
codingbuddy-landing Ready Ready Preview, Comment Apr 11, 2026 1:22pm

Resolves the bug where statusLine renders leftover fields from a
prior session (e.g. sessionId="manual-fix", currentMode="ACT" when
user is in PLAN mode) instead of the current state.

New lib/hud_session.py module:
- detect_stale_session(): 4-signal staleness check
  (empty / repair marker / stdin mismatch / age > 4h)
- heal_stale_state(): soft reset, returns copy, doesn't write disk
- reset_stale_session(): durable variant for session-start boot
- SESSION_STALE_SECONDS constant (4 hours)

codingbuddy-hud.py::main() heals state before rendering so every
statusLine render sees a valid snapshot.

24 new tests in test_hud_session.py cover all 4 staleness signals,
heal semantics (clear / preserve / non-mutation / empty state),
and reset_stale_session edge cases (fresh noop, marker healed,
missing file silent, malformed silent).

179/179 tests pass (Golden Rule 133 + Wave 0 22 + Wave 1-B 24).

Closes #1468
Part of #1464 (Wave 0 statusbar refactor)
Combined Wave 0 polish items from the #1465/#1485 review cycle:

1. Narrow `except Exception` to `except ImportError` in the 3 lib
   fallback import blocks (qual-1465 HIGH-1). Real logic bugs
   (SyntaxError, NameError, AttributeError) inside lib modules now
   surface immediately instead of being silently swallowed by a
   catch-all.

2. Drop inline stub functions for format_rate_limits and
   _get_fresh_version (qual-1465 HIGH-2). Eliminates the signature
   drift between canonical lib definitions and in-file fallback stubs
   observed on the integrator branch (Wave 1-A plugin_json_file
   kwarg drift). The outer main() try/except still catches any runtime
   failure and emits the minimal safe output via the BUDDY_FACE
   constant.

3. Hoist hud_velocity and hud_cache_savings imports to module top as
   _format_velocity_segment and _format_cache_savings (perf-1485 H1).
   Eliminates ~0.47us sys.modules lookup per render. Integrator branch
   only - no-op on refactor/wave branches where the inline imports
   don't exist yet.

4. Bump next to 16.2.3 for GHSA-q4gf-8mx6-v5v3 (landing-security-check).
   Aligns eslint-config-next and updates setup.test.ts assertion.

Refs: qual-1465 HIGH-1/2, perf-1485 H1,
GHSA-q4gf-8mx6-v5v3
@JeremyDev87 JeremyDev87 force-pushed the feat/statusbar-wow-session branch from bd8346d to c7eb3b9 Compare April 11, 2026 13:11
@JeremyDev87 JeremyDev87 added statusbar-wave:1 Statusbar Wow bug fixes (Wave 1-A~1-D) fix review:approved EVAL review 통과 (Critical/High = 0) labels Apr 11, 2026
@JeremyDev87
Copy link
Copy Markdown
Owner Author

Superseded by #1485

This PR was part of a stacked PR structure (feat/statusbar-wow-refactor base) that was incompatible with the repo's rebase & merge policy — each sub-PR targeted an intermediate branch, not master.

All of this PR's commits have been consolidated into #1485 (now with base: master and a linear 12-commit history after rebase). The consolidated PR contains:

  • Wave 0 — de622cc refactor(hud): extract 9 modules
  • Wave 1-A — cdf0772 fix(hud): version resolution fallback
  • Wave 1-B — 0606698 fix(hud): session self-heal
  • Wave 1-C — 87b779a feat(hud): rate limit severity icons
  • Wave 1-D — 894f515 feat(hud): adaptive layout engine
  • Wave 2-A — 5e8389d feat(hud): breathing buddy face states
  • Wave 2-B — 78ec6c5 feat(hud): cost velocity indicator
  • Wave 2-C — a306920 feat(hud): cache savings badge
  • Wave 2-D — 0fb3d5c feat(hud): mode rainbow ANSI coloring
  • Wave 2-E — 8cd78b2 feat(hud): smart context bar
  • Wave 3 — 295f5c4 feat(hud): integrate Wave 2-B/2-C
  • Review iter1 — b330528 fix(hud,landing): narrow fallback imports + next 16.2.3

EVAL review results from this PR (all reviewers, iter1 converged → Critical=0, High=0) already applied in #1485.

Closing as superseded. Use #1485 with GitHub's Rebase and merge button to land all 12 commits linearly on master.

@JeremyDev87 JeremyDev87 deleted the feat/statusbar-wow-session branch April 11, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:hud HUD / statusLine 영역 fix plugin packages/claude-code-plugin review:approved EVAL review 통과 (Critical/High = 0) statusbar-wave:1 Statusbar Wow bug fixes (Wave 1-A~1-D)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant