feat: arm changelogs in fragment mode #123
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#123
Loading…
Reference in a new issue
No description provided.
Delete branch "build/115-changelog-armed-fragment-mode"
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 #115
Worklog
fragments-diraction inputAcceptance criteria
-devfragment trees require the marker, reject## Unreleased, and validate every fragmentchangelog_fragment_problemfragments-dirinputbash test/run.shgreen; shellcheck and actionlint cleanEvidence
bash test/changelog-armed.test.shexits 1 with 12 fragment-contract failures while all 24 applicable legacy/environment rows pass.439b5cf:bash test/run.shpasses 16/16 test files; shellcheck passes 35 tracked scripts; actionlint passes six workflows;git diff --checkand changed-path assertions are clean.🔎 reviewing head
439b5cf8a5Verdict: approve
Reviewed head
439b5cf8a555d0439289d1a51457e28ca545ba74against #115's acceptance criteria and the load-bearing dual-mode contract (D7/D8/D9).Spec coverage
changelog.d/→ legacy, existing rows unmodifiedif [ -d "$fragments_dir" ]; all prior test rows remain and pass-dev+ marker + well-formed fragments → greenchangelog_fragment_problemoverchangelog_fragments;-devexits clean## Unreleased→ red, names it## Unreleased(empty heading still fails)README.md→ redprintf 'changelog-armed: %s\n' "$diagnosis"withchangelog_fragment_problem(no local copy of the rules)changelog-assemble $verfix## <ver>+ consumed dir → greenchangelog_section_problemthen top-section identity check; no re-arm shapechangelog_section_problemfragments-dirinput defaultedaction.yml+FRAGMENTS_DIRenv + positional arg 3Code notes (non-blocking)
-dev/bare split, so bare trees with garbage fragments fail with a well-formedness fix rather than only "not consumed"; both are refusals with a concrete fix.## Unreleasedabove the prior entries; good.Verification
bash test/run.sh— 16/16 files green (including 36 changelog-armed rows: legacy + fragment + env wiring).shellcheck -e SC1091 actions/changelog-armed/changelog-armed.shclean (SC1091 only on the existing sourced libs).section '…' has no entries; multiple survivors list aschangelog.d/10.md, changelog.d/9.md.Meets every acceptance criterion on #115. Approve.
🔎 reviewing head
439b5cf8a5🔎 reviewing head
439b5cf8a5Approve at
439b5cf.Verified (ran, not read)
bash test/run.sh: 16/16 files green;test/changelog-armed.test.shalone: 36/36 rows..github/scripts/shellcheck-all.sh: clean over 35 tracked scripts;actionlint: clean.## Unreleased(rule 6, which has no test row) → refused with the adoption diagnosis, because the Unreleased check runs before the dev/bare split;changelog_fragmentsorder (changelog.d/115.md, changelog.d/99.md) with there-run 'changelog-assemble 1.2.3'remedy;-devfragment smuggling a##heading → refused viachangelog_fragment_problem's verbatim diagnosis;changelog.d/with noREADME.md→ refused with the marker diagnosis.Against the spec (#115)
Mode detection is the directory, the
fragments-dirinput is defaulted and rides the existing positional/env shape, all fragment rules are read fromlib/changelog.sh(no second copy — the guard's only own assertions are the marker, the Unreleased scan, and the top-version equality, none of which live in the lib), both new diagnostics match the spec's wording, and the header comment carries all three required paragraphs: what fragment mode asserts, why box#108 is structurally impossible under it, and why the legacy bare-tree asymmetry has no counterpart. The cross-mode row (fragments-cross-mode) proves the same changelog gets opposite verdicts with and without the directory. Changelog line present, inserted above the previous entry.Non-blocking nits (address at your discretion)
## Unreleased) has no row —fragments-unreleasedonly covers the-devside. I verified the bare case refuses correctly by hand; a one-tree row would pin it against a future reordering of the checks (the coverage only holds because the Unreleased scan sits above the dev/bare split).fragments-bare-survivorlists a single surviving fragment, so the comma-join in the "not consumed" message is never exercised by the suite; a two-fragment row would cover the list formatting and its ordering.Verdict: APPROVE —
439b5cf("feat: arm changelogs in fragment mode", closes #115).Acceptance criteria (issue #115), checked one by one
if [ -d "$fragments_dir" ]block prepended before it. All pre-existing rows pass locally except the twopackage-jsonones, which fail only because this box has nonode(version_read: node is required) — same environmental failure hits five other untouched test files (version,facts,drill-recordedneed node;ruling,labels-reconcile,issueflow-reconcileneedjq). CI runners ship both.-dev+changelog.d/+ no## Unreleased+ well-formed fragments → green — rowsfragments-dev-empty,fragments-dev-flat,fragments-dev-groupedpass.-dev+ surviving## Unreleased→ red, naming the section — row passes; message is the issue's own wording ("a '## Unreleased' section survived the adoption — move its entries into 'changelog.d/.md' and delete the heading"). The fixture's Unreleased is empty, covering the "heading is the problem, not its contents" row. The awk check ($1 == "##" && $2 == "Unreleased") is whole-word and position-independent, matching the spec's "no## Unreleasedsection" anywhere in the file.-dev+ missingchangelog.d/README.md→ red — row passes, message names the marker and the fix.changelog_fragment_problem's diagnosis and the file — rows for a bad name (notes.md) and a no-entries fragment pass, and the diagnosis is reproduced verbatim fromlib/changelog.sh. I additionally constructed a fragment with a bullet followed by a trailing dangling### Fixedheading: exit 1 withfragment 'changelog.d/115.md' has an empty heading: '### Fixed'— the empty-heading branch fires through the guard (the PR's own dangling-heading row lands on the no-entries rule first, since that fixture has no bullet at all; both diagnoses are correct refusals).changelog.d/115.mdand names the fix (re-run 'changelog-assemble 1.2.3'), the issue's second new diagnostic verbatim.## <ver>with entries + consumed directory → green — row passes, including an older section still present below.changelog_section_problem— row passes ("no section for '1.2.3'"). I also probed a stamped-but-empty section: exit 1 withsection '1.2.3' has no entries — a heading is not an entry, and a bare tree with both a surviving## Unreleasedand a valid stamp: exit 1 on rule 2/6, which the code correctly enforces before the version branch.lib/changelog.shand callschangelog_fragments,changelog_fragment_problem, andchangelog_section_problem; no rule is re-implemented in the file.Header-comment tasks: the rig#44/cast#108 warning is intact and unmoved; the new fragment paragraph states what fragment mode asserts, why box#108 is structurally impossible in it, and that a bare release has no re-armed shape in this mode.
action.ymlgains the defaultedfragments-dirinput wired throughFRAGMENTS_DIR, the script takes it as the third positional, and theenv-fragmentsrow proves the wiring with a non-default directory. Changelog entry: one line under## Unreleased, inserted at the top of the list — convention-conformant.Verification run
bash test/changelog-armed.test.sh— 34/36; the 2 failures are the pre-existingpackage-jsonrows (nonodeon this box). All 13 new fragment-mode rows and the cross-mode row pass.bash test/run.sh— 9/16 files pass; all 7 failures are node/jq absence in untouched files, not this diff.awkhere is mawk 1.3.4, so the new awk passed under the mawk constraint..github/scripts/shellcheck-all.sh) — clean, 35 tracked scripts, exit 0.actionlint-all.shlints only.github/workflows/*.ymland this PR touches no workflow.action.ymlparses as YAML and its new input is exercised by the env-var test row.git diff --check— clean.Nits (non-blocking)
fragments-dangling-groupfixture (a lone### Changed) trips the no-entries rule, not the empty-heading rule the row's name suggests. The empty-heading path is reachable and I verified it manually, but renaming the row or giving the fragment one bullet plus a trailing heading would make the suite exercise that branch itself.Both are discretionary; nothing here blocks. Convergence-wise this is one approval of the current head
439b5cf.