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

nordisk/facett

facett-demo/Cargo.toml

[package]
name = "facett-demo"
description = "facett — the showcase app: ONE eframe binary that exercises every facett component with fake-but-realistic data, switchable across all palettes (the living D4 compliance proof + screenshot gallery)"
# Showcase binary, opted in to crates.io. PUBLISH ORDER: osm-katana (its dep,
# pulled by the default `region-clip` feature, ~line 52) must be released to
# crates.io FIRST — it is now `publish = true` in the znippy workspace and all its
# own deps are on crates.io, so it is releasable; once osm-katana 0.3.x is up,
# facett-demo (which pins `version = "0.3.0"` below) resolves and publishes.
publish = true
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
# Development notes, agent instructions and machine-local tooling stay in the
# repository; they are not part of the published crate.
exclude = [
    ".nornir/",
]

[dependencies]
facett-flow = { path = "../facett-flow", version = "0.2.0", features = ["host", "layered", "status", "rate", "labels", "compact-state"] }
# The umbrella crate (every component). The wgpu GPU paint-callbacks (`map-wgpu` /
# `map3d-wgpu`) are a **native-only** opt-in — see the `[target.cfg(not(wasm))]`
# block below. On wasm the CPU painters draw the maps, so the base `facett` here
# carries no wgpu features.
#
# The demo is the reference app: it is the consumer that opts IN to the umbrella's
# four heavy, off-by-default components, because it renders all of them
# (`facett::docview`, `facett::plotters`, `facett::video`, `facett::model3d`).
facett = { path = "../facett", version = "0.2.0", features = ["model3d", "docview", "video", "plotters"] }
facett-map = { path = "../facett-map", version = "0.2.0" }
# The reusable 3D-model viewer (embedded glTF skull, CPU-lit, status-tinted eyes).
# The demo names it directly as well as through the umbrella's `model3d` feature,
# because `src/lib.rs` uses the `facett_model3d::` path.
facett-model3d = { path = "../facett-model3d", version = "0.2.0" }
# The app-framework layer (NavModel + Router + Sidebar/NavShell) — Fas 1 of the
# facett framework införandeplan. Demoed via the `nav` tab.
facett-app = { path = "../facett-app", version = "0.2.0" }
# CONS-CORE GRAPH-DEMO: the consolidated graph render ENGINE. Not re-exported by
# the umbrella `facett` (it is the render kernel below the `facett-graph` skin), so
# the demo depends on it directly to drive the `graphview` tab through the shared
# `facett-core::render` L0 Canvas (the `render_to_rgba_l0` path). No `gpu` feature
# here: the demo's headless test + the wasm bundle draw the L0 lane on the CPU
# (`vello_cpu`), which is always available.
facett-graphview = { path = "../facett-graphview", version = "0.2.0" }
# The bare pan/zoom graph CANVAS (the borrowed `draw_graph` renderer + a
# `GraphView` transform + the `GraphPanView` Facet), adopted from nornir's viz
# graph_render. Not re-exported by the umbrella `facett` (it is the minimal canvas
# half, distinct from facett-graphview's consolidated render engine), so the demo
# depends on it directly to wire the `graphpan` tab into the deck.
facett-graphpan = { path = "../facett-graphpan", version = "0.2.0" }
# facett-graphnav — the GRAPH NAVIGATOR (V.G) IDE surface: pan/zoom camera,
# Appearance ranking/partition, Arrow table view, GEXF/GraphML I/O, stats panel.
facett-graphnav = { path = "../facett-graphnav", version = "0.2.0" }
facett-graphgen = { path = "../facett-graphgen", version = "0.2.0" }
# facett-grid — the Arrow-backed flagship grid the V.G data-laboratory table uses.
facett-grid = { path = "../facett-grid", version = "0.2.0" }
# facett-manual — the real in-app MANUAL pane (compiled-in Markdown + typeset SVG
# book), wired as a deck tab for the error-code showcase's "facett MANUAL" section.
facett-manual = { path = "../facett-manual", version = "0.2.0" }
# facett-sdp — the Spark Declarative Pipelines editor (flows = named Spark-SQL
# queries over deps, + a dep-DAG preview + static validation). A leaf crate that
# mirrors the Facet shape (title/ui/state_json) but does NOT depend on facett-core,
# so the demo adopts it into the deck via a thin `sdp_tab::SdpTab` wrapper. Pure
# egui + serde → wasm-clean.
facett-sdp = { path = "../facett-sdp", version = "0.2.0" }
# facett-brokkr — the brokkr CI/build-pipeline BUILDER (text `brokkr.toml` editor +
# a structural CLICK builder with a topo DAG preview). Like facett-sdp it mirrors
# the Facet shape without depending on facett-core, adopted via `brokkr_tab::BrokkrTab`.
# Pure egui + serde + toml → wasm-clean.
facett-brokkr = { path = "../facett-brokkr", version = "0.2.0" }
# facett-pipeline with the `runa-adapter` feature ON — pulls in the RunaPipelineAdapter
# so the `runa` tab renders a dwarves forge `dwarves_runa::Pipeline` on the REUSED animated
# node-DAG viewer (features unify with the umbrella `facett`'s own facett-pipeline dep,
# so `facett::pipeline::RunaPipelineAdapter` is available too).
facett-pipeline = { path = "../facett-pipeline", version = "0.2.0", features = ["runa-adapter"] }
# facett-releaseview — the RELEASE-CONVERGENCE view: the constellation dep DAG in
# THREE states (LOCAL manifest · SPARRING Gate-B rehearsal · CRATES_IO published)
# that a release drives to CONVERGE (a 3-plane depth render + a 2D tri-badge
# fallback). Reached directly like the other view adoptions (the umbrella `facett`
# re-exports skins, not this view). Pure egui + serde + facett-core/graph → wasm-clean.
facett-releaseview = { path = "../facett-releaseview", version = "0.2.0" }
# `runa` — the dwarves forge's typed pipeline authoring layer (edda leaf). Used by
# `runa_tab` to build the seeded korp-ci pipeline the `runa` tab renders. Path
# mirrors the other edda-leaf path-deps (`../../edda/crates/<name>`).
dwarves-runa = { path = "../../edda/crates/dwarves-runa", version = "0.3.0" }
facett-core = { path = "../facett-core", version = "0.3.0" }
# facett-git — the git repository facet (branches / commit log / file tree /
# syntax-coloured source). Not re-exported by the umbrella `facett`, so the demo
# depends on it directly to wire the `Git` tab. Built WITHOUT the heavy `gix`
# feature (the `GitView::demo()` seed needs no repo on disk), so it is wasm-clean.
facett-git = { path = "../facett-git", version = "0.2.0" }
# facett-warehousedeck — the multi-pane lakehouse dashboard (a FacetDeck WALL of N
# panes, each binding a table to a view-kind: 3D graph / grid / chart / blob).
# Not re-exported by the umbrella `facett`, so the demo depends on it directly to
# wire the `warehousedeck` tab. Pure egui + arrow + the CPU graph3d painter → wasm-clean.
facett-warehousedeck = { path = "../facett-warehousedeck", version = "0.2.0" }
# facett-jobview — the reusable hierarchical/streaming job-tree panel (parent
# populate job + foldable child sub-jobs), adopted from nornir's viz jobs panel.
# Demoed with a fake `nordisk` populate so the fold/unfold + live-stream story is
# visible in the gallery. Host-agnostic (korp/njord reuse the same JobList).
facett-jobview = { path = "../facett-jobview", version = "0.2.0" }
# facett-zoneui — the TWO shared zone/jera framework widgets (ZonePane +
# JeraCentral) every suite app drops in. Demoed via `demo_zoneui`: the zone-populate
# pane (with a demo generator) + the jera-central panel (jobs WITH their zone column).
facett-zoneui = { path = "../facett-zoneui", version = "0.2.0" }
# The two net-new Spark-UI components (the "better-than-Databricks" Spark 4.x lane):
# the swimlane Gantt (jobs/stage/task event timeline) + the metric-bearing operator
# DAG (cost-heat / collapsible WholeStageCodegen / AQE initial-vs-final). Not
# re-exported by the umbrella `facett`, so the demo depends on them directly to wire
# the `timeline` + `plandag` tabs into the deck.
facett-timeline = { path = "../facett-timeline", version = "0.2.0" }
facett-plandag = { path = "../facett-plandag", version = "0.2.0" }
# facett-security — the software-supply-chain security report view (verdict +
# findings + EPSS/KEV + a CVE/advisory table), the UI twin of modgunn's scan
# output. Reached directly like the graphview/graphpan/jobview adoptions (the
# umbrella `facett` re-exports the skins, not this view). `local()` seeds a Block
# report so the gallery shows a real verdict + non-trivial findings with no host.
facett-security = { path = "../facett-security", version = "0.2.0" }
# facett-helix — the TIME-HELIX DAG view: a plan/dependency DAG rendered as a glowing
# helix advancing ALONG a time axis (idea/task/test/crate nodes on per-system strands,
# soft rubberband deps, windable spindle coils, multi-helix scenes + inter-helix links,
# an animated traverse + sweep bloom). Reached directly (the umbrella `facett` re-exports
# skins, not this view). The demo builds a nordisk-constellation scene so the gallery
# shows real multi-coil winding through release time with a live RUSTSEC CVE event.
facett-helix = { path = "../facett-helix", version = "0.2.0" }
# POP-GRAPH: the canonical, pure-Rust Swedish 11-million-person population graph
# generator (12-label graph DB). NO falkordb / arrow / network / fs deps (optional
# serde only), so it compiles for wasm32-unknown-unknown — the demo calls
# `simulate()` / `schema()` directly and renders the resulting `PopGraph` with no
# backend, no network. This IS the wasm-clean "graph-mem database"; the `pop_model`
# / `pop_tab` modules build a thin LOD/filter layer over it. The path
# `../../knut/crates/knut-popsim` resolves from facett/facett-demo to the sibling
# knut checkout. `serde` is on so a PopGraph can be (de)serialized.
knut-popsim = { path = "../../knut/crates/knut-popsim", version = "0.3.0", features = ["serde"] }
# ── The 2026-08-20 roster completion: the workspace components the gallery NEVER
# wired (the roster gate compared against the umbrella `facett`, which none of these
# are in — see tests/roster_gate.rs for the by-construction fix). All wasm-clean
# (pure egui + serde; stubbed/seeded fixtures, no network); the two native-only ones
# (facett-deploykey / facett-buildthing) live in the native table below. ──────────
# facett-cicd — the CI/CD forge panel (pipeline roster → runs → stages/steps + log
# tail); `CicdPanel::demo()` seeds three pipelines. The `cicd` tab.
facett-cicd = { path = "../facett-cicd", version = "0.2.0" }
# facett-brokkrview — the brokkr RUN viewer (roster ⇄ tree ⇄ DAG of a forge
# pipeline's runs) — the READ side beside the `brokkr` BUILDER tab. `demo(title)`
# seeds a green build→test→ship run. The `brokkrview` tab.
facett-brokkrview = { path = "../facett-brokkrview", version = "0.2.0" }
# facett-lineage — the data-lineage browser (skade lineage_events as a navigable
# dataset DAG over the GRAPH NAVIGATOR). `demo()` seeds a raw→clean/metrics→gold
# multi-hop lineage. The `lineage` tab.
facett-lineage = { path = "../facett-lineage", version = "0.2.0" }
# facett-fleet-view — the fleet gate board (members × declared test surfaces as
# coloured cells + the RED `Gap == ∅` banner). `local()` seeds a 3-member board
# with a real hole. The `Fleet` tab.
facett-fleet-view = { path = "../facett-fleet-view", version = "0.2.0" }
# facett-holger — the holger registry & artifact browser; `Default` mounts the
# seeded no-backend fixture (8 repos, a crates-mirror listing).
facett-holger = { path = "../facett-holger", version = "0.2.0" }
# facett-korp — the korp caseworker panes. Only the `IngestPane` is wired (its
# `demo()` roster is self-contained); the other three korp panes have empty
# defaults needing live host rows — see the "Not shown here" doc block.
facett-korp = { path = "../facett-korp", version = "0.2.0" }
# facett-auth-ui — the device-code sign-in pane over a pluggable LoginSeam; driven
# by the network-free `StubLogin`. The `Sign in` tab.
facett-auth-ui = { path = "../facett-auth-ui", version = "0.2.0" }
# facett-binview — the binary-analysis pane (checksec badges + size sparkline +
# bloat treemap + snapshot diff) over the `StubBinaryData` seam. The `Binary
# analysis` tab.
facett-binview = { path = "../facett-binview", version = "0.2.0" }
# facett-coderoom-view — the world coderoom (crates + semver compat edges + the
# what-breaks impact set) over the `StubCoderoomData` seam. The `World coderoom` tab.
facett-coderoom-view = { path = "../facett-coderoom-view", version = "0.2.0" }
# facett-claude — the Claude conversation pane over a pluggable ClaudeBackend;
# the demo seeds one round-trip turn through the offline `EchoBackend` at
# construction so the surface opens POPULATED (the demo's law). The `Claude` tab.
facett-claude = { path = "../facett-claude", version = "0.2.0" }
# facett-about — the shared About-card WIDGET (not a Facet): the one identity
# surface every suite app mounts. Wrapped demo-locally by `about_tab` (the
# errcode_tab pattern) so the gallery shows it inline + as the real modal window.
facett-about = { path = "../facett-about", version = "0.2.0" }
egui = { workspace = true }
serde_json = { workspace = true }
# `egui-wgpu` for the GFX v2 tab's device lanes (see the `gfx-v2-gpu` feature).
# In the ALL-TARGET table, not the native one, on purpose: `eframe`'s
# `wgpu_no_default_features` already puts `egui-wgpu` in the wasm bundle, so making
# it optional-here costs the web demo nothing, while a target-scoped optional dep
# would make the default feature set differ per target — which is the kind of
# thing that compiles on the machine you tried it on and nowhere else.
# `default-features = false`: `egui-wgpu/default` ends in `wgpu/default` +
# `wgpu/webgl`, which would re-admit GLES/`glow` past the workspace `wgpu` list.
egui-wgpu = { version = "0.36", optional = true, default-features = false, features = [
    "fragile-send-sync-non-atomic-wasm",
    "macos-window-resize-jitter-fix",
] }
arrow-array = "59"
arrow-schema = "59"

