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

nordisk/nornir

.nornir/viz-architecture-tab.md

The 🏛 Architecture viz tab — the EPIC ARCH board, native in egui

Design + guide for the Architecture tab in nornir viz (nornir-ui): it draws the EPIC ARCH wiring diagram (UI-component ↔ gRPC ↔ core-fn ↔ warehouse-table) natively in egui, inside the running viz.

Companion to .nornir/architecture-wiring.md (the EPIC ARCH model + src/arch/). Laws honoured: #1 inject-assert tests · #2 this doc · #3 facett theme · #4 egui-native wgpu screenshot proof · #6 "see what the user sees" as state_json data + $NORNIR_VIZ_TRACE · CLI/viz parity (the same graph nornir arch svg / the arch_graph MCP tool emit is now viewable in the app).

TL;DR

How it reads the graph

architecture_wiring is historized per repo (one graph per repo per git sha; see src/arch/warehouse.rs). A workspace's board is the union of its members' latest boards. The merge lives in:

// src/arch/warehouse.rs
pub fn latest_arch_for_repo(wh, repo) -> Result<Option<ArchGraph>>;
pub fn merged_arch_from_warehouse(wh, members)
    -> (ArchGraph, /*members_with_data*/ Vec<String>, /*errors*/ Vec<String>);

Nodes dedup by id, edges dedup by (from, to, kind), both deterministically sorted (matching build_graph's ordering → byte-stable). A member with no board contributes nothing (the others still render); a per-member load error is reported, never blanking the board (per-member isolation, like the Knowledge warehouse read).

Source split (mirrors every other pane):

mode path
local / fat open the warehouse directly + merged_arch_from_warehouse
thin / remote Viz.Architecture RPC → server runs the same merge (it holds the lock)

The Viz.Architecture RPC (proto/nornir.proto, handler in src/bin/nornir-server.rs, client viz::remote::fetch_architecture) returns JSON { graph: ArchGraph, members_with_data: [..], errors: [..] } — decoded into ArchPayload. The merge is pure, so thin == fat.

The native render

src/viz/arch_tab.rs lays the merged graph out in layered columns (the same model as arch::layers_of: layer 0 = sources, tables pinned to the rightmost "warehouse rail"), then paints with egui::Painter:

The pane follows the broadcast_palette / set_palette contract: the app pushes the active palette into arch.set_palette(p) on construction + every switch, so a 🎨 palette change re-skins the board with everything else.

LAW #6 — readable data

state_json["architecture"] (folded in app.rs) exposes exactly what's painted:

{
  "source": "local|remote", "workspace": "...",
  "node_count": 6, "edge_count": 4,
  "components": 2, "grpc": 1, "core_fns": 1, "tables": 2,
  "nodes": [{ "id", "label", "kind" }, ...],
  "edges": [{ "from", "to", "kind" }, ...],
  "members_with_data": ["nornir"], "members": [...], "errors": [],
  "load_error": null,
  "selected": "ArchTabState", "traced_downstream": ["ArchTabState", ...],
  "empty": false, "palette": "default"
}

$NORNIR_VIZ_TRACE carries architecture.load IN (source + workspace) and architecture.render END (counts per kind + selection), edge-triggered on data/selection change (not per frame).

Tests

Build

cargo build --features viz,mcp,server (green). The Viz.Architecture proto RPC regenerates via build.rs. Re-render snapshots with cargo test --features viz --test viz_arch_pane.