Skip to content

chore: record what shipped today, and stop a tag stranding it (#377) - #403

Merged
rainmanjam merged 1 commit into
mainfrom
chore/changelog-guard
Aug 16, 2026
Merged

chore: record what shipped today, and stop a tag stranding it (#377)#403
rainmanjam merged 1 commit into
mainfrom
chore/changelog-guard

Conversation

@rainmanjam

Copy link
Copy Markdown
Owner

Closes #377, and records the entries today's two merges did not.

Two failures, and #377 is only one of them

What #377 describes. [Unreleased] sits above the version sections, so under Keep a Changelog its contents are newer than the release below. Every PR appends there and nothing folds it forward. It reopened twice on 2026-08-14; the second time it stranded all seven security fixes from #366 and the VOD editor from #365.

That is not cosmetic: GHSA-7jqx points at these release notes, and the fix for its worst defect — 0.7.0's seal-at-rest migration leaving plaintext keys in the WAL — was in the section a tag would have skipped.

The guard is the first step of the first release job, before anything is built or pushed, because a release that has uploaded assets and then finds its notes wrong is one somebody has to delete.

Proven both ways, not asserted:

Input Exit
[Unreleased] populated (this commit) 1
[Unreleased] = "Nothing yet." 0

What #377 cannot catch — and it is what happened today

Entries that were never written. #397 recorded one of its seven changes; #400 recorded none. [Unreleased] would have been empty and this guard would have passed while the website, the docs rendering, the comparison pages, the SEO work, #387's first change and the port-allocator fix all went unrecorded.

A guard trusted for more than it does is worse than none, so that limit is written at the step. The second check it implies belongs on the pull request, not the tag, and is deliberately not smuggled in here.

A correction

I first reported [Unreleased] as empty. It wasn't — I read it from the main working tree, which is parked on a stale branch. On origin/main it held the tour entry. The gap was narrower than I said and is now recorded accurately.

Now recorded

The 6→35 page site including 23 rendered documents · llms.txt, security.txt, the touch icon, HowTo data, git-derived sitemap lastmod · the _headers bug that shipped four of six pages with no revalidation · 114 inert Copy buttons · eleven copy defects on pages naming other people's products · the contiguous-port-window fix · #387's first change, whose one intended behaviour difference (GET /system reading the store rather than the engine snapshot) is called out, because "no behaviour change" with an exception is not no behaviour change.

https://claude.ai/code/session_01HeLrWaDmsNeeNSbHQfEofX

TWO SEPARATE FAILURES, and only one of them is #377.

WHAT #377 DESCRIBES: entries land under [Unreleased], nothing folds them into
the version being tagged, and because [Unreleased] sits ABOVE the version
sections a tag cut now omits every line below it. It reopened twice on
2026-08-14; the second time it stranded all seven security fixes from #366 and
the VOD editor from #365. GHSA-7jqx points at these notes, and the fix for its
worst defect -- 0.7.0's seal-at-rest migration leaving plaintext keys in the WAL
-- was in the section a tag would have skipped.

The guard is now the FIRST step of the FIRST release job, before anything is
built or pushed, because a release that has already uploaded assets and then
discovers its notes are wrong is a release somebody has to go and delete. Proven
both ways rather than asserted: exit 1 against the populated file in this commit,
exit 0 against an empty [Unreleased]. "Nothing yet." is treated as the empty
state it is.

WHAT #377 CANNOT CATCH, and it is what actually happened today: entries that were
never written. #397 recorded ONE of its seven changes and #400 recorded none, so
[Unreleased] would have been empty and the guard would have passed while the
website, the documentation rendering, the comparison pages, the SEO work, #387's
first change and the port-allocator fix all went unrecorded. A guard trusted for
more than it does is worse than none, so that limit is written at the step and
the second check it implies -- on the pull request, not the tag -- is not
smuggled in here.

I also read this wrong before writing it. [Unreleased] looked empty because the
main working tree is parked on a stale branch; on origin/main it held the tour
entry. The gap was narrower than I first said and is now recorded accurately.

WHAT WAS MISSING, now written: the 6-to-35 page site including 23 rendered
documents; llms.txt, security.txt, the icon, HowTo data and git-derived sitemap
lastmod; the _headers bug that shipped four of six pages with no revalidation;
114 inert Copy buttons; eleven copy defects across pages naming other people's
products; the contiguous-port-window fix; and #387's first change, whose one
intended behaviour difference -- GET /system reading the store rather than the
engine snapshot -- is called out because "no behaviour change" with an exception
is not no behaviour change.

Claude-Session: https://claude.ai/code/session_01HeLrWaDmsNeeNSbHQfEofX
Copilot AI lite review requested due to automatic review settings August 16, 2026 01:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

@rainmanjam
rainmanjam merged commit d0f2c13 into main Aug 16, 2026
29 checks passed
@rainmanjam
rainmanjam deleted the chore/changelog-guard branch August 16, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Guard: fail the release build when [Unreleased] is non-empty

2 participants