fix(changelog): remove stale Unreleased entry and guard against manual entries#5369
Merged
Conversation
…l entries The changelog is generated automatically at release time by craft (changelogPolicy: auto). craft only regenerates the "## Unreleased" section when it is empty, so a single leftover manual entry suppresses generation and drops every other change from the release notes. This is what broke the 6.7.0 release, which shipped with a single entry (the stale #5025 line) despite dozens of merged PRs. - Remove the stale manual entry from CHANGELOG.md so craft regenerates 6.7.0 from git history. - Add a Changelog Guard workflow + scripts/verify-changelog.sh that fails any PR adding a manual entry under "## Unreleased". - Update CONTRIBUTING.md, which still instructed contributors to hand-add "## Unreleased" entries (the source of the stale line), to reflect the automatic changelog policy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jamescrosswell
commented
Jul 10, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5369 +/- ##
=======================================
Coverage 74.24% 74.24%
=======================================
Files 509 509
Lines 18412 18412
Branches 3604 3604
=======================================
Hits 13670 13670
Misses 3869 3869
Partials 873 873 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Flash0ver
reviewed
Jul 10, 2026
Flash0ver
reviewed
Jul 10, 2026
Flash0ver
reviewed
Jul 10, 2026
…t bullets craft trims the Unreleased section body and skips auto-generation whenever it is non-empty (`if (!changeset.body)` after `.trim()`). The previous check only failed on bullet lines, so a heading-only leftover (e.g. a bare "### Features") would still suppress generation and drop the rest of the release notes. Match craft's behaviour exactly: fail on any non-whitespace content under "## Unreleased"; a bare/empty heading still passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nto changelog-unreleased-ci-guard
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c5771de. Configure here.
craft supports richer changelog entries via a '### Changelog Entry' section in the PR description (used verbatim instead of the PR title). Point contributors at it from both CONTRIBUTING.md and the guard's failure message. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Stefan Pölz <38893694+Flash0ver@users.noreply.github.com> Co-authored-by: James Crosswell <jamescrosswell@users.noreply.github.com>
…lution Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Without recursively-checked-out submodules under modules/, builds and tooling break in confusing ways (e.g. generate-solution-filters.ps1 silently drops the missing projects from the *.slnf files, as happened while preparing this PR). Point contributors/agents at ./dev.cs cleanslate up front. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ntries The previous check grepped the extracted section body, so reported line numbers were offset from the actual file. Emit real file line numbers (awk NR) in a single pass instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Why the 6.7.0 changelog broke
The 6.7.0 release shipped with a single changelog entry despite dozens of merged PRs.
Root cause: the repo generates its changelog automatically via craft (
changelogPolicy: autoin.craft.yml). Craft only regenerates the## Unreleasedsection when it is empty (prepare.ts —if (!changeset.body)guards the git-based generation, and the body is.trim()-ed first). A stale, hand-written entry (#5025) had been left under## Unreleased, so craft saw non-empty content, skipped generation entirely, and just renamed## Unreleased→## 6.7.0. Everything else was silently dropped.That stale line got there because
CONTRIBUTING.mdstill instructed contributors to hand-add## Unreleasedentries — contradicting theautopolicy (andAGENTS.md/CLAUDE.md, which already say do not add changelogs manually).How changelog entries are meant to be produced
Under
changelogPolicy: auto, nobody editsCHANGELOG.md. craft builds each entry one of two ways:feat:PR becomes a Feature, afix:PR a Fix, etc.### Changelog Entrysection in the PR description — if present, craft uses that text verbatim instead of the title, which lets a PR provide a richer or multi-line entry (or several entries). See craft docs.Either way, the
## Unreleasedsection must stay empty so craft regenerates it at release time.Changes
CHANGELOG.md— remove the stale manual## Unreleasedentry so craft regenerates 6.7.0 from git history (the feat: Add exponential backoff and log deduplication to Spotlight #5025 feature is still captured — it's afeat:commit in range)..github/workflows/changelog-guard.yml+scripts/verify-changelog.sh— aChangelog Guardcheck that fails any PR leaving content under## Unreleased. It mirrors craft's own emptiness test: any non-whitespace content fails (a bullet, or even a bare### Featuressub-heading), while an empty## Unreleasedheading passes. Reports the offendingCHANGELOG.mdline numbers. Runnable locally:./scripts/verify-changelog.sh.CONTRIBUTING.md— replace the stale "add a## Unreleasedheading" instructions with the automatic-changelog policy, documenting both entry mechanisms above.AGENTS.md— add a Getting Started note to check out submodules first (./dev.cs cleanslate); without them, tooling likegenerate-solution-filters.ps1silently drops projects from the*.slnffiles.Sentry.slnx/.generated.NoMobile.slnx— register the new workflow and script in the solution.Follow-up (not in this PR)
The 6.7.0 release itself needs to be re-cut after this lands so craft regenerates the full changelog. Consider making
Changelog Guarda required status check.🤖 Generated with Claude Code