The five UI items in TODO.md become an executable pipeline. Planning files only — no application code changed. - 01_severity_language: one Python threshold table + `severity` on the values the pages colour, plus the .hero style. Today the thresholds are magic numbers at six JS call sites (75/90 here, 80/92 there), which is exactly how "same colour, four meanings" happens. - 02_overview_fleet_and_alerts: /api/summary gains a derived `alerts` list; the page drops to fleet + warnings. Unconfigured sources must not alert — that is invariant 3, tested. - 03_system_per_host_panels: per-host hero cards, no per-core, shared multi-host charts and the detail picker deleted. The six card metrics already exist in the payload, so the first task pins them with tests instead of inventing fields. - 04_llm_chart_readability: charts.js already exports sparkline() and no page calls it — that is why the page reads flat. Port llm_monitor's drawSpark behaviour (fixed max, right growth, p95 foots) and keep the provenance tags. - 05_ups_hero_battery_glyph: charge/load/runtime hero + an SVG battery whose fill is the charge, verified against both real UPSes and the low-charge/on-battery states only the simulator can produce. PLAN.md records the ratified anchors and the deviation worth knowing: severity vocabulary is ok|warn|fail, matching dash.css and nut.py, not the "danger" wording in the proposal — one synonym for one colour. TODO.md cleared to a bare heading; the items are now phases. .gitignore stops ignoring all of .agents/ (the roadmap is project history) while keeping phase-sessions/ and pipeline.log out. deploy/nut-sudoers rewritten: its header still blamed a port mystery that is solved; the remaining need is reading upsd.users so adding a scoped dashboards user does not delete the accounts upsmon authenticates as. LLM-Generated: true
3.1 KiB
Phase 04 — LLM page is readable again
Source: TODO.md L6 — "LLM usage drifed from initial request to copy Experimental/llm_monitor. The charts got less useful. Need simplified and more readable."
Story: n/a
Context: .agents/PLAN.md → Anchors (hand-rolled SVG only), ~/Projects/Experimental/llm_monitor/static/index.html (the reference implementation), src/dashboards/web/static/page-llm.js (CELLS, makeCharts), src/dashboards/web/static/charts.js (sparkline, LineChart), src/dashboards/sources/llm.py
Objective
The LLM page drifted into a 14-cell grid where everything is the same size and nothing shows
recent shape. Bring back what made llm_monitor legible — big throughput numbers, a sparkline
in each metric cell, percentiles as foot lines — without losing what this project added since:
per-engine provenance tags, history windows, and severity colour.
llm_monitor is the design reference, not a dependency. It is a separate app on :8095 and
stays that way; nothing here imports from it.
Dependencies
01_severity_language(todo) — KV-cache pressure and queue depth get coloured from the API verdict, not a per-page threshold.03_system_per_host_panels(todo) — touchescharts.jsfirst; this phase builds on the same shared helpers and must not fight it for them.
Tasks
01_chart_set_decision.md— read both implementations side by side and write the decision note (which cells live, which get sparklines, what is demoted).02_sparkline_upgrade.md— bringDashCharts.sparkline()up tollm_monitor'sdrawSparkbehaviour: right-aligned growth, fixed max, current/max labels, severity colour.03_llm_layout_simplified.md— restructurellm.html+page-llm.js: hero throughput, compact sparkline cells, percentile foot lines, conditional alarm cells.04_side_by_side_verification.md— verify againstllm_monitoron:8095with the same live engines.
Testing & Quality
- Python: none expected beyond the phase-01 severity fields;
/api/llm/*stays as-is (additive-only anchor). uv run pytest -m live --livemust stay green —test_engine_still_publishes_the_series_we_parseis the assertion that the numbers on screen are backed by resolved upstream series.- Browser: both engines live (gufo on
deskwork:8731, vLLM ondriveripper:8000), plus the single-engine case: with one*_BASE_URLunset the page must show one clean half rather than a red panel. - Coverage: ≥94% overall maintained.
Completion Criteria
- decode and prompt throughput are the two largest numbers per engine, colour-coded
- every remaining metric cell carries a sparkline showing the selected window
- latency cells show mean and p95 without needing a hover
- a source-provenance tag is still visible on every throughput number (
AGENTS.md: never invent a number) /llmwith only one engine configured still renders cleanly- screenshots of this page and
llm_monitorside by side indata/logs/, plusNOTES-chart-set.md uv run pytestgreen, coverage ≥94%,ruff+pyrightclean- no behavior change in completed phases