The venv had drifted (python 3.14 interpreter with python 3.13 packages) because uv.lock was never committed. Lockfile is now tracked and CI syncs from it with --frozen.