0.3.0 — repair the fragment shape, move the one-shape rule onto the PR, cut the tag #157

Closed
opened 2026-07-24 15:43:01 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-24 15:43:01 +00:00 (Migrated from github.com)

Minted from discussion #156 at the operator's direction (@danmt, 15:33Z: "please take care of this"). The findings are the discussion's; the split and the decisions below are triage's.

All line references pinned at f168bbf.

Context — the release that stopped at the assembler

The content side of 0.3.0 is done: eleven fragments banked (130 131 134 135 137 139 144 145 149 151 154), no open PRs, everything the operator wanted in. The cut cannot run:

$ bash bin/changelog-assemble 0.3.0 --check
changelog-assemble: fragment 'changelog.d/151.md' is grouped but
'changelog.d/154.md' is not — a repo is one shape or the other

Four fragments carry a ### group heading (135.md, 137.md, 144.md, 151.md — landed in #147, #143, #150, #152); the other seven are flat. Each grouped fragment passed CI individually, because the one-shape rule is cross-fragment and lives only in changelog_assemble (lib/changelog.sh L185-L192), while changelog-armed validates fragments one at a time (changelog-armed.sh L90-L98). So shape drift is structurally invisible until whoever cuts the release runs the assembler by hand — the single moment when stopping costs the most, and it will recur every release until the guard moves.

Why the tag matters beyond this repo: the operator's stated goal for 0.3.0 is the pin bump into the governed repos, and that bump also carries the attention bootstrap into each of them — the remaining half of #83's first operator item, tracked on discussion #102. Refs #83.

Decisions

