release / govulncheck (push) Failing after 2s
release / go (push) Successful in 1m49s
release / web (push) Successful in 1m8s
release / integration (push) Successful in 4m39s
release / android (push) Successful in 5m45s
release / Build signed APK (releases and dev) (push) Successful in 5m58s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped
test-go, test-web and android were separate workflows on the same push as release.yml, so the image build could not see their verdict: :dev meant "it built", never "it passed". All lanes now live in release.yml, and both publishing jobs (image-release and the new release-assets) need every lane and require `result == 'success'` from each by name, so a skipped lane blocks the publish just as a failed one does (rule 177). - New lanes: govulncheck (in golang:1.26-bookworm, the builder's image, so it checks the stdlib that ships) and `npm audit --omit=dev` in web. - Attaching the APK to a Release moved out of android-release into release-assets, behind the gate; the APK still builds in parallel. - `docker buildx build --pull`, so floating base tags can't serve a stale Go patch release from the runner's cache. - Integration wait uses `pg_isready` via docker exec: the old /dev/tcp probe never connects under dash (rule 81) and burned two minutes a run. - workflow_dispatch input force_red fails the go lane on purpose, to watch the gate refuse. - release_gate_test.go pins the gate: every job must be classified, and every publisher must need and require success from every lane. Lanes have no path filters any more; a web-only push runs the Go suite too, because "not run" must never read as "passed". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>