🧪 The shining Test pane — per-repo × per-aspect health matrix (EPIC L5)
Design + guide for the flagship
nornir vizTest tab (src/viz/test_tab.rs,Tab::Test). EPIC L5 turned the old flat run/case list into a gorgeous repo × aspect matrix painted on the facett palette, with metric badges, per-aspect trend sparklines, per-repo health scores, a summary strip, and click-to-drill-down. THE_BIG_PLAN LAWs apply: everything rendered is exposed as data (state_json()["test"]["grid"]+$NORNIR_VIZ_TRACE), the test inject-and-asserts the real grid, and a wgpu PNG snapshot is the acceptance artifact.
What it shows
A grid over the warehouse test_results table (which since EPIC L carries aspect: String + metric: f64 per row):
| element | meaning |
| rows | one per repo, taken from that repo's latest run (newest ts_micros) |
| columns | the aspects present in the data, in canonical order: build · unit · doctest · clippy · fmt · audit · bench-smoke · coverage · feature-powerset · msrv · examples |
| cell colour | status on the active palette: green = pass, red = fail/stalled, amber/grey = skip/ignored, faint = not-run |
| cell mark | a painted primitive (filled dot = pass, ✗ strokes = fail, ring = stall, hollow = skip) — drawn as shapes so it renders in every font (the bundled emoji font lacks ✓/✗) |
| metric badge | type-aware, right-aligned: coverage 87%, clippy ⚠3, audit 🛡0, unit Np Mf (pass/fail counts) |
| sparkline | per (repo, aspect), across the last SPARK_RUNS (12) runs — coverage rising, warnings falling (warning/advisory counts are inverted so "fewer = up") |
| health badge | a 0–100 score per repo on a red→amber→green ramp |
| summary strip | total green / red / skip / not-run cells across the whole matrix |
| palette picker | switches the facett palette (default · sci-fi · nordic-aurora · cyberpunk-neon · amber-crt · deep-space · hugin-noir); re-skins everything |
| drill-down | click a cell → a bottom panel lists that repo×aspect's failing cases (suite::name + message) |
Health score
health_score(aspects, cells) (in src/viz/test_matrix_grid.rs) blends, over the aspects that actually ran in the latest run:
- green ratio (green / (green+red+skip)) — the dominant term,
- coverage % when measured (+25 pts weight; redistributed to green-ratio when there is no coverage signal),
- a penalty for clippy warnings (−4 each) and audit advisories (−6 each), each capped, so one noisy aspect can't drive the score negative.
Result is clamped to 0–100. All-green + high coverage + no warnings → ~95–100; a build fail + low coverage + several warnings → well under 50.
Architecture — pure model + thin renderer
The LAW "components expose readable data" is met by splitting the pane:
src/viz/test_matrix_grid.rs— pure, no egui.Matrix::build(&[TestResultRow])groups rows by repo, picks each repo's latest run, builds oneCellper aspect column (rolling the unit aspect's per-test rows into pass/fail counts + drill-downRedCases), computes the health score, and the per-aspect sparkline series. Unit-tested in isolation; folded verbatim intostate_json.src/viz/facett_theme.rs— the facett palette family, vendored. nornir's viz is onegui 0.33while upstreamfacett-coreis onegui 0.34; a direct dependency would link two incompatible eguiColor32/Uitypes into one binary. So the palette (names, colours,ALLorder) is a verbatim copy offacett_core::theme::Theme, plus the semantic status ramp (status_fill) and health ramp (health_color). When facett ships on egui 0.33 this collapses to a re-export. (Blocker recorded: the egui-version skew is why we vendor rather than depend.)src/viz/test_tab.rs— the egui renderer. Paints the grid on a canvas (painter) honouring the activeTheme: zebra rows, hover highlight, selection accent, rounded status tiles, health pills, sparklines. Emits the grid asstate_json()["test"]["grid"]and tracestest.matrix.{load,build,end}+test.matrix.{palette,drilldown}events.
state_json shape (["test"]["grid"])
{
"aspects": ["build","unit","doctest","clippy","fmt","audit","coverage"],
"repos": ["nornir","skade","znippy"],
"rows": [
{
"repo": "znippy",
"run_id": "znippy-new",
"health": 49.0,
"cells": [
{
"aspect": "clippy", "status": "fail",
"ran": true, "red": true, "green": false,
"metric": 3.0, "badge": "⚠3",
"count": 1, "passed": 0, "failed": 1,
"red_cases": [{ "test_name": "clippy", "suite": "znippy",
"status": "fail", "message": "3 clippy warning(s)" }],
"spark": [0.0, 40.0] // inverted: 5→3 warnings reads as rising
}
// … one cell per aspect column (blank cells: ran=false, badge="")
]
}
],
"totals": { "green": 15, "red": 2, "skip": 1, "blank": 3 }
}
The legacy keys (runs, cases, selected_run, selected_repo, selected_green, plus the new palette + selected_cell) remain on ["test"] for back-compat with the run-summary consumers.
Tests (LAW #1 + LAW #4)
cargo test --lib viz::test_matrix_grid— 9 pure unit tests: rows-are-repos / cols-are-aspects, metric badges, unit roll-up, latest-run-wins, not-run blanks, health high/low, coverage sparkline rising, warning sparkline inversion.cargo test --lib viz::facett_theme— palette uniqueness/lookup, status ramp, health ramp.-
tests/viz_test_pane.rs:test_pane_exposes_run_summaries_and_cases— legacy run shape still correct.test_pane_exposes_repo_x_aspect_grid— injects a 3-repo × 7-aspect × multi-run matrix and asserts the grid: repo/aspect ordering, per-cell status + metric + badge (88%,⚠3,🛡0,1p 1f), blank not-run cells, health ordering (skade ≥ nornir > znippy), sparkline series (coverage 71→88, clippy warnings inverted), and summary totals (2 red, 1 skip).viz_snapshot_test_pane— wgpu render of the populated, colourful matrix totests/snapshots/viz_test_pane.png(the acceptance artifact), plus a functional assert that 3 repos × 7 aspects with ≥1 red cell are on screen.
How to drive it live
nornir test all # populate test_results across repos
nornir viz # open nornir-ui → 🧪 Test tab
# pick a palette from the top strip; click any cell to drill into its failures.
NORNIR_VIZ_TRACE=/tmp/t.jsonl nornir viz # machine-readable IN/OUT/END twin