facett platform gaps — the pane-suite audit (2026-07-13)
Full inventory of the 66-crate facett UI platform against the Palantir-grade pane suite the constellation needs, mined from the workspace + git history + the
nornir testfunctional/robot-ui matrix. Headline: the suite is essentially complete — every headline pane exists and most are matrix-covered. The honest gaps are (a) ~10 orphan panes that emit no test-matrix cell of any aspect and are not wired into the demomega_matrixcoverage gate, and (b) GUI-polish tranches already filed elsewhere. This doc is the longest gap list; the round's concrete fix is at the bottom.
1. Pane inventory — the headline suite ALL EXISTS
| Palantir-grade surface | facett crate | status |
| graph / link-analysis | facett-graph · facett-graphview · facett-graphpan · facett-graphnav |
✅ rich, matrix-covered |
| 3D graph / call-cloud | facett-graph3d (+ DNA/time-helix) · facett-helix |
✅ |
| timeline / swimlane | facett-timeline · facett-gantt |
✅ (gantt is a leaf, see §3) |
| table / grid | facett-table · facett-grid · facett-arrow |
✅ flagship, copy-to-TSV |
| map / 3D-OSM / flight | facett-map (MapLayer trait) · facett-map3d(+-flight) · facett-geomap · facett-osm |
✅ ONE renderer, layers |
| forms | facett-form |
✅ (garde-validated) |
| warehouse deck | facett-warehousedeck · facett-icebergview · facett-table::Warehouse… |
✅ |
| security / supply-chain | facett-security (modgunn twin) |
✅ |
| claude chat pane | facett-claude |
✅ extraction complete (Elm seam, ClaudeTransport, robot JSON-drive + testmatrix cell) |
| job view | facett-jobview |
✅ |
| plan-DAG / query-profile | facett-plandag · facett-pipeline · facett-sdp · facett-brokkr/-brokkrview/-cicd |
✅ |
| data lineage | facett-lineage |
✅ code, ⚠ no matrix cell (this round's fix) |
| PM analytics | facett-kanban · facett-calendar · facett-cfd |
✅ leaf crates (§3) |
| docs / markdown / plot | facett-docview · facett-markdown · facett-plot · facett-plotters |
✅ |
| console / log / stat / tabbar | facett-console · facett-log · facett-stat · facett-tabbar |
✅ |
| misc surfaces | facett-card · facett-menu · facett-syschart · facett-model3d · facett-video · facett-git · facett-filedialog · facett-search · facett-file · facett-confirm · facett-toast · facett-matrix · facett-pop |
✅ |
Nothing on the headline suite is missing. The MapLayer trait unification (one renderer, selectable data-to-draw layers, OSM/Trafikverket as sources) is built (facett-map/src/layer.rs, .nornir/maptrait-design.md). facett-claude is a complete, in-design extraction. Do not re-invent any of these (Law #1).
2. THE REAL GAP — panes with zero test-matrix presence
nornir test builds its matrix from two aspects: functional rows (facett_core::testmatrix::emit → nornir_testmatrix::functional_status) and robot-ui rows (nornir-robotui RobotSession/Scenario). A pane invisible to BOTH is a coverage hole: a regression that blanks it shows no red cell.
Panes emitting no cell of either aspect (verified by grep for testmatrix::emit and RobotSession/run_scenario), and not covered by the demo mega_matrix gate (not in the demo LEGEND):
| pane | facett-core dep | testmatrix feature |
has robot.rs drive | note |
| facett-lineage | ✅ (3 refs) | ✅ declared | ✅ (Msg-drive asserts) | wired but forgot to emit — clean fix (§5) |
| facett-brokkrview | ✅ (1) | ✗ | headless.rs+render.rs | needs feature + a functional cell |
| facett-cfd | ✗ (egui-only) | ✗ | ✅ | leaf (§3) |
| facett-gantt | ✗ (egui-only) | ✗ | ✅ | leaf (§3) |
| facett-kanban | ✗ (egui-only) | ✗ | ✅ | leaf (§3) |
| facett-calendar | ✗ (egui-only) | ✗ | ✅ | leaf (§3) |
| facett-markdown | ✗ (egui-only) | ✗ | render.rs | leaf |
| facett-search | ✗ (egui-only) | ✗ | render.rs | leaf |
| facett-sdp | ✗ (egui-only) | ✗ | render.rs | leaf |
| facet-wrapped | ✅ (3) | ✗ | wasm_smoke | wasm host, not a pane per se |
Note: facett-holger and facett-brokkr DO emit robot-ui rows (via nornir-robotui Scenario) even though they emit no functional cell — they are covered, not gaps. facett-plandag/-timeline/-korp emit functional cells.
3. Design tension — the egui-only leaf panes
facett-kanban, facett-calendar, facett-gantt, facett-cfd, facett-markdown, facett-search, facett-sdp deliberately do not depend on facett-core — each Cargo.toml has an off-by-default facett = [] feature and a comment:
"Off by default so the crate compiles egui-only (robust against the facett repo's churn). Enable + add the path/registry dep when moving to facett."
So wiring a facett_core::testmatrix::emit cell into them means pulling facett-core as a (dev-)dependency, against their stated churn-robust design. Two honest routes, a decision for Rickard, not a unilateral edit:
- (A) demo-side coverage — wire these leaves into
facett-demo'sLEGEND+mega_matrixcell registry. The coverage gate then protects them, one place, and the leaf crates stay egui-only. Preferred (single-source, matches the existing gate). Cost: amega_matrixcell + data fixture per pane in facett-demo. - (B) opt-in leaf cell — add
facett-core+ atestmatrix = ["facett-core/testmatrix"]passthrough as a dev-dependency and emit from each crate's own robot.rs (asfacett-lineagedoes). Keeps the cell next to the drive test but adds the dep.
Recommend (A) for the four PM/analytics leaves (kanban/calendar/gantt/cfd) since the demo already showcases the deck; leave markdown/search/sdp as-is (thin).
4. Secondary gaps (already filed — do not duplicate)
- GUI tiptop / graphics SOTA — CSM/VSM shadows, bloom mip-pyramid, GTAO, TAA:
.nornir/graphics-sota-roadmap-reasoning.md. Idle auto-rotate + click-to-Yggdrasil for the 3D map/graph panes:.nornir/idle-auto-rotate.md. - korp Tools-menu "fill OSM Sweden roads" demo as a jera job — collectors + MapLayer bridge exist; verify the end-to-end trigger (
.nornir/facett-worklist.mdP1). - stale doc
facett-demo-reasoning.md(describes a 19-facet deck; deck is 57+). - empty-states / clipping / theming polish — per-pane pass; most panes handle empty state (see cfd placeholder, gantt empty range) — spot-check the thin leaves.
4b. LANDED — the ONE shared discovery-driven probe (backlog top-10 #6)
The highest-leverage Law-#1 win for the zero-cell gap was not hand-writing 14 per-crate cells but building one generic harness every pane reuses. That landed this round in facett-core:
facett_core::harness::probe_facet(&mut dyn Facet, &[&str]) -> FacetProbe— headless-renders ANY object-safeFacet, then plays a scripted list ofupdate_jsonJSON messages, snapshottingstate_jsonafter each. Returns aFacetProbewith the initial render's vertex proof + per-messageProbeSteps (msg, vertices,changed, state). No display, no GPU, no concreteMsgtype at the call site.FacetProbe::{drew,responded,cardinality}give the three facts a matrix cell needs (drew geometry · input surface is live · reports domain data).facett_core::testmatrix::emit_facet_probe(component, &probe)and the one-shotprobe_and_emit(component, &mut facet, &msgs)turn a probe into the functional rows (headless_render+responds_to_input), feature-gated so release strips the edge. A blank OR zero-cardinality pane → RED; a deadupdate_json→ RED.
Adoption is one line: a leaf builds its pane via its own demo()/local() constructor and calls probe_and_emit. facett-brokkrview is the first consumer (facett-brokkrview/tests/robot.rs) — this simultaneously closes its zero-cell gap (§2, follow-up #2) AND its missing robot json-drive scenario (the [medium/medium] upgrade-render-proof item), from one shared path. The remaining zero-cell panes with a facett-core dep (and the demo-side route for the egui-only leaves, §3) now backfill through this same call instead of re-inventing render+emit.
4c. LANDED (2026-07-14) — dead update_json robot seams made LIVE (5 panes)
A distinct gap from §2 (which is about matrix presence): several panes that DO emit an in-view ui_render functional cell were nonetheless not robot-drivable through the standard JSON seam. The impl_facet_via_elm! bridge generates no update_json, and Facet::update_json defaults to a no-op — so unless a pane overrode it (as facett-brokkrview / facett-korp::GraphPane do), a headless robot / the shared probe_facet harness fed it messages that changed nothing. The pane looked "covered" (it had a render cell) but its FC-2 input surface was dead.
Fixed this round for 5 panes by (a) deriving Serialize, Deserialize (rename_all="snake_case") on each pane's Msg, (b) overriding update_json to parse one tagged Msg and apply it through the single Elm::update path, and (c) adding a one-test tests/robot.rs that drives a real state-changing message chain through the SHARED facett_core::testmatrix::probe_and_emit:
| pane | drive script | new cells |
facett-matrix |
select_repo→clear_selection |
headless_render + responds_to_input |
facett-cicd |
select_pipeline→clear_selection |
same |
facett-log |
set_search→clear_filters |
same |
facett-stat |
set_title→clear_rows |
same |
facett-security |
select(id)→select(null) |
same (hand-written impl Facet) |
responds_to_input is NEW RED-when-broken coverage: it goes red if any of these seams regresses back to a no-op. All additive (L2) — no view/render path changed. Same one-line-adoption path as §4b; the remaining macro-bridged panes with a serde-able Msg (see §6) can adopt it identically. Note: panes whose Msg carries non-serde nested types (e.g. facett-tabbar's egui::Rect, facett-graphpan's egui::Vec2) need those types made serde-able first, or a #[serde(skip)] on the offending variant, before their JSON seam can go live.
4c-follow-up (2026-07-14, second pass) — remaining macro-bridged panes CLOSED
The six panes flagged above as remaining are now all LIVE, same pattern, all additive, each with its own tests/robot.rs. None needed a render-only fallback — every Msg was made cleanly serde-drivable:
| pane | drive script | serde note |
facett-jobview |
select→clear_selection |
Msg payloads (SortKey/JobEntry) already serde-able |
facett-icebergview |
select_snapshot(100)→(200) (time-travel) |
all-primitive Msg, trivial |
facett-warehousedeck |
select_pane→clear_selection |
DeckLayout/usize/String, trivial |
facett-git |
select_path→show_pane(log) |
Pane/Blob already derive serde → full drive |
facett-graphpan |
select→pan_by([x,y]) |
Vec2 variants reuse the Model's existing vec2_serde [x,y] codec |
facett-tabbar |
select_tab×2 |
internal FC-7 AdvanceUnderline{egui::Rect} tick is #[serde(skip)] (never robot-driven); the one real input SelectTab is fully drivable |
The facett-tabbar case is the notable one: rather than teach egui::Rect a serde codec, the offending variant is an internal injected-clock tick the pure view emits to itself, not a user input — so #[serde(skip)] is exact and minimal, and the real input surface (SelectTab) is fully covered.
With this pass the dead-update_json seam is closed across all 11 macro-bridged Elm panes that carry a mutable Msg surface (5 first pass + 6 here). Each adds headless_render + RED-when-broken responds_to_input cells.
5. This round's fix — facett-lineage functional-matrix cell
facett-lineage is the only zero-matrix pane already fully wired for the functional aspect (facett-core dep + testmatrix passthrough feature declared in Cargo.toml) that simply never calls emit — a half-wired, in-design gap. It is also the flagship Palantir surface (data lineage / link-analysis over the skade lineage_events fact log, rendered through the facett-graphnav graph-DB IDE).
Fix: a testmatrix_cell_lineage_dag test in facett-lineage/tests/robot.rs that drives the full lineage-DAG gesture chain (build → query → select → provenance path → layout → export) and emits one functional row per meaningful check via facett_core::testmatrix::emit, mirroring facett-graphnav's pattern. No-op in release (feature off); a real row on the sink under --features testmatrix. The Palantir lineage pane now shows green in the nornir test functional matrix instead of being invisible.
6. Follow-up backlog (ranked)
- Decision (A vs B) for the egui-only leaves (§3) — then backfill kanban/calendar/gantt/cfd cells. Preferred: demo
mega_matrixwiring. DONE (§4b): the sharedfacett-brokkrview— addtestmatrixfeature + functional cellprobe_and_emitpath intests/robot.rs.- Backfill the remaining facett-core-dep zero-cell panes (
facett-holger,facett-korp, …) through the SAMEprobe_and_emitpath — a one-linetests/robot.rseach, no new per-crate boilerplate. - Wire
facett-lineage(andfacett-form) into the demoLEGEND/mega_matrixso the coverage gate protects them too (defence in depth). - GUI-polish tranche (§4) — graphics SOTA + idle-rotate on the 3D panes.