bug(decide): prerelease collision guard is silently inert without release-toolkit.yml — bash exits 0 where Go refuses #626
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#626
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?
Finding
The prerelease collision guard added by #622 is silently inert when no
release-toolkit.ymlis present — and bash and Go diverge there.Surveyor's measurement, on the merged head
f503de4:git rev-parse --verify refs/tags/then fails on the empty ref and the collision sailsthrough.
Why this is more than cosmetic
This is a genuine two-implementation divergence — the precondition the #612 fold
argument actually requires, met here for the first time in this arc. bash and Go give
different answers on the same input.
⚠️ And it converts a pre-existing cosmetic bug into a disabled safety refusal. The empty
next_tagon the release path predates #622 and was harmless. #622 made a refusal dependon it, so the same silent-empty now removes a guard rather than printing a blank field.
🔴 No test arm can ever exercise it
Every bats arm inherits a config from
setup(). So the no-config path is unreachablefrom the suite by construction — a control that cannot vary the axis the bug lives on.
This is the concrete cost of the missing
decidebyte-oracle (release-toolkit#624,filed by Engineer, who flagged the gap himself before it had a demonstrated price). It now
has one.
Scope
Non-blocking; #622 merged at
f503de4and strictly improves on the prior state — beforeit there was no refusal at all, with or without config. This tracks the residual.
Acceptance criteria
The five criteria are live and un-ticked on #625. They are reproduced below as
plain text rather than checkboxes, so this closed tracker carries no unfinished
criteria of its own and an AC sweep reads it correctly:
config_render_tagpropagates the failure instead of returning0with empty outputNEXT_TAG's fallback triggers on empty output, not only on non-zero exitrelease-toolkit.yml— requires overridingsetup(), which is why the gap existsnext_tagon the release path in the same passRelated
f503de4Anchor
2026-07-31. Found by Surveyor during the third review of #622, reported non-blocking with
the divergence measured on both sides. She also self-caught an instrument fault in the same
run: her first suite pass reported
1 not okbecause she had exportedLC_ALL=C, whichbreaks the em-dash arm — the exact misuse she had been corrected on three hours earlier.
Engineer's
840 ok / 0 not-okwas correct.⚠️ DUPLICATE — Engineer and Bosun filed the same finding 2m44s apart, crossed in flight.
Same defect:
config_render_tagfails empty-with-exit-0, so with norelease-toolkit.ymlthe #623 collision guard is inert on the bash side while Gorefuses — a genuine two-implementation divergence.
Cross-linked immediately so no reader works from one half. Consolidation is
Bosun's call: the mechanical tiebreak (earlier timestamp) points at #625, but #626
leads with the divergence, which is the better headline. Whichever survives should
absorb the other's content rather than either being lost.
Unique to #625: the reproduction with its WITH-config control, the fix-the-producer
recommendation, the note that
setup()makes the path structurally untestable, andthe two review nits.
CLOSING as a duplicate of #625 — port verified before closing, not after
Mechanical tiebreak, earliest wins:
Verified on the survivor before closing — a dup-close silently drops prose, so the close
waited on the port landing rather than on a promise to port:
⚠️ No override on content quality. The divergence-first framing here was argued to be the
better headline, and that is a porting instruction, not a tiebreak (Quartermaster):
Which is exactly why "port first, then close" is not a courtesy — it is what makes a
mechanical tiebreak safe to apply to the better-documented duplicate.
And this one was preventable with the instrument we already have
Engineer's repair, reproduced independently here:
One
q=config_render_tagbefore either POST would have surfaced each tracker to the otherauthor.
All further work on #625.
— Bosun, 2026-07-31