release-init after 0.6.3 — the survey, and the one ruling that decides the next window's identity #268
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:docs
scope:guards
scope:labels
scope:release-flow
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#268
Loading…
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?
Closed unshipped 2026-08-27: the operator ruled option C — no
0.6.4, nowindow. The ruling is recorded in the closing comment below and the body is
corrected to match it. This was the release-init working surface for the window
after 0.6.3, opened off that cut per
RELEASES.mdstep 5 — "treat that close asthe trigger for the next window." 0.6.3 had no epic to close, so the cut itself
is the trigger, as triage said it would be on !267.
It deliberately carries no membership record. Under #343 a window stands only
on an open
release-labeled issue whose## Membersrecord holds at least oneopen member, with no fallback to the gate —
release_window_membersreads thatheading and nothing else. Release-init writes that record at step 3, and step
3 never ran. No window ever stood here, no membership call is owed on any mint,
and the sweep draws no window flag.
Predecessor gate
Cleared, with nothing to declare it against. !267 merged as
8f0ef79at2026-08-26T20:18:17Z; the door tagged and published
0.6.3at 20:20:18Z andre-armed
mainto0.6.4-devatbcbcd90. 0.6.3 cut epic-less, so there is nopredecessor issue for this epic to gate on.
The release is sound on the one check that could only run at the merge:
CI / self-guardsis success on8f0ef796(run 2399), sochangelog-assembledgraded the real fragment set at the real merge base. Thatis the check 0.6.2 failed.
Step 1 — the survey
Measured 2026-08-26T20:26Z against
origin/mainatbcbcd90.The board is empty. Open issues: exactly one, #265, at
post-merge. Openpull requests: none. Open proposals: none. There is also no predecessor epic, so
there is no "to mint when this arc opens" list to draw from — 0.6.3 left none.
The one accumulated deferral.
docs/UPSTREAM-SYNC.md: "Upstream'sdrill-record fixes and the upstream
0.7.0through0.7.4line remain deferredto the next sync campaign." That is the only recorded, unspent deferral in the
tree, and it has grown past what the record says:
.upstream-ref)8c3a4d1dee2bdb5ac06a632a285bb65ab2615214— upstream0.6.0, merged by #1980.7.0through0.7.40.7.0through0.7.6— seven releases0.7.50.7.60.6.2's content came across by port (#229, #230) rather than merge, so no
upstream ancestry moved and
.upstream-refstill names upstream0.6.0.The one finding this survey held back — now minted as #269. That deferral
range is stale by two releases. Whether it was a standalone doc fix or would be
absorbed by a campaign rewriting the whole port record depended on the ruling,
so the survey left it. The ruling answered both halves at once: fix the record
now, and the campaign that eventually consumes it merges rather than ports.
#269 carries both,
readyand unblocked.Steps 2 and 3 — never ran
There was nothing to graph and no membership to write while the ruling stood,
and option C means there never will be: a window with no members has no graph.
## Membersstays absent, which is exactly how #343 says a non-window reads.Step 4 — ruled: C, no window
RELEASES.mdnames the operator's blessing as the one step this chain neverautomates, and it was a hard block rather than a timed default because the
choice sets a published tag's version number. It was answered on
2026-08-27T09:48:51Z: C — no window yet, no
0.6.4, close this epicunshipped.
RELEASES.mdrelease-init anticipates exactly this outcome — "ifinit finds no work worth minting, the operator either folds the empty window
into a later release or skips the version, recording that ruling on the epic
before closing it unshipped."
The ruling's two directions are dispatched: the
docs/UPSTREAM-SYNC.mdrecordfix is minted as #269, and the next window's identity — the sync campaign, and
it merges (
A/merge) — is recorded both in the closing comment below and,by #269, in the procedure file itself. Nothing was held waiting on this: the
board was idle by design, not by blockage.
Task list
graph, no waves, and no
## Membersrecord0.6.4, no windowtrigger for another window: the next release-init runs when there is work to
survey, or when the operator calls for the sync campaign
Board note, not part of this window
#265 stays on its own
post-mergetrack and is not a member of anything here.Its code shipped in
d439ff6; only its criterion 8 is outstanding, waiting on anoperator
workflow_dispatchofself-labels-sweep.ymlwithbootstrap=yes.Re-measured at this survey: ceremony's live
needs-triagedescription is still"Did not come through triage — owes normalization or conversion to a
discussion", against
LABELS.md's "a proposal or stray issue that did not comethrough triage — it owes normalization into work or a reasoned refusal".
Unchanged. Its fallback date is unchanged: 2026-09-01T22:20Z.
🧭 needs-ruling — what the next release window is, and therefore what version number it cuts.
Options: A — run the deferred upstream sync campaign as the next window and cut at upstream's number B — cut a forge-local
0.6.4first and defer the sync campaign again C — open no window yet; close this epic unshipped and re-run release-init when work accumulatesRecommend: A, because it is the only accumulated work this survey found, and it has already grown by two releases while sitting deferred.
Blocked: release-init steps 2 and 3 stop here — the dependency graph and the membership record cannot be written against an unidentified window — as does the mint of the stale-range doc fix; everything else continues, the board having no open work issue, no open proposal and no open PR, and #265's
post-mergetrack being untouched either way.Default: none — hard block. The choice sets a published tag's version number,
release.ymlrefuses to re-release an existing tag, andRELEASES.mdreserves this step to the operator in the first place.Analysis
Why this is a ruling and not triage's pick
Two separate things make it the operator's.
RELEASES.mdstep 4 — "Ask theoperator to bless the order... The operator's blessing is the one step this
chain never automates." And
TRIAGE.mdoutcome 3 — published artifacts. Aversion number is published and untakeable back, which is also why the
Default:line above is a hard block rather than a timed default:BUILDER.mdsays unsure is not a tie, and published artifacts are hard blocks by
construction.
What each option costs
A — the sync campaign is the window. Standing resolution #197 D2 is that
VERSIONand bothCEREMONY_SELF_REFcarriers take upstream's number, sothis window would cut
0.7.6(or upstream's number when it closes), not0.6.4. The merge door's re-arm ofmainto0.6.4-devatbcbcd90ismechanical and the campaign would overwrite it; that is a consequence to expect,
not a defect to repair first.
This option carries one sub-decision that does not need its own ruling now,
because
docs/UPSTREAM-SYNC.mdalready frames it: port or merge. "If thatcampaign merges rather than ports, it is the campaign that advances
.upstream-ref; another port leaves the ancestry baseline unchanged." 0.6.2was a port, so the ancestry baseline is still upstream
0.6.0(8c3a4d1) whileupstream has cut seven releases past it. The gap between "content baseline" and
"ancestry baseline" widens with every port. I would graph that choice at step 2
and put it in front of you with the waves at step 4 — but if you want to settle
it in the same breath as this ruling, say
A/mergeorA/port.B — a forge-local
0.6.4first. This is the option the survey cannotsupport on its own: there is no forge-local work on the board to fill it. Open
issues total one, #265, and it is
post-merge— already shipped code awaiting asingle dispatch. Picking B is therefore also a statement that work exists which
this survey could not see, and I would need it named before steps 1 through 3
could run.
C — no window yet. Cheapest and fully reversible.
RELEASES.mdprovides forit: "If init finds no work worth minting, the operator either folds the empty
window into a later release or skips the version, recording that ruling on the
epic before closing it unshipped." The board is already idle and truthful, so C
costs nothing today; its only price is that the sync deferral keeps growing, and
the record of it in
docs/UPSTREAM-SYNC.mdstays two releases stale.Why the recommendation is A
The deferral is not theoretical and it is not static. It was written naming
upstream
0.7.0through0.7.4; upstream0.7.5was in fact already tagged(2026-08-19) when it was written, and
0.7.6landed 2026-08-25. Seven upstreamreleases now sit outside this tree's ancestry. Each further port widens the
delta that the next merge has to reconcile, so the campaign gets more expensive
the longer C runs — which is the argument for A over C, and there is no
identified work behind B.
What I am not doing on my own
Not minting the
docs/UPSTREAM-SYNC.mdrange fix. Under A the campaign rewritesthat whole port record and the standalone fix becomes churn; under B or C it is
a real small mint. Minting it now would decide this question by the back door.
Not writing a membership record. Under #343 that heading is the window, so
writing one before this ruling would stand a window whose contents nobody has
blessed, and would immediately start charging every new mint a binary membership
call against it.
@claude-bot-andresmgsl — this ruling is 12 hours past its
labeledevent: the ladder's12h rung (BUILDER.md — the ruling ask,
heavy-duty/ceremony#50 D13). Mechanically read, the escalation carries
Default: none— a hard block; no default ever fires.The rung's duty is the flag-setter's: re-read the
Default:againsteverything that has landed since the flag went up — does it still hold, and
has reasonable doubt appeared? A stale default does not fire, and new doubt
makes it a hard block. The rungs run on the
labeledclock and do notreset on activity; this comment fires once per flag episode.
⏱️ 12h rung — the re-read, not a fire. I set this flag, so the rung is mine to answer. Re-measured 2026-08-27T09:07Z, against everything that has landed since the
labeledevent at 2026-08-26T20:27:42Z.Nothing has landed that touches it.
origin/mainbcbcd90(VERSION=0.6.4-dev)post-merge, labels unchanged0.7.60.7.6(git ls-remote --tags github.com/heavy-duty/ceremony).upstream-ref8c3a4d1— upstream0.6.0The
Default:still holds, and it cannot go stale.Default: none — hard blockdoes not rest on a measurement that could move:RELEASES.mdstep 4 reserves the blessing to the operator, the choice sets a published tag's version number, andrelease.ymlrefuses to re-release an existing tag. Nothing that could land would convert that into a timed default. No default fires; the block stands.No new doubt appeared, so there is nothing to harden — it was a hard block on day one. The recommendation is unchanged: A. Its case moves in one direction only, and it did not move in these twelve hours: no upstream release cut, so the range recorded in
docs/UPSTREAM-SYNC.mdis stale by exactly the same two releases as at the survey, not three.The
Blocked:line is also still true as written. Release-init steps 2 and 3 stop, and thedocs/UPSTREAM-SYNC.mdrange fix stays unminted; nothing else is held. The board's idleness is by design — there is no open work issue, no open proposal, no open PR — so the wait costs nothing today beyond the deferral's own growth.What the next rung does, so the shape of the wait is visible. The 24h rung falls at 2026-08-27T20:27:42Z. Because triage set this flag, that rung and the past-24h rung land on the same actor: if the ruling has not arrived by then, it becomes my duty to pick, record the pick as a decision, and stay accountable for it (
TRIAGE.mdoutcome 3, #50 D13–D14). I would pick A, and would take the unresolved sub-decision asA/mergeunless you say otherwise, since a further port is what keeps widening the ancestry gap. Nothing publishes by that: the version stamp still lands in a release PR you gate at merge, and the membership record steps 2 and 3 would write is a heading, editable and reversible.A one-word reply —
A,A/merge,A/port,B, orC— closes this out and I run the held steps in the next tick.Ruling: C — no window yet.
A is the right destination, but not now. Measured: upstream
0.7.0–0.7.6is448 commits / 87 files / +24,161 lines — roughly 25× the 0.6.2 port — and it
rewrites all three files the forge delta lives in (
runner-isolated+1619,labels-reconcile+889,issueflow-reconcile+758). That is not a campaign toopen while crew's burn work is unfinished and its main is red.
The "it gets more expensive while you wait" argument doesn't carry the decision:
the cost is the 24k lines already standing, and upstream adds about one release
a week. A short wait is noise against that.
B is unsupported — the survey is right that there is no forge-local work to fill
a 0.6.4.
So: close this epic unshipped per
RELEASES.md, no0.6.4, no window.Two directions:
docs/UPSTREAM-SYNC.mdrange fix now. The record says0.7.0through
0.7.4; it is0.7.0through0.7.6. Under C that is a real smallmint, and the record should be true while it waits.
A/merge..upstream-refhas been pinned at upstream0.6.0since #198 because 0.6.2came across as a port. Another port leaves it pinned and guarantees a third,
larger campaign. When it runs, it advances the ancestry baseline.
Re-run release-init when there is work to survey, or when I call for the sync.
✅ Ruling recorded — C. This epic closes unshipped, and
needs-rulingcomes off with it.I set this flag, so closing it out is mine (
TRIAGE.mdoutcome 3). The decision, in one place, so nobody has to reconstruct it from the thread:0.6.4, which is what step 1 said and the ruling confirmedRELEASES.mdprovides for exactly this outcome — "if init finds no work worth minting, the operator either folds the empty window into a later release or skips the version, recording that ruling on the epic before closing it unshipped." The body above has been corrected to match the ruling rather than left describing a pending block: steps 2 and 3 are marked never-run, step 4 carries the answer, and the task list no longer shows an open ladder.The two directions, both dispatched in this tick
1. The
docs/UPSTREAM-SYNC.mdrecord fix is minted: #269,readyand unblocked. It is the mint this survey deliberately held back, and C is what releases it. No collision edge is owed (#288) and no membership call is owed (#343): board read 2026-08-27T09:57Z — no open PRs, and #265 ispost-merge, so it is neither claimable nor a carrier.#269 fixes the range and the sentence beside it in one edit, because the ruling made both stale at once. The record said upstream
0.7.0through0.7.4; the floor is right and the ceiling expired before it was written —0.7.5was tagged 2026-08-19, five days beforefdb7d75recorded the range on 2026-08-24, and0.7.6landed 2026-08-25. So #269 records a floor and a dated measurement instead of a new ceiling that would expire inside a month at upstream's tagging rate.2. The next window is the sync campaign, and it merges —
A/merge. That answers the sub-decision I flagged as unresolved at the 12h rung, and it is recorded twice on purpose: here, and by #269 indocs/UPSTREAM-SYNC.mditself under a new## The next campaign mergessection. A decision that only lives in a closed epic is one the next sync will not read; the procedure file is where it will be looked for..upstream-refhas been pinned at8c3a4d1— upstream0.6.0, merged by #198 — since 0.6.2 came across as a port, and another port would leave it pinned and guarantee a third, larger campaign. The campaign that runs advances the ancestry baseline.Board state after this tick
release-labeled issue is open; no window stands and none ever did here —## Memberswas never written, which under #343 is silence rather than a false flag. No mint owes a membership call.ready, unblocked, unassigned) and #265 (post-merge, criterion 8 still waiting on an operatorworkflow_dispatchofself-labels-sweep.ymlwithbootstrap=yes, fallback date 2026-09-01T22:20Z — untouched by this ruling either way). No open PRs.mainstays atbcbcd90,VERSION=0.6.4-dev. The ruling does not reserve0.6.4: under standing resolution #197 D2 the sync campaign cuts upstream's number, so the re-arm's-devstring is mechanical and decides nothing. Nothing was tagged or published, which is why C is fully reversible.attentionis set: this epic is unassigned and #269 is unclaimed, and flagging an unassigned issue is a board bug rather than a demand.Closing this epic releases nothing — no open issue declares it as a blocker — and this close is not a trigger for the next window, which is the one way it differs from a shipped close. The next release-init runs when there is work to survey, or when @andres calls for the sync.