Fixes the sole Round-3 wart: annotating one object from two views now yields
ONE anchor (the single-view fallback is superseded in place by the
triangulation, same id) instead of a sibling pair. Adds DELETE /api/anchors/{id}
(unlinks annotations, 404 on unknown) + a deletable anchor list in the
correction panel. db gains get/update/delete_anchor + get_annotations(event_id).
CR-3 filed (additive). Suite 101 -> 103; frontend build clean; delete UI
verified live (state + DOM + 3D scene stay consistent).
Also: docs/ideas.md (future extensions), plan/ISSUES.md (seeded with the
gemini-2.5-flash retirement, FIXED), plan/status/phase4.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
42 lines
2.8 KiB
Markdown
42 lines
2.8 KiB
Markdown
# Status — phase4 (polish + field test)
|
||
|
||
## Round 1 — 2026-07-16 — STATUS: polish ready_to_merge; field test AWAITING FOOTAGE
|
||
|
||
**Directives acknowledged:** round 3 + addendum of plan/DIRECTIVES.md (anchor supersede + delete,
|
||
docs/ideas.md, suite ≥101, field-test protocol + ISSUES.md; local `.env` is machine-local).
|
||
|
||
### Polish pass — DONE
|
||
- [x] **Anchor supersede (fixes the Round-3 wart).** One anchor per event: first annotation
|
||
creates it (single-view fallback); a later view that triangulates **supersedes it in place**
|
||
(same anchor id, response gains `superseded: true`); a later fallback links without moving.
|
||
Annotations with no event stay independent.
|
||
- Evidence: reproduced the old "2 anchors for 1 object" scenario → now **1 anchor**, both
|
||
annotations link to the same id, superseded position err **0.0000** from ground truth
|
||
(`tests/test_resolve.py::test_two_view_annotation_supersedes_to_single_anchor`).
|
||
- [x] **`DELETE /api/anchors/{id}`** (additive) — unlinks annotations (NULLs `resolved_anchor_id`)
|
||
then deletes; 404 on unknown. `db.get_anchor`/`update_anchor`/`delete_anchor` +
|
||
`get_annotations(event_id=)` added.
|
||
- Evidence: `tests/test_resolve.py::test_delete_anchor_unlinks_annotations_and_404`.
|
||
- [x] **Frontend delete affordance** — the correction panel now has a scrollable **anchors list**
|
||
(color dot + label + ✕). Delete → `DELETE` → splice `state.anchors` → `anchors-changed`
|
||
(scene3d refresh; overlays read state each frame). `_submit` upserts by id so a supersede
|
||
replaces (not duplicates) the anchor in state. `npm run build` clean (18 modules).
|
||
- [x] **`docs/ideas.md`** created (gaussian splatting, MP4 path export, realtime ingest,
|
||
multi-modal audio, object tracking, QoL).
|
||
- [x] **CR-3** filed + APPLIED in plan/CHANGE_REQUESTS.md (strictly additive).
|
||
- [x] **Suite: 101 → 103 passed** (`../.venv/bin/python -m pytest`), frontend build clean.
|
||
|
||
### Field test — AWAITING FOOTAGE (protocol ready)
|
||
Scaffolding in place: this file + `plan/ISSUES.md` (seeded with ISSUE-1, the gemini-2.5-flash
|
||
retirement, FIXED). When 2–4 real overlapping clips land in `data/raw/`, run
|
||
`ingest → sync → reconstruct → events → serve` and record here: per-pair sync confidence +
|
||
offsets, COLMAP registration rate, and which milestones survived real footage. File failures as
|
||
`plan/ISSUES.md` entries, don't rush fixes.
|
||
|
||
**Blockers / notes for coordinator:**
|
||
- Field test cannot start until the human provides real footage (carried item).
|
||
- Human focused-browser M4 sync eyeball still open (carried from Round 2/3).
|
||
- `.env` (Gemini + OpenRouter creds) is machine-local + gitignored; present on this machine.
|
||
|
||
**Next:** merge `phase4/polish-field-test` → `main`; run the field test when footage arrives.
|