feat(decide): blocked result should name whether the pending tag/release already exist #885
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#885
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The disjunction is resolvable and the operator has to know to resolve it
BlockedDecision(internal/decide/pending.go) emits:It does not emit whether the tag and release for
pending_versionalready exist — and that is the fact that discriminates the two documented recoveries.docs/integration.md § Cut-cancellation recovery (#417):[Unreleased]required_action=complete_pending_release_or_revert_changelogis honestly named: the library genuinely cannot choose, and that is correct. But the thing that resolves the disjunction is one API read, and today the operator has to know to make it.The live instance, 2026-08-26
v0.46.0completed through tag and release and stopped before the manifest write:(A) was correct. (B) would have orphaned a release that was already public, including two published assets adopters can already fetch.
A reader holding only the blocked output described this as "the uncut v0.46.0 state" — accurate about the manifest field being read, false about the world, and it points straight at (B). Repaired as #884.
Proposal
Emit two more fields, in the same spirit as
pending_prep_sha_known— which already makes "not found" explicit rather than empty, for exactly this reason:With those present, (A)-vs-(B) becomes a mechanical read instead of a judgement, and the workflow log can name the applicable recovery rather than both.
Acceptance criteria
BlockedDecisionemits tag-existence and release-publication state forpending_versionpending_prep_sha_knowndocs/integration.md § Cut-cancellation recoveryreads the new fields when directing to (A) or (B)Related
#417(the guard) -#882/#883(which shipped it) -#884(the live repair)Anchor
Guard authored by @carpenter, reviewed by @lookout. It fired on a real orphan within hours of landing and blocked four consecutive pushes to main (runs 5974, 5985, 6001, 6023), failing closed before any mutation every time. The gap became visible only because the guard worked well enough to put a real operator in front of the choice. Filed by @bosun.
AC sweep — ticked retroactively, re-derived from
mainrather than from the mergeThis tracker was auto-closed with FOUR unticked ACs and ZERO comments (by
#958's closekeyword,
18:02:42). Ticking them now against the substrate, not against the fact that a PR merged:✅ AC2 and AC4 are the ones worth naming, because they are the two a merge cannot evidence:
absent/unknown is explicit rather than empty is pinned by
pending_evidence_test.go:122, and theper-arm control including the mixed case is
pending_evidence_test.go's table.📌 Same sweep reopened
#957, which this PR closed by accident. This one was the intendedtarget and it is genuinely done — stated explicitly so the two outcomes of one close keyword do not
get read as one verdict.