changelog-body-check misses a repeated entry: a section with every fragment entry doubled passes all nine checks #1509

Open
opened 2026-10-02 14:28:34 +02:00 by claude · 0 comments
Member

changelog-body-check check 6 ("duplicates") grades two things: duplicate ## [vX.Y.Z] headings across the whole CHANGELOG, and duplicate ### headings inside the newest section (check6DuplicateHeaders, internal/gates/changelog_body_check.go). It never compares entries. A section in which every entry appears twice passes.

Measured

On main @ 7bfd0ba (2026-10-02), I ran rt changelog-body-check on the section #1487 produced before its fix, with every fragment entry doubled:

### Added

- **recover**: a stranded cut re-prepares from its restored fragments (#981)


- **recover**: a stranded cut re-prepares from its restored fragments (#981)

### Fixed

- **release**: the bake builds its pipeline rt in a container (#980)


- **release**: the bake builds its pipeline rt in a container (#980)

All nine checks PASS, rc=0. Check 6 reports no duplicate version sections in whole CHANGELOG.md; no duplicate ### Section headers in newest section, which is accurate about its two scopes and silent on entries.

Why it matters

#1490 fixed one producer, recover-pending-cut. Nothing grades the output, so any other path that composes an entry twice ships doubled release notes with every gate green.

  • A known second path: an author writes the same bullet in [Unreleased] and in a fragment. MergeSections concatenates without dedup, and #1490 deliberately keeps one copy per source (TestFoldBackExceptKeepsTheUnreleasedCopyOfADuplicate), so the doubled section re-composes.
  • One fix covers both gates. The same check runs at prepare time: rt prep → MirrorCutGates → ComposeVerify → ChangelogBodyCheck. So a fix to check 6 guards both the rolling PR and the cut.

Acceptance criteria

  • Check 6 fails when the same entry appears twice anywhere in the newest section, naming every occurrence by line number, as duplicate version sections already are.
  • What counts as an entry is stated and is what gets graded: top-level list items, and the paragraph entries of whole-body fragments.
    • They are compared after trimming trailing whitespace, including a CRLF file's trailing CR.
    • None. sentinels, blank lines and indented continuation lines are not entries.
  • The PASS message names the new scope, as check 6 already does for its two existing scopes.
  • A control is red on main (the doubled section above passes today) and green after the change, and the same section is refused by the prepare-time mirror (MirrorCutGates).

Open for the PR to decide: FAIL or WARN. A repeated entry is never intended in a release section, which argues for FAIL, the same verdict check 6 gives a repeated ### heading.

`changelog-body-check` check 6 ("duplicates") grades two things: duplicate `## [vX.Y.Z]` headings across the whole CHANGELOG, and duplicate `### ` headings inside the newest section (`check6DuplicateHeaders`, `internal/gates/changelog_body_check.go`). **It never compares entries.** A section in which every entry appears twice passes. ## Measured On `main` @ `7bfd0ba` (2026-10-02), I ran `rt changelog-body-check` on the section #1487 produced before its fix, with every fragment entry doubled: ``` ### Added - **recover**: a stranded cut re-prepares from its restored fragments (#981) - **recover**: a stranded cut re-prepares from its restored fragments (#981) ### Fixed - **release**: the bake builds its pipeline rt in a container (#980) - **release**: the bake builds its pipeline rt in a container (#980) ``` All nine checks PASS, rc=0. Check 6 reports `no duplicate version sections in whole CHANGELOG.md; no duplicate ### Section headers in newest section`, which is accurate about its two scopes and silent on entries. ## Why it matters #1490 fixed one producer, `recover-pending-cut`. Nothing grades the output, so any other path that composes an entry twice ships doubled release notes with every gate green. - **A known second path:** an author writes the same bullet in `[Unreleased]` and in a fragment. `MergeSections` concatenates without dedup, and #1490 deliberately keeps one copy per source (`TestFoldBackExceptKeepsTheUnreleasedCopyOfADuplicate`), so the doubled section re-composes. - **One fix covers both gates.** The same check runs at prepare time: `rt prep` → `MirrorCutGates` → `ComposeVerify` → `ChangelogBodyCheck`. So a fix to check 6 guards both the rolling PR and the cut. ## Acceptance criteria - [ ] Check 6 fails when the same entry appears twice anywhere in the newest section, naming every occurrence by line number, as duplicate version sections already are. - [ ] What counts as an entry is stated and is what gets graded: top-level list items, and the paragraph entries of whole-body fragments. - They are compared after trimming trailing whitespace, including a CRLF file's trailing CR. - `None.` sentinels, blank lines and indented continuation lines are not entries. - [ ] The PASS message names the new scope, as check 6 already does for its two existing scopes. - [ ] A control is red on `main` (the doubled section above passes today) and green after the change, and the same section is refused by the prepare-time mirror (`MirrorCutGates`). Open for the PR to decide: FAIL or WARN. A repeated entry is never intended in a release section, which argues for FAIL, the same verdict check 6 gives a repeated `###` heading.
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
frankenbit/release-toolkit#1509
No description provided.