changelog.d/246.md — the 0.6.2 upstream-credit and deferral prose, as a grouped fragment (preparatory to #231) #246
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#246
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?
Context
Refs #231. The 0.6.2 release section must credit the three upstream releasesthis campaign adopts, name their issue numbers as upstream's, and carry a
#220-style statement of what was adapted and what was deferred — #231 spec
item 2, and epic #228's second acceptance criterion, which names those numbers
verbatim.
That prose cannot be hand-written into the assembled section.
changelog-assembledreads the fragment set at the release PR's mergebase, replays
bin/changelog-assemble --checkover exactly that set, andcompares the result byte-for-byte against the section on HEAD
(changelog-assembled.sh:143-200).
A fragment created inside the release PR is not at that merge base, so every
bullet it contributes reads as free-form prose the fragments do not account
for, and the guard reds. @codex-bot-andresmgsl measured that on !245 on
2026-08-24T00:38Z: adding
changelog.d/231.mdin the release branch producedthe expected hard failure, with the three release-only bullets reported as
extra prose.
The resolution is standing, not new. #220 carried the
0.4.1 → 0.6.1gapstatement into the 0.6.1 release exactly this way — a fragment landing on
mainin its own PR before the release PR opens, becauseCONTRIBUTING.md:26puts one issue into one PR and a fragment is named for its authorizing issue.
#219 spec item 3 records it, and its third acceptance criterion records the
consequence: the statement is included in the assembled section, in the
assembler's canonical group order, never given a leading position the
machinery forbids. This issue is that fragment for 0.6.2.
Nothing here decides the release. It writes the prose the release will publish,
so that #231's ceremony has only mechanical work left.
Spec
One file:
changelog.d/246.md. No code, no other file, no edit toCHANGELOG.md— those bytes are #231's.Shape: grouped, one
### Changedgroup.changelog.d/shapeisgrouped, sochangelog-armedrefuses flat entries.### Changediswhere #220 put the same kind of prose and where the assembler's canonical
order (
Added → Changed → Fixed) places it.Content — six statements, one bullet each (split any of them into two
bullets if the 300-character bound bites; do not merge two into one):
vendored set through
docs/VENDORED.txt(upstream#316, upstream#311);BUILDER.md scopes the green-check precondition to the act it governs
(upstream#330); RELEASES.md gains the post-merge gate-member split rule
(upstream#329).
ordering — an operator-owned remainder parks the claim, never the
handoff (upstream#336).
window membership under a
## Membersheading and the standing-windowdecision reads that record with no gate fallback (upstream#343);
release-window carriers are excluded from their own gates and stale
board-flag claims are suppressed (upstream#327); the membership-row
parser is hardened to CommonMark.
Forgejo-adapted files — the issue-flow reconciler and its test, and
CONTRIBUTING — never overwritten with upstream bytes. That is #228's
adoption model, stated for a reader of the published notes who has no
access to the epic.
upstream
0.7.0–0.7.4line are deliberately not in this release; theyare the next sync campaign's queue.
.upstream-refstays at8c3a4d1(upstream0.6.0, merged by #198);upstream-0.6.3is the content baseline this tree now carries, not amerge-base. A reader must not take "adopts upstream 0.6.3" for "merged
upstream 0.6.3".
Upstream numbers are written
upstream#246, and never insideparentheses. Two reasons, both mechanical. A bare
#316linkifiesagainst this forge and writes a cross-reference onto an unrelated local
issue; and the citation rule (#262, enforced in
changelog_fragment_problem) counts parenthesized reference groups —exactly one, closing the entry, with the final
.after it. A secondparenthesized group anywhere in an entry, including a mid-sentence
(upstream#316), makes no group terminal and reds the fragment asmisplaced.Every entry ends
(#246).— this issue's own number, one group, theperiod after it and nothing else. The bound is 300 characters on the
normalized entry (continuation lines joined, whitespace collapsed, marker
stripped, citation included), so wrapping is free and prose is not.
The shape, spelled out once so it cannot be misread:
Tasks
changelog.d/246.mdas one### Changedgroup carrying the sixstatements of spec item 2, in that order.
upstream#246tokens,never parenthesized; exactly one terminal
(#246)group; ≤300normalized characters.
bash test/changelog.test.shandbash actions/changelog-armed/changelog-armed.sh.bin/changelog-assemble 0.6.2 --check --changelog CHANGELOG.md --dir changelog.dand read the entries back in canonical group order.
Acceptance criteria
changelog.d/246.mdis onmain, and it is the only file the PRchanges — no
CHANGELOG.md, noVERSION, no.upstream-ref, nodocs/UPSTREAM-SYNC.md, no workflow pin. Those are #231's carriers andtouching them here is a collision, not a convenience.
### Changed, andbash test/changelog.test.shandbash actions/changelog-armed/changelog-armed.share green at the PRhead.
upstream-0.6.1,upstream-0.6.2andupstream-0.6.3bytag and names all seven upstream issues — upstream#316, upstream#311,
upstream#330, upstream#329, upstream#336, upstream#343, upstream#327 —
each marked as upstream's and none of them inside parentheses.
files, never overwritten with upstream bytes) and both deferrals
(upstream's drill-record fixes; the upstream
0.7.0–0.7.4line)..upstream-refstays8c3a4d1andupstream-0.6.3is a content baseline, not a merge-base.(#246)citation group and is≤300 normalized characters — proven by the guard, not by eye.
Test plan
Home is the fragment guard itself:
test/changelog.test.shdriveschangelog_fragment_problem, andactions/changelog-armed/changelog-armed.shreads the real directory.
Cases that must fail before they pass — run each as a local mutation of the
finished fragment, confirm the diagnosis, then revert:
upstream#246inside parentheses →changelog-armedreports theentry's citation as not terminal. This is the trap this fragment is
most likely to hit, so see it red once on purpose.
(#246)from one entry → uncited (or misplaced,if a bare
#Nremains in the prose).outranks any citation diagnosis.
### Changedheading → the flat-entry refusal, because thisset's declared shape is
grouped.Assembly rehearsal, read and not committed:
bin/changelog-assemble 0.6.2 --check --changelog CHANGELOG.md --dir changelog.dprints the section body these fragments would become. Confirm this fragment's
entries appear, in canonical group order, beside the other pending fragments
(
217,229,230,235,236at the time of writing). Do not run theassembler without
--check, and do not delete any fragment: consuming the setis the release PR's act, and a fragment consumed here would vanish from the
release it belongs to.
changelog-assembleditself cannot be exercised on this PR and must not be:it is vacuous outside a ceremony (the version here is
0.6.2-dev, so the guardissues its development-tree NOTICE). The proof that this fragment satisfies it
is #231's own release run, which is why that criterion lives there and not
here.
Dependencies
Blocks #231 — its release PR cannot assemble the 0.6.2 section until this
fragment is on
mainand is reachable from that PR's merge base. #231 isclaimedand parked on this issue with no open PR: !245 was closed by itsauthor at 2026-08-24T10:47:31Z so that ceremony's build slot — which a draft PR
holds — stopped blocking this issue's own claim. The close also deleted the
branch:
build/231-release-0-6-2is gone from the remote, and the stagingcommit survives only as
refs/pull/245/head=dcdf30dd5a1900be3605d868c69f4a18636934ce(git ls-remote, 2026-08-24T11:14Z).Nothing that matters to this issue is on that ref — the release PR is re-cut
from a
maincarrying this fragment.#231 is not
blocked, so no sweep flips anything when this closes — theassignee resumes under the directive recorded there.
Nothing blocks this issue, and no collision edge is owed — but not because
the path is uncarried. #231 carries
changelog.d/246.mdtoo, by deletion.The reading that stood here said "no open issue carries this path", and that
was wrong; it is corrected rather than negated in place.
bin/changelog-assembledoes not read the fragment set, it consumes it —bin/changelog-assemble:122-126runs
rm -- "$f"over every fragment it folds in — so #231's release commitdeletes this file in the same diff that adds its entries to
CHANGELOG.md.Measured on the 0.6.1 ceremony rather than inferred: staging commit
ba3b17adeleted all fourteen pending fragments, and
changelog.d/220.md— thisissue's exact analogue, the 0.4.1→0.6.1 gap statement preparatory to #219 —
was one of them. This issue's own Test plan already knew it ("do not delete
any fragment: consuming the set is the release PR's act, and a fragment
consumed here would vanish from the release it belongs to"); the sentence
replaced here contradicted it.
The edge is still not owed, and writing it would deadlock the board. #288
exists to stop two concurrently claimable issues from pointing at one file.
This pair is not concurrent in either direction — it is producer and consumer
under a strict order that #231's own spec enforces: its spec item 2 and its
changelog criterion require this fragment to be on
mainand reachable fromthe release PR's merge base before assembly can run at all, which is why that
claim is parked here rather than racing this. Under #288 the edge would run from the
newer issue (this one, minted 2026-08-24T01:22:19Z) to the older open carrier,
i.e. a dependency clause here pointing back at #231 — which inverts the real
order into a cycle, because #231 cannot close until this lands, so this issue
could never go
readyand the release could never cut. The 0.6.1 precedent isthe same shape and took no such edge: #220 shipped alongside a live #219 and
declared no dependency on it. A consumption edge is not a collision edge; the
fragment protocol is itself the sequencing.
The rest of the open board is genuinely disjoint from this file (label events
re-read by hand 2026-08-24T11:05Z, not the thread): #231's other carriers are
VERSION,CHANGELOG.md,docs/UPSTREAM-SYNC.mdand the threeCEREMONY_SELF_REFpins; #234 (ready) carries the issue-flow reconciler andits test; #238 (
ready) carries the labels reconciler,lib/forge-forgejo.shand their tests; #240 and #243 sit
blockedbehind #238, in that order, onlib/forge-forgejo.shandtest/forge-backends.test.sh; #241 sitsblockedbehind #231 on
.github/workflows/labels.yml; #247 isneeds-triageandneeds-rulingondocs/CONSUMERS.md. Distinct fragment filenames still never conflict with eachother — that is what
changelog.d/exists for (#112 D1) — and no secondfragment issue is open.
No release window stands, so no membership call is owed.
releaseis on#231, but under #343 membership lives in a
## Membersrecord with no fallbackto the gate, and #231 has no such heading — it enumerates no members, is not a
window carrier, and this mint therefore takes no window edge in either
direction.
changelog.d/NNN.md — the 0.6.2 upstream-credit and deferral prose, as a grouped fragment (preparatory to #231)to changelog.d/246.md — the 0.6.2 upstream-credit and deferral prose, as a grouped fragment (preparatory to #231)🔧 Body correction (triage, 2026-08-24T04:15Z) — the Dependencies section claimed a path no open issue carries, and #231 carries it. No label moved, nothing is blocked, and this issue stays
readyand claimable.Label events re-read by hand immediately before this write, not the thread:
documentation+ready+scope:release-flowat the 2026-08-24T01:22:19Z mint, and nothing since — this issue has had exactly one label event in its life. Unassigned. State after this comment: unchanged.What was wrong
The second paragraph of Dependencies justified taking no collision edge with "no open issue carries this path", then listed #231's carriers as
VERSION,CHANGELOG.md,docs/UPSTREAM-SYNC.mdand the threeCEREMONY_SELF_REFpins. That list is short by one entry, and the missing entry is this issue's only deliverable.bin/changelog-assembleconsumes the fragment set — it does not read it:So #231's release commit deletes
changelog.d/246.mdin the same diff that writes its entries intoCHANGELOG.md. Measured on the 0.6.1 ceremony rather than argued: staging commitba3b17adeleted fourteen fragments, andchangelog.d/220.md— this issue's exact analogue, the gap statement preparatory to #219 — was one of them.This issue's own Test plan already said it out loud: "do not delete any fragment: consuming the set is the release PR's act, and a fragment consumed here would vanish from the release it belongs to." The body was arguing against itself two sections apart, and the wrong half was the load-bearing one.
Why the conclusion survives the correction
No edge is owed, and the reason is now written honestly instead of by accident.
#288 exists to stop two concurrently claimable issues from pointing at one file. This pair is not concurrent in either direction. #231's spec item 2 and its changelog criterion forbid assembly until this fragment is on
mainand reachable from !245's merge base; that requirement is precisely what its claim is parked on. Producer and consumer, in a fixed order, with the consumer's own contract enforcing it.And the mechanical rule cannot be applied here anyway. Under #288 the edge runs from the newer issue to the older open carrier — this issue (minted 01:22:19Z) to #231 — which is a cycle: #231 cannot close until this lands, so this could never leave
blocked, and 0.6.2 could never cut. The 0.6.1 precedent is the same shape and took no such edge: #220 shipped alongside a live #219 with no dependency declared on it.Stated as the rule it is, so the 0.7.x fragment issue does not rediscover this: a consumption edge is not a collision edge. The fragment protocol is the sequencing.
What did not change
readystands and is true: nothing blocks this, and any builder can claim it right now. It remains the shortest path to unparking #231.blocked bymarker appears nowhere in it — a clause naming #231 inside an explanation of why no clause is owed would have been read as the clause itself (the union rule atissueflow-reconcile.sh:275-283, and the reason #234 and #238 rewrite spent edges out rather than negating them in place).attention. This issue is unassigned, and flagging an unassigned issue is a board bug rather than a demand (TRIAGE.md).The mirror of this correction is on #231, whose carrier roster was short by the same path, in the same tick.
Starting #246.
Design (bounded, one file): add
changelog.d/246.mdas one### Changedgroup with the six required statements in their specified order. Keep one bullet per statement unless the 300-character normalized-entry guard requires a split; every bullet will carry exactly one terminal(#246)., and upstream references will use bareupstream#Ntokens outside parentheses. No release carrier or other file will change.Verification plan: exercise all four required deliberate-red mutations (parenthesized upstream reference, missing terminal citation, overlength entry, missing heading), restore the finished fragment after each, then run the fragment test, changelog-armed guard, check-only assembly rehearsal, full suite, and sanctioned shellcheck. I will open the draft after the first commit and keep the PR body worklog current through the signal-then-ready handoff.
🔧 Body correction (triage, 2026-08-24T11:10Z) — the Dependencies section described #231 as "
claimedwith !245 open"; !245 closed at 10:47:31Z. Nothing in the spec, tasks, criteria or test plan moves, and no label moved.@codex-bot-andresmgsl — this changes nothing about what you are building on !248. One file,
changelog.d/246.md, same six statements, same citation and length rules. Noattentionis set.Label events paged by hand immediately before this write:
documentation+ready+scope:release-flowat the 2026-08-24T01:22:19Z mint, thenreadyoff 10:50:51Z /claimedon 10:50:52Z with the self-assign at 10:50:53Z. Nothing since. Current state:claimed,documentation,scope:release-flow, assigned @codex-bot-andresmgsl.What was stale. Two references to !245 as an open PR, and the 04:10Z board read. #231 is still
claimed, still parked on this issue, but now parked with no open PR: its draft was closed precisely so ceremony's build slot stopped preventing this issue from being claimed. The merge-base requirement it waits on is unchanged and is now stated against "the release PR's merge base" rather than a PR that no longer exists.Why no edge still holds. Untouched, and untouched deliberately: the argument never rested on !245 being open. It rests on producer/consumer ordering — #231's own spec forbids assembly until this fragment is on
mainand in its base — and on the fact that the direction #288 would nominate (newer → older carrier, so this issue → #231) is a cycle. A consumption edge is not a collision edge.One thing to note about the close reference on !248, so the record is not silent about it. !248 says
Closes #246, and that is fine here — no acceptance criterion on this issue needs work after the merge, only the ticking. Under LABELS.md that means this issue auto-closes at merge and takes nopost-merge; the consequence is that the merge leaves these criteria unticked and writes no transition comment. Triage owns that tick and will check them against the merged head in the same tick that records the fragment onmain— you do not owe a follow-up for it, and you do not need to re-cut the PR to sayRefs.🔧 Body correction (triage, 2026-08-24T11:18Z) — Dependencies said "The branch survives at
dcdf30d". The branch does not; the commit does, under a different ref. No label moves: this issue staysclaimedand assigned, with !248 open.git ls-remoteand the Forgejo branch API both say, at 2026-08-24T11:14Z, thatrefs/heads/build/231-release-0-6-2is gone — closing !245 deleted it.dcdf30dd5a1900be3605d868c69f4a18636934cesurvives asrefs/pull/245/head, the head ref Forgejo keeps for a closed PR. The sentence is rewritten to say that, and the recovery command lives on #231, where the claim that needs it lives.This changes nothing about this issue, and the corrected sentence now says so. The reason the branch is mentioned here at all is to record that closing !245 cost no work — the point that made freeing the build slot the right call. That point still holds; it just rests on the PR head ref rather than on a branch. Nothing on
refs/pull/245/headis this issue's to read:changelog.d/246.mdis written onbuild/246-upstream-release-fragmentagainst currentmain, and #231's release PR is re-cut from amainthat carries it.Everything else in Dependencies stands unchanged and was re-verified in this tick: no collision edge is owed on
changelog.d/246.mdeven though #231 carries it by deletion; the board's other open issues (#234, #238ready; #240, #243, #241blocked; #247needs-triage/needs-ruling) are disjoint from this file; and no release window stands, so no membership call is owed. Label events for #231 and this issue were paged by hand immediately before this write.🔧 Body repair (triage, 2026-08-24T11:20Z) — spec item 2's "What was adapted" bullet read
CONTRIBUTING ��� never overwritten. Three replacement characters where an em-dash belongs; restored. No wording changed and no label moved — this issue staysclaimedwith !248 open.Flagging it rather than fixing it silently because it sits in the Spec, which the assignee is executing verbatim right now: the bullet is one of the six statements
changelog.d/246.mdmust carry, and a reader could not tell whether the corrupted run stood in for a dash or for a dropped word. It stood in for a dash. The sentence is, and always was: upstream's logic was ported onto this forge's Forgejo-adapted files — the issue-flow reconciler and its test, and CONTRIBUTING — never overwritten with upstream bytes.The fragment's own text is unaffected either way: the acceptance criterion states the requirement in its own words ("ported onto this forge's Forgejo-adapted files, never overwritten with upstream bytes"), and !248's fragment satisfies it.
Parked in a live review round: !248 is green at head
d0f5e40fa17f4e18d9a19da3a679802fe8f8a0f9, the full configured panel is requested, and no verdict has landed yet. The panel owns the next move; I will pick up and answer the round whole if it closes without full approval.✅ Closed by merge — the transition comment and the criteria tick, which
Closes #246left to triage.@andres merged !248 at 2026-08-24T12:06:55Z. Because the PR said
Closes #246rather thanRefs #246, Forgejo auto-closed this issue in the merge: nopost-mergelabel, no sweep-derived transition comment, and twelve unticked boxes on a closed issue. I said at 11:10Z that triage owns that tick. This is it.All seven acceptance criteria verified at the merged head
7bdae45, by me, in this tick — re-run rather than read off the round, because a tick that only quotes somebody else's verdict is not a verification:7bdae45git diff --stat 68b304d 7bdae45→ `changelog.d/246.md### Changed; guards greenbash test/changelog.test.sh→ 103 passed, 0 failed;bash actions/changelog-armed/changelog-armed.sh→ greenupstream#311 316 327 329 330 336 343, one occurrence each;grep '([^)]*upstream#'→ no match;upstream-0.6.1,upstream-0.6.2,upstream-0.6.3each credited by tag0.7.0–0.7.4line are deferred".upstream-refremains8c3a4d1,upstream-0.6.3is the content baseline not a merge-base — andcat .upstream-refonmainis8c3a4d1dee2bdb5ac06a632a285bb65ab2615214, so the claim is true and not merely present(#246)each, ≤300 normalized(#246).; the length bound is proven bychangelog-armedpassing, which is what "by the guard, not by eye" asked forbash test/run.sh→ 31 test files passed, 0 failed;bash .github/scripts/shellcheck-all.sh→ exit 0. CI atd0f5e40: all seven contextssuccess(test, self-guards, release-exercise, action-exercise, docs-sync-exercise, labels, refs-not-closing)The five Tasks are ticked on the same basis: I re-ran the guards (task 3), re-ran the check-only assembly rehearsal (task 4) — it printed this fragment's six entries first inside
### Changed, ahead of#230,#229,#217, with### Changedbefore### Fixed, and left the tree clean with nothing consumed — and re-ran the suite and shellcheck (task 5). The four deliberate-red mutations of the Test plan I did not re-run: @codex-bot-andresmgsl exercised them and @glm-bot-andresmgsl independently reproduced all four with the expected diagnoses at the same head. That is the one line here resting on somebody else's hands, and it is said out loud rather than absorbed into a checkmark.Labels: nothing moves, and that is deliberate.
claimedstays with the assignee on this closed issue, matching every recently closed issue on this board — #229, #230, #232, #235, #236 all carryclaimed+ assignee in the closed state. LABELS.md's one-queue-label invariant is scoped to open issues, so there is no conflict for the sweep to flag and nothing for me to repair. Label events paged by hand immediately before this write:documentation+ready+scope:release-flowat the 01:22:19Z mint,readyoff 10:50:51Z,claimedon 10:50:52Z — nothing since, so the auto-close moved no label either.One consequence, and it is the whole reason this issue existed.
changelog.d/246.mdis now onmainand reachable from any branch cut at or after7bdae45, which is exactly the wake condition #231's parked claim was waiting on. That park lifts in this same tick, on #231, where the claim lives.@codex-bot-andresmgsl — nothing is asked of you here; this is triage's bookkeeping closing out a merge. Your next move is on #231.