# ── native (desktop) ────────────────────────────────────────────────────────
# eframe runs the **wgpu** backend (the map tabs' GPU paint callbacks need a wgpu
# RenderState). `osm-katana` (the in-process region clip, parquet + threads) is
# native-only too.
#
# NOTE: this block once also held the wgpu-feature passthroughs, to keep WebGPU out
# of the wasm build in favour of "wider browser support". That is retracted — the web
# demo is WebGPU-only now (see the wasm block below, which enables `map-wgpu` /
# `map3d-wgpu` on purpose). Modern platforms only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# `wgpu_no_default_features`, NOT `wgpu` (same reason as the wasm block below):
# eframe's plain `wgpu` feature expands to `egui-wgpu/default` → `wgpu/default` +
# `wgpu/webgl`, re-admitting GLES/`glow`. The backends come from the workspace
# `wgpu` list via facett-core's GPU lane.
eframe = { version = "0.36", default-features = false, features = ["default_fonts", "wgpu_no_default_features", "wayland", "x11"] }
facett = { path = "../facett", version = "0.2.0", features = ["map-wgpu", "map3d-wgpu"] }
# The standalone 3D OSM viewer demo (`src/bin/osm3d_demo.rs`) drives the 3D map
# component + the `Way` type directly (native-only bin).
facett-map3d = { path = "../facett-map3d", version = "0.2.0", features = ["wgpu"] }
# The AAA planetary FLIGHT-SIM engine layer (floating origin + 6DOF camera rig +
# real-DEM terrain). The standalone flight demo (`src/bin/flight_demo.rs`) drives
# its `FlightCamera` / `FlightController` / `TerrainField` directly. The `egui`
# feature adds the live `ControlFrame::from_egui` "actually fly it" adapter; the
# GPU flight renderer is a roadmap seam, so no `wgpu` feature here — the demo does
# its own CPU perspective paint of the terrain mesh (like osm3d_demo). Native-only.
facett-map3d-flight = { path = "../facett-map3d-flight", version = "0.2.0", features = ["egui"] }
# region-clip: run the OSM region clip IN-PROCESS (no shell-out). Optional path dep
# on the converter crate in the sibling znippy workspace. Gated behind the
# `region-clip` feature (ON by default); building `--no-default-features` (as the
# wasm build does) drops it and the picker shows a graceful "feature off" message.
osm-katana = { path = "../../znippy-zoomies/osm-katana", version = "0.3.0", optional = true }
# korp-collectors: the standalone LEAF connector layer (depends on NEITHER facett
# nor korp — that's what lets facett-demo consume it without a cycle). Its `osm`
# feature brings the `RegionSource` fetch seam; the region picker's `with_source`
# uses it to FETCH a region's `.osm.pbf` BEFORE the in-process clip+load. The seam
# passes a FILE PATH (`.osm.pbf`) — NO arrow types cross the boundary, so korp's
# arrow version never enters the demo. Gated behind `region-connector` (OFF by
# default). Native-only (fetch + convert). `default-features = false` keeps it lean.
korp-collectors = { path = "../../korp-collectors", optional = true, default-features = false, features = ["osm"] , version = "0.2.0" }
# facett-deploykey — the 🔑 SSH deploy-key surface (key state / remote fleet /
# resolution ladder). NATIVE-ONLY: its `nornir-git` dep pulls gix + tokio + russh,
# none of which build for wasm32. `demo()` seeds a FETCHING fleet. The `Deploy key`
# tab, gated like the seven korp caseworker-flow tabs.
facett-deploykey = { path = "../facett-deploykey", version = "0.2.0" }
# facett-buildthing — the ⚒ Build Thing deck (variant menu / feature graph / build
# result). NATIVE-ONLY: `nornir-build-thing` is a native plugin seam. `demo()`
# seeds the holger-shaped menu. The `Build Thing` tab, gated the same way.
facett-buildthing = { path = "../facett-buildthing", version = "0.2.0" }
# The GPU adapter selector (`gpu_select`) logs the chosen wgpu adapter at startup.
log = "0.4"
# znippy's fork-join **gatling** engine (`gatling_for_each`, one no-barrier worker
# per core) — the ONLY sanctioned parallelism (rayon is FORBIDDEN). Drives the
# native parallel population generation in `pop_model::sample_parallel`. Native-only
# (no threads in the wasm sandbox — the wasm path stays single-threaded).
znippy-zoomies = { path = "../../znippy-zoomies", version = "0.1.26" }
# The reusable robot-UI driver (nornir-robotui): the `Observable` observe seam +
# a declarative `Scenario` + the CHOOSABLE Headless(CI)/Watch(visible) replayer the
# `facett_robot` bin drives (see `src/robot.rs`). Optional + behind the `robotui`
# feature so the default demo build never pulls the driver.
#
# **Pinned to 0.2.6 via a CONTAINED `path` (the edda checkout), NOT a root
# `[patch.crates-io]`.** 0.2.6 (edda `194ce3f`) is the build where the WATCH window
# resolves clicks through the LIVE AccessKit tree (so the robot drives the REAL deck
# tabs/controls with no recorded `▶` rail) and adds the `watch-wgpu` renderer (so the
# OSM 3D city paints on the GPU in the visible window instead of the glow→CPU
# fallback). It is not on crates.io yet (the index tops out at 0.2.5), and the
# workspace root MUST stay patch-free — the nornir-server builds the facett *library*
# crates from its own clone and a root patch would reach these dev files. A `path`
# scoped to this leaf DEMO binary (never a server dependency), gated behind the
# optional `robotui` feature, is the contained way to consume the unpublished build:
# it rewrites the crate for `facett-demo` ONLY, leaving facett-app / facett-graph /
# facett-brokkr / facett-graphnav / facett-holger on their registry 0.2.x. Swap the
# `path` for a plain `version` once 0.2.6 publishes.
# Native-only — the watch window is a winit/wgpu|glow windowing stack, never in the
# wasm bundle. egui 0.34, matching facett's stack. `watch-wgpu` implies `watch`.
nornir-robotui = { version = "0.4.0", features = ["watch-wgpu"], optional = true }

