**Note** from Bead: Incident Viewer Taos Engine App · [canonical source](https://redfish.acequia.io/guerin/.agents/cbf8b027-e80c-4b9f-8eb3-91d40af072d5/2026-06-11/notes/03-incidents-catalogs-ui-organization.md) · session 2026-06-11 · discussion: Talk: Incident Viewer Taos Engine App
> **CORRECTION (same day):** the catalog substrate question was already decided upstream — see bead [#catalog `90f902e0`](https://redfish.acequia.io/guerin/.agents/90f902e0-2e45-4aa1-b998-918ca3688e94/about.md) (hatched from [#incident-cataloging `c38c1239`](https://redfish.acequia.io/guerin/.agents/c38c1239-bfd3-44dd-8d97-1a0aa39ac8da/about.md)): **one canonical STAC catalog that duck-types to each viewer** (viewer-3d `incidents.json`, alertLive `imageMeta`/`imagePoses`, santafe.live, taos-misb) as Plan-9-style projections — no copies. Layer = Collection, product = Item, files = assets+roles, FMV pose = a custom 6-DOF pose-stream extension; cataloging is the catalog's **dual** (search↦subscribe, GET↦observe). This note's "converge on catalog.json" should read: **catalog.json and incidents.json are both projections of the STAC catalog**, and incident-viewer's layers panel/timeline/selection map to Collection/Item-datetime/Item. taos-engine step-4 is the named proving ground. The UI design below stands; the substrate is STAC. Stephen's ask (2026-06-11): review the thread for how to organize incident-viewer to manage incidents and catalogs, how they're selected/managed onscreen, other tabbed views; review the current interface and suggest. This note is the synthesis; the chat is ground truth.
## The two catalog dialects in play (must converge) 1. **`viewer-3d/incidents.json`** (live today) — hierarchical, folder-mirroring: `incidents[] → folders[] → folders[] → aircraft[]`, leaf = `{video, telemetry, startUTC, duration}`. Already holds **2 incidents** (2025Palisades ×3 N57B clips, 2026SandyFire ×5 N42Z clips). Video-only; can't say "perimeter" or "IR image." 2. **`catalog.json`** (cataloging-incident bead `97559992`) — normalized: `{incident{name,id,vendor,tailNumbers,center,bbox,counts}, products[{id,type,subtype,token,center,bbox,files{},klv{summary},provenance}]}`. Open taxonomy: `VIDEO`, `IMAGE/IR`, `IMAGE/HS`, `FEATURE/HEATPERIMETER`, … **Decision proposed:** the viewer consumes **`catalog.json` per incident** (the typed, flat, product-record model) and a thin **incidents index** (`incidents.json` reduced to `[{id, name, catalog: <url>, center, bbox, timespan}]`). The current incidents.json's folder-nesting dissolves — grouping is a UI projection of `type`/`subtype`/`tailNumber`, not data structure. This IS the bead's catalog→viewer binding. **Gap found:** `catalog-incident.mjs` requires a vendor `mission.json`; the **2025Palisades archive (563 MB, 13 subdirs) has none** — it's hand-assembled (air-intel FMV ×6 clips/2 tails, perimeters ×5 w/ acreage-in-name, IR/HS KMZ ×13, GIS structures, CAL FIRE gdb/PDFs, aircraft tracks, splat, camera events). The skill needs a **folder-walker mode** (infer products from filename conventions: `…Z_VIDEOCLIP_<token>`, `…Z_PERIM_<token>_<acres>acres`, paired `.kmz/.png`) to catalog Palisades. Sandy similarly lives as loose files at simtable.
## Information architecture **Incident → (mission) → product**, projected onto **one UTC master timeline**. Time is already the app's spine (UTC model, `viewStartMs/viewEndMs` deliberately variable-ized for a master span — step-4 was designed for this). Every product has (or gets) a time: FMV = span, perimeter = instant (+acreage), IR/HS = instant, tracks = span. The incident's timespan = union.
## Onscreen organization (proposed) - **Incident picker** — top-left compact dropdown (current incident name + ▾): reads the incidents index; selecting fetches that catalog, flies to incident bbox, rebuilds layers + timeline. Plus "Open catalog URL…" entry (paste any catalog URI — resource-as-URI, supports ad-hoc/foreign incidents). - **Layers panel** (left, collapsible) — products grouped by type/subtype with counts from `catalog.counts`: ☑ FMV (per-clip rows: tail + startUTC), ☑ Perimeters (time-stepped), ☑ IR/HS images, ☐ Aircraft tracks, ☐ Structures, ☐ Splat. Row click = select (inspector + timeline highlight + fly-to bbox); checkbox = visibility. Selected FMV is what `h` sensor-locks to and what the transport controls. - **Master timeline** (existing canvas, generalized) — lanes per product group (santafe.live `tlBuildDots` lane-packing, hit-test, tooltips — explicitly deferred in `timeline-pan-zoom-plan.md` until "the timeline shows items, not just a clip"; that's now). FMV clips = spans (click to load+play), perimeters = markers (stepping = fire progression), images = dots. Wheel-zoom/shift-pan already generalize (window vars exist). Scrubbing into a clip's span activates it. - **Inspector** (the current #settings panel, repurposed) — properties of the *selected* product: today's Image/Opacity/World-Cap/Focus rows are really FMV-product properties, not app settings. Add metadata (sensor, tStart/tEnd, bbox, files, provenance link).
## Tabs (keep few) 1. **View** (default — the 3D scene; everything above is overlay) 2. **Catalog** — sortable/filterable product table (the "queryable" face of catalog.json: type, subtype, tail, tStart, duration, acres, files). Row click → back to View, selected. 3. **About/Provenance** — incident metadata, counts, attribution, source URIs, AAR links. Defer: 2D Map tab (the 3D view top-down mostly covers it), Edit/Curate tab (catalog generation stays in the skill, offline — the viewer is a read-only consumer; "managing" = selecting + toggling, not editing).
## Current-interface critique - **#desc is overloaded** — ~20 keybindings in one 11px line. → `?` help overlay; keep ≤4 hints inline. - **#settings mislabeled** — it's the FMV inspector (see above). - **Clip-local time is ambiguous** in a multi-product world — lead with UTC; `tcur/tdur` become secondary (per-selected-clip). - **No loading/error surface** — catalog/product fetch states need a small status chip (network log behind backtick is dev-only). - **`h`/transport need a target** once N clips exist → "selected product" concept (single-selection model resolves it). - **Mode button "World/Cap"** label opaque → "Drape / Sphere" + tooltip. - **Deep-link everything**: `?incident=&product=&t=&view=` — citable URIs (house ethos); currently zero URL state. - Keyboard: stop minting single letters per feature; `?` palette and per-selection actions.
## Migration steps (smallest first) 1. Extend the catalog skill with folder-walker mode → generate `2025Palisades.catalog.json` (offer, don't write into incidents/ from the bead). 2. Thin incidents index + incident picker + load-by-catalog in the viewer (FMV products only at first — N57B ×3, N42Z ×5 already listed in viewer-3d's incidents.json). 3. Master timeline lanes + clip spans (port santafe dot/lane code). 4. Perimeter renderer (KML → line mesh at terrain height; time-stepped). 5. IR/HS KMZ ground overlays (textured quad draped at bbox / second Projector). 6. Tracks, structures GeoJSON; splat much later.
## References (bead cross-links) - Bead: Catalog · [canonical](https://redfish.acequia.io/guerin/.agents/90f902e0-2e45-4aa1-b998-918ca3688e94/) - Bead: Incident Cataloging · [canonical](https://redfish.acequia.io/guerin/.agents/c38c1239-bfd3-44dd-8d97-1a0aa39ac8da/)