Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

.nornir/test-matrix.md

holger test matrix

The per-component green/red GRID of holger's test aspects, plus the fully aggregated robot-UI grid (mannequin + every holger-server-ui surface) and the CI-safe in-process mannequin boot cell. Driven by the published nordisk engine nornir-testmatrix — the same engine behind nornir 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:

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:

  1. its unit + integration cells land automatically — pivoted from the engine by suite == "mannequin";
  2. mannequin::boot-inproc — the CI-safe in-process boot cell, run for real in the light pass every push. It constructs the real MannequinServer in-process (a fresh in-memory CA, no subprocess, no files), serves it on an ephemeral port, and asserts /health plus a real CA PEM from the PKI subsystem (mannequin/tests/smoke_serve.rs::mannequin_boots_in_process_and_serves, driven by mannequin_boot_inproc_cell in holger_matrix.rs). So the boot aspect is genuinely green in CI — not merely deferred to the heavy pass.
  3. mannequin::boot — the heavy #[ignore]'d smoke test (smoke_serve.rs::mannequin_serve_boots_and_listens): builds + boots the real holger-mannequin serve daemon and asserts it accepts a TCP connection. In the light pass it's recorded ignored (the row still shows, pointing at the heavy pass); the --ignored pass runs it for real and asserts a green boot cell.
  4. 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:

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.)