lib/changelog.sh + changelog-armed — the one-shape rule fails the PR that introduces the drift #159
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#159
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?
Part of #157. All line references pinned at
f168bbf.Context
The one-shape rule (#112 D4) is enforced in exactly one place: inside
changelog_assemble, which compares fragments against each other at assembly time (L185-L192). On a development tree,changelog-armedvalidates fragments one at a time (L90-L98); a single fragment carrying### Fixedis individually legal, so nothing in the per-PR path can see the drift. Four PRs (#143, #147, #150, #152) each passed CI with a grouped fragment on this flat repo, and the mix surfaced only when the0.3.0cut ran the assembler by hand — the assembler is deliberately not a CI step (bin/changelog-assembleL4), and stays that way.The consequence is structural: shape drift is always found at release time, by whoever is cutting, never by the change that caused it. This issue moves the rule onto the PR, the same move #112 D9 made for per-fragment malformedness.
Spec
Decisions, per #157 D3:
lib/changelog.sh—changelog_shape_problem <changelog> <fragments-dir>— with the same contract as the other*_problemfunctions: print the first reason and return 1, silence and 0 otherwise. The cross-fragment detection currently inlined inchangelog_assemblemoves into it (or into a helper both call);changelog_assemblekeeps refusing a mixed set with the same diagnosis it prints today, delegating rather than duplicating, so guard and assembler cannot disagree.<changelog>has at least one published##section, the set's shape must match the newest section's shape (a section is grouped iff its body contains a###line —changelog_sectionis the extractor). This is what catches an all-grouped set on a flat repo, which rule 1 structurally cannot. No published section, or an empty fragment set → the rule is vacuous, not a failure.A refusal names the offending fragment(s), the expected shape, and where the expectation comes from (the neighbouring fragment, or the published section).
changelog-armedcalls it in fragment mode after the per-fragment loop, on every tree. On a bare tree the set must already be empty, so the check is effectively the dev-tree guard — which is the point: it fires on the PR that introduces the drift.bin/changelog-assemblecalls it too, before assembling — it knows the changelog path, so it picks up the anchor rule the lib-levelchangelog_assemblecannot (that function takes only a directory and does not grow a new argument).changelog.d/→ today's rules verbatim) is untouched.changelog.d/159.mdfragment for this PR, flat.Tasks
changelog_shape_probleminlib/changelog.sh;changelog_assembledelegates its mixed-set refusal to the shared code.changelog_shape_problem.changelog-armed.sh's fragment mode and intobin/changelog-assemble.test/changelog.test.sh/test/changelog-armed.test.shcovering the must-fail and must-pass cases below.changelog.d/159.md, flat.Acceptance criteria
changelog-armed— the exact #143 case, individually legal today.bin/changelog-assemblewith the same diagnosis text as today, and now failschangelog-armedwith the same shared diagnosis.changelog_assembleor the action.bash test/run.shgreen.Test plan
test/changelog-armed.test.shalready drives the action script.Dependencies
Part of #157. Blocked by #158 —
changelog-armedself-consumes from the PR's own tree, so this check would refuse its own PR whilechangelog.d/is still mixed. Blocks #160 (#157 D6).Every issue named by
Blocked byis closed. The sweep is moving this issue toready.Claimed by @codex-bot-andresmgsl. I am starting implementation now and will open a draft PR after the first commit.