# ── wasm (the LIVE WEB DEMO) ────────────────────────────────────────────────
# Built by `cargo xtask demo-wasm` for `wasm32-unknown-unknown` and published to
# Codeberg Pages. eframe runs the **wgpu (WebGPU)** path here, and the wgpu paint
# callbacks are ON for the web (`map-wgpu` / `map3d-wgpu` below) so the real GPU
# OSM-3D ships to the web demo. The native-only `region-clip`/osm-katana is still
# feature-gated out (the demo is built `--no-default-features` for wasm, and
# `osm_tabs::load()` falls back to its synthetic in-memory sample since there is no
# filesystem in the browser).
#
# `wgpu_no_default_features`, NOT `wgpu`: eframe's plain `wgpu` feature expands to
# `egui-wgpu/default`, whose list ends in `wgpu/webgl`. That compiles wgpu's WebGL2
# backend and `glow` into this bundle, and `preferred_backends()` is
# `Backends::BROWSER_WEBGPU` on wasm32 — so the runtime mask can never reach it.
# Measured on this bundle (post `wasm-opt -Oz`): removing it took the wasm from
# 18,722,627 to 16,250,211 bytes — 2.36 MiB of download for code that cannot run.
[target.'cfg(target_arch = "wasm32")'.dependencies]
eframe = { version = "0.36", default-features = false, features = [
    "default_fonts",
    "wgpu_no_default_features",
] }
facett = { path = "../facett", version = "0.2.0", features = ["map-wgpu", "map3d-wgpu"] }
facett-map3d = { path = "../facett-map3d", version = "0.2.0", features = ["wgpu"] }
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
# `js-sys` + the DOM features: `wasm_start` reads `navigator.gpu` / `isSecureContext`
# reflectively, awaits `requestAdapter()`, and writes the plain "no GPU" message into
# the page instead of leaving a black canvas (facett_core::adapter_retry).
js-sys = "0.3"
web-sys = { version = "0.3", features = ["HtmlCanvasElement", "HtmlElement", "Window", "Document", "Element", "Node", "Navigator", "Location"] }
console_error_panic_hook = "0.1"
log = "0.4"

