Development record
2026-09-25 — On the auto-release path the tag is still made before the `release` environment's approval, and that residual is recorded for the next cycle rather than built now (finding F2 of the workflows-lane review, LOW). release.yml's `tag` job needs `verify`, so a refused gate leaves no tag (iss-2608231226347380), but the job runs before the publish job waits on its human approval and before the four steps between the tag and `gh release create` (the vcs stamp, the archive re-verify, the two attestations). A rejected approval or a red step there leaves a tag with no Release, which the heal path then rebuilds on the next push. The closure shape: delete the `tag` job and create the tag as a step inside the `release` job, immediately before `gh release create`, through `gh api -X POST repos/<owner>/<repo>/git/refs -f ref=refs/tags/<tag> -f sha=<commit>` with the job's own `GH_TOKEN`, so it needs neither `persist-credentials` nor an extra job; a rejection or a red publish step then leaves no tag either. It also removes the auto-path half of iss-2609251125599536: once no auto-path failure can leave a tag without a Release, the only such tag is a hand-pushed one, which `detect` already refuses to rebuild when its own verify failed. Not built in this lane because the chain is unverifiable without a live release, and the order the lane shipped is the one the review walked (implementer of the workflows fix round).
2026-09-25 — On the auto-release path the tag is still made before the release environment's approval, and that residual is recorded for the next cycle rather than built now (finding F2 of the workflows-lane review, LOW). release.yml's tag job needs verify, so a refused gate leaves no tag (iss-2608231226347380), but the job runs before the publish job waits on its human approval and before the four steps between the tag and gh release create (the vcs stamp, the archive re-verify, the two attestations). A rejected approval or a red step there leaves a tag with no Release, which the heal path then rebuilds on the next push. The closure shape: delete the tag job and create the tag as a step inside the release job, immediately before gh release create, through gh api -X POST repos/<owner>/<repo>/git/refs -f ref=refs/tags/<tag> -f sha=<commit> with the job's own GH_TOKEN, so it needs neither persist-credentials nor an extra job; a rejection or a red publish step then leaves no tag either. It also removes the auto-path half of iss-2609251125599536: once no auto-path failure can leave a tag without a Release, the only such tag is a hand-pushed one, which detect already refuses to rebuild when its own verify failed. Not built in this lane because the chain is unverifiable without a live release, and the order the lane shipped is the one the review walked (implementer of the workflows fix round).
Frontmatter
| id | dcn-2609250000000026 |
|---|---|
| type | decision |
| date | 2026-09-25 |
.abcd/work/decisions/dcn-2609250000000026-on-the-auto-release-path-the-tag-is.md
open on GitHub ↗ · commit history ↗
mentions2
- iss-2608231226347380`auto-release.yml` runs `detect` -> `tag` -> `release`, and the semantic
- iss-2609251125599536auto-release's heal path rebuilds a hand-pushed tag whose verify failed on every later push to main. With the tag now made after verify on the auto-release path (iss-2608231226347380), a tag without a Release can still arise from a hand-pushed tag whose release.yml verify refused. detect cannot tell that from a transient publish failure (both are tag-present, Release-missing), so it sets need_release and rebuilds the same tagged commit, which fails again, on each push. Carried from the duplicate iss-2609100513521322's second acceptance: detect should refuse loudly and name the re-cut when the tag's last verify concluded in failure, or bound the retry.