Note 04 — pose forking by reference frame (2026-06-17) (Image Pose Uxui)

**Note** from Bead: Image Pose Uxui · [canonical source](https://redfish.acequia.io/guerin/.agents/74c30681-2b0c-48b2-b2a8-9e21190a4926/2026-06-16/notes/04-pose-forking-by-reference-frame.md) · session 2026-06-16 · discussion: Talk: Image Pose Uxui

> **Status (2026-06-17): concept HELD, not in the script.** When-to-fork is a real UX question; Stephen > chose to hold it. The script reverted to a single per-image append-log (`poses/<imageId>.jsonl`, each > entry still records `context.reference` + constraints). An **AI handles forking** via > [skills/handle-pose-forking.md](../skills/handle-pose-forking.md) until it's worth baking in — a worked > instance of `#intelligence-bake-to-script`. The per-`(image,reference)` file layout below was prototyped > then reverted; it's the bake-to-script target, not the current behavior. Stephen: *"webdav append log is good. though we may have forking where an image pose may be different in different context given the set of constraints. eg this is its pose based on google 3d photo tiles vs someone else's lidar model that will serve as a base soft constraint."*

## The insight An image does **not** have one pose. A pose is the solution of `(image × reference-frame × constraint-set) → (6-DOF + intrinsics)`. Fit the same photo against **Google Photorealistic 3D Tiles** and against **someone's LiDAR mesh** and you get **two different, both-valid poses** — they live in different reference frames with different error surfaces. So pose history is **not linear; it forks by context.** This is the same factor-graph / "every constraint is soft" frame (feedback_every-constraint-is-soft): each reference model is a set of soft constraints; the pose is the local minimum *given that frame*. One frame's pose can seed another as a **soft prior** (the LiDAR solution as a base constraint for the tiles solve, or vice-versa) — cross-frame bidirectional coherence, exactly the bundle-adjustment-over-constraint-links idea.

## The store (implemented) Per-`(image, reference)` append-log — forks are first-class as distinct files: ``` 2026-06-16/artifacts/poses/<imageId>/<reference-slug>.jsonl e.g. .../poses/0a0ce0ad/google-photoreal-3dtiles.jsonl .../poses/0a0ce0ad/lidar-<hash>.jsonl (a future frame) .../poses/0a0ce0ad/aws-terrarium.jsonl ``` - One NDJSON line per save (WebDAV PUT = read-append-write; single writer per fork, so no clobber across frames). Latest pose in a frame = last line; full history = the file. - Each record carries `context.reference` (the model fit against) + `pose` + `pins` + `propertyConstraints` + `method`. **Forking falls out of the path** — no branch bookkeeping needed.

## Record shape ```json { "ts": …, "imageId": "…", "image": "https://…", "displayName": "…", "context": { "reference": "google-photoreal-3dtiles", "slug": "google-photoreal-3dtiles" }, "pose": { "Latitude":…, "Longitude":…, "Elevation":…, "heading":…, "pitch":…, "roll":…, "fov":…, "fovy":… }, "method": "campanile-solve" | "snapshot-view-as-pose", "intrinsicsSolved": true, "pins": [ {u,v,lon,lat,elev} … ], "propertyConstraints": { … } } ```

## Next (not yet built) - **`parent` link:** when a solve is seeded from another frame's pose (LiDAR → tiles prior), record `parent: { reference, ts }` so the cross-frame derivation is explicit (provenance + reweighting). - **Frame registry:** a `poses/<imageId>/index.json` listing the frames + latest pose each, for the "select image → fly to its saved pose in frame X" UX (H currently flies to the in-session pose). - **LiDAR/mesh as a reference:** add it as a `reference` (its URI), so the calibrator can fit against it and the fork appears automatically. The reference model itself is the base soft constraint. - This is an in-the-small instance of decentralized-cache-management / the duplicate-tab fork model: many valid paths-of-light for one resource, reconciled by soft coherence, not a single truth.