D4.5 guarantees "a build failure blocks every publish target" and its Prevents clause names "a partial publish, e.g. a Docker image pushed while .NET publish failed and no release was cut". The item names one escape from that guarantee, a failed package push. There is a second, and the item's own ordering language contradicts itself about it.
1. Docker pushes before github-release runs, so a release failure strands a pushed image
build-docker pushes inside its own job, via docker/build-push-action with push: ${{ inputs.push }}. github-release carries build-docker in needs:, so the image reaches the registry before github-release starts.
Any failure inside github-release therefore leaves a pushed image with no tag and no release: the pattern: download, the gh release view existence check, or gh release create itself. That is the exact shape the Prevents clause names, reached by a path the item does not mention. D4.5 covers only the failed-package-push case, which sits after github-release for the trusted-publishing reason section 3 gives.
2. "The terminal registry pusher (Docker)" contradicts the same item three clauses later
D4.5 calls Docker "the terminal registry pusher" while also establishing that "the publish-<target> job runs after the whole release task and so after github-release". A publish-<target> job is a registry push, so Docker is not the terminal one. The condensed D4 catalog in .agents/skills/workflow-ci-contract/references/d-guarantees.md inherits the same phrase.
The phrase is presumably load-bearing for the guard rationale, Docker being the last pusher inside the release task, so the fix is probably to say that rather than to delete it. Which it should say is the decision here.
Why they are filed together
Both are about where a push sits relative to github-release, and item 2's wording is what makes item 1 easy to miss: a reader who accepts Docker as terminal has no reason to look for a pusher that runs earlier.
Related
Found by the adversarial passes on #1215. Related to #1200 and #1212 for the other section 4 and condensed-catalog defects, and to #1201, which records that no part of section 5 checks D4.5 at all, so nothing would catch either of these today.
D4.5 guarantees "a build failure blocks every publish target" and its Prevents clause names "a partial publish, e.g. a Docker image pushed while .NET publish failed and no release was cut". The item names one escape from that guarantee, a failed package push. There is a second, and the item's own ordering language contradicts itself about it.
1. Docker pushes before
github-releaseruns, so a release failure strands a pushed imagebuild-dockerpushes inside its own job, viadocker/build-push-actionwithpush: ${{ inputs.push }}.github-releasecarriesbuild-dockerinneeds:, so the image reaches the registry beforegithub-releasestarts.Any failure inside
github-releasetherefore leaves a pushed image with no tag and no release: thepattern:download, thegh release viewexistence check, orgh release createitself. That is the exact shape the Prevents clause names, reached by a path the item does not mention. D4.5 covers only the failed-package-push case, which sits aftergithub-releasefor the trusted-publishing reason section 3 gives.2. "The terminal registry pusher (Docker)" contradicts the same item three clauses later
D4.5 calls Docker "the terminal registry pusher" while also establishing that "the
publish-<target>job runs after the whole release task and so aftergithub-release". Apublish-<target>job is a registry push, so Docker is not the terminal one. The condensed D4 catalog in.agents/skills/workflow-ci-contract/references/d-guarantees.mdinherits the same phrase.The phrase is presumably load-bearing for the guard rationale, Docker being the last pusher inside the release task, so the fix is probably to say that rather than to delete it. Which it should say is the decision here.
Why they are filed together
Both are about where a push sits relative to
github-release, and item 2's wording is what makes item 1 easy to miss: a reader who accepts Docker as terminal has no reason to look for a pusher that runs earlier.Related
Found by the adversarial passes on #1215. Related to #1200 and #1212 for the other section 4 and condensed-catalog defects, and to #1201, which records that no part of section 5 checks D4.5 at all, so nothing would catch either of these today.