feat(tui): catch the dashboard up to the schema #33

Merged
alee merged 4 commits from feat/tui-overhaul into main 2026-09-05 15:36:21 +00:00

4 Commits

Author SHA1 Message Date
adlee-was-taken
4c8e1abd59 test(tui): pin all /metrics warning classes render in the panel
The 2026-09-04 vision-ceiling incident was invisible for ~19 hours because
a whole warning family was computed correctly and never displayed. The fix
there was surfacing, not computing -- so the guard has to be a test that
fails when a class exists but nothing renders it.

Two directions, both load-bearing. Every REGISTERED class must fire against
a fixture that provokes all ten, catching the fixture rotting or a message
shape drifting under a matcher. And every EMITTED warning must be
registered, catching a new class added to scoring_coverage that nothing
displays -- this one fails with the RAW warning text, because the whole
point is that nobody knew the class existed.

No assertions on warning count: the numbers move as fixture semantics
evolve, and what matters is class coverage, not arity.

Three fixes to the fixture the plan specified, found by running it:
proficiency.last_updated is NOT NULL; a seed_reference row is identified by
task_category rather than a `kind` column that does not exist; and
scoring_coverage reads `.value` off default_flex_preference, which is an
enum in real config, so a bare string is not a faithful stand-in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
2026-09-05 02:24:14 -04:00
adlee-was-taken
a9bfad00de feat(tui): quota panel leads with balance and runway
The panel led with a progress bar against plan_kwh, which is misleading:
usage routinely exceeds 100% and nothing fails, because overage bills
against a credit balance. PR #30 made balance, burn rate and runway
available on /metrics; this surfaces them.

Balance and runway now lead, in a bold #quota-lead line, with the plan
percentage bar demoted below. Wired outside the plan-configured gate on
purpose -- the credit balance is meaningful whether or not a kWh plan is
set, and it is the figure that actually stops traffic.

burn and runway are legitimately None when the sample segment is too short
to extrapolate, which is PR #30's guard against a wild rate right after a
top-up. On the live deployment that is the CURRENT state, so it is the
first thing an operator sees rather than an edge case. The lead renders
"burn n/a" and #quota-note carries runway_note verbatim -- never blank,
never a bare 0, never the literal None. Tests assert all three.

Formatting is 2dp rather than _fmt_usd's 6: money an operator acts on, not
per-request micro-money.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
2026-09-05 02:19:40 -04:00
adlee-was-taken
bc3c7f4be8 feat(tui): decision table time and profile columns, exploration flag
The decision feed had no timestamp at all and the eight columns predated
five schema additions. Adds `time` first (short HH:MM:SS local -- the date
is almost always today and would crowd out `selected`, the column operators
actually read) and `profile` after `ctx`, since a decision cannot be read
without knowing which profile filtered the candidate set.

`flex` becomes `flags` and now composes the flex label with an `E` marker
for epsilon-greedy picks. One cell rather than two columns: the terminal is
not wide, and an exploratory pick must be visually distinguishable or an
operator reads a deliberate random sample as the router's judgement.

`profile` renders `or ""` so an absent value is blank rather than the
literal "None", which in a dense table reads as a real profile name.

Placeholder row widened to arity 10 -- a short placeholder raises inside
Textual at render time rather than looking wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
2026-09-05 02:17:01 -04:00
adlee-was-taken
537eb5ac87 feat(tui): surface six drifted route_decisions columns behind a schema drift test 2026-09-05 02:09:34 -04:00