changelog · diff

git:20260713.d210701 to git:20260724.ba2c70f

19 added, 15 removed. Audit A to A.

---
name: changelog
description: "Add CHANGELOG.md entries, derive them from commits, or cut a Keep a Changelog and SemVer release."
user-invocable: true
allowed-tools: Read, Edit, Write, Bash, AskUserQuestion
---
# changelog
- Manage `CHANGELOG.md` per Keep a Changelog 1.1.0 + SemVer 2.0.0. Three actions: **add** (one hand-written entry), **from-commits** (derive from Conventional Commits), **release** (cut a version).
+ Manage `CHANGELOG.md` per Keep a Changelog 1.1.0 and SemVer 2.0.0:
- Edits `CHANGELOG.md` ONLY — never version files, never `git tag`/`git commit`. `release` prints suggested commands.
+ - **add:** one entry;
+ - **from-commits:** derive entries from Conventional Commits;
+ - **release:** cut a version.
+ Edit only `CHANGELOG.md`. Never change version files, commit, or tag; `release` prints suggested commands.
+
## Step 1 — Resolve the action
- `$ARGUMENTS` contains `add` / `from-commits` (or `commits`) / `release` → that action; else infer from the request, and `AskUserQuestion` (`add | from-commits | release`) if still ambiguous.
+ Resolve `add`, `from-commits` (`commits`), or `release` from `$ARGUMENTS` or the request; ask if ambiguous.
## Step 2 — Pre-flight (all actions)
```bash
root=$(git rev-parse --show-toplevel 2>/dev/null) || root=.
ls "$root/CHANGELOG.md" 2>/dev/null
```
- All actions read/edit `$root/CHANGELOG.md` (repo-root, never cwd-relative).
+ Always use `$root/CHANGELOG.md`, never a cwd-relative path.
- - Exists → `Read` it; note its style (compare-link footers? PR refs? capitalization?).
- - Missing + `add`/`from-commits` → write the standard Keep a Changelog 1.1.0 skeleton (title + intro linking keepachangelog.com/en/1.1.0 and semver.org/spec/v2.0.0, then `## [Unreleased]`), then proceed.
- - Missing + `release` → STOP: nothing to release; suggest `/changelog add` or `/changelog from-commits`.
+ - Existing: read and preserve style.
+ - Missing for `add`/`from-commits`: create the standard linked title, intro, and `## [Unreleased]` skeleton.
+ - Missing for `release`: stop and suggest `/changelog add` or `/changelog from-commits`.
## Step 3 — Insert under `[Unreleased]` (add, from-commits)
- Via `Edit`, append `- <imperative description>` under the entry's `### <Category>` within `## [Unreleased]`, creating the subsection in Keep a Changelog's canonical order if absent. Obey the contract in `references/writing-guidelines.md` (never modify released sections, never date `[Unreleased]`).
+ Append `- <imperative description>` to its category under `[Unreleased]`, creating the category in canonical order. Never edit released sections or date `[Unreleased]`.
## Step 4 — Run the action
- `references/writing-guidelines.md` is the single source of truth for entry rules, the Conventional Commits map, and the SemVer bump table — load it for every action.
+ Load [writing guidelines](references/writing-guidelines.md) for entry rules, commit mapping, and SemVer bumps.
- - **add** — entry from the user's text; else `AskUserQuestion` for category (the six Keep a Changelog categories) + a ≤15-word description. Tighten wording per writing-guidelines, then insert (Step 3).
- - **from-commits** — see below.
+ - **add** — use the user's text or ask for one of the six categories and a ≤15-word description; tighten and insert it.
+ - **from-commits** — follow the process below.
- **release** — follow `references/release.md`.
### from-commits
The changelog, not git tags, is the source of truth for what shipped — derive entries, don't mirror the log.
- 1. **Range.** `git tag --sort=-version:refname | head -5`: ≥1 tag → `<latest-tag>..HEAD`. No tag but a prior `## [X.Y.Z]` section → `git log --grep="release.*X\.Y\.Z" -iE -1 --format=%H` for the lower bound. No baseline → `git rev-list --count HEAD`, print N, `AskUserQuestion` (`all N | last 30 | last 100 | other`). Never silently default to all commits.
- 2. **Gather.** `git log --oneline <range>`, then `git log --pretty=format:"%h %s%n%b%n---" <range>` (BREAKING footers live in bodies).
- 3. **Classify → filter → aggregate.** Per writing-guidelines: map prefixes to categories, keep macro-only changes, collapse a 10–20-commit feature into 1–3 entries. De-duplicate against existing `[Unreleased]` entries.
- 4. **Propose & confirm.** Show entries grouped by category, plus what was skipped/aggregated (one-line reasons). Get approval, then insert per Step 3.
+ 1. **Range:** use `<latest-tag>..HEAD`; without tags, find the commit for the latest released section. Without either baseline, show the commit count and ask for all, last 30, last 100, or another range. Never silently choose all.
+ 2. **Gather:** inspect subjects and bodies; breaking footers may be in bodies.
+ 3. **Derive:** map, filter, aggregate, and deduplicate per the guidelines. Collapse a 10–20-commit feature into 1–3 user-facing entries.
+ 4. **Confirm:** show grouped proposals plus skipped or aggregated items with reasons, then insert only after approval.