festifun/plan/status/foundation2.md
type-two 51650c728e foundation2 (phase 5a): contracts, stubs, hooks & UI wiring for lanes E/F/G
- DB: paths table (contract #3) + helpers; patch_anchor (label/color)
- API: GET /api/beats, POST /api/director (valid-empty degradation),
  /api/paths CRUD (validated POST -> 422), PATCH /api/anchors/{id};
  manifest gains capsule:false (test_api.py key-set lock updated consciously)
- CLI: features | direct | capsule subcommands -> lane stubs (exit-2 degradation)
- Backend stubs with frozen contracts in docstrings: audio_features, director, capsule
- Frontend: six lane stub modules imported from main.js; all phase-5 buttons
  pre-wired hidden in index.html; write-ui/body.capsule read-only mode;
  __F4D_API_BASE__ runtime override in state.js
- Hooks (contract #6): transport.captureAudioStream/releaseAudioStream,
  scene3d.focusOn, scene3d.setHelpersVisible (+registerHelper; camPath gizmos)
- Suite 121 -> 127 passed; npm build clean; live-browser verified (status file)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 17:31:08 +10:00

56 lines
3.7 KiB
Markdown

# Status — foundation2
## Round 1 — 2026-07-17 — STATUS: ready_to_merge
**Directives acknowledged:** Round 4 of plan/DIRECTIVES.md. Single-agent phase 5a — main
working directory on branch `foundation2` (per directive 3).
**Acceptance checklist** (plan/20-phase5.md "foundation2 scope"):
- [x] DB: `paths` table (contract #3) + helpers `add/get/get_one/delete_path`, plus
`patch_anchor` (label/color only) — `db.py`
- [x] API: `GET /api/beats` (serves `config.BEATS_JSON`, 404 when absent),
`POST /api/director` (degrades to a VALID empty camPath + `note` while lane E is
stubbed), `GET/POST/DELETE /api/paths*` (implemented — CRUD over the helpers was
cheaper than stubbing; POST validates the camPath shape → 422),
`PATCH /api/anchors/{id}` (contract #4) — `api.py`
- [x] Manifest gained `"capsule": false``test_api.py` exact-set lock updated in the same
commit (pitfall #3)
- [x] CLI: `features`, `direct`, `capsule` subcommands dispatch into stubs; house
degradation (exit 2, no traceback) — `cli.py`
- [x] Backend stubs raise NotImplementedError with the frozen contract in the docstring:
`audio_features.py`, `director.py`, `capsule.py`
- [x] Frontend stub modules created + imported from `main.js`, each wiring its own hidden
button in init(): `director.js`, `exportVideo.js`, `anchorPanel.js`, `photoMode.js`
(+ per-frame `fx.update()` call in the master loop), `fx.js`, `pathsStore.js`
- [x] index.html: ALL phase-5 buttons pre-wired hidden — #btn-director, #btn-path-save,
#path-load-select, #btn-path-del, #btn-export, #btn-photo, #btn-fx, #btn-anchors,
#anchor-panel container; `.write-ui` class + `body.capsule .write-ui{display:none}`
- [x] Hooks (contract #6): `transport.captureAudioStream()/releaseAudioStream()` (post-gain
tap, spatial included, tracks re-join across seeks), `scene3d.focusOn(x,y,z)`,
`scene3d.setHelpersVisible(bool)` (+ `registerHelper`; camPath gizmos registered)
- [x] `state.js`: `window.__F4D_API_BASE__` ?? `VITE_API_BASE` ?? localhost (contract #5);
`state.capsule` from the manifest toggles `body.capsule`
- [x] Suite ≥ 121 + new tests: **127 passed** (121 floor + 6 in `test_phase5_api.py`)
- [x] Ownership table updated (paths-route bodies → foundation2; noted in 20-phase5.md)
**Done this round — evidence:**
- `uv run pytest backend/tests`**127 passed** (was 121).
- `npm run build` → clean (pre-existing chunk-size warning only).
- Live browser (Vite :5173 + uvicorn :8000, synthetic fixture): app boots (3 videos, sync
+0 ms); all 9 new controls present and `display:none`; `setHelpersVisible(false)` hides
grid (and restores); `focusOn(1,0.5,0)` retargets OrbitControls to exactly [1,0.5,0];
`captureAudioStream()` returns a MediaStream with 1 audio track, release clean;
`POST /api/director``{version:1, keyframes:[], note:…}` and round-trips
`camPath.fromJSON` (0 keyframes, no throw); paths save→load→fromJSON reproduces 2
keyframes, DELETE → 200 then 404; `PATCH /api/anchors/1 {color}` → updated dict;
`GET /api/beats` → 404; `body.capsule` hides #annot-panel/#btn-path-save/#btn-path-del.
**Blockers / questions for coordinator:** none. One conscious deviation, self-adjudicated
(coordinator == foundation2 agent this round): paths route bodies implemented here instead
of stub-marked for lane G — they were one-line calls into the db helpers I had to write
anyway; stubbing them would have been more code than implementing. Lane G scope shrinks to
capsule + pathsStore.js + deepening test_paths.py.
**Next:** merge to `main`, then lanes E, G, F in parallel (each in its own worktree —
directive 3 is mandatory for 5b).