# The standalone, self-contained 3D OSM viewer (NOT the shared demo). Opens the
# `facett-map3d` orbit-camera viewer on `$FACETT_OSM_PARQUET` (a ways.parquet) or
# a synthetic fallback so it runs fixture-free. Native-only (empty `main` on wasm).
[[bin]]
name = "osm3d_demo"
path = "src/bin/osm3d_demo.rs"

# The standalone, self-contained FLIGHT demo (NOT the shared demo). Opens the
# `facett-map3d-flight` 6DOF flight rig over real-DEM Sweden terrain (synthetic
# procedural fallback so it runs with NO `.hgt` files on disk); WASD/mouse fly it.
# Native-only (empty `main` on wasm).
[[bin]]
name = "flight_demo"
path = "src/bin/flight_demo.rs"

# The ONE connected flow: pick Sweden → clip the cached planet OSM to the Sweden
# polygon (one continuous animated progress bar) → fly the clipped result in 3D with
# the 6DOF flight camera. Planet source + clip cached on a large disk
# (`$FACETT_OSM_CACHE` or /mnt/work4t/facett-osm-cache, NEVER T9), keyed by
# region+source-hash so a second run skips the clip. Honest fallback (embedded
# Sigtuna + procedural DEM) when no planet .pbf is present. Native-only (empty
# `main` on wasm).
[[bin]]
name = "osm_fly_demo"
path = "src/bin/osm_fly_demo.rs"