Shared constraints. Children implement them; do not reopen them in a PR.

  • D1 — ceremony is flat, and that is not decided here. #112 D3 names ceremony flat and the grouped shape as the consumers'; both published sections (## 0.1.0, ## 0.2.0) are flat. The four grouped fragments are drift from a settled decision, repaired in place — not a shape question to relitigate.
  • D2 — the repair changes no prose and writes no fragment of its own. The changelog rule keys the fragment on a behavior change (CONTRIBUTING L43-L48); a diff entirely inside changelog.d/ that alters no published prose has none. This is the rule's own scope, not the release PR's structural exemption (L51-L60) — that one stays the release PR's alone.
  • D3 — the one-shape rule gains a PR-time enforcement point through one definition. The cross-fragment check moves out of changelog_assemble into a lib function both the assembler path and changelog-armed call (the #112 D9 discipline: one definition, so guard and assembler cannot disagree). It also gains an anchor: when CHANGELOG.md has a published section, the fragment set's shape must match the newest section's shape — that is what catches an all-grouped set on a flat repo, which cross-fragment comparison alone structurally cannot. bin/changelog-assemble stays deliberately not-a-CI-step (header L4); armed is the CI enforcement point.
  • D4 — the drill is the release issue's work, not its own issue. The #118 worked example: the rehearsal is a task and its record an acceptance criterion, the run is the work and the record the evidence, and a waiver is the operator's call and still a record. A separate drill issue would let the release claim ride while the drill sits unclaimed — the exact decoupling drill-recorded exists to refuse.
  • D5 — 0.3.0, minor. Child 2 changes the contract a consumer's CI runs against (armed gains a refusal), the same bar that made 0.2.0 minor.
  • D6 — the tag waits for the guard, deliberately. The release is blocked by the repair and by child 2: the tag that repairs this drift should carry the thing that prevents its recurrence into every consumer at the pin bump it already owes them — otherwise each consumer inherits fragment mode with the same release-time trap armed for their first cut. Cost: one small, fully-specced PR ahead of the release. @danmt overturns this by merging the release without it; the dependency line is the only thing that changes.

Children, in dependency order

  • #158changelog.d/ — strip the grouped headings from the four drifted fragments (landed 2026-07-24 16:05Z as #162, merge f19d671)
  • #159lib/changelog.sh + changelog-armed — the one-shape rule fails the PR that introduces the drift (landed 2026-07-24 16:57Z as #163, merge a7aedfd)
  • #160 — Release 0.3.0 (landed 2026-07-24 17:39Z as #164, merge bc469d9 = tag 0.3.0; post-merge criteria verified and closed by triage 17:56Z)

Also carried here

The four consumer pin bumps to 0.3.0 are not minted now — wrong time: rig and incubator are still mid-adoption of 0.2.0 (#112's checklist) and a bump issue against a tag that does not exist yet would sit unbuildable. They get minted when the tag lands, and each carries its repo's labels dispatch (the attention bootstrap, #102).

Minted from discussion [#156](https://github.com/heavy-duty/ceremony/discussions/156) at the operator's direction ([@danmt, 15:33Z](https://github.com/heavy-duty/ceremony/discussions/156#discussioncomment-17768052): *"please take care of this"*). The findings are the discussion's; the split and the decisions below are triage's. All line references pinned at [`f168bbf`](https://github.com/heavy-duty/ceremony/tree/f168bbfbacf5e15825750b338e2a06d47c567cc5). ## Context — the release that stopped at the assembler The content side of `0.3.0` is done: eleven fragments banked (`130 131 134 135 137 139 144 145 149 151 154`), no open PRs, everything the operator wanted in. The cut cannot run: ``` $ bash bin/changelog-assemble 0.3.0 --check changelog-assemble: fragment 'changelog.d/151.md' is grouped but 'changelog.d/154.md' is not — a repo is one shape or the other ``` Four fragments carry a `### ` group heading (`135.md`, `137.md`, `144.md`, `151.md` — landed in #147, #143, #150, #152); the other seven are flat. Each grouped fragment passed CI individually, because the one-shape rule is **cross-fragment** and lives only in `changelog_assemble` ([`lib/changelog.sh` L185-L192](https://github.com/heavy-duty/ceremony/blob/f168bbfbacf5e15825750b338e2a06d47c567cc5/lib/changelog.sh#L185-L192)), while `changelog-armed` validates fragments one at a time ([`changelog-armed.sh` L90-L98](https://github.com/heavy-duty/ceremony/blob/f168bbfbacf5e15825750b338e2a06d47c567cc5/actions/changelog-armed/changelog-armed.sh#L90-L98)). So shape drift is structurally invisible until whoever cuts the release runs the assembler by hand — the single moment when stopping costs the most, and it will recur every release until the guard moves. Why the tag matters beyond this repo: the operator's stated goal for `0.3.0` is the pin bump into the governed repos, and that bump also carries the `attention` bootstrap into each of them — the remaining half of #83's first operator item, tracked on discussion #102. Refs #83. ## Decisions Shared constraints. Children implement them; do not reopen them in a PR. - **D1 — ceremony is flat, and that is not decided here.** #112 D3 names ceremony flat and the grouped shape as the consumers'; both published sections (`## 0.1.0`, `## 0.2.0`) are flat. The four grouped fragments are drift from a settled decision, repaired in place — not a shape question to relitigate. - **D2 — the repair changes no prose and writes no fragment of its own.** The changelog rule keys the fragment on a *behavior change* ([CONTRIBUTING L43-L48](https://github.com/heavy-duty/ceremony/blob/f168bbfbacf5e15825750b338e2a06d47c567cc5/CONTRIBUTING.md#L43-L48)); a diff entirely inside `changelog.d/` that alters no published prose has none. This is the rule's own scope, not the release PR's structural exemption (L51-L60) — that one stays the release PR's alone. - **D3 — the one-shape rule gains a PR-time enforcement point through one definition.** The cross-fragment check moves out of `changelog_assemble` into a lib function both the assembler path and `changelog-armed` call (the #112 D9 discipline: one definition, so guard and assembler cannot disagree). It also gains an anchor: when `CHANGELOG.md` has a published section, the fragment set's shape must match the newest section's shape — that is what catches an *all*-grouped set on a flat repo, which cross-fragment comparison alone structurally cannot. `bin/changelog-assemble` stays deliberately not-a-CI-step ([header L4](https://github.com/heavy-duty/ceremony/blob/f168bbfbacf5e15825750b338e2a06d47c567cc5/bin/changelog-assemble#L4)); `armed` is the CI enforcement point. - **D4 — the drill is the release issue's work, not its own issue.** The #118 worked example: the rehearsal is a task and its record an acceptance criterion, the run is the work and the record the evidence, and a waiver is the operator's call and still a record. A separate drill issue would let the release claim ride while the drill sits unclaimed — the exact decoupling `drill-recorded` exists to refuse. - **D5 — `0.3.0`, minor.** Child 2 changes the contract a consumer's CI runs against (`armed` gains a refusal), the same bar that made `0.2.0` minor. - **D6 — the tag waits for the guard, deliberately.** The release is blocked by the repair *and* by child 2: the tag that repairs this drift should carry the thing that prevents its recurrence into every consumer at the pin bump it already owes them — otherwise each consumer inherits fragment mode with the same release-time trap armed for their first cut. Cost: one small, fully-specced PR ahead of the release. @danmt overturns this by merging the release without it; the dependency line is the only thing that changes. ## Children, in dependency order - [x] #158 — `changelog.d/` — strip the grouped headings from the four drifted fragments (**landed** 2026-07-24 16:05Z as [#162](https://github.com/heavy-duty/ceremony/pull/162), merge `f19d671`) - [x] #159 — `lib/changelog.sh` + `changelog-armed` — the one-shape rule fails the PR that introduces the drift (**landed** 2026-07-24 16:57Z as [#163](https://github.com/heavy-duty/ceremony/pull/163), merge `a7aedfd`) - [x] #160 — Release `0.3.0` (**landed** 2026-07-24 17:39Z as [#164](https://github.com/heavy-duty/ceremony/pull/164), merge `bc469d9` = tag `0.3.0`; post-merge criteria verified and closed by triage 17:56Z) ## Also carried here The four consumer pin bumps to `0.3.0` are **not** minted now — wrong time: rig and incubator are still mid-adoption of `0.2.0` (#112's checklist) and a bump issue against a tag that does not exist yet would sit unbuildable. They get minted when the tag lands, and each carries its repo's `labels` dispatch (the `attention` bootstrap, #102).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/ceremony#157
No description provided.