# Lane E — Director & export (branch `lane/e-director`) **Scope: phase-5 milestones M10 + M11 + M12** (beats/onsets, auto-director, cinematic export) — see [`20-phase5.md`](20-phase5.md). - Owned files: `backend/festival4d/audio_features.py`, `backend/festival4d/director.py`, `backend/tests/test_audio_features.py`, `backend/tests/test_director.py`, `frontend/src/director.js`, `frontend/src/exportVideo.js`. Nothing else. - Fill the stub bodies foundation2 left; signatures, routes, and CLI dispatch already exist. - Contracts you consume (frozen): `beats.json` shape, camPath JSON (quat `[x,y,z,w]`, Three.js space — convert COLMAP poses via `geometry.colmap_to_threejs`, never inline), `transport.captureAudioStream()`. - Build order M10 → M11 → M12: the director consumes beats; export consumes the director's path. Each milestone is independently mergeable — don't hold M10/M11 hostage to M12. - Degradation: no beats → director skips beat-snapping; no poses → director returns a clear error body, never a crash; export with no path → button stays disabled. **Done when:** M10–M12 acceptance passes (browser evidence for M11/M12 in your status file), `pytest` ≥ 121 + your tests, merged to `main` with synthetic end-to-end intact.