# The Sigtuna 3D NAVIGATOR: the embedded Sigtuna real-OSM clip CROPPED to its dense
# town core, extruded into the AAA GPU 3D map, flown by the cinematic tour autopilot —
# start HIGH circling the houses from the air, DESCEND to street level, then DRIVE down
# a real Sigtuna street. The Google-Maps-3D-quality demo on REAL data (reuses
# facett-map3d's Map3D + SigtunaTour + route; osm_tabs::crop_to_town_core makes the
# houses house-scale). Native-only (drives eframe/wgpu); empty `main` on wasm.
[[bin]]
name = "sigtuna_demo"
path = "src/bin/sigtuna_demo.rs"

# The CHOOSABLE robot-UI entry point: `facett_robot run` (HEADLESS egui_kittest
# drive → matrix rows, CI) / `facett_robot watch` (a REAL paced eframe window you
# watch), or no subcommand → `ROBOTUI_WATCH=1` chooses. Behind `required-features`
# so a plain demo build never compiles it or the robot driver. See `src/robot.rs`.
[[bin]]
name = "facett_robot"
path = "src/bin/facett_robot.rs"
required-features = ["robotui"]

[features]
# Falsett resident curves and animated packets.
flow-wgpu = ["facett/flow-wgpu", "facett-flow/wgpu", "facett-pipeline/wgpu", "facett-plandag/wgpu", "facett-brokkrview/wgpu", "facett-brokkr/wgpu"]
# The demo always builds facett with `map-wgpu` (see the dependency above), so
# this passthrough is ON by default — it gates the demo-side `with_gpu(true)`
# opt-in for the OSM 2D tab's line-ways GPU fast-path. Building the demo with
# `--no-default-features` drops the demo-side opt-in (the CPU painter still draws);
# the GPU lane needs a real GPU + the installed renderer to actually run.
# `gpu` is ON by default as of 2026-07-22. It is the ONLY thing that calls
# `install_cloud_renderer` (main.rs), and without that call `Graph3D`/the warehouse
# deck/CodeVault tessellate every node disc and edge line on ONE CPU core each frame.
# The instanced GPU cloud existed and was proven by tests, but no host armed it, so
# the live GPU path was theoretical — measured on oden (RTX 4090): the shipped demo
# ran the CPU painter. Turning it on is fail-safe by construction: `draw_cloud`
# returns false (and the CPU painter draws) when there is no `RenderState`, no
# installed renderer, or a degenerate rect — so a GPU-less box is unaffected. It sits
# beside `map-wgpu`/`map3d-wgpu`, which are already default and already wgpu.
default = ["flow-wgpu", "map-wgpu", "map3d-wgpu", "region-clip", "gpu", "gfx-v2-gpu", "graph-layout-gpu", "graph-wgpu"]
# The 2-D graph (facett-graph `GraphView`, the `graph` tab) on the shared instanced GPU
# cloud lane — the same `graphcloud` renderer `gpu` installs; facet-wrapped has carried
# `facett-graph/wgpu` since the lane landed and the pages demo did not (2026-10-01).
# Without an installed renderer the egui painter draws, so a GPU-less build is unaffected.
# Since 2026-10-01 it also lights the same lane in facett-graphpan (`graphpan`),
# facett-graphview (`decograph` — the DecoratedGraphView falkor / World coderoom use) and
# facett-graphnav (`Graphs`, `lineage`: the resident cloud above SCALE_NODES); the
# `Universe` tab draws on that resident lane directly.
graph-wgpu = ["facett/graph-wgpu", "facett-graphpan/wgpu", "facett-graphview/gpu-cloud", "facett-graphnav/wgpu", "facett-graphgen/graph-wgpu", "facett-graphgen/cloud"]
# The graph navigator's force layout as a NON-BLOCKING GPU job on the device eframe
# already holds (facett-graphnav `gpu` + `install_layout_device` in main.rs). Its own
# feature, not folded into `gpu` above: that one selects the instanced RENDER cloud,
# this one selects where the LAYOUT is computed, and a host may want either alone.
graph-layout-gpu = ["facett-graphnav/gpu", "facett/graph-layout-gpu", "facett-graphgen/graph-layout-gpu"]
# `gpu` turns on the GPU depth-tested / bloom lanes in facett-graph3d (the emissive
# bloom pass the 🫧 System Map + CodeVault + Graph3D feed their glass/glow through).
# OFF by default: the CPU painter draws the translucent glass + fluid (wasm-clean +
# the headless snapshot proof), so a GPU-less build is unaffected; `--features gpu`
# lights up the wgpu glass+fluid bloom path on Loki's RTX 5080.
gpu = ["facett/graph3d-wgpu", "facett-graphgen/graph3d-wgpu", "facett-graphgen/cloud"]
map-wgpu = ["facett/map-wgpu"]
# region-clip: enable the in-process OSM region clip (Sverige/Skandinavien/Europa
# buttons in the 🌍 Region picker). Pulls in the osm-katana converter crate and
# calls its `convert()` lib API directly on a background thread — no subprocess.
region-clip = ["dep:osm-katana"]
# region-connector: feed the 🌍 Region picker from a `korp-collectors` RegionSource
# CONNECTOR — a region's OSM `.osm.pbf` is FETCHED by the connector (e.g. the
# Geofabrik-style `HttpOsmSource`) BEFORE the picker converts+loads it. Pulls
# `region-clip` so the fetched PBF can be turned into GeoParquet in-process. The
# default facett-demo build does NOT enable this (the picker keeps its cached-planet
# path); turning it on adds `RegionPicker::with_source(...)`. OFF by default.
region-connector = ["dep:korp-collectors", "region-clip"]
# The OSM 3D tab's depth-tested GPU Z-buffer city render.
map3d-wgpu = ["facett/map3d-wgpu"]
# ── GFX v2 (the renderer-track showcase tab) ────────────────────────────────
# `gfx-v2-gpu` turns on the DEVICE lanes of the `GFX v2` tab: the item-8 `R32Uint`
# pick pass and the item-4 GPU label-collision pass, both driven through
# `facett_core::render::gpu`. It exists as a feature, and not as an unconditional
# dependency, for two reasons:
#
#  1. It needs `facett-core/wgpu` and `egui-wgpu` NAMED in this crate. They already
#     arrive transitively (`map-wgpu` → `facett-map/wgpu` → `facett-core/wgpu`), but
#     *relying* on a transitive feature to make a module compile is how a build
#     breaks when an unrelated dependency drops its own wgpu edge. So the tab
#     declares what it uses.
#  2. It is native-only. The tab itself is in the wasm bundle and works there — the
#     CPU painter draws the dots and the names, `state_json` reports
#     `gpu.armed = false`, and the item-6 lane (pure `View` maths) is unaffected.
#     What wasm does NOT get is the two device passes.
#
# ON by default, and deliberately so: the whole point of the tab is that the device
# lanes RUN. Five closed GFX_V2 items were features nothing called — an off-by-default
# showcase would be the sixth. Fail-safe by construction: un-armed, `pick_at` returns
# `None` and the CPU lane answers, `LabelLane::draw` returns false and the CPU painter
# draws the names, and the tab SAYS "device: NOT ARMED" on screen rather than looking
# GPU-driven while the CPU does the work.
gfx-v2-gpu = ["dep:egui-wgpu", "facett-core/wgpu"]
# L1 vello beauty lane (the `Velo L1` tab's right pane). Passthrough that turns on
# facett-core's `l1-vello` overlay (gradients / antialiased curves / gaussian glow
# composited over the L0 SDF base). OFF by default — desktop-GPU only, never
# required; without it the tab shows L0 alone + reports `l1_available = false`.
# Native only in practice (vello = fat-GPU compute); the wasm demo leaves it off.
l1-vello = ["facett-core/l1-vello"]
# L4: turn on the functional-status emitter so the demo's mega-matrix +
# screenshot tests feed the `nornir test` matrix. No-op in release.
testmatrix = ["facett/testmatrix"]
# The reusable robot-UI seam (`src/robot.rs` + the `facett_robot` bin): pulls the
# `nornir-robotui` driver and compiles the `Observable` impl + the choosable
# Headless/Watch entry point. Native-only (the optional dep lives in the native
# dependency table); the wasm web demo never turns it on.
robotui = ["dep:nornir-robotui"]

