Files
dashboards/.agents/phases/todo/01_severity_language/00_phase.md
T
ducoterra 4b4962d7fb chore(agent): phase roadmap from TODO.md, 5 phases
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
2026-10-16 20:10:23 -04:00

2.6 KiB
Raw Blame History

Phase 01 — Severity language

Source: TODO.md L5, L7 — "proper green (good), yellow (warn), red (danger) color coding" / "charge, load, and runtime left to be big, obvious, and color coded" Story: n/a Context: .agents/PLAN.md → Architectural Anchors (severity computed in Python, JS renders classes), src/dashboards/sources/host.py, src/dashboards/sources/nut.py, src/dashboards/api.py, src/dashboards/web/static/dash.css, src/dashboards/web/static/app.js

Objective

Introduce one place that decides whether a number is fine, worrying, or bad, and put that verdict on the values the API already returns. Phases 02–05 all want the same colour language; doing it here means they render a class instead of each inventing its own thresholds.

Deliverable: severity next to the value in the payloads the pages colour, and CSS/JS helpers that make a "hero number" one call.

Dependencies

— (none)

Tasks

  1. 01_severity_module.md — src/dashboards/severity.py: the threshold table and the classifier, unit-tested.
  2. 02_severity_in_payloads.md — attach severity to host and UPS values and to the /api/summary rows; API tests.
  3. 03_hero_number_style.md — a .hero big-number style on the existing .ok/.warn/.fail colours, plus Dash.hero() and Dash.severityFrom(payload) so pages read the verdict instead of passing thresholds.

Testing & Quality

  • Unit: every threshold boundary (below warn, exactly at warn, between, exactly at danger, above), None input, and the "unknown is not ok" rule — a value the upstream does not publish must get severity: null, never a green pass.
  • API: /api/system/snapshot, /api/ups/snapshot, /api/summary carry severity where the spec says, and no existing field changes name or meaning (additive-only anchor).
  • Coverage: >90% on new/modified code.
  • Live: uv run pytest -m live --live must stay at 6 passed.

Completion Criteria

  • uv run python -c "from dashboards import severity; print(severity.classify('cpu.usage_pct', 95))" → fail; 60 → ok; None → None
  • curl -s localhost:8090/api/ups/snapshot | python3 -m json.tool shows severity beside charge_pct, load_pct, battery_runtime
  • no new colour vocabulary: classes stay .ok / .warn / .fail as in dash.css
  • uv run pytest green; coverage ≥94% overall, >90% on severity.py
  • uv run ruff check src tests agent && uv run pyright clean
  • Existing pages render unchanged (severity is additive; nothing consumes it yet) — one screenshot in data/logs/
  • no behavior change in completed phases