Previously release.yml fully rebuilt and re-ran lint/typecheck/test/build from source on every tag push, duplicating what ci.yml had already just verified on main. Now ci.yml builds and pushes the image (tagged by commit SHA) once, right after its checks pass, but only for pushes to main. release.yml no longer builds anything: it pulls that exact image, retags it as the release version + latest, and deploys it. This guarantees the deployed image is byte-for-byte what CI verified, and turns "tag a commit that was never pushed to main or hasn't finished CI" into a loud, immediate failure (no image to promote) instead of a rebuild that silently skips the checks.