From 4bc2638c125fdf1dcf0930fd695b72b5ba85ec8a Mon Sep 17 00:00:00 2001 From: type-two Date: Fri, 17 Jul 2026 17:50:44 +1000 Subject: [PATCH] =?UTF-8?q?lane=20G:=20status=20=E2=80=94=20M16+M17=20comp?= =?UTF-8?q?lete,=20169=20passed,=20capsule=20E2E=20evidence,=20CR-4=20note?= =?UTF-8?q?d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- plan/status/lane-G.md | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 plan/status/lane-G.md diff --git a/plan/status/lane-G.md b/plan/status/lane-G.md new file mode 100644 index 0000000..37eceaa --- /dev/null +++ b/plan/status/lane-G.md @@ -0,0 +1,101 @@ +# Status — lane G (persistence & capsule, branch `lane/g-capsule`) + +## Round 1 — 2026-07-17 — STATUS: ready_to_merge + +**Directives acknowledged:** Round 4 of plan/DIRECTIVES.md (phase 5 begins; foundation2 merged; +worktree rule followed — this lane runs in its own git worktree). + +**Acceptance checklist** + +M16 — server-side camera paths: +- [x] Routes implemented — by foundation2 (per the phase-5 ownership table); lane G deepened + coverage only, per scope. +- [x] `backend/tests/test_paths.py` — 30 tests: roundtrip deep-equal incl. float precision + + a 500-keyframe path, multiple paths coexist / id-ordered listing / summary-only shape, + duplicate + unicode + whitespace + 300-char names verbatim, ISO `created_at`, empty-keyframes + path valid (director degrade must be saveable), extra JSON keys ride along, get/delete 404s, + delete idempotence, an 18-case parametrized 422 matrix over the frozen camPath contract, + 422 creates no row, missing/aliased request fields 422. Cleans up its rows (test_phase5_api + runs later and asserts an empty table). +- [x] `frontend/src/pathsStore.js` filled: 💾 save = name prompt + POST `camPath.toJSON()`; + dropdown load = GET `/api/paths/{id}` + `camPath.fromJSON(data.json)`; 🗑 delete with + confirm; dropdown refreshed after every mutation (new save left selected); controls + unhidden + `ready = true`. Capsule mode: save/del hide via `write-ui`; the load dropdown + stays (paths are baked read-only — below) and hides itself if the listing fetch fails. +- [ ] Live save → reload page → load reproduces keyframes exactly — NEEDS LIVE BROWSER (list + for coordinator below). The exact-roundtrip property is locked server-side by + `test_roundtrip_preserves_float_precision` / `test_roundtrip_large_keyframe_list`. + +M17 — memory capsule: +- [x] `backend/festival4d/capsule.py::build_capsule` per the frozen contract: copies + `frontend/dist` (clear "run `cd frontend && npm run build`" error if missing), copies the + manifest-referenced media to `media/`, bakes every read-only API response extension-less at + the live API's relative paths (`api/manifest` with `capsule: true` + `has_capture: false`, + `api/events`, `api/anchors`, `api/videos/{id}/poses`, `api/beats`/`api/pointcloud`/ + `api/splat` when present, `api/audio/{id}` via the same lazy `ingest.extract_audio_hq` + cache the live route uses), injects `` ahead of + the app `