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

nordisk/dwarves

.nornir/funnel-run-history-bottleneck-design.md

Funnel ForgePane — run history + bottleneck annotation (design)

The dwarves funnel pane (nornir-funnel-embed::FunnelPanel) already draws the plan-DAG growing live (auto-poll Funnel.Show ~1.5 s + submit strip) and keeps a de-duped size trajectory (FunnelHistory — the node-count trail). This adds the next layer of "addera historik och annat": a selectable run history and a bottleneck hint.

f0 — the whole

Two additive surfaces over the existing live DAG, both robot-observable in state_json and both reusing the shared facett-plandag renderer + its constraint analysis (no second renderer, no recomputed bottleneck — L5). The live view stays the default/"latest".

f1 — run history (FunnelRunLog)

f2 — bottleneck annotation (CONSUMED, not recomputed)

f3 — the seams (state_json / update_json)

Added to the funnel pane's state_json: runs (array of {seq,node_count,edge_count,outcome,captured_at_s}), run_count, selected_run (null = live), bottleneck (top id or null), bottleneck_title, critical_path, and plandag now reflects the shown DAG (live or snapshot). Added to update_json: {"select_run":<seq>|null} (view a past run / return to live) and {"clear_runs":true} (drop the log + back to live). Existing keys unchanged (additive, L2).

Update — the EVENT-SOURCED ledger now exists alongside this

funnel-core retains RunRecorded (it previously validated and dropped the payload), so the funnel's REAL run history is now readable from a replayed Funnel (runs() / runs_to_json()) and the pane surfaces it as event_runs — see funnel-live-graph.md. The two are complementary, not duplicates: event_runs answers "what actually RAN" (executions, actors, outcomes), the FunnelRunLog below answers "what did the DAG LOOK LIKE" (a re-viewable rendered snapshot per poll) and remains the picker's source, since a remote Funnel.Show still carries no run ledger on the wire.

Why a client-side snapshot log (and what stays deferred)

nornir-server's Funnel.Show RPC returns the current funnel only — there is no run-ledger on the wire. So the run history is a client-side capture of the DAG as it grows (each distinct poll = a re-viewable run). A true server-side funnel-run ledger (jera JobRecord over a new Funnel.Runs RPC) is the deferred leg; record_run is the insertion point (swap its caller for a wire-fed history without touching the picker/render).