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>
2.8 KiB
2.8 KiB
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
- 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). DELETE /api/anchors/{id}(additive) — unlinks annotations (NULLsresolved_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.- Frontend delete affordance — the correction panel now has a scrollable anchors list
(color dot + label + ✕). Delete →
DELETE→ splicestate.anchors→anchors-changed(scene3d refresh; overlays read state each frame)._submitupserts by id so a supersede replaces (not duplicates) the anchor in state.npm run buildclean (18 modules). docs/ideas.mdcreated (gaussian splatting, MP4 path export, realtime ingest, multi-modal audio, object tracking, QoL).- CR-3 filed + APPLIED in plan/CHANGE_REQUESTS.md (strictly additive).
- 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.