Skip to content

Commit b1c8dfd

Browse files
committed
feat(hud): integrate Wave 2-B/2-C in format_status_line (Wave 3)
Wave 3 integrator: - Merged all 9 parallel Wave sub-branches (Wave 0 + 1-A/B/C/D + 2-A/B/C/D/E) - Added Wave 2-B velocity suffix + Wave 2-C cache savings suffix to cost segment - 5 integration tests lock the Wave 3 assembly Cost segment output examples: "$1.23" (plain, no data) "$1.23↗$0.08/m" (velocity only) "$1.23💰$4.56 saved" (savings only) "$1.23↗$0.08/m💰$4.56 saved" (both) Defensive try/except imports ensure format_status_line still works when the optional modules are temporarily broken. Follow-up Wave 2 modules merged but not yet wired into format_status_line: - Wave 2-A: hud_buddy dynamic face per phase - Wave 2-D: hud_rainbow mode label coloring - Wave 2-E: hud_context_bar visual bar - Wave 1-D: hud_layout fit_segments adaptive truncation 381/381 tests pass (9 Wave-level test suites + Wave 3 integration). Closes the Wave 3 task. Part of #1464 (Wave 0 statusbar refactor effort).
1 parent faccfde commit b1c8dfd

2 files changed

Lines changed: 112 additions & 1 deletion

File tree

packages/claude-code-plugin/hooks/codingbuddy-hud.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,30 @@ def format_status_line(
458458

459459
cost_prefix = "$" if is_exact else "~$"
460460

461+
# Wave 3 integration: append optional Wave 2-B velocity and
462+
# Wave 2-C cache-savings suffixes to the cost segment. Both
463+
# helpers return empty string when they have nothing to show,
464+
# so the downstream segment renders unchanged in the common case.
465+
velocity_suffix = ""
466+
savings_suffix = ""
467+
try:
468+
from hud_velocity import format_velocity_segment
469+
velocity_suffix = format_velocity_segment(stdin_data, hud_state) or ""
470+
except Exception: # pragma: no cover - defensive
471+
pass
472+
try:
473+
from hud_cache_savings import format_cache_savings
474+
savings_suffix = format_cache_savings(stdin_data) or ""
475+
except Exception: # pragma: no cover - defensive
476+
pass
477+
461478
ver_str = f" v{version}" if version else ""
462479

463480
segments = [
464481
f"{BUDDY_FACE} CB{ver_str}",
465482
f"{mode_label} {health}",
466483
duration,
467-
f"{cost_prefix}{cost:.2f}",
484+
f"{cost_prefix}{cost:.2f}{velocity_suffix}{savings_suffix}",
468485
]
469486
if cache_segment:
470487
segments.append(cache_segment)

packages/claude-code-plugin/tests/test_hud.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,3 +743,97 @@ def test_empty_stdin_fallback(self):
743743
)
744744
assert result.returncode == 0
745745
assert "\u25d5\u203f\u25d5" in result.stdout
746+
747+
748+
# ========================= Wave 3 Integration Tests ========================
749+
750+
751+
class TestWave3Integration:
752+
"""End-to-end integration regression for Wave 2-B/2-C cost suffixes."""
753+
754+
_NO_PLUGINS = "/tmp/_nonexistent_plugins_wave3.json"
755+
756+
def test_velocity_suffix_present_when_cost_and_duration_available(self):
757+
"""Wave 2-B velocity suffix appears after the cost segment."""
758+
stdin = {
759+
"cost": {"total_cost_usd": 1.0, "total_duration_ms": 60_000},
760+
"model": {"id": "claude-sonnet", "display_name": "Sonnet"},
761+
"context_window": {"used_percentage": 5},
762+
}
763+
state = {
764+
"version": "5.5.0",
765+
"sessionStartTimestamp": datetime.now(timezone.utc).isoformat(),
766+
"currentMode": "PLAN",
767+
}
768+
result = hud.format_status_line(
769+
stdin, state, plugins_file=self._NO_PLUGINS
770+
)
771+
# $1.00 over 60s → $1.00/m (hot burn tier)
772+
assert "$1.00" in result
773+
assert "/m" in result
774+
775+
def test_savings_suffix_present_when_cache_reads_exist(self):
776+
"""Wave 2-C cache savings suffix appears after the cost segment."""
777+
stdin = {
778+
"cost": {"total_cost_usd": 1.0, "total_duration_ms": 60_000},
779+
"model": {"id": "claude-opus"},
780+
"context_window": {
781+
"used_percentage": 50,
782+
"current_usage": {
783+
"input_tokens": 1000,
784+
"cache_creation_input_tokens": 0,
785+
"cache_read_input_tokens": 1_000_000,
786+
},
787+
},
788+
}
789+
state = {
790+
"version": "5.5.0",
791+
"sessionStartTimestamp": datetime.now(timezone.utc).isoformat(),
792+
"currentMode": "PLAN",
793+
}
794+
result = hud.format_status_line(
795+
stdin, state, plugins_file=self._NO_PLUGINS
796+
)
797+
# 1M cache_read on opus → $13.50 saved
798+
assert "saved" in result
799+
assert "\U0001f4b0" in result # 💰
800+
801+
def test_no_velocity_when_cost_missing(self):
802+
"""Velocity suffix is omitted when the cost payload is absent."""
803+
stdin = {"context_window": {"used_percentage": 5}}
804+
state = {"version": "5.5.0", "currentMode": "PLAN"}
805+
result = hud.format_status_line(
806+
stdin, state, plugins_file=self._NO_PLUGINS
807+
)
808+
assert "/m" not in result
809+
810+
def test_no_savings_when_cache_reads_zero(self):
811+
"""Savings suffix is omitted when there are no cache reads."""
812+
stdin = {
813+
"cost": {"total_cost_usd": 1.0, "total_duration_ms": 60_000},
814+
"context_window": {
815+
"used_percentage": 5,
816+
"current_usage": {
817+
"input_tokens": 1000,
818+
"cache_creation_input_tokens": 0,
819+
"cache_read_input_tokens": 0,
820+
},
821+
},
822+
}
823+
state = {"version": "5.5.0", "currentMode": "PLAN"}
824+
result = hud.format_status_line(
825+
stdin, state, plugins_file=self._NO_PLUGINS
826+
)
827+
assert "saved" not in result
828+
829+
def test_all_wave_modules_importable(self):
830+
"""Sanity: every Wave 2 module is importable through lib/."""
831+
import hud_buddy # noqa: F401
832+
import hud_velocity # noqa: F401
833+
import hud_cache_savings # noqa: F401
834+
import hud_rainbow # noqa: F401
835+
import hud_context_bar # noqa: F401
836+
import hud_layout # noqa: F401
837+
import hud_session # noqa: F401
838+
import hud_version # noqa: F401
839+
import hud_rate_limits # noqa: F401

0 commit comments

Comments
 (0)