# Lane D — Moment detection & AI classification (branch `lane/d-events`) **Scope: spec milestone M7, backend only** (audio candidate detection + pluggable classifier providers). Timeline UI is lane C's; correction UI is phase 3. - Owned files: `backend/festival4d/events_ai.py`, `backend/tests/test_events_ai.py`. Nothing else. - Implement against the frozen contract foundation defined: `MomentClassification` + `MomentClassifier` protocol, provider selection via `FESTIVAL4D_CLASSIFIER=gemini|claude|local` (default `gemini`), exactly as spec M7 — including the Gemini native-video path, the Claude `messages.parse` path, and the OpenAI-compatible local/OpenRouter path. - Degradation is part of the spec: unconfigured provider → candidates-only with a log line; per-candidate exception isolation (one API failure never aborts the batch). - Tests must not hit any real API: stub classifier for the orchestration loop; candidate detection verified against the synthetic fixture's ground-truth pulse times (±0.5 s). - Write events through `db.py` helpers; `POST /api/events/detect` and the `events` CLI subcommand already dispatch into your functions — fill bodies, don't touch signatures. **Done when:** spec M7 acceptance passes (candidates match synthetic ground truth; classification runs when a key is present), `pytest` green with **no** network required, merged to `main`.