| name | wtf.changelog |
| description | This skill should be used when a developer wants to generate release notes or a changelog entry after merging a Feature or closing an Epic — for example "write the changelog", "generate release notes", "what shipped in this release", "create a GitHub Release for this feature", "document what we built", "update CHANGELOG.md", or "summarize what merged". Derives user-facing language from closed Task Gherkin scenarios and Feature Acceptance Criteria rather than from raw commit messages. |
Changelog
Generate a changelog entry or GitHub Release from merged work. Core value: derives user-facing language from the spec hierarchy (Epic → Feature → Task Gherkin) rather than raw commit messages — so the output reads as product changes, not implementation details.
Shared behavior:
- User-question style →
../references/questioning-style.md
- Commit / tag / release syntax →
../references/commit-conventions.md
Process
0. GitHub CLI setup
Run ../references/gh-setup.md. Stop if gh is not installed or not authenticated.
1. Identify the release scope
If an Epic or Feature number was already passed in as context (e.g. from wtf.retro), skip the question and use it directly.
Otherwise ask the user whether the changelog covers a Feature, an Epic, or a date range. Each scope has distinct follow-up queries:
- Feature scope — walk the Feature and its closed child tasks per
../references/spec-hierarchy.md to extract Gherkin and Functional Description per task.
- Epic scope — walk Epic → Features → Tasks per the same reference, in parallel at each level.
- Date range scope — fetch merged PRs between two dates via
gh pr list --state merged --json number,title,mergedAt,body and filter with --jq.
2. Classify and translate each change
For every closed Feature or Task in scope, do two things in one pass:
a. Classify into one of these buckets using the signal column:
| Type | Signal |
|---|
| Added | New capability — Feature or Task implements a previously-unavailable user action |
| Changed | Refactor, performance, or UX enhancement reflected in Gherkin Then steps |
| Fixed | Linked bug issue, or Gherkin scenario describes a failure path that now passes |
| Deprecated | Mentioned in Feature ACs or Task Functional Description as phasing out |
| Removed | Task or Feature explicitly tears down prior behavior |
| Breaking | Contract change in Task Contracts section, ! in PR title, or BREAKING CHANGE: trailer per ../references/commit-conventions.md |
b. Translate into user-facing language:
- Pull the domain actor and business outcome from the Feature capability name or Task Functional Description.
- Use the Gherkin
Then steps as the concrete observable change, translated to plain language.
- Do NOT use implementation vocabulary ("refactored X", "migrated Y", "updated the API") — use domain outcomes ("Merchants can now filter settlements by date range").
- Drop internal-only work (test infra, CI config, internal refactors with no user-facing effect) unless the release contains nothing else.
3. Draft the changelog entry
Follow Keep a Changelog conventions. Omit any section with no entries. For Epic-level changelogs, group entries under Feature headings if there are more than 5 entries.
## [<version or date>] — <YYYY-MM-DD>
### Added
- <Domain Actor> can now <business action> — [#<issue>](<url>)
### Changed
- <What changed from the user's perspective> — [#<issue>](<url>)
### Fixed
- <What was broken and is now resolved> — [#<issue>](<url>)
### Deprecated
- <What is being phased out and the replacement> — [#<issue>](<url>)
### Removed
- <What was removed and the migration path> — [#<issue>](<url>)
### Breaking
- <What requires action from integrators or users> — [#<issue>](<url>)
4. Review with user
Show the draft. Then call AskUserQuestion (per ../references/questioning-style.md):
- question: "Does this accurately describe what shipped?"
- header: "Draft review"
- options:
- Approve and write → apply as-is and proceed
- Add missing items → add items before writing
- Adjust the phrasing → edit specific entries
Apply edits, then proceed.
5. Choose the output target
Call AskUserQuestion (per ../references/questioning-style.md):
- question: "Where should I write this changelog?"
- header: "Output target"
- options:
- Update CHANGELOG.md → prepend entry to the changelog file
- Create GitHub Release → create a tagged GitHub Release
- Both → update CHANGELOG.md and create a GitHub Release
6. Write CHANGELOG.md (if selected)
Read the current file (or create it with a # Changelog header if missing). Prepend the new entry after the # Changelog heading, above any existing entries.
Commit per ../references/commit-conventions.md:
git add CHANGELOG.md
git commit -m "chore(changelog): add release notes for <scope>"
7. Create the GitHub Release (if selected)
Call AskUserQuestion (per ../references/questioning-style.md):
- question: "Which tag should I use for this release?"
- header: "Release tag"
- options: from
git tag --sort=-version:refname | head -5; user can type a new tag
Write the entry to a temp file ($NOTES) with the Write tool, then create the release via the gh body helper (../references/gh-body-helper.md) so the notes survive UTF-8 on Windows:
python3 .wtf/gh-body.py release <tag> \
--title "<release title>" \
--notes-file "$NOTES"
8. Report and offer to continue
Print the release URL and/or CHANGELOG.md path. Then call AskUserQuestion (per ../references/questioning-style.md):
- question: "What's next?"
- header: "Next step"
- options:
- Run retro → run
wtf.retro to close out the Epic (recommended if changelog covered an Epic)
- Done → exit, no further action