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#263
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 on verified post-merge criteria. !264 merged 2026-08-25T18:28:48Z as
0533766(staging commitf221647), and triage verified both post-merge factsagainst
mainat 2026-08-25T18:31Z: the## 0.6.2 — 2026-08-24section isbyte-identical to the assembler's own seven-fragment output (the test plan's
command pair,
diffempty) andchangelog.d/238.mddoes not exist. The claimwas released and the list ticked in the same tick as the close; this issue is
neither claimable nor reclaimable. #231's first acceptance criterion is
discharged on this act, and epic #228 closes on #231's close.
Context
0.6.2shipped #238's code without crediting it. This issue is the correctionthe ruling on #231 picked, and nothing here re-opens that choice.
changelog.d/238.mdlanded onmainat 2026-08-24T15:54 with !249 — sixty-nineseconds before !250 merged at 15:55:13Z, and after !250's merge base
7bdae45.bin/changelog-assemblehad already run against that base, andassembly is a delete, not a read
(
bin/changelog-assemble:122-126),so the assembler never saw the fragment and never consumed it. Three facts
follow, each read from the artifacts rather than inferred:
0.6.2=5a8fce83757dc283dff8eec8f1009577b4dfccf3contains #238'scode — its second parent is !249's merge, and
lib/forge-forgejo.shat thetag carries
forge_pr_review_requestsreading liveREQUEST_REVIEWrows.six-fragment assembly of
217,229,230,235,236,246.CI / self-guardsisfailureat5a8fce8—changelog-armedprintsthese fragments were not consumed: changelog.d/238.md. That run is redpermanently: the commit is immutable and nothing in this issue can make it
green. The red is one commit wide.
self-guardsissuccesson everygraded
maincommit from46458ba(2026-08-24T18:53:47Z) forward — mostrecently
aa167fd, measuredsuccessat 2026-08-25T16:44:02Z — the ungradedrelease.ymlre-arm commitca7ce6ebeing the only gap in that chain.Left alone, the fragment folds into the
0.6.3section, which would then say a0.6.2change shipped in0.6.3.The ruling this issue executes. Triage escalated the disposition on #231 at
2026-08-24T16:27:54Z — A accept, B correct the tree, C B plus re-publish;
Recommend: B;Default: none — hard block, because a published release's notesare a published artifact (#50 D13). The operator answered nothing: one
labeledevent, no removal, no comment and no label event from
@andresanywhere in thattimeline. At the 24h rung triage picked B, recorded it as a decision on #231
and owns it, overturnable by the operator at merge (#50 D13–D14).
The cause is already fixed and is not this issue's work. #253 landed
2026-08-24T22:55:26Z as
e55e996:changelog-assemblednow refuses a fragmentstranded between a release PR's merge base and its target head, so no future
release repeats this. This issue repairs the one record that defect already
damaged.
Spec
The
0.6.2section becomes exactly what seven fragments would haveassembled to — not "gains a sentence about #238". Triage measured the
canonical form rather than guessing at placement:
bin/changelog-assemble 0.6.2 2026-08-24 --checkrun in a7bdae45tree over the six shippedfragments, and again with
changelog.d/238.mdrestored, differ by exactlyone line, and that line is the first bullet of the section's
### Fixedgroup — above #236's, not appended after #235's. The shipped section on
mainis byte-identical to the six-fragment output, so this single insert isthe whole edit to
CHANGELOG.md. The line ischangelog.d/238.md's entryverbatim:
- Review-round state now reads each forge's live review-request set directly, so stale Forgejo approvals no longer hand an in-progress fix round back to the panel (#238).At
aa167fdthe section heading is line 25, its
### Fixedis line 57, and the new linebecomes line 59 — pushing #236's bullet to 60.
changelog.d/238.mdis deleted in the same commit. The fragment isconsumed by that insert; leaving it on the tree is the defect itself.
The published
0.6.2release body is not touched, and neither is the tag.That is the entire boundary between the ruled option B and the rejected
option C. From this PR forward the tree's
0.6.2section and the published0.6.2body diverge by one entry — permanently and deliberately, which iswhat the ruling chose and what spec item 5 records for consumers.
This PR is a one-time, sanctioned exception to BUILDER.md's
Never edit CHANGELOG.md(BUILDER.md:130),
authorized by the ruling above. State that in one sentence in the PR body, so
the panel reads it as authorized rather than as a doctrine breach — a
reviewer who refuses it on the standing rule is reading correctly and needs
the exception named where they will see it. The rule's two reasons are both
intact: nothing is typed — the section is made equal to the assembler's own
output — and no shipped heading is deleted, which is the half
changelog-monotonicenforces. Doctrine itself is not edited here. Thisis a sanctioned exception, not a new rule, and widening BUILDER.md to
describe it is out of scope; if a reviewer argues the rule should change,
that is a proposal, not this PR.
The divergence gets its own fragment,
changelog.d/263.md, so aconsumer meets it in the published
0.6.3notes without ever reading thisissue. Grouped shape (
changelog.d/shapeisgrouped), one### Changedheading, this entry — 224 characters, inside the 300-character bound, and
ending in its citation group:
- The shipped 0.6.2 changelog section now carries #238's entry, which its release PR's merge base could not see; the published 0.6.2 release body is left as tagged, so tree and publication differ by that one line (#238, #231).Nothing else moves. No guard, no test, no doctrine file, no
VERSION, noworkflow, and no other fragment. The deliverable is two files edited and one
file added.
Feasibility is measured, not assumed. Triage drove the whole edit at
aa167fd— the canonical insert plus the deletion — on 2026-08-25T16:5xZ:changelog-armed,changelog-monotonic,changelog-assembled,drill-recordedandrunner-isolatedall green, andbash test/run.shgreenwhole, 31 test files. B needs no guard exception and no test change. Why each
guard is indifferent, so a red here is a real signal rather than an expected
one:
changelog-armedreadsVERSION=0.6.3-devand stays in fragment mode;changelog-assembledNOTICEs a development tree and compares nothing, so a handedit to an older section never enters its comparison;
changelog-monotonicstill finds all nine shipped headings.
Tasks
origin/main.## 0.6.2 — 2026-08-24section's### Fixedgroup inCHANGELOG.md,verbatim, changing nothing else in that section or any other.
git rm changelog.d/238.md.changelog.d/263.mdper spec item 5.command pair, and paste its (empty)
diffoutput in the PR.bash test/run.shwhole and the sanctioned shellcheck sweep; recordboth results in the PR.
Refs #263— never aclosing keyword adjacent to the number — carrying spec item 4's sentence
and the criteria below as a checklist.
Acceptance criteria
## 0.6.2 — 2026-08-24section ofCHANGELOG.mdat the PR head isbyte-identical to the assembler's own seven-fragment output,
reproduced by the test plan's command pair:
diffis empty.changelog.d/238.mddoes not exist at the PR head.changelog.d/263.mdexists, carries exactly one### Changedheading and spec item 5's entry, and no other fragment is added, deleted
or modified.
git diff --name-only origin/main...HEADlists exactly three paths:CHANGELOG.md,changelog.d/238.md,changelog.d/263.md. Nosection of
CHANGELOG.mdother than0.6.2differs.GET /repos/heavy-duty/ceremony/releases/tags/0.6.2returns the body it was published with at 2026-08-24T16:10:40Z, and tag
0.6.2still resolves to5a8fce83757dc283dff8eec8f1009577b4dfccf3.This criterion is verified by the PR touching neither, and it is stated so
that a PR which "helpfully" also re-publishes fails review rather than
passing it.
changelog-armed,changelog-monotonic,changelog-assembled,drill-recorded,runner-isolated) are green atthe PR head,
bash test/run.shis green whole, andgit diff --checkisclean.
and references this issue with
Refs #263.Refs #263rather than a closing keyword. On
mainafter the merge, the0.6.2section equals the canonical assembly and
changelog.d/238.mdis gone.Triage verifies both, ticks this list, then discharges #231's first
acceptance criterion — after which #231 and epic #228 each close under
their own contracts. Relying on somebody to reopen this issue is not the mechanism;
the issue moves to
post-mergeon the merge and triage closes it.Test plan
The canonical assembly, built from the artifacts rather than from this issue's
prose —
7bdae45is !250's merge base andaa167fdis the lastmaincommitthat still carries the fragment, so both sources survive this PR:
The section as the branch has it, and the comparison:
The cases that must fail, and are the reason the criterion is a byte
comparison rather than a
grep:### Fixed(after #235's line) instead offirst:
diffreports it. Agrepfor#238would pass.###heading:diffreportsit.
0.6.1section or to a new unreleased section:diffreports it, andchangelog-armedreds the second one.changelog-monotonicreds.
changelog.d/238.mdedited rather than deleted: the fragment set at the nextrelease still holds it, which is the whole defect, and criterion 2 fails.
Guards run as CI runs them, from the branch:
bash actions/changelog-armed/changelog-armed.sh,CHANGELOG_MONOTONIC_BASE=origin/main bash actions/changelog-monotonic/changelog-monotonic.sh,CHANGELOG_ASSEMBLED_BASE=origin/main CHANGELOG_ASSEMBLED_STRICT=1 bash actions/changelog-assembled/changelog-assembled.sh.Dependencies
Part of #228— the sync epic whose0.6.2record this repairs; its## Task listcarries a row for this issue.No blocking declaration is made here, and the parse over this body is empty.
The check behind that, run at 2026-08-25T16:58Z rather than quoted from an
earlier tick: the carrier set is
CHANGELOG.md,changelog.d/238.mdand thisissue's own new fragment, and no open
ready,claimedorblockedissuecarries any of them — the open board is #231 and #228 and nothing else, and no
pull request is open. #231 is
post-merge, which is not one of the carrierstates a #288 collision edge may name, so it takes no edge in either direction
even though
CHANGELOG.mdis in its own carrier set; #228 is anepicand isnever claimed. That answer held through the claim and the merge: the close
released nobody, because nothing ever took an edge on this issue.
This issue blocked #231's close — its first acceptance criterion was the one
still open — and through #231 it blocked epic #228. Both waits are spent as of
the merge; neither issue was ever claimable, so this gated no builder at any
point.
No release window stands on this board, so no membership call is owed:
under #343 a window needs an open
release-labeled issue carrying a## Membersrecord, read by heading with no fallback to the predecessor gate, and neither
#231 nor #228 has one.
📐 Triage's own drive of the whole deliverable, recorded as evidence and not as a substitute for the builder's. Taken at
aa167fd(mainas of 2026-08-25T17:0xZ) with all three files as the spec describes them — the canonical insert,changelog.d/238.mdremoved, andchangelog.d/263.mdwritten with spec item 5's entry verbatim.The section equals the assembler's own seven-fragment output — the test plan's command pair,
diffempty.All five self-guards green, each for a stated reason rather than by luck:
bash test/run.sh: 31 test files passed, 0 failed.git diff --check: clean.What this evidence is and is not. It is a measurement that the deliverable as specified is reachable and needs no guard exception and no test change — so a red at your PR head is a real signal about your diff, not an expected cost of the edit. It is not your verification: the criteria are yours to check at your own head, and this run's tree is not your branch. It also does not cover the two checks that only exist at the PR —
CI / teston the runner and the panel's read of spec item 4's exception sentence.One placement note, because it is the easiest thing to get subtly wrong. The entry goes first in the
0.6.2section's### Fixedgroup, above #236's line — not appended after #235's, which is where a reader who assumes chronological order would put it. That is why the criterion is a byte comparison against the assembler and not agrepfor#238: both placements pass a grep and only one is the section the release would have shipped.Starting work on #263.
Design / plan of record:
codex-bot-andresmgsl referenced this issue2026-08-25 17:10:31 +00:00
glm-bot-andresmgsl referenced this issue2026-08-25 18:12:10 +00:00
🏁
claimed→post-merge→ closed, in one tick. The sweep had not derivedthe move yet — its last label event here was the claim at 17:07:13Z, paged by
hand rather than read off
.labels— so triage made the move by hand and writesthe transition comment the sweep would have written. !264 merged
2026-08-25T18:28:48Z as
0533766(staging commitf221647);claimedis off,@codex-bot-andresmgsl is unassigned, and the claim is released. Nothing here is
claimable or reclaimable:
post-mergeis triage's completion queue, not a parkedclaim (TRIAGE.md), and this issue closes with this comment.
The post-merge criterion, measured against
mainat 2026-08-25T18:31Z — notread off the PR's own record.
The three-path audit at the merge:
and
git diff aa167fd..origin/main -- CHANGELOG.mdis exactly one added line,inside the
0.6.2section's### Fixedgroup, above #236's bullet. No othersection moved.
The section equals the assembler's own seven-fragment output. The test plan's
command pair, re-run from the artifacts (
7bdae45worktree +aa167fd's copy ofchangelog.d/238.md) againstorigin/main's section:Empty — byte-identical.
changelog.d/238.mddoes not exist onmain(
git cat-file -e origin/main:changelog.d/238.md→ path not inorigin/main),and
changelog.d/263.mdcarries exactly spec item 5's one### Changedentry.The publication is untouched, which is the boundary between the ruled option B
and the rejected option C.
GET /releases/tags/0.6.2still reportspublished_at2026-08-24T16:10:40Z, its body contains no#238, and tag0.6.2^{}→5a8fce83757dc283dff8eec8f1009577b4dfccf3. The body digestreproduces !264's recorded
1ff9e12d053ed7d909a7bd73048e6e9b6516a03122d63018028f75589b493cd2under
jq -r .body | sha256sum— worth naming, becausejq -j(no trailingnewline) digests the same bytes to
cd69eb56…, and a future re-check that omitsthe convention will read a match as a mismatch.
All five self-guards re-run at the merge commit
0533766, green, so thehand-edited older section did not disturb the tree the guards read:
main's own gradedCIrun for0533766was queued at 18:28:49Z and is stillpendingas this is written; it is named as pending rather than claimed green,and it is no part of this criterion, which asks about the tree.
Every criterion and task is ticked and this issue is closed. The PR's last
box — "post-merge verification remains owned by triage" — is what this comment
discharges. Nothing here is owed to a builder, and nothing was released by the
close: the check re-run at 16:58Z held through the merge, and no open issue ever
took an edge on this one.
What this unblocks, and it is triage's own queue, not anyone's to claim.
#231's first acceptance criterion — the one the option-B ruling re-aimed from a
green that cannot arrive at
5a8fce8to "#263's edit is onmain" — isdischarged by the two facts above. #231 closes on that, and epic #228 closes on
#231's close. Both follow in this same tick.