"""Auto-director: events -> keyframed camera path (spec M11, lane E). STUB — lane E fills. Contract (frozen at foundation2 merge — phase-5 contract #2): :func:`generate_path` returns a **camPath-compatible** dict:: {"version": 1, "keyframes": [{"t_global": float, "pos": [x, y, z], "quat": [x, y, z, w], "fov": float}]} Poses are **Three.js scene space**, quaternion order **[x, y, z, w]** — convert from the COLMAP rows via :func:`festival4d.geometry.colmap_to_threejs`, never inline (pitfall #1). Deterministic v1 rules — no ML: take the top-N events by confidence (ties -> earlier); for each, choose the registered camera with a pose nearest the event time; keyframes at ``t_event - lead_s`` and ``t_event + duration``; when ``config.BEATS_JSON`` exists, snap keyframe times to the nearest beat (no beats file -> no snapping — degrade, don't block); FOV from that camera's intrinsics (``2 * atan(height / (2 * fy))`` in degrees, the same formula as ``scene3d.snapTo``). """ from __future__ import annotations def generate_path(top_n: int = 8, lead_s: float = 2.0) -> dict: """Build a camPath JSON dict from the detected events (see module doc).""" raise NotImplementedError("auto-director (lane E / M11)")