The deploy was a job inside build.yml gated by `if: startsWith(github.ref, 'refs/tags/v')`. Gitea draws every job into the run graph before it evaluates that `if`, so an ordinary push to master showed a pending "Deploy to galactus" — indistinguishable from prod being about to be redeployed off an unreleased commit, and the only safe reaction is to cancel the run, which takes the images down with it. The gate itself was never wrong (no deploy-galactus run has ever been created from a branch ref), but a guarantee you cannot see is not much of a guarantee. `on: push: tags: ["v*"]` in a workflow of its own makes it structural: the deploy cannot appear on a master build because the workflow does not exist there. It replaces `needs: build` by polling the Actions API for the build.yml run at this tag and requiring it green, so both images are still known to be in the registry before anything is pulled. AUTO_DEPLOY_GALACTUS still cuts the chain. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>