holger test matrix
The per-component green/red GRID of holger's test aspects, plus the fully aggregated robot-UI grid (
mannequin+ everyholger-server-uisurface) and the CI-safe in-process mannequin boot cell. Driven by the published nordisk enginenornir-testmatrix— the same engine behindnornir test.
TL;DR
# light cells (workspace unit/integration test grid + the real mannequin-GUI robot-UI cell)
cargo test -p xtask --test holger_matrix
# + heavy cells (actually build + boot the mannequin daemon)
cargo test -p xtask --test holger_matrix -- --ignored
Output: one row per component (workspace crate) × aspect, printed with nornir_testmatrix::render_matrix and persisted append-only to target/holger-testmatrix.jsonl via a nornir-testmatrix JsonFileSink (the leaf-repo TestSink; nornir itself sinks the same rows into its Urðr Iceberg warehouse).
Where it lives
| File | Role |
xtask/tests/holger_matrix.rs |
the matrix harness — drives the engine, pivots rows into the component grid, adds the mannequin cells, persists + prints |
mannequin/tests/gui_robot.rs |
the real headless robot-UI cell (facett harness render + state_json observe) |
mannequin/tests/smoke_serve.rs |
the heavy mannequin boot cell (#[ignore]'d; spawns the daemon, asserts it listens) |
mannequin/src/gui.rs → build_system_chart() |
single source of truth for the GUI's SystemChart topology; both the live GUI and the robot-UI cell build from it |
xtask (a publish = false member, already the test/bench orchestrator) hosts the harness because the holger root Cargo.toml is [workspace]-only and can't own a tests/ dir.
The grid
Rows = components (workspace crates), pivoted from the engine's per-test output by suite. Columns = aspects. Cell colours follow nornir_testmatrix::model::status:
pass— greenfail/stalled— red (a hung test is made visible, never silently eats the clock)ignored/skip— neutral/amber (a#[ignore]'d heavy cell, or an aspect whose tool isn't installed)
The light pass runs the Unit aspect (the workspace's native nextest/cargo test runner) across every crate. Build/Clippy/Fmt/Audit are deliberately left to the release-gate sweep (nornir test) which has the warehouse + time budget — cargo build --all-features over holger's iceberg/tantivy/arrow×2 dep graph is minutes-long, and compiling the matrix test target already proves the workspace builds.
mannequin is a first-class component
mannequin (the holger test-dummy daemon: PKI / OIDC / mock-Nexus, with a facett --gui) appears in the grid three ways:
- its unit + integration cells land automatically — pivoted from the engine by
suite == "mannequin"; mannequin::boot-inproc— the CI-safe in-process boot cell, run for real in the light pass every push. It constructs the realMannequinServerin-process (a fresh in-memory CA, no subprocess, no files), serves it on an ephemeral port, and asserts/healthplus a real CA PEM from the PKI subsystem (mannequin/tests/smoke_serve.rs::mannequin_boots_in_process_and_serves, driven bymannequin_boot_inproc_cellinholger_matrix.rs). So the boot aspect is genuinely green in CI — not merely deferred to the heavy pass.mannequin::boot— the heavy#[ignore]'d smoke test (smoke_serve.rs::mannequin_serve_boots_and_listens): builds + boots the realholger-mannequin servedaemon and asserts it accepts a TCP connection. In the light pass it's recordedignored(the row still shows, pointing at the heavy pass); the--ignoredpass runs it for real and asserts a green boot cell.mannequin::robot-ui— see below.
So the matrix always answers "does mannequin still build + boot (in-process every push, as a real daemon in the heavy pass) + draw its GUI."
The robot-UI rows (ALL surfaces aggregated)
holger now has its own operator UI (holger-server-ui, server/ui) alongside mannequin --gui, and holger_matrix.rs aggregates every holger robot-UI surface — the grid reflects holger's full UI coverage, not a sample. All are real (headless render / headless AccessKit drive, no display), never stubs:
| cell | what it drives | source |
mannequin::robot-ui |
mannequin's real facett GUI headlessly (SystemChart render + state_json) |
mannequin/tests/gui_robot.rs (robot_ui_cell) |
holger-server-ui::robot-ui |
holger's operator view-models against a real LocalHolger, asserting each view's state_json |
server/ui/tests/robot_ui.rs (holger_server_ui_robot_cell) |
holger-server-ui::robot-app |
the flagship — the real egui app driven by egui_kittest AccessKit clicks through nornir-robotui, 20 scenarios over every tab + all five Tools panes |
server/ui/tests/robot_ui_app.rs (gui feature, holger_server_ui_robot_app_cell) |
holger-server-ui::demo-walk |
the --demo scripted per-frame walk over the real app |
server/ui/tests/demo_walk.rs (gui, holger_server_ui_demo_walk_cell) |
holger-server-ui::lineage |
the live proxy-cache-filling Lineage view-model | server/ui/tests/lineage_feed.rs (holger_server_ui_lineage_cell) |
holger-tools::tool-robot |
the non-UI data twin — each working tool verb's SAFE path on the real holger-server binary |
server/cli/tests/tools_robot.rs (holger_tools_robot_cell) |
holger-server-ui::look |
holger's unified facett look & feel surface (active facett_core::look::Theme preset + palette) |
holger_server_ui_look_cell |
Build-surface cells — BUILT vs ATTESTED
The build rows are split into two aspects on purpose, because collapsing them is how a grid ends up claiming a build it never ran:
| cell | what it drives | proves |
holger-build-space::build-verb |
re-invokes xtask/tests/build_verb.rs — spawns the real xtask binary, runs build --list, asserts all three tiers print their exact materialized cargo command lines + the emitted xtask/build::build_list row (build_verb_cell) |
describe-level, all 3 tiers: the declaration resolves and hasn't drifted from server/cli/Cargo.toml's required-features. Compiles nothing. |
holger-build-space::press-embedded · press-mini · press-full |
holger_build_space::press_tier over a synthetic stand-in file at each tier's declared artifact path (build_space_press_cell) |
attest-level, per tier: the provenance record binds the right artifact path, the digest verifies against the record, the proof is never fabricated-sealed. Proves nothing about whether the tier compiles. |
Each press cell's message says NOT built out loud, and the grid asserts that string is there — an honest cell cannot silently start reading as a real build. Before 2026-07-21 there was a single press cell, covering full only, whose doc read like a build; build_verb.rs was a good three-tier test the matrix never invoked at all.
Nothing in the light grid compiles a tier. The compiling proofs are the #[ignore]d heavy tests build_variant_presses_a_tier_end_to_end and build_all_assembles_every_deployment_tier (xtask/tests/build_verb.rs), and the cargo run -p xtask build --all verb itself — the full tier's federation closure takes far longer than a matrix cell may. See .nornir/holger-tiers.md.
Each cell follows the LAW (inject real input + assert real output): e.g. gui_robot.rs injects distinct badge counts (PKI=7, OIDC=3, Nexus=5), drives a click via SystemChart::select("oidc"), observes state_json, and asserts it carries back the 3 nodes/badges/edges + selection and actually tessellated vertices (RenderReport::drew()) — the cell goes red if the GUI stops drawing the systems or loses the selection.
nornir-robotui (now real)
The reusable nornir-robotui crate (egui_kittest drive + facett state_json observe + matrix rows) exists and is what holger-server-ui::robot-app/demo-walk drive the real egui app through; gui_robot.rs and the other cells follow the same drive→observe→row shape. The earlier "future: a second holger::robot-ui row when holger grows its own UI" is done — those holger-server-ui::* rows above are it.
Inject-assert guarantees
Per the nordisk LAW, every cell feeds real input and asserts real output:
holger_component_matrix_is_green— runs the real workspace test runner, asserts mannequin is a row, its robot-ui cell is green, its boot cell is present (ignored), and no component cell is red.holger_matrix_heavy_mannequin_boot(#[ignore]) — actually builds + boots the daemon; the real boot outcome drives the cell, asserted green.red_cell_shows_up_red_in_the_grid— feeds a deliberately failing synthetic cell and asserts the renderer marks it red + counts it failed. This proves the grid distinguishes pass from fail (not merely "didn't panic").
Making the --features gui cells visible to nornir test run holger
The real robot-UI cell server/ui/tests/robot_ui_app.rs is #![cfg(feature = "gui")] (it drives the actual egui app via egui_kittest + nornir-robotui). Likewise the testmatrix emitter that turns the headless view-model self-tests (robot_ui.rs, local_core.rs) into functional rows is gated on --features testmatrix. A plain nornir test run holger builds the default feature set, so cargo never compiles those #[test]s and the cells are silently skipped.
The matrix already has the one seam needed: nornir_testmatrix::runner::test_features() reads NORNIR_TEST_FEATURES and the unit aspect appends cargo test --features <list>. Cargo accepts a --features that some workspace member defines even at holger's virtual-workspace root, so gui,testmatrix lights up holger-server-ui's gated tests without naming the package.
To wire it without forking the matrix, nornir honors a per-repo [repo.<name>].test_features field (added in nornir/src/config.rs; consumed by run_test_one in nornir/src/bin/nornir.rs, which seeds NORNIR_TEST_FEATURES for the run — an explicit env override still wins). Add one line to the nordisk workspace's release/nornir.toml (e.g. workspace_nordisk/release/nornir.toml) under the holger entry:
[repo.holger]
private = true
test_features = "gui,testmatrix" # compile + run the gui robot-UI + testmatrix cells
After that, nornir test run holger discovers and runs robot_ui_app.rs (and the testmatrix functional rows) as first-class matrix cells. No change to the nornir-testmatrix engine or holger's tests is required — only the config line. (The remote nornir test run holger --server … path still takes its features from the client's NORNIR_TEST_FEATURES; the per-repo field drives the local CLI run.)