Gunnar

nordisk/knut

.nornir/popviz-ui-atoms.md

<!-- nornir:class: design -->
# knut-popviz — UI atoms over the command seam (remote-controllable)

The population-preview UI is now **remote-controllable as data**, per the north-star
law (*every UI atom drivable in code, no display, no AI at runtime*).

## The seam
`PopvizState` already exposed **`state_json()`** (observe what's on screen). It now also
exposes **`update_json(&str)`** (drive it) — a pure in-memory command channel:

| atom | command | effect |
|---|---|---|
| target select | `{"select_target":"falkor"\|"iceberg"}` | sets the load sink |
| phase | `{"set_phase":"loading vertices"\|"indexing"\|"done"\|…}` | the load lifecycle the bars reflect (`Phase::from_label`) |
| population progress | `{"advance":{"label":"Person","loaded":N}}` | bumps one per-label bar |
| reset | `{"reset":true}` | back to idle, progress zeroed |

Garbled/unknown input is a safe no-op (never panics). The GUI (`--features gui`) renders
the **same** shared `PopvizState`, so a headless robot drive and a visible `watch` on
DISPLAY:0 exercise one contract.

## Coverage (in code, self-driving)
`tests/robot_ui_atoms.rs` → `robot_drives_popviz_ui_atoms_via_command_seam`: drives every
atom via `update_json`, asserts `state_json`, and emits a `nornir-testmatrix` cell per atom
(`knut-popviz/ui_atom/{target_select,phase_set,progress_advance,phase_done,reset}`) — reuses
edda's `nornir-testmatrix` (real row under `--features testmatrix`, no-op otherwise). Green
default AND `--features testmatrix`.

![ui atoms](assets/popviz-ui-atoms.svg)