LAW — Testable code + self-emitters (the prompt every code agent runs under)
A nordisk constellation LAW, written as a directive prompt. Any agent (or human) that writes or changes product code MUST satisfy this before pushing. It consolidates the emit-doctrine first captured in self-emitters.md and the test doctrine in test-design.md / test-bench-chains.md / completeness-gate.md into ONE enforceable rule. Sibling law: reuse-common-functionality (see
workspace_nordisk/.nornir/mega-prompt.md§0).
THE LAW (one sentence)
No behaviour ships without a way to observe it — every function is written so a test can assert its outcome from outside, and where the outcome is a side-effect that can't be seen from outside, the function emits a functional_status row that a test reads back. A feature is not done until its observable behaviour is asserted AND recorded as a matrix row.
THE PROMPT (run this checklist on every change)
You are writing product code for a nordisk repo. Before you commit + push, prove you obeyed the emit-doctrine:
1. Design for observation FIRST
- Prefer pure, return-a-value shapes: a function that returns its result + exposes state via
state()/state_json()is testable with zero emitter machinery. Reach for this first. - Push side-effects (render, file write, network, spawn) to the edge; keep a pure core that returns the decision the side-effect will act on, and assert the core.
- If you find yourself unable to test a function without "just running the whole app", that is a DESIGN smell — split out the observable core.
2. The three-tier emit-doctrine (verbatim, non-negotiable)
DEFAULT → assert on the RETURN VALUE / object state (the returned result + state()/state_json()).
FALLBACK → ONLY when the result can't be observed from outside (a render / side-effect): implant a
functional_status(...) INSIDE the function under test, then read the row back in the test.
RELEASE → every emit AND its detail-building is gated `#[cfg(feature = "testmatrix")]`, so a plain
build strips it to nothing. NO emit exists in a release build.
3. Wire the emitter the canonical way (never hand-roll a twin — see the reuse law)
- Consume the shared emitter:
nornir_testmatrix::functional_statusvia each crate's ownsrc/selftest.rsbridge (selftest::emit(component, check, ok, detail)), or the preferredassert_emit!macro — whichassert!s on the REAL value AND records the verdict as a row. - Add the passthrough feature to the crate's
Cargo.toml:testmatrix = ["nornir-testmatrix/testmatrix"]. One flag lights every gated call site. - A new
crates/*leaf carries its OWNselftest::emitbridge + a#[cfg(all(test, feature = "testmatrix"))]wiring test that drives its real surfaces and drains the rows back. Register it in the per-crate emit roster in self-emitters.md §5.
4. What a test must cover (additive to the code you shipped)
- The happy path asserted on the real return value / state over a KNOWN seeded input.
- At least one RED-when-broken assertion (ok=false path) — a test that would go red if the behaviour regressed. Correctness-sensitive code (bounds, data-skipping, exactly-once, security gates) MUST have a red-when-broken test; a green-only test is not acceptable there.
- For render / PNG / side-effect paths: a headless
#[cfg(feature="testmatrix")]drive hook + a non-blank / bytes-written emitter row read back from the sink.
5. Gate + run
cargo build --workspace --features testmatrixmust be green with emits stripped in any non-test build (prove the release build carries no emitter code).- Run the matrix drive:
cargo test --features "…,testmatrix" -- --test-threads=1for the self-emitter tests; the row you added must appear (and go red if you break the behaviour). - The completeness / surface-coverage gate (completeness-gate.md, aut5-surface-coverage-gate.md) must not regress: a new enumerated functional surface (viz tab, server RPC, warehouse path, CLI verb, engine) needs a functional row, or it counts as an uncovered surface.
6. Bench chains (the test↔bench link)
- A
#[ignore]'d HEAVY arm must never be the ONLY coverage of a path — pair heavy benches with a light functional test so the surface is exercised in a normalcargo test(test-bench-chains.md, theno_light_on_heavyidea).
7. UI surfaces are ROBOT-TESTED (robot tests are first-class, not optional)
Every user-facing surface ships a robot test that DRIVES it like a user and emits matrix rows — robot coverage is a definition-of-done item, not an afterthought.
- egui Facets / viz panels →
nornir-robotui(egui_kittest / AccessKit): realclick_label/click_button/type_into/ key-press / scroll, then assert the component'sstate_json(what the user WOULD see, not pixels). Each(action → expected outcome)step emits anornir_testmatrix::TestResultRow— the run fills the matrix. - web views → a
nornir robotWebDriver TOML scenario (a plan-tests DAG,needs = []edges) driving a REAL browser (real clicks/keys), rows emitted the same way. Recorded UI sessions replay/drive vianornir saga --drive(WebReplayDriver). - Elm components get the lighter
facett_core::harness::{drive, snapshot}Msg-injection test as the unit layer; the robot test is the integration layer on top. - A UI surface with NO robot test counts as an uncovered surface for the completeness gate.
DEFINITION OF DONE (a change is not "done" until ALL are true)
- Observable core exists (return value /
state_json) — side-effects at the edge. - Behaviour asserted from outside (DEFAULT), or emitter-implanted + read back (FALLBACK).
- At least one RED-when-broken assertion; correctness-sensitive code has one for sure.
- Every emit gated
#[cfg(feature = "testmatrix")]; release build carries none. - Consumes the shared
functional_statusemitter viaselftest/assert_emit!— no twin. cargo testGREEN (push only if green — the constellation LAW).- New functional surface → new functional row (completeness gate not regressed).
- Every UI surface it touches is ROBOT-TESTED (egui via nornir-robotui/kittest, web via
nornir robotWebDriver) withTestResultRows emitted into the matrix.
WHY (so no one waters it down)
The Loki bencher + nornir test matrix + autonom coverage are only as honest as the emitters. Code that "works" but emits nothing is invisible to the constellation's own dashboards, silently drops off the coverage matrix, and lets a regression ship un-caught. Testable-by-construction + self-emitting is what lets nordisk audit itself.