[dev-dependencies]
# The golden-image GUARD (`facett_core::golden`) the screenshot proofs compare
# through — dev-only, so the shipped demo carries no extra `image` edge.
# `cloud-test-gate`: `tests/four_tabs_at_scale.rs` opens the installed-renderer gate
# without a device to count what the resident lanes upload (process-global, so that
# test is its own binary and nothing else calls it).
facett-core = { path = "../facett-core", version = "0.3.0", features = ["golden", "cloud-test-gate"] }
egui_kittest = { version = "0.36", features = ["wgpu", "snapshot"] }
# fix #12 — the chunked-geom-buffer test (`tests/gpu_chunk.rs`) names
# `egui_wgpu::RenderState` directly (egui_kittest returns it). Same 0.34 stack as
# facett-map's GPU kernel.
egui-wgpu = { version = "0.36", default-features = false, features = [
    "fragile-send-sync-non-atomic-wasm",
    "macos-window-resize-jitter-fix",
] }
image = { version = "0.25", default-features = false, features = ["png"] }
# lane TL, 2026-09-03 — the tagless-SOURCE guard
# (`osm_tabs::tests::a_tagless_ways_source_reaches_the_deck_as_overprint`) has to write a
# parquet with a `geometry` column and NO `tags` column, because the whole seam is the
# SCHEMA. Same arrow-59 generation `facett-osm` reads with, dev-only — the shipped demo
# gains no edge.
arrow-array = "59"
arrow-schema = "59"
parquet = { version = "59", default-features = false, features = ["arrow"] }
# D5b2 — the robot-UI **live-drive** matrix row. Each scripted (action → expected)
# step becomes a `robot-ui` TestResultRow, so driving the whole demo fills one
# matrix line. The matrix engine is the same lean sibling D5b1 / facett already use.
nornir-testmatrix = { version = "0.2", features = ["testmatrix"] }
anyhow = "1"
# `nornir-robotui` is the reusable robot-UI driver this row is built on — except this
# test target does NOT depend on it: `tests/robot_demo.rs` carries an in-crate PORT of
# robotui's API (`Observable` / `RobotSession` / `Scenario` / `Action` / `Assert` /
# `run_scenario`, aspect "robot-ui").
#
# ⚠ CORRECTED 2026-09-01. The justification that used to stand here — "its published
# 0.1.0 pins egui 0.33 … facett is egui 0.34, so the two egui majors can't share a
# `Harness`" — is STALE in both halves. MEASURED: nornir-robotui is **0.3.4 on
# egui/eframe 0.35**; facett is **egui 0.35**. The egui-major split that justified the
# port is gone, and the stated re-enable condition ("once it's 0.34") can never be met
# because robotui went past 0.34 without ever stopping there.
#
# The twin has already cost a bug. `Step::assert` was a SETTER in both copies, so a
# chained `.assert(a).assert(b)` kept only the last clause. robotui fixed it in 0.3.4;
# this crate's copy had to be fixed SEPARATELY (2026-09-01) because a version bump
# cannot reach a twin. LAW 5 — reuse, do not twin.
#
# TODO: delete `mod robot` from `tests/robot_demo.rs` and add the real dep below. The
# other facett crates already do exactly that (`nornir-robotui = { version = "0.3" }`
# in facett-app / -graph / -graphnav / -holger / -brokkr), so the swap is well-trodden.
# nornir-robotui = "0.3"   # ← the swap: uncomment, then delete `mod robot`.