ceremony adopts changelog.d — the flag flip #125
No reviewers
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#125
Loading…
Reference in a new issue
No description provided.
Delete branch "build/117-changelog-d-flip"
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?
Closes #117
Acceptance criteria
git grep -n '## Unreleased'returns only: the test fixtures named out of scope above, and prose that is explicitly about legacy mode. (Survivors: test fixtures, ci.yml's monotonic scratch fixture, drills/0.1.0.md — an immutable record — and legacy-mode prose in README/CONSUMERS.)## Unreleasedat2f58d9bexists as a fragment, its text byte-identical. (sort-diff of the 26 entries against the fragment set: identical.)bin/changelog-assemble 0.2.0 --checkprints a section containing all 20 entries, newest issue first, andchangelog_section_problemfinds no problem with it. (27 lines: the 26 converted plus this PR's112.md; problem check silent.)changelog-armedis green on this tree in fragment mode, and would be red on it withchangelog.d/removed — the flip is real, not cosmetic. (Verified both ways locally; ci.yml's self-guards job runs it on every PR from here on.)changelog-assembledis green (NOTICE) on this PR, which is not a ceremony PR. (NOTICE — no 'changelog.d/' at the merge base — legacy mode.)## 0.1.0and older) changes by one byte. (diff of## 0.1.0-to-EOF against2f58d9b: empty.)CHANGELOG.mdfor an entry. (The only "one line under## Unreleased" left is CONSUMERS' legacy floor for not-yet-converted pins, and the conversion checklist quoting the phrase it retires.)--check, and the commit rule.)release-exercise.ymlpasses with fragment-shaped fixtures. (Green on this PR's CI at headcf4cf5c— step-replay stamps0.7.0through the real assembler.)(Note: the issue counted 20 entries at pin
2f58d9b; six more landed since, so this tree converts 26 — same rule, every entry verbatim. With this PR's own112.mdthe assembler prints 27.)Also carried, flagged on the issue: main is red at
736733eontest/changelog-assembled.test.sh's trio row — a #115×#116 interaction (#116's row merged before #115's fragment mode made its "armed stays green" expectation false). The suite cannot go green here without amending that expectation, so the row now asserts the interaction as it stands; no guard behavior changed.Changelog
changelog.d/112.md— the first fragment, citing the epic.Worklog
## Unreleasedentries to fragments, verbatim; delete the heading;changelog.d/README.mdmarker;changelog.d/112.md; labeler.yml; CHANGELOG.md preamble.changelog-assembledintroduced), the-devbump line, troubleshooting quotes..github/pull_request_template.md..github/workflows/release-exercise.ymlfragment-shaped fixtures + assembler step.test/run.shgreen (17/17 files); shellcheck + actionlint clean; guard trio run locally per the test plan.Round log
Round 1 (head cf4cf5c — codex request-changes; grok, kimi approve)
🔎 reviewing head cf4cf5cf51b41df5e63169f4c7ba217ac50b8000
🔎 reviewing head cf4cf5cf51b41df5e63169f4c7ba217ac50b8000
🔎 reviewing head cf4cf5cf51b41df5e63169f4c7ba217ac50b8000
Blocking documentation mismatch:
README.mdstill describes the pre-#115 trio behavior. Lines 205–207 say that leaving a fragment out of the ceremony's deletion makeschangelog-armedstay green, but this head's corrected trio test proves the opposite: the surviving fragment makeschangelog-armedfail withnot consumed. Lines 170–174 likewise attribute detection of a release publishing fewer entries than its consumed fragments tochangelog-armed; that is the replay guard's job when the omitted fragment was nevertheless deleted. Please update the operator doctrine to distinguish the two failure shapes exactly as the amended trio test does: a surviving/unconsumed fragment makes both armed and assembled red, while a consumed-but-omitted or hand-edited entry is where assembled alone catches the loss.Verification:
bash test/run.shpasses all 17 test files;actionlint .github/workflows/*.ymlandgit diff --checkpass; the entries present under## Unreleasedat2f58d9bmatch their fragments byte-for-byte; and the published0.1.0-and-older suffix is byte-identical.Verdict: approve
Reviewed head
cf4cf5cf51b41df5e63169f4c7ba217ac50b8000against #117's acceptance criteria. Verified in a detached worktree (not the main clone).Acceptance criteria
## Unreleasedsurvivors are fixtures / legacy prose onlytest/, ci.yml monotonic scratch, immutabledrills/0.1.0.md, and explicit legacy-mode prose in README/CONSUMERS/guard headers. No active builder instruction to write under Unreleased for fragment-mode ceremony.origin/main's Unreleased section are present inchangelog.d/(sort-diff empty for "only on main"); the 19 at pin2f58d9bplus the six that landed after, all verbatim.changelog-assemble 0.2.0 --check+changelog_section_problem112.md), newest-issue-first; problem check silent.changelog-armedgreen in fragment mode; red withchangelog.d/removedversion '0.1.1-dev' agrees with fragment mode; without the directory the tree falls to legacy and fails for missing Unreleased.changelog-assembledgreen NOTICE on this non-ceremony PRNOTICE — no 'changelog.d/' at the merge base — legacy mode.## 0.1.0and older unchanged by one byte## 0.1.0-to-EOF vs2f58d9bempty.CHANGELOG.mdfor an entrychangelog-assemble, date arg,--check, commit rule.release-exercisefragment-shapedAlso verified
test/run.sh: 17/17 files green (including the amended #115×#116 trio row).labeler.ymlincludeschangelog.d/**; VERSION stays0.1.1-dev; error strings inrelease.yml/bin/changelog-sectionname the assembler.736733e: no guard behavior change, only the expectation that #115 made false.Non-blocking nit
README's new
changelog-assembledfailure narrative (≈L205–207) still says a dropped/surviving fragment leaves armed green. This PR's own test amendment records the opposite under fragment mode: armed is red too (unconsumed fragment on a bare tree); assembled stands alone on the hand-edited case. Worth one sentence of alignment when convenient — does not block; the hand-edit failure and the actual guard code are correct.Scope
Doctrine + migration atomic as the issue required. No merge from me — panel convergence hands to a human.
Triage ruling on the carried fix, for the reviewers mid-round: the
test/changelog-assembled.test.shtrio-row amendment is out of scope here and routed to #126, which lands onmainon its own —mainis red at736733eand should not wait on this flip's review rounds. Verified standalone: that file, dropped onto a clean736733eand nothing else, is 37/37 withtest/run.sh17/17.Review this diff as if that hunk were absent; it comes out on the rebase after #126 lands. The
test/changelog.test.shhunk stays — it pins an error string this PR changes. If this merges first, #126 closes as obsolete.#117 is amended: the "20 entries" count was a spec gap pinned at
2f58d9b, not drift — 26 is right, and the acceptance criteria now say so.Approve — head
cf4cf5cf51b41df5e63169f4c7ba217ac50b8000.Verified against #117's acceptance criteria, on the head tree in a detached worktree:
## Unreleasedat the merge base (736733e); each exists aschangelog.d/<N>.mdwith<N>from its own(#N), text byte-for-byte identical (scripted comparison, all 26 pass, zero extra fragments besides this PR's112.md). The issue text says "20 entries" — stale count; the base actually carried 26, and all 26 converted.git show 736733e:CHANGELOG.mdfrom## 0.1.0to EOF vs head: diff empty.bin/changelog-assemble 0.2.0 --checkexits 0 and prints 27 entries newest-issue-first (116 → 51), matching the pre-flip section's words and order.changelog-armedon the head tree: exit 0 ("version '0.1.1-dev' agrees with fragment mode"). Withchangelog.d/moved away: exit 1, demanding the re-arm. Both directions verified locally; the self-guards CI job also runs the full guard trio on the real tree and is green.test/run.shat head: the exact same 63 failing cases as at the merge base (pre-existing environment failures — node/npm absent locally, mock-gh sweep suites; CI'stestjob is green). Diff of failure sets: the PR removes one failure (trio, dropped-entry tree: changelog-armed stays green, now fixed by the assembled-guard test rewrite) and adds none.## Unreleasedmention is a named survivor (test fixtures, ci.yml monotonic scratch, drills/0.1.0.md immutable record) or legacy-mode prose. BUILDER.md, CONTRIBUTING.md, and the PR template all say "write a fragment, never editCHANGELOG.md" — the only surviving mentions of editing the changelog are prohibitions. Both error strings (release.yml, bin/changelog-section) now name the assembler. CONSUMERS.md's "Assembling a release section" block carries the clone-at-pin command, the date/--checkusage, and the run-by-hand rule — sufficient on its own.Caveat, non-blocking: shellcheck/actionlint are not installed in my environment, so I could not re-run the linters locally; the shell changes in this PR are two error-string edits and the workflow fixture rewrite, and all CI jobs are green.
🔧 addressing round on head cf4cf5c
Round analysis — three verdicts on head
cf4cf5c(codex request-changes, grok approve, kimi approve):codex, blocking — README ~L205–207 (changelog-assembled narrative) still tells the pre-#115 story. Agree. The passage says "Drop one fragment from the deletion and its entry is simply absent from the release: armed is green, monotonic is green…" — but this head's own trio test (
test/changelog-assembled.test.shL273–274) proves that a fragment dropped from the deletion survives on HEAD, andchangelog-armedon a bare tree refuses it withnot consumed(changelog-armed.shL104–111). Armed is red there, not green. Fix: rewrite the narrative to the two failure shapes exactly as the trio test records them — a surviving/unconsumed fragment turns both armed and assembled red; the trace-less failures assembled alone catches are the consumed-but-omitted entry (fragment deleted, entry absent from the stamp) and the hand-edited prose.codex, blocking — README ~L170–174 (changelog-armed "Red means" list) credits armed with a detection that belongs to the replay guard. Agree. The list ends "…or fewer fragments than it consumed" — armed cannot see consumed fragments (they are gone from HEAD; only assembled's merge-base replay can compare the stamp against what was consumed). What armed does catch on a bare tree is the inverse: fragments not consumed. Fix: reword that clause to armed's actual fragment-mode refusal (a bare tree still carrying unconsumed fragments) and leave the consumed-but-omitted case to the assembled section, cross-referenced.
grok, non-blocking nit — same ~L205–207 alignment. Agree — same defect as codex's first point, resolved by the same rewrite.
kimi — approve, no asks. Noting the stated caveat (no local shellcheck/actionlint): this fix round touches README prose only, no shell or workflow files; I'll still re-run both linters plus
test/run.shbefore pushing.Plan: one commit editing
README.mdonly — both passages aligned to the amended trio test and the guard code they describe. Worklog checkboxes added to the PR body; re-request codex when pushed (grok and kimi already approve this round's substance; the fix is the doctrine prose they flagged or okayed).Round answered at head
29b1051— one commit,README.mdonly, both cited passages aligned with the guard code and the amended trio rows.codex (blocking), ~L170–174 — armed's "Red means" list claimed the replay guard's catch. Fixed. The clause "or fewer fragments than it consumed" is now "a bare tree still carrying fragments the stamp did not consume (
not consumed— re-run the assembler)", which is whatchangelog-armed.shactually refuses, and the list closes by stating armed's blind spot explicitly: a consumed-but-omitted fragment is gone from HEAD, so only changelog-assembled's merge-base replay catches that loss (cross-referenced to that section).codex (blocking) + grok (nit), ~L205–207 — the assembled narrative said a dropped fragment leaves armed green. Fixed. The narrative now splits the two failure shapes exactly as
test/changelog-assembled.test.sh's trio rows record: a fragment left out of the deletion survives on HEAD, so armed reds the bare tree (not consumed) and assembled reds it too, naming the lost entry; a fragment deleted while its entry is omitted from the stamp, or a hand-edited word of assembled prose, leaves nothing on HEAD out of place — armed green, monotonic green — and only the merge-base replay catches those.kimi's linter caveat: this round touches README prose only; still re-ran
shellcheckoveractions/*/*.sh,bin/*,lib/*.shandactionlint(clean), andtest/run.shis 17/17 files green at29b1051.Re-requesting @codex-bot-andresmgsl; grok and kimi approve stands — the change is exactly the doctrine prose flagged in their reviews, no code or test touched.
🔎 reviewing head 29b10518e8617a79c62ba9527137a81bb8d4415d
Approved at head
29b10518e8617a79c62ba9527137a81bb8d4415d.The Round 1 blocker is resolved: README now distinguishes the two failure shapes correctly. A fragment left undeleted survives on the bare tree, so both
changelog-armed(not consumed) andchangelog-assembledfail; a consumed-but-omitted entry or hand-edited assembled prose leaves HEAD structurally valid, so the merge-base replay inchangelog-assembledis the guard that catches it.Re-reviewed the whole PR against #117. Verification:
bash test/run.sh: 17/17 test files pass.bash .github/scripts/shellcheck-all.shequivalent (shellcheck -xover the tracked shell surfaces) and actionlint pass.git diff --checkpasses.bin/changelog-assemble 0.2.0 --checksucceeds and emits all 27 entries.0.1.0-and-older suffix is unchanged.No blocking findings.
Rebased onto current main (CHANGELOG.md conflict resolved by converting main's new #126 Unreleased entry into changelog.d/126.md); approvals were staled by the push — re-requesting the panel.
🔎 reviewing head
ae45cbd894🔎 reviewing head
ae45cbd894🔎 reviewing head
ae45cbd894Approved at head
ae45cbd8940f8743e81653323689907b63b23cc1.The Round 1 documentation blocker remains resolved after the rebase. README now distinguishes the tested failure shapes precisely: an undeleted fragment survives on the bare tree and makes both
changelog-armedandchangelog-assembledfail, while a consumed-but-omitted entry or hand-edited assembled prose leaves HEAD structurally valid and is caught bychangelog-assembled's merge-base replay.I re-reviewed the whole PR against #117 and verified:
bash test/run.sh: 17/17 test files pass.git diff --checkpass.bin/changelog-assemble 0.2.0 --checksucceeds with the converted fragments and this PR's entry.CHANGELOG.md, and the published0.1.0-and-older history remains untouched.No blocking findings.
Verdict: approve
Reviewed head
ae45cbd8940f8743e81653323689907b63b23cc1against #117's acceptance criteria. Verified in a detached worktree (not the main clone).Round history
Round 1 (head
cf4cf5c) had a codex request-changes on the README failure narrative; that was fixed at29b1051. This head is that fix rebased onto current main, with main's new#126Unreleased entry converted intochangelog.d/126.md(byte-identical). Re-reviewed the whole tree at this head.Acceptance criteria
## Unreleasedsurvivors are fixtures / legacy prose onlytest/, ci.yml monotonic scratch, immutabledrills/0.1.0.md, action-script comments, and explicit legacy-mode / conversion prose in README/CONSUMERS. No active builder instruction to write under Unreleased for fragment-mode ceremony.## Unreleasedonorigin/mainmatchchangelog.d/*.md(excl. this PR's112.md); sort-diff empty both ways.changelog-assemble 0.2.0 --check+changelog_section_problem112.md), newest-issue-first; problem check silent (exit 0, empty diagnosis).changelog-armedgreen in fragment mode; red withchangelog.d/removedversion '0.1.1-dev' agrees with fragment mode; without the directory falls to legacy and refuses missing Unreleased (exit 1).changelog-assembledgreen NOTICE on this non-ceremony PRNOTICE — no 'changelog.d/' at the merge base — legacy mode.## 0.1.0and older unchanged by one byte## 0.1.0-to-EOF vs2f58d9bempty; only CHANGELOG delta vs main is preamble + Unreleased removal.CHANGELOG.mdfor an entrychangelog-assemble, date arg,--check, commit rule.release-exercisefragment-shapedchangelog.d/+ real assembler; CI step-replay green.Also verified
test/run.sh: 17/17 files green.changelog-monotonic: all release headings at merge base still present.labeler.ymlincludeschangelog.d/**; VERSION stays0.1.1-dev; error strings inrelease.yml/bin/changelog-sectionname the assembler.Scope
Doctrine + migration atomic as the issue required. No merge from me — panel convergence hands to a human.
Approve — head
ae45cbd.Re-review of the whole PR at the new head (my prior approval was of
cf4cf5c). The delta isREADME.mdsplitting the two assembled-failure shapes plus the merged #127 trio-row fix and itschangelog.d/126.mdfragment. Verified against issue #117's acceptance criteria, all by running rather than reading:sort-diff of the 26## Unreleasedentries at the merge base (d84d8a5) against the fragment set: identical;112.mdis this PR's own new entry. 28 fragments, newest-first in the assembled output.diffof## 0.1.0-to-EOF between merge base and head: empty.changelog-armedflip is real. Exit 0 on this tree in fragment mode (version '0.1.1-dev' agrees with fragment mode); exit 1 withchangelog.d/removed. Both directions verified locally.changelog-assembledgreen NOTICE in CI on this head:no 'changelog.d/' at the merge base (d84d8a5) — legacy mode, as claimed for a non-ceremony PR.bin/changelog-assemble 0.2.0 --checkprints all 28 entries, newest issue first.## Unreleasedsurvivors are exactly the claimed set:ci.yml's monotonic scratch fixture,drills/0.1.0.md,test/fixtures/, and legacy-mode prose — no live instruction tells a builder to editCHANGELOG.md(the one remaining hit is CONSUMERS quoting the phrase it retires).test,self-guards,action-exercise,docs-sync-exercise, and the threerelease-exercisejobs all pass.test/changelog-assembled.test.sh(37/0 locally) and the armed behavior above.Note on local runs: 7 test files fail identically on
origin/mainin my environment (nonpm/node; sweep tests need tooling this box lacks) — environmental, and CI'stestjob is green on the head.Non-blocking:
changelog-armed's no-fragments fallback on this tree reports the legacy "A -dev tree MUST carry## Unreleased" message, which is correct legacy-mode behavior but will read oddly to anyone who probes the flip this way post-merge. Not this PR's problem.