Handover 2026-09-29 — navgraph in dev mode, GPU graph lanes, 100k points in Streamlit
nornir:class=design · written on loki at the end of the 2026-09-28 session. It moves the work to dwarf's claude container (tmux session facett).
Owner orders that hold (read these first)
- The navgraph is GO (2026-09-28): numbered navigation graph in dev mode, and it must work on plain egui too, not only on facett components. The design is
.nornir/navgraph-design.md(§10 covers plain egui). Look and feel v2.0 is still NOT started: use the v1look::tokens. - A GPU always exists (2026-09-28). An integrated GPU counts; SwiftShader and llvmpipe do not. GPU-able work (layout, FDEB, point prep, 100k-point graphs) goes to WebGPU/wgpu. Do not build new CPU fallbacks for it, and do not delete the existing ones. With no hardware adapter, state says "no GPU" plainly. gatling/wasm workers only for work that cannot go on the GPU, and only when a measurement shows it helps.
- Use 2 agents for this work (owner, 2026-09-28).
- THE LAW:
workspace_nordisk/nornir-workspace.tomllines 1-90. Pure Rust, reuse the nordisk crates, Build Thing for variants, nogit stash, nogit add -A, nocargo fmtover a repo. Commit and push every green step.
Done and on main
| commit | what |
549dfbd |
Merge navgraph phase 1: facett-core/src/navgraph.rs (per-frame arena, numbering 1.2.3, ~ guessed, ? undeclared, top-layer overlay, Ctrl+G <n> Enter, to_json), plain-egui harvest (§10), facett-demo NavOrder, Streamlit dev mode (facet-wrapped/src/devmode.rs, facet_dev, facet_navgraph), charts.rs, more registry entries (wheel 0.1.19 = 36 components), 2-D map and graphpan GPU lanes installed, gallery_probe example, web_time clocks (std Instant panicked the osm3d GPU upload in the browser). |
5b312f3 |
The navgraph demo snapshot (facett-demo/tests/snapshots/navgraph_demo.json), force-added because tests/snapshots/ is gitignored. |
branch feat/wasm-threads-gatling @ 3b19509 |
100k graphs on the GPU: grid-pyramid layout kernel (facett-graphview/src/layout_grid.wgsl, GridLane, O(n log n) per step above GRID_MIN_NODES), resident graph cloud for graphnav above SCALE_NODES, per-model frame index, facet_state read on demand instead of serialised every frame, browser_bench.rs, frame_cost example. Merged with main (5 conflicts resolved: Cargo.toml features, two comments, the frame loop now calls devmode::draw on the RefCell facet, the lane guard has 8 rows). Merge to main only after its tests pass (see the status line at the end). |
Test evidence from 2026-09-28: facett-core navgraph 11/11, navgraph_demo 4/4 (after the snapshot), lane guard 5/5, graphview (gpu) 160 passed, graphnav + facet-wrapped all green on the branch before the merge, wasm32 cargo check of facet-wrapped clean.
Open — helper A's lane (navgraph + Streamlit components)
gallery_probe(headful Chrome, RTX) run at 20:45: osm2d fails —WebGPU renderer failed to start: No suitable graphics adapter foundwhile osm3d on the same page got "nvidia lovelace". The 2-D map lane asks for its adapter differently from the 3-D one; make it take the host's device like the others.- graph2d, lineage and geomap have no GPU lane (egui painter only). Per the GPU ruling that is a defect: give them the shared
graphcloud/facett_map::gpulane. - Read the navgraph back from a live tab:
robot_streamlit.py --gallery --dev(or the Rustgallery_probe) must assertfacet_navgraph()numbers per frame. - facett-demo registers one pane as
⟨unregistered⟩ graph(see the snapshot): give it a real id. - Wire the one-call overlay into korp-ui and dwarves-gui (plain egui harvest), then design §6 phase 2 (korp
NavOrder). - Finish the inventory: every
facett-*crate either in the Streamlit registry or listed with the reason it is not. Runcargo xtask test-demoand report the counts.
Lane A status (2026-09-29, branch lane-a/navgraph-streamlit, dwarf)
Blocker: loki is down (No route to host since ~22:25 UTC, same as lane B), so nothing that needs a GPU or a browser has run. Built and staged on dwarf in ~/runs/facett-0929/tmp/laneA-stage/: dist/ (wasm bundle of 7d203c7), index.html (loader), demo_payloads.json, gallery_probe, graph_gpu_cloud_lane, geomap_gpu_cloud_lane (stripped test binaries). Loki commands below.
| # | state | what, with shas |
| 1 osm2d adapter | todo | Not reproduced (loki). Read: the 2-D map lane does NOT request its own adapter — install_gpu_lanes (facet-wrapped/src/wasm.rs) installs facett_map::gpu on eframe's RenderState exactly like osm3d/graphcloud, and the failing text No suitable graphics adapter found is wgpu's RequestAdapterError::NotFound from WebRunner::start, i.e. navigator.gpu.requestAdapter() returned null for that iframe before any lane ran. With --groups graph,map the manifest order puts osm2d FIRST in the run, so the likelier cause is "the first mount in a fresh Chrome gets no adapter", not the map lane. gallery_probe --names osm3d,osm2d (7d203c7) tells the two apart in one run: if osm3d then fails and osm2d passes, it is first-mount; the fix is then a bounded retry in start(), not a lane change. |
| 1b retry | done, browser-unproven | 7b362e5: start() retries ONLY NotFound — 4 attempts, 250/500/1000 ms, rebuilding the consumed component; final refusal no GPU: WebGPU gave this page no adapter after 4 attempts …; adapter_attempts in every facet_state() and in the probe line. Policy facet-wrapped/src/adapter_retry.rs, 5 unit tests. The staged dist/ predates it — rebuild with cargo xtask wrap-wasm before the loki run. |
| 2 GPU lanes | done, GPU-unproven | fff05f6: graph2d (facett-graph new feature wgpu) and geomap (map-wgpu) push their cloud through graphcloud::cloud::draw_cloud; CPU painters kept, none added; state lane = lane::cloud_lane_json (gpu: "no GPU" when no renderer). lineage already rode graphnav's lane. GPU tests facett-graph/tests/gpu_cloud_lane.rs, facett-geomap/tests/gpu_cloud_lane.rs (lane_flag gpu + CloudRenderer frames > 0) built, unrun. |
| 3 navgraph per frame | done, browser-unproven | 7d203c7: facet_navgraph() carries frame; gallery_probe --dev samples it 6× and asserts the spine on every sample and ≥ 2 distinct frames. |
| 4 demo pane id | done | fff05f6: facet-graph-1 registers graph; pane is facett-demo.deck.graph/graph (1.2.2), snapshot re-blessed; navgraph_demo 4/4. |
| 5 korp/dwarves | done in code, uncompiled | overlay: korp navgraph-overlay @ 76b7e4b, dwarves navgraph-overlay @ 0763014 (neither workspace resolves on dwarf: korp needs ../tunnr, dwarves ../gunnar). Phase 2 built generically in the scene renderer (b7859b9, navgraph-design §9 "Phase 2 as built"), facett-app/tests/navgraph_scene.rs 3/3; the korp-side robot test is designed there, not written. |
| 6b atoms declared | done | 42c2a65: navgraph::declare_own_draw_order(ui) in 22 component views; navgraph_demo sweep over all 89 tabs: undeclared component atoms 198/210 → 8/210, CEILING 8. |
| 6b' atoms to 0 | done | e6e5e3b: scene-in-a-pane, scene slots, widgets, GFX v2 and map3d declare too — sweep 0 undeclared of 210, CEILING 0. |
| 6c forge seams | done | 25e23e1: cicd, brokkrview, holger wrapped (data seams + gallery payloads); inventory 35 wrapped / 40 entries / 13 'no data seam yet'. |
| 6d more seams | done | 05d8b09 releaseview + binview, 76297f4 coderoom (component serde shapes; a malformed checksec or list is refused); 744645e sharper reasons: 38 wrapped / 43 entries / 34 listed, 5 'no data seam yet' (fleet-view next). |
| 6e fleet + buildspace | done | 5f1c1d5 fleet (payload = FleetRunView, its own serde state); a87fc82 buildspace = GaloisPane over FeatureAxis (already serde in facett-buildthing; edda CrateAnalysis serde too — no sibling change), Facet impl added; robot.rs fixed for edda Toolchain drift. 40 wrapped / 45 entries / 3 'no data seam yet' (docview, manual, model3d). |
| t14s run | done | 2026-09-29 09:30–09:49 on the t14s (Radeon 890M RADV STRIX1, load 0.1–0.7, edge 33–35 °C, Tctl 34.5–36.9 °C), HEADLESS Chrome only (gallery_probe --headless, 9528e2b). GPU tests (9528e2b: facett adapter policy — kittest's default had opened llvmpipe): graph2d PASS (lane_flag gpu, 930 red node pixels), geomap PASS (CloudRenderer frames 1). --names osm3d,osm2d: 2/2, adapter "amd rdna-3", adapter_attempts 1 each. --dev graph+map: 10/10 after f5696bd (probe nudge fixed: iframe resize; graphview gpu-cloud feature on) — six distinct frames per component, spine 1 / 1.1 on every sample. FULL --groups all --dev: 45/45 PASS, every adapter "amd rdna-3", adapter_attempts 1 everywhere, ≥ 2 distinct navgraph frames on all 45. Not a failure but open for lane B: graphnav and lineage report canvas.layout_lane: cpu (the probe does not count layout lanes). Raw results: dwarf ~/runs/facett-0929/tmp/laneA-results/h1..h4.{json,txt,meta}. Headful runs earlier the same morning (X11/Wayland, windows on the owner's screen) gave null adapters and were stopped. |
| 6 inventory | done; test-demo not run | fff05f6: facet-wrapped/tests/inventory.rs — 72 facett-* crates, 32 wrapped behind 37 entries (+progress = facett-pop), 40 listed with a reason (16 "no data seam yet"). cargo xtask test-demo NOT RUN: it pip-installs from a holger index on 127.0.0.1:8455; none runs on dwarf, and holger does not build there (its manifest needs edda/crates/appliance-grow, absent from the depth-50 edda). |
Loki, when it is back (ports 8601-8619, nothing compiled there):
rsync -a ~/runs/facett-0929/tmp/laneA-stage/ rickard@192.168.1.102:runs/facett-0929-laneA/
# on loki, in ~/runs/facett-0929-laneA:
./graph_gpu_cloud_lane --nocapture; ./geomap_gpu_cloud_lane --nocapture
WAYLAND_DISPLAY=wayland-0 XDG_RUNTIME_DIR=/run/user/1000 ./gallery_probe --dist dist --loader index.html \
--payloads demo_payloads.json --port 8601 --dev --out probe.json # graph + map groups
WAYLAND_DISPLAY=wayland-0 XDG_RUNTIME_DIR=/run/user/1000 ./gallery_probe --dist dist --loader index.html \
--payloads demo_payloads.json --port 8602 --names osm3d,osm2d # item 1: first-mount or lane?
Open — helper B's lane (100k points, benches)
- Measure 100k nodes in Streamlit in headful Chrome: time to first frame, layout time to settle, fps while panning, memory; GPU lane on the RTX 5080 and on an integrated GPU (dwarf has a Radeon 680M, but the container has no
/dev/dri). - Parity test:
GridLaneagainst the O(n²) GPU lane and the CPU lane on the same small graph (positions within tolerance), plus a timing row. - Testmatrix + benches: rows for layout 1k/10k/100k × {gpu, gpu-grid, cpu-1 baseline}, FDEB, point cloud 100k/1M, native vs wasm. Numbers go into
.nornir/facett-benchmarks.mdwith the box, the GPU and the load average. .nornir/wasm-threads-plan.md: record the GPU ruling. The threads bundle and the COOP/COEP front are PARKED unless a measurement shows a CPU-side stage that matters.
Lane B status (2026-09-29 00:25 UTC, branch lane-b/gpu-100k-bench, dwarf)
Blocker: loki is down. 192.168.1.102 answered at 22:20 UTC (idle, RTX 5080 44 °C) and has given No route to host (no ARP; the LAN router answers) since ~22:25 UTC. Nothing that needs a GPU or a browser has run. Everything is built and staged on dwarf in ~/runs/facett-0929/stage-laneB/ (layout_matrix, browser_bench, frame_cost, gv-test-baseline = graphview gpu lib test binary as of 2bab36c, dist/ = wasm bundle); the loki commands are at the end of .nornir/facett-benchmarks.md ("GPU lanes at 100k").
| # | state | what, with shas |
| flake | todo | Not reproduced (needs loki). Static read of facett-graphview/src: the GPU tests that open a device WITHOUT gputurn::hold() are gpu_layout.rs gpu_front_door_lays_out_in_box_and_contracts_edges (two bring-ups), layout_job_matches_the_blocking_lane, the_host_device_seam_installs_and_clears, fdeb_gpu.rs cpu_and_gpu_bundle_agree, and the gpu.rs / lib.rs GpuRenderer::new render tests — the parallel-bring-up shape gputurn.rs's table records as SIGSEGV. First suspects; prove with the 20× loop before fixing. |
| 1 | todo | 100k in headful Chrome not measured (loki). browser_bench --port added (2bab36c) so the run stays in 8701-8719. Radeon 680M: not measured, container has no /dev/dri. |
| 2 | written, unrun | GpuLayout::new_grid + grid_all_pairs_and_cpu_agree_on_a_small_graph (gpu_layout.rs, 2bab36c): 400 nodes, 30 steps, all-pairs vs CPU ≤ 1e-2, grid vs CPU cos > 0.98 and ≤ 5 % of span, prints [parity-timing]. Compiles; tolerances not yet held against a GPU. |
| 3 | partial | examples/layout_matrix.rs (2bab36c, --cpu-only 8b4be60). dwarf CPU rows in facett-benchmarks.md: cpu-1 100k 194.5 ms/step, cpu-all 111.4 ms/step, graphnav native first frame 8.35 s / steady 96.8 ms at 100k, load 22-25 on 12 threads. GPU, FDEB-gpu, cloud and wasm rows owed. |
| 4 | done | GPU ruling recorded at the top of wasm-threads-plan.md (3ccd4f4); threads bundle + COOP/COEP front PARKED. |
| flake fix | built, unproven | d8b6dd6: the seven device-opening graphview lib tests take gputurn::hold() (no helper on those paths takes it, so no re-entry). dwarf 134/134 (GPU tests self-skip). Staged gv-test-baseline vs gv-test-fixed for the 20× loop. |
| CPU 100k | done | df3c7bd: cached facet_state() read at 100k 741/655 → 380/405 ms (stats sig, acyclic cache, schema in frame index); the native 8.35 s "first frame" is the CPU layout (GPU job's in a browser), the frame after it is 140-225 ms. graphnav 92/92, facet-wrapped 81/81. |
| staging | done | 6689f0e: browser_bench finds the session (wayland/X11, uid runtime dir), default port first free of 8701-8719. Binaries need glibc ≥ 2.43. Runbook in facett-benchmarks.md. |
| flake | done, proven | t14s Radeon 890M, 20 runs each: gv-test-baseline (2bab36c) parallel 8/20 SIGSEGV in libvulkan (threads of the 7 unturned GPU tests), --test-threads=1 0/20; gv-test-fixed (d8b6dd6) 0/20 and 0/20. |
| parity | done | 20dcd9a: grid held per step + by settled shape (30-step positions diverge by chaos: 10.3 of 28.7). Radeon: all-pairs vs CPU 1.84e-3, grid step cos 1.0000, gpu_layout:: 15/15, full gv lib 134/134. |
| graphnav GPU job | done | a436a0c: no size floor — gallery-sized graphnav/lineage now lay out on gpu-job in the browser (lane A saw cpu). |
| 100k browser | done (t14s) | headless Radeon: first frame 228-229 ms, settled 1.36-1.38 s on gpu-job/grid, 60 fps under a synthetic drag, wasm 285 MB, JS heap 118 MB. loki (RTX 5080) rows still owed. |
| integration | done | integration/0929 @ 42c366c (lane A c9d9401 + lane B 51b727b): 3545 passed / 135 failed / 39 ignored over 552 test binaries on dwarf; 121 failures need a GPU adapter, 13 do not (list in the report). Staged ~/runs/facett-0929/stage-int/ + RUNBOOK.txt + STAGED_SHA; smoke on the t14s all green. |
| knut matrix | done | 39f3403: knut-pipelines dev-dep restored (commented out by accident in e565e0a, 2026-07-13); knut_facett_matrix 2/2, silenced_tests_guard green; gate of fe52fd7 reverted. |
| GPU-only on t14s | done | integration b9ad95e: 91 failing-on-dwarf test binaries run one at a time, --test-threads=1, VK_LOADER_DRIVERS_SELECT=*radeon* (llvmpipe invisible): 76 green on the Radeon; 7 are path-bound (compiled-in /home/rickard/runs/facett-0929/facett-int paths); 3 real GPU reds (geomap osm_paint_order, map3d gfx_v2_item6_parity, map3d postfx_bypass); 5 main debt. dwarf CPU run b9ad95e: 3553 passed / 129 failed / 39 ignored, every non-GPU red is main debt. |
Where things run
- Build on dwarf's
claudecontainer (12 cores, shared with the gunnar session in tmuxclaude, so use-j 4andnice). Fresh clones under~/runs/facett-0929/(facett, znippy-zoomies full; edda, knut, draupnir, korp-collectors, nornir, skade, Skidbladnir, funnel-core at--depth 50); do not touch~/git/*there. Cargo targets under~/runs/facett-0929/target.funnel-corelives atgit@codeberg.org:mikronova/funnel-core.git(not nordisk — open item 1 ofopen-items-2026-09-18-plan.mdis answered by that). - GPU and browser tests on loki, reachable from the container at
192.168.1.102(tailscale addresses do not answer from the container). loki: RTX 5080, headful Chrome:WAYLAND_DISPLAY=wayland-0 XDG_RUNTIME_DIR=/run/user/1000 google-chrome-stable --user-data-dir=<throwaway> --ozone-platform=wayland --enable-unsafe-webgpu --enable-features=Vulkan <url>. WebGPU needs a secure context: serve on loki and openhttp://localhost:<port>. Never compile on loki: it runs hot (95 °C under load). - korp-server-gpu runs on loki as the system unit
korp-serveron:50051. Do not restart it. The Streamlit live panes point there. - oden (Streamlit ran there,
:8501, tailnet https:8443) went offline at ~00:00 on 2026-09-29. Its~/runs/navAand~/runs/perfBhold nothing that is not pushed.
Status at handover (2026-09-29 ~00:40, measured on loki, idle)
feat/wasm-threads-gatling merged to main after: facet-wrapped 81/81, facett-graphnav 92/92, facett-graphview (gpu) lib 133/133 three runs in a row, navgraph_demo 4/4, lane guard 5/5, wasm32 check of facet-wrapped clean. One flake to chase: in one of five runs, cargo test -p facett-graphview --features gpu --lib died with no test result line (the process ended mid-run, most likely a GPU test crashing under parallel tests). Run it in a loop with --test-threads=1 and without to find which test.