festifun/plan/CHANGE_REQUESTS.md
m3ultra e5d6b2c47f Integration (M8 + M9): annotation→3D, camera paths, README, v0.1.0
M8: POST /api/annotations resolves a bbox to a 3D point (ray → two-view
triangulation / nearest-point / centroid-depth) via lane B's geometry
primitives; correction panel + bbox-drawing UI; resolved anchors render live
in overlays and the 3D scene. CR-2 (additive): annotations.event_id +
PATCH /api/events/{id} + db.update_event.

M9: keyframed god's-eye camera paths (Catmull-Rom position + slerp
orientation, export/import), gizmos, path-mode camera hooks.

Verified: 101 backend tests pass (two-view corner recovery err 0.00000);
frontend build clean; live in-browser M8 triangulation (gap 0.21) + M9 path
(camera on keyframe at t) + M4 sync ~16ms. Cleanup: worktrees removed, debris
stash dropped, pristine demo DB.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 09:59:51 +10:00

3.6 KiB

Change Requests

Lanes that believe a frozen file must change (db.py schema, api.py routes/shapes, cli.py, config.py, synthetic.py, pyproject.toml, the pose contract) do not edit it. Instead append an entry here and work around it locally; the integration agent adjudicates.

Format (one entry per request, newest at the bottom):

### CR-<n> — <lane> — <date> — <one-line title>
- **File:** <frozen file + symbol>
- **Problem:** why the current contract blocks you
- **Proposed change:** the minimal change you need
- **Workaround in place:** what you did locally so you're not blocked
- **Decision:** (integration fills this: applied | rejected — rationale)

CR-1 — lane D — 2026-07-16 — Update obsolete stub assertion in test_api.py

  • File: backend/tests/test_api.py::test_detect_degrades_gracefully
  • Problem: That foundation test asserted the stub contract of POST /api/events/detect ("note" in data), which was correct only while lane D was unimplemented. With M7 landed, run_events no longer raises NotImplementedError, so api.py returns the real {result, events} shape (spec M3) and the stub assertion fails.
  • Proposed change: rename to test_detect_events_endpoint and assert the real landed contract (200; result is the run_events summary with candidates/classified/… keys; events is a list; idempotent on repeat).
  • Workaround in place: applied the minimal edit directly (test file, not a frozen contract file). The frozen api.py app is unchanged. Only lane D's owned modules + this obsolete stub assertion were touched. Full suite green (89 passed).
  • Decision: APPLIED (integration, 2026-07-16). Confirmed against the frozen api.py docstring: POST /api/events/detect returns {result, events} (spec M3). The renamed test_detect_events_endpoint asserts exactly that shape and is idempotent. No frozen file changed; approval also recorded in DIRECTIVES round 1.
  • File: db.py (Annotation schema), api.py (AnnotationIn, events routes)
  • Problem: Spec M8 requires (a) triangulating "another annotation for the same event from a different video" — but the frozen annotations schema has no event reference, and AnnotationIn carries no event id, so annotations can't be grouped per event; and (b) a correction dropdown that "writes source='user'" to an event's type — but there is no event-update helper or endpoint (only add/clear).
  • Proposed change (additive only — no existing shape altered):
    1. annotations.event_id — new nullable ForeignKey("events.id") column. Nullable ⇒ existing rows/inserts unaffected; the synthetic fixture creates annotations = none, so no migration. Serves the two-view grouping.
    2. AnnotationIn.event_id: int | None = None — additive optional request field.
    3. db.update_event(event_id, event_type=?, source=?, description=?) helper + PATCH /api/events/{event_id} — additive route; existing GET/POST/detect unchanged.
  • Workaround in place: none needed — adjudicated and applied directly in this integration phase (the phase where the ownership matrix ends and frozen contracts may change on an approved CR). All changes are strictly additive; every pre-existing route/shape/column and the timebase + pose contracts are byte-for-byte unchanged. Full suite stays green.
  • Decision: APPLIED (integration, 2026-07-16). Additive, backward-compatible, and required for M8 acceptance. Frontend and backend M8 both depend on it.