GRAPH-CLIP-TEST — the start→pixel clip discipline for the graph renderer
The graph twin of
facett-map3d's clip pipeline. Brings the same emitter + final-picture-PNG-blob + sensitivity-proven oracle discipline that caught the 3D-map "draws, but ink escapes the rect" bug to the graph engine. Ratified byfacett/.nornir/render-engine.md(the graph path:layout → cull → nodes → edges → picking → composite, bench/emit columnfacett.graph.<step>).
What it is
A graph view almost never owns the whole framebuffer — it lives inside a widget rect carved from a larger canvas (a panel, a split, a dashboard cell). The invariant the map3d work proved for the 3D map — nothing a render pass paints lands outside the component's own rectangle — must hold for the graph engine too.
facett_graphview::clip (src/clip.rs) renders a GraphModel into a rect ⊆ canvas and instruments the chain:
layout ─→ cull ─→ nodes ─→ edges ─→ picking ─→ composite
│ │ │ │ │ │
project drop emit emit hit-test raster + PIXEL SCISSOR
all off-rect chips clipped (return) + ink_outside_rect oracle
nodes nodes/ (return) edges + PNG final-picture BLOB
edges counts (return) (EMIT — pixel stage)
API
| item | what |
render_graph_clipped(model, deco, cam, w, h, rect, bg, clip) -> (Frame, GraphClipReport) |
CPU lane. clip=true = production (scissor → ink_outside_rect==0); clip=false = the deliberately-unclipped bug variant (negative control). |
render_graph_clipped_gpu(...) (feature gpu) |
GPU lane: builds the vello GPU scene over the clipped geometry (proves the seam), readback through the shared CPU raster (the #17 follow-up keeps one pixel contract), emits lane=gpu. |
pick(model, cam, rect, x, y) -> Option<&str> |
the picking stage — return-asserted hit-test honouring the rect. |
GraphClipReport::state_json() |
the observable the EMIT-DOCTRINE asserts on (per-stage counts). |
WidgetRect |
the screen-px region the graph may paint into (the egui::Rect twin). |
Verification doctrine (return-vs-emit — the EMIT-DOCTRINE)
Per the spec: assert the return wherever the result is observable; implant an in-function functional_status emitter only for the can't-observe pixel stage.
layout—nodes_in == projected,nan == 0→ return (GraphClipReport).cull—drawn + culled == in, monotone → return.nodes—nodes.drawn == expected→ return.edges—edges.drawn == expected→ return.picking— probe→chip inside rect; gap/outside →None→ return (pick).composite— opaque pixels ⇒ EMIT two rows (testmatrix-gated):composite_lit(lit_px > 0) andcomposite_ink_outside_rect(ink_outside_rect == 0, the graph twin of the map clip oracle).
Oracles (inject-assert — real input, real output)
A REAL graph (deterministic grid generator, known node/edge counts) is fed; the asserts read REAL outputs, never "didn't panic":
composite.ink_outside_rect == 0— no painted pixel lands outside the widget rect (re-derived from the reloaded PNG blob, agent-readable).nodes.drawn == expected,edges.drawn == expected— exact in-rect counts.pick(centre) == that node,pick(gap|outside) == None.
Fail-on-bug / pass-on-fix (sensitivity — teeth proven)
unclipped_variant_leaks_ink_the_clipped_one_does_not renders the SAME sprawling graph twice: clip=false (no scissor) leaks ink_outside_rect = 7644 > 0 (RED), clip=true (scissor) leaks 0 (GREEN). Same nodes_drawn both ways (only the scissor differs), so the fix doesn't blank the view — it confines it. The GPU lane runs the same bug/fix pair.
Final-picture PNG blob
composite_clipped_… writes the rendered frame to $NORNIR_WAREHOUSE_ROOT/facett-graphview/graph_clip_final_picture.png (fallback $TMPDIR/facett-graphview/…), then reads it back and re-derives the non-blank + contained-in-rect oracles from the file — so an agent can Read the actual rendered image without asking a human. The GPU lane writes graph_clip_final_picture_gpu.png alongside.
Tests (tests/graph_clip.rs)
| test | stage(s) | proves |
layout_cull_nodes_edges_counts_are_exact |
layout/cull/nodes/edges | exact counts (12 nodes, 9 edges, 0 culled) |
cull_drops_offscreen_nodes_monotonically |
cull | drawn+culled==in, real partition |
picking_resolves_chip_under_probe_and_respects_rect |
picking | probe→chip; gap/outside→None |
composite_clipped_has_no_ink_outside_rect_and_writes_a_nonblank_png |
composite | ink_outside_rect==0 + PNG blob round-trip |
unclipped_variant_leaks_ink_the_clipped_one_does_not |
composite | sensitivity (bug RED / fix GREEN) |
decorated_clipped_render_is_clean_and_nonblank |
nodes/edges/composite | rings + emphasis edges stay in-rect |
gpu_lane_clipped_render_has_no_ink_outside_rect (feature gpu) |
composite (GPU) | vello GPU seam + clip oracle + GPU sensitivity |
Run:
export CARGO_TARGET_DIR=/home/<you>/.cache/claude-build/graphclip # compile off T9
cargo test -p facett-graphview --test graph_clip # CPU lane
cargo test -p facett-graphview --test graph_clip --features testmatrix # + matrix rows
cargo test -p facett-graphview --test graph_clip --features gpu # + GPU lane
Wiring into the nornir test-matrix
testmatrix = ["facett-core/testmatrix"] (Cargo.toml) gates every facett_core::testmatrix::emit(...) to a no-op in release. With --features testmatrix the composite emitters + the test-level emit rows append to $NORNIR_TESTMATRIX_OUT, one functional row per real check, which nornir test reads back. Emitted rows seen: render_graph_clipped::{composite_lit, composite_ink_outside_rect}, render_graph_clipped_gpu::composite_ink_outside_rect (lane=gpu), and the graph_clip::{counts_exact, cull_monotone, picking_resolves, composite_clipped_clean, sensitivity_bug_red_fix_green, decorated_clean, gpu_lane_clipped_clean} rows.