Goal
Review generate_changelog.py and improve it. The script is invoked automatically during ./gradlew release via the generateAIChangelog task (build.gradle:266-268, wired into beforeReleaseBuild at line 277). It collects commits since the last tag, pre-categorizes them, sends the commit messages + diffs to the OpenAI API, and prepends the generated Markdown to CHANGELOG.md. Because it runs inside the release flow, a failure or bad output directly affects releases.
This is a review-and-improve task, not a reported outage. Below are concrete observations from a first read to seed the review — confirm/reject each and implement what's worthwhile.
Correctness / reliability
CHANGELOG.md handling
Cost / context / security
Cleanup / minor
Prompt & manual-content improvements (output quality)
Motivating evidence: in the current CHANGELOG.md, the ## [5.1.0] block appears twice — the raw script output sits above the # Changelog title (generic ### Features / Fixes / Breaking / Refactoring / Documentation / Testing / Other skeleton), and a hand-rewritten ## [5.1.0] sits below the title. The hand-written version is far better: a ### Security category, CWE IDs, SUF-01..06 references, a dedicated "Behavior changes (client impact)" section, HTTP status / response-code specifics, and a SemVer rationale. Today the AI output is effectively discarded and rewritten by hand. Goal: get the raw output close enough that it's edited, not replaced.
Prompt changes (prompt block at lines 126-167)
Incorporate manually-written content (ranked by value-to-effort)
Out of scope
Not proposing to remove the AI changelog approach — just to harden it. Keep the existing generateAIChangelog integration point.
Goal
Review
generate_changelog.pyand improve it. The script is invoked automatically during./gradlew releasevia thegenerateAIChangelogtask (build.gradle:266-268, wired intobeforeReleaseBuildat line 277). It collects commits since the last tag, pre-categorizes them, sends the commit messages + diffs to the OpenAI API, and prepends the generated Markdown toCHANGELOG.md. Because it runs inside the release flow, a failure or bad output directly affects releases.This is a review-and-improve task, not a reported outage. Below are concrete observations from a first read to seed the review — confirm/reject each and implement what's worthwhile.
Correctness / reliability
generate_changelog()(lines 169-181) makes an OpenAI call with no try/except. A missingOPENAI_API_TOKEN, network error, or API error throws mid-beforeReleaseBuild, potentially leaving a release half-done. Make the changelog step fail gracefully (skip/warn) or clearly non-fatal.model="gpt-5". Confirm the intended model and fix the comment. Consider making model/temperature configurable rather than hardcoded.input()fallback can hang CI. Lines 220-224 fall back toinput()when no version arg is passed. The release task passes the version, but any other invocation path in a non-interactive shell would hang. Consider failing fast instead.categorize_commits()fallback (lines 87-92) does substring matching forfix/bug/add/new/implementagainst the entire diff text. Almost every diff contains these words, so commits without a conventional prefix get bucketed arbitrarily. Either drop the diff-heuristic or make it meaningfully stronger.CHANGELOG.md handling
update_changelog()(lines 187-199) writes the new## [version]block at byte 0 of the file, ahead of any# Changelogheader/preamble. This likely contributes to the known release-time changelog duplication / "section above the title" behavior we clean up manually post-release. Insert after the title and consider adopting Keep a Changelog structure ([Unreleased], version links, dates).Cost / context / security
Cleanup / minor
import re(line 6) is unused.git showinvocations per commit (--stat --patchat 38-40 and--name-statusat 43-45) could be consolidated to reduce subprocess overhead.Prompt & manual-content improvements (output quality)
Motivating evidence: in the current
CHANGELOG.md, the## [5.1.0]block appears twice — the raw script output sits above the# Changelogtitle (generic### Features / Fixes / Breaking / Refactoring / Documentation / Testing / Otherskeleton), and a hand-rewritten## [5.1.0]sits below the title. The hand-written version is far better: a### Securitycategory, CWE IDs, SUF-01..06 references, a dedicated "Behavior changes (client impact)" section, HTTP status / response-codespecifics, and a SemVer rationale. Today the AI output is effectively discarded and rewritten by hand. Goal: get the raw output close enough that it's edited, not replaced.Prompt changes (prompt block at lines 126-167)
### Securitycategory and instruct the model to lead with it, referencing CWE IDs and ticket IDs (e.g.SUF-xx) found in commit text. The current format block (lines 144-164) has no Security section, yet it's the first thing added by hand for this library.user.*prefix; endpoints return a numeric responsecode; frame changes for consuming applications.[Gradle Release Plugin] …,*-SNAPSHOTbumps) that currently land in "Other." Set a low temperature for consistency.Incorporate manually-written content (ranked by value-to-effort)
--pretty=format:%H|%s— subject only. The detailed rationale (and squash-merged PR descriptions) lives in the body (%b) and merge-commit messages, which are dropped today. Adding%bhands the model prose already written by hand.gh. Merge commits carry PR numbers; fetching PR bodies surfaces the CWE analysis / client-impact writeups that usually originate there.## [Unreleased]section. Humans jot notes under[Unreleased]during the cycle; at release the script refines and merges those notes with commit analysis rather than generating from scratch, so hand-notes become authoritative input.Out of scope
Not proposing to remove the AI changelog approach — just to harden it. Keep the existing
generateAIChangelogintegration point.