**Note** from Bead: Sandy Fire Camera Tuner · [canonical source](https://redfish.acequia.io/guerin/.agents/0671f6fa-eb89-42a1-a854-6a95b97af23f/2026-06-22/notes/00-app-brief-and-orientation.md) · session 2026-06-22 · discussion: Talk: Sandy Fire Camera Tuner
**Bead:** `0671f6fa` (sandy-fire-camera-tuner) · 2026-06-22 · read first.
## The app in one line Tune the **fire-in-taos** spread model (rendered by **taos-engine**) until its simulated fire matches the **Sandy Fire** as seen by the **AlertWildfire cameras** and as recorded by the **`toa-2026sandyv1`** time-of-arrival reference — manually and/or via **Levenberg-Marquardt** "through-the-lens" optimization. In world-model terms (`a617e16d`) this app **is the calibration/assimilation step**: it fits block **M** (the forecast model) against MEASURE-side observations, the first place the loop closes for a real fire.
## The data (verified this session) - **Fit target — `toa-2026sandyv1`** (`182bd1a7/2026-06-18/artifacts/ref-2026sandyv1/progression.{png,pgw,json}`): 9 dated perimeters 2026-05-18→05-22, **0→2175 acres**; RGB minutes-from-origin (red = MSB); dual worldfiles (Web-Mercator 3857 **and** 4326); bounds ≈ lon[-118.7684, -118.7141], lat[34.2204, 34.2517]; America/Los_Angeles. - **Imagery — AlertWildfire/AlertCalifornia PTZ** (`apps/camera-grid/`, `cameras-sandy.json`): ~10 Sandy cameras with per-frame `az/el/fov` telemetry + frames over a UTC scrubber; grid⇄map morph; `plume.js` already does silhouette space-carving + co-view selection. - **Model — `fire-in-taos.html`**: slope-biased fire CA on the real Sandy DEM in taos-engine; sliders `slope effect / base spread / wind / wind dir / speed`; ignites at observed origin on `IGNITION_UTC`; model-vs-observed hectares + ROS graphs; master clock; observed-perimeter overlay. - **LM precedent — `through-the-lens-test-v1.html`** (`74c30681/repo/`): a working Levenberg-Marquardt solve over camera pose+intrinsics `[x,y,z,yaw,pitch,fov]` with a reprojection residual + framebuffer snapshot overlay. The optimizer we reuse.
## What Debbie and Frank produced Brought in as persona-subagents (each read its own bead to recover method, then the real source): - **Debbie (senior-uxui-designer `c4a8e2f1`)** → [`01-debbie-uxui-sketches.md`](https://redfish.acequia.io/guerin/.agents/0671f6fa-eb89-42a1-a854-6a95b97af23f/2026-06-22/notes/01-debbie-uxui-sketches.md): 5 sketch-ux UX sketches — match surface (lens overlay vs side-by-side vs TOA diff) · tuning gesture (hand vs solver vs **seed-then-refine with pinnable params**) · residual gauge (one-score vs bars vs **honesty-fuzz**) · screen (cockpit vs **stage+drawer** on a shared clock) · authorship (defer the scenario shelf, ship a citable deep-link). - **Frank (senior-architect `b2d9f6e1`)** → [`02-frank-architecture-sketches.md`](https://redfish.acequia.io/guerin/.agents/0671f6fa-eb89-42a1-a854-6a95b97af23f/2026-06-22/notes/02-frank-architecture-sketches.md): 5 architecture sketches across his planes — residual space (**image vs world**) · per-camera pose (input contract vs joint-solve) · where the LM runs (**in-browser** vs headless) · output on the bus (**STAC forecast product reusing the TOA contract**) · point-estimate vs ensemble (**LM now, EnKF later, same loop**).
## The striking convergence (the headline of this turn) Debbie and Frank, working independently, surfaced **the same crux from two sides**: - **Debbie's "one genuinely hard question":** *which residual is authoritative when the lens and the TOA disagree?* (image-space "what a camera saw" vs top-down TOA timing). - **Frank's "load-bearing question" (Sketch A):** *image-space vs world-space residual?* — and his answer: they won't minimize together; do a **weighted, re-weightable sum** of both (per *every-constraint-is-soft*). Same fork. Both also independently concluded: **the app is the composition of two HTML files that already exist** (`fire-in-taos` ⊕ `through-the-lens-test-v1`) plus reuse of the existing LM — a *wiring* exercise, not research. And both recommend the **same build order**: 1. **World-space / TOA residual first** (Frank A2 + D1; Debbie's TOA-diff surface + seed-then-refine): derive a model-TOA raster, diff against `ref-2026sandyv1`, run the existing LM over `[slope, base, wind, wdir]`, emit a `scenario.json` + fitted TOA in the *same* RGB-MSB + dual-worldfile shape. **Zero new infra, no camera calibration needed.** Demo: "watch the sliders converge so model-TOA matches observed-TOA." 2. **Through-the-lens residual second** (Frank A1 + B1; Debbie 1A overlay + 3C honesty): calibrate one co-viewing camera (Saddle Peak / Topanga), render fire+smoke from its pose, add `|render − frame|` as a second weighted residual. Demo: "now it also matches what the camera saw." Build Debbie's **honesty gauge alongside**, not after. 3. **Ensemble (EnKF) last** (Frank E2 on the headless CDP lane): generalize the single param-vector to an ensemble → burn-probability + uncertainty. The world model, live.
## The one decision that gates the design **The lens-vs-TOA residual authority.** Both designers landed on "weighted + re-weightable + shown honestly," but the *default weighting* and *which is primary for v1* is Stephen's call. The recommended path (TOA-first, lens-second) sidesteps it for v1 by making TOA the always-on backbone and the lens an additive term — but the moment both are on, the weight is a real choice.
## Other gated decisions - Which Debbie sketch / Frank plane to drive to prototype first (rec: Frank step 1 = Debbie 2C+TOA-diff). - Deploy target for the app (new `apps/` dir? alongside camera-grid? in this bead's `repo/`?). - Per-camera `imagePose` contract — define now (it's a world-model contract) and calibrate which camera first.
## Reading order `00` (this) → `01` (Debbie) → `02` (Frank). Then fork a sketch/plane or answer the residual-authority question.