feat: fail shape drift on the introducing PR #163
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#163
Loading…
Reference in a new issue
No description provided.
Delete branch "build/159-changelog-shape-guard"
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 #159
Summary
Move fragment-set shape validation into one shared library predicate, enforce it in the PR-time guard and release-time assembler, and anchor fragments to the newest published changelog section.
Acceptance criteria
changelog-armed.changelog-armed.changelog-armed.changelog_assembledelegates to it.bash test/run.shis green.Worklog
changelog_shape_problem.changelog_assemblemixed-shape diagnoses through the shared predicate.changelog-armed.bin/changelog-assemble.changelog.d/159.mdfragment.🔎 reviewing head
eb25b38c14🔎 reviewing head
eb25b38c14Verdict: approve
Reviewed head
eb25b38c142f05f88d7f30e6574a145f0f9499e1against #159's acceptance criteria and the #157 D3 shape contract.Spec
changelog-armedchangelog_shape_problem; testfragments-dev-mixedfragments-dev-all-grouped-over-flatchangelog_shape_problem; both callers print itchangelog_shape_problem;changelog_assemblepasses empty changelog so it only reuses cross-fragment (anchor stays in bin, per the issue — lib does not grow a path arg)bash test/run.shgreenCode
changelog_assemblewithout changing the refusal text; single-file mix still diagnosed.Unreleased##section andchangelog_sectionbody for###presence — matches family extractors.changelog-armedruns the shared predicate after the per-fragment loop (dev-tree PR path);bin/changelog-assembleruns it with the real changelog path before assemble so release-time also gets the anchor.changelog.d/159.mdis a flat bullet, consistent with this repo's published flat shape.Verification
bash test/run.sh— all green.shellcheck -xonlib/changelog.sh,changelog-armed.sh,bin/changelog-assemble— clean.changelog-armedagrees;changelog_shape_problem CHANGELOG.md changelog.dsilent.test/self-guards/ action exercises green on this head.release-exercise / fixture-chainfailed at "Set up job" with HTTP 429 downloadingactions/checkout— infrastructure, not this diff.No blocking findings. Ship when the rest of the panel converges.
🔎 reviewing head
eb25b38c14Approve — head
eb25b38c142f05f88d7f30e6574a145f0f9499e1, reviewed against #159's acceptance criteria in a detached worktree.Every criterion verified by execution, not just reading:
changelog-armedexits 1 withfragment 'changelog.d/115.md' is grouped but fragment 'changelog.d/114.md' is not — a repo is one shape or the other. Reproduced on a constructed tree.newest published section '1.2.3' in 'CHANGELOG.md' is flat. Reproduced.bin/changelog-assemblerefuses with byte-identical text toorigin/main'schangelog_assemblestring (grep + direct run of the main-branch lib), andchangelog-armedemits the same shared diagnosis. Verified.bin/changelog-assemblerefuse before assembling; the changelog file is left untouched. Verified.changelog_shape_problemtests, which pass locally.changelog_shape_problem;changelog_assembledelegates with an empty changelog arg (anchor rule vacuous, cross-fragment rule intact). The re-scan ofgrouped_ininchangelog_assembleis assembly-mode selection, not a second copy of the rule — no diagnosis text is duplicated.changelog.d/159.mdpresent and flat, matching this repo's newest published section (0.2.0, flat), so the guard does not refuse its own PR; no grouped fragments remain inchangelog.d/at this head.What I could not run locally and what I relied on instead: this box has no
node, nojq, noshellcheck, noactionlint(mawk-only awk). The package-json version-source cases and theruling/issueflow-reconcilesuites fail here for that reason alone; the PR touches none of that surface, and the changelog-family suites (changelog,changelog-armed,changelog-assemble,changelog-assembled) pass locally in full. For the rest I relied on CI: thetest,self-guards,action-exercise,docs-sync-exercise, and bothstep-replayjobs are green on this head.One non-blocking note:
release-exercise / fixture-chainis red, but the log shows a GitHub-side 429 downloadingactions/checkout— the job never ran a line of PR code. A re-run should clear it; no code change owed.Approve — reviewed the whole PR at head
eb25b38, in a detached worktree.Verified, not opined:
bash test/run.shat the head: 18 test files, all green.shellcheck-all.shandactionlint-all.shboth clean.changelog_shape_problem(lib/changelog.sh:159) against whatchangelog_assemblecarried on main — byte-identical, so the mixed-set diagnoses survive exactly as #159 requires.changelog_assembledelegates (lib/changelog.sh:227) by passing an empty changelog path, which keeps the anchor rule out of the lib-level function without growing it a new argument — precisely the spec's shape. No second copy of the validation survives in either caller.Unreleased##heading; grouped iff itschangelog_sectionbody has a###line. The$1 == "##"awk idiom matches the existing uses at changelog-armed.sh:85 and bin/changelog-assemble:89, so the family keeps agreeing on what a heading is. Empty set, no published section, and absent changelog are all vacuous, per spec.--check, which the release-replay path inherits; the added grouped-replay coverage in test/changelog-assembled.test.sh caught exactly that interaction.changelog-armedwith the shared two-fragment diagnosis (the #143 case); an all-grouped set over a flat published section goes red naming fragment, section, and file (the case rule 1 structurally cannot see); a mixed set still fails the assembler with today's text and fails the guard with the same shared text; grouped/grouped, flat/flat, no-published-section, and empty-directory all pass;changelog.d/159.mdis present and flat.actions/changelog-armed/changelog-armed.shon the PR's own tree: exit 0 — the all-flatchangelog.d/anchors cleanly against the flat newest published section, so the #158 ordering paid off.CI note:
release-exercise / fixture-chainis red at this head, but the job died in "Set up job" on a GitHub-side 429 rate limit downloadingactions/checkout— no repo code ever ran. Its content is the same contracttest/release-chain.test.shexercises, which is green locally at this head. A plain re-run should clear it; nothing in the diff to answer for it.Non-blocking nit (builder's discretion): test/changelog-assembled.test.sh:88 — the
sed -i '/^- The shipped entry/i ### Fixed\\\n'insert leaves a literal trailing backslash in the fixture: the seeded heading is### Fixed\, not### Fixed. It still matches^###, so the replay anchors exactly as intended, but the fixture reads as a typo; seeding the grouped changelog with a heredoc (as the armed tests do) would say what it means.