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

nordisk/nornir

.nornir/funnel-3d.md

Rotating 3-D funnel view (viz::funnel3d)

Face: the Funnel tab's 🌐 3D toggle paints the selected plan's DAG as a spinning, depth-shaded node cloud that cycles three layouts — sphere → helix → force — instead of the flat egui-snarl 2-D graph.

Map (where it lives)

Part Location
Render + layout math src/viz/funnel3d.rs (Funnel3D, Layout3D)
Toggle + layout-cycle UI src/viz/funnel_tab.rs — controls bar (🌐 3D, ⟳ <layout>, spin)
Central-panel routing src/viz/funnel_tab.rs::draw (3-D branch vs the snarl branch)
Robot state state_json()["funnel"]["view3d"] + ["funnel"]["graph3d"]
Test hooks FunnelTabState::{set_3d_for_test, cycle_3d_layout_for_test}
Unit tests src/viz/funnel3d.rs #[cfg(test)] (3 tests)
Injection test tests/funnel_3d.rs (demo → 3-D → assert graph + cycle)

Territory (what it does)

Spine (why it's here / the facett relationship)

The user wanted "a rotating 3 graph of funnel tasks … make it in facett if not". The component already exists in facett as facett-graph3d::Graph3D (../facett/facett-graph3d) — same projection, same three Layout3Ds, same state_json() shape. We could not depend on it directly: nornir is pinned to egui 0.33 (the highest egui-snarl 0.9 supports) while facett is on egui 0.34, so pulling facett-graph3d would fork the egui tree.

src/viz/funnel3d.rs is therefore the egui-0.33-native sibling of facett-graph3d: the layout + projection math is intentionally identical (so the state_json shapes match for the robot matrix). When nornir adopts egui 0.34 (an egui-snarl bump), cut this over to the shared facett-graph3d component and delete the local copy — the data contract is already aligned.

CLI / parity note

The 3-D view is a viz render mode (it visualises the same FunnelView the CLI nornir funnel show already dumps as data); there is no new CLI surface to add. The robot-UI driver toggles it headlessly via the test hooks and observes the result in state_json["funnel"]["graph3d"] (LAW: components expose what they render as readable data).