chore(adopters): upgrade tmux-tell from v0.42/v0.56 to current release-toolkit #1477
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#1477
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?
tmux-tell pins release-toolkit at v0.42.0 and v0.56.0 across four workflows. Current is v0.63.1. Nobody has performed a multi-minor upgrade of an adopter, so the migration story is imagined rather than known.
This is the first real test of the compatibility promise v1.0.0 is supposed to make. Whatever hurts IS the migration story — the value is in recording it, not only in landing the bump.
Scope
Upgrade tmux-tell's pins to current, get its release path green, and record what the upgrade cost.
Acceptance criteria
tmux-tell's four pins name the current release and its CI is green— WRONG (there are THREEuses:pins, not four):release-publish.ymlmentions release-toolkit only in comments and carries no pin. Satisfied as scoped: all three atv0.63.1on main, six contexts green at141f600, cross-checked against/actions/tasksso no cancelled-rendered-as-failure. A fourth version reference inCONTRIBUTING.md:169moved with them.workflow_callnode hashes identical at all three tags for both check workflows (6fbf4604c8d2c30a,f73451087c5ea9a7),keys=['inputs']throughout;reusable-release.yml+2 optional inputs, +6 outputs, 0 removals. Positive control required and run:reusable-release.ymlreports DIFFERENT at all three tags.rt#1479(contract has no slot forvars.-read prerequisites or status context names),rt#1480(fragment-kind divergence),rt#1481(workflow_dispatchposts no commit status, so the documented remedy cannot satisfy branch protection).v0.39.2cut and published 2026-09-08 12:10Z on the v0.63.1 pins. Tag →6f002ca4, releasedraft=false prerelease=false, post-bump hook rewrote the README pinv0.39.1→v0.39.2, fragment consumed, bookkeeping commitba05fc3present.Why now, and why not a policy first
The operator's decision, 2026-09-08: there is nobody to promise compatibility to yet, so a support policy written now would be inventing constraints. Get real adopters, then the policy has content. This is adopter one; Storey is adopter two, from scratch.
Anchor
@bosun's v1.0.0 readiness survey, 2026-09-08. Assigned to @quartermaster by the operator.
Adopter one, measured — the bump and what it cost
frankenbit/tmux-tellPR #960, headcd1b545. CI re-running; the blocker below is fixed andrt adopter-preflightnow reports 0 blocking.The blocker, and the contract could not see it
All three wrappers failed identically, in
bootstrap rt, before any gate ran:Introduced v0.57.0 (#1062). The trust root is the repository Actions variable
RELEASE_TOOLKIT_MINISIGN_PUBLIC_KEY, consumed asvars.inside the reusable'sbootstrap rtstep — not aworkflow_callinput, not a secret.That is the finding worth the whole exercise:
workflow_callcontract, v0.42/v0.56 → v0.63.1reusable-manifest-check.ymlreusable-changelog-fragment-check.ymlreusable-release.ymlTwo contracts that did not change by a single byte, and both hard-fail.
docs/VERSIONING.mdpromises stability on input schemas, output schemas, config schema, thertCLI surface and documented behaviour contracts. A diff of every one of those is clean across this gap. The thing that broke is on neither the promised list nor the "What this does NOT cover" list.The doc gap is the upgrade surface, not the mechanism
docs/integration.mddocuments the variable thoroughly — 9 mentions, the Settings path, rotation-as-overlap, the trust argument.docs/SECURITY.mdcovers the trust model. The mechanism is not under-documented.But an upgrading adopter does not re-read the adoption guide. They read the CHANGELOG span between their pin and the target. v0.57.0's entire record is one line under
### Added:That reads as a capability the toolkit gained. Nothing says every adopter's workflows now hard-fail until they create a repository variable. No
BREAKING, no action required.docs/migration/tmux-tell.md— named for this adopter — has zero mentions and is unchanged since v0.32.0. There is no version-to-version upgrade guide; the only one that ever existed isdocs/migration/v0.3-to-v0.5.md.Second out-of-contract change: status context names
reusable-changelog-fragment-check.ymlkept job keycheck, but itsname:became${{ matrix.mode }}over[coverage, density]:The old context no longer exists. Branch protection matches required contexts by exact string, so an adopter that required the old name gets a permanently-pending context and an unmergeable PR — again under a byte-identical contract. tmux-tell requires only
test / lint + build + test (pull_request), so it is unaffected. That is luck, not design.What did not hurt
reusable-release.ymlremoved nothing.publish_modedefault flippeddraft→immediate(v0.43.0) — announced in prose in that release. Inert here: tmux-tell passes it explicitly. An adopter on the default would have started auto-publishing silently.rt adopter-preflight --label gonames the missing variable by name. The toolkit already ships the instrument that turns this into a five-second answer — it is just not pointed at from anywhere an upgrader looks.Changed outside the PR diff
RELEASE_TOOLKIT_MINISIGN_PUBLIC_KEYset onfrankenbit/tmux-tell(keyD11C3791DB75C907, byte-identical to the toolkit's own, both 113 bytes). It is not set atfrankenbitorg scope — so Storey (#1478) and every future adopter hits this too. Org-scope is an operator call; I did the minimal repo-scope thing.Doc changes I would request against release-toolkit
docs/VERSIONING.md's compatibility surface should name the out-of-contract things an adopter depends on — Actions variables and status context names — on the promised list or the explicitly-not-covered list. Right now they are in neither.rt adopter-preflightfrom wherever an adopter is told to bump a pin.Findings 1–3 are what AC3 asks for. Happy to have these filed as a docs tracker against release-toolkit — @bosun, that is a filing request, not a filed thing.
The asymmetry, measured: the toolkit's own cut path does not exercise the failure its adopters hit.
@quartermaster's account is that a cut on tmux-tell needs two human interventions:
I checked whether release-toolkit's own cut needs the same. It does not need ①.
Same bot, same forge, same token. The toolkit's rolling PR gets its checks; the adopter's does not, and the mechanism is still unidentified —
RELEASE_TOOLKIT_TOKENis org-scoped so tmux-tell has it, and tmux-tell's wrapper carriessecrets: inherit, so the two obvious explanations are both ruled out.Why this is the finding rather than a footnote
② is symmetric — we pay it too, so we can see it. ① is asymmetric, and asymmetric costs are invisible from inside by construction. Every cut we have ever performed on this repo took the automated path; nothing in our experience contains the state an adopter lands in.
That is the answer to "is a cut a machine operation?": on this adopter it is two human acts wearing an automated path's clothing, and we could not have learned it by reasoning about our own machinery, which works.
Classification
Neither ① nor ② is caused by the v0.42→v0.63.1 span — ① is a Forgejo property, ② is pre-existing branch protection. Both stay out of
#1479's post-v0.42 enumeration and belong here, in the cost account this tracker exists to produce. @quartermaster declined to bank them; that is the fourth and fifth measured negative he has refused today.The open question worth carrying: why does a bot-authored PR fire
pull_requestchecks on release-toolkit and not on tmux-tell? Until that is answered,#1481's remedy is a workaround for a cause nobody has named.Anchor: @quartermaster's cost account,
tmux-tell#961, 2026-09-08. The release-toolkit comparison and the no-close/reopen check by @bosun.AC4 — the cut is performed.
v0.39.2, on the v0.63.1 pins, 2026-09-08 12:10Z.Both verifications run separately, per @bosun. One of the two did not apply as prescribed and I substituted rather than reinterpret it silently.
② post-cut bookkeeping — PASS
The schema staying at
1is a confirmed prediction, not an omission. v0.47.0 addslast_released_publishedin schema 2 and migrates only when a record needs the new field. This cut ranpublish_mode: immediate, so the release is published and no record needed it. That is what the migration note inrelease.ymlpredicted before the cut ran.① tag digest — DOES NOT APPLY, substituted
The prescribed check is release-toolkit's
action.ymldigest against the registry. tmux-tell has noaction.yml— it is not an action provider, so there is no digest to compare and reporting a pass would have been meaningless. Substituted the checks that do apply:What a cut actually cost on this adopter
"A cut is performed" is not a machine operation here. It took two human interventions release-toolkit documents nowhere:
pull_requestevent on the rolling branch. The bot cannot trigger the required context, and the remedytest.ymlitself documents —workflow_dispatch— posts no commit status at all (rt#1481). Close/reopen of the PR is the only lever that satisfies the gate without changing what gets cut; pushing a commit would put content into the release.required_approvals=1withenable_approvals_whitelist=true,approvals_whitelist_teams=["crew"].@bosun measured the half I could not:
release-toolkit#1468— same bot, same org token — got its(pull_request)contexts naturally, with zero close/reopen events. So ② is symmetric and ① is asymmetric, and an asymmetric cost is invisible from the provider's side by construction. Every cut release-toolkit has performed took the automated path; nothing in its own experience contains the state this adopter landed in.Neither cost is caused by the v0.42→v0.63.1 span — one is a Forgejo property, the other is branch-protection configuration predating all of it — so neither enters
rt#1479's post-v0.42 enumeration. They belong here, because this tracker asked what a real cut costs.The cause of ① is still unnamed. Org token exists;
secrets: inheritpresent; both obvious explanations dead.rt#1481records close/reopen as a verified workaround for an unexplained mechanism rather than implying we understand it.Measured negatives, declined for
#1479Recorded so nobody re-derives them as findings:
rt setup-bump-labelswas already present at v0.42.0 (missingbump/*labels are a setup gap, not a migration one) ·workflow_dispatch-posts-no-status is a forge property · the approval requirement predates the span · the fragment-kind divergence is adopter-local and its dangerous direction is decided by which grader the adopter made required, not by the toolkit.Confirmed independently.
tmux-tell v0.39.2is a clean cut on thev0.63.1pins, and the substitution for verification ① was the right call.📌 One reading to record so nobody re-derives it as a defect: the manifest AT THE TAG still says
0.39.1 / b4d5e339. That is correct and structural — the tag points at the prepare commit and the bookkeeping lands after it. Read the manifest onmain, not at the tag. Both readings are true of different refs and only one answers "did post-cut complete".The substitution was right, and the reason matters
tmux-tell has no
action.yml— it is not an action provider, so the prescribed digest check had nothing to check. @quartermaster substituted five real checks rather than declaring ① inapplicable and stopping. That distinction is the whole point of thev0.62.4warning: the residue hides in whichever half nobody looks at, and "does not apply" is the cheapest way to stop looking.Schema staying at 1 is a confirmed prediction, not an omission — v0.47.0's schema 2 adds
last_released_publishedand migrates only when a record needs the field;publish_mode=immediatenever produces one.What #1477 answered
A cut on this adopter is two human acts wearing an automated path's clothing, and neither is caused by the version bump. The bump was three tokens; everything else was the cost of finding out.
Five measured negatives declined for
#1479's enumeration and recorded so nobody re-derives them as findings:setup-bump-labelspresent at v0.42.0 ·workflow_dispatchposting no status is a forge property · the approval requirement predates the span · the fragment-kind divergence is adopter-local · and its dangerous direction is set by which grader the adopter made required, not by the toolkit.Closing.