afc-release-notes
Generate release notes from git history
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Generate release notes from git history
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Code and component analysis — analyze code, trace flows, audit consistency, inspect components
Architecture analysis and design review
Full auto pipeline — run spec-to-clean cycle automatically for new features
Save session state for later resumption
Resolve spec ambiguities with clarifying questions
Pipeline artifact cleanup and codebase hygiene
| name | afc:release-notes |
| description | Generate release notes from git history |
| argument-hint | [v1.0.0..v2.0.0 | v2.0.0 | --post] |
| allowed-tools | ["Read","Bash","Glob","Grep"] |
| model | sonnet |
Rewrites commit/PR history into user-facing release notes and optionally publishes to GitHub Releases. This is a standalone utility — not part of the auto pipeline. Does NOT modify local files (CHANGELOG updates are handled by
/afc:launch).
$ARGUMENTS — (optional) Version range and flags
v2.3.0..v2.4.0 — specific tag rangev2.4.0 — from that tag to HEAD--post — publish to GitHub Releases after preview (can combine with any range)Parse the arguments:
--post flag if present..: split into {from_tag}..{to_tag}{version}..HEADgit describe --tags --abbrev=0!git describe --tags --abbrev=0 2>/dev/null || echo "[NO_TAGS]"
!git log $(git describe --tags --abbrev=0 2>/dev/null || echo "")..HEAD --pretty=format:"%H %s" --no-merges 2>/dev/null || git log --pretty=format:"%H %s" --no-merges
from_tag to that tag, to_tag to HEADto_tag is specified (not HEAD), verify it exists: git rev-parse --verify {to_tag} 2>/dev/nullto_tag is a version tag: use it (e.g., v2.4.0)to_tag is HEAD: use "Unreleased" or the from_tag bumped (ask user)Run these commands to gather change context:
# Commit history (no merges)
git log {from_tag}..{to_tag} --pretty=format:"%H %s" --no-merges
# Merged PRs since the from_tag date
from_date=$(git log -1 --format=%aI {from_tag})
gh pr list --state merged --search "merged:>$from_date" --json number,title,author,labels,body --limit 100
If gh is not available or the repo has no remote, skip PR collection — proceed with git-only data.
Search commit messages and PR titles for breaking change indicators:
BREAKING, BREAKING CHANGE, !: (conventional commits feat!:, fix!:)breaking, breaking-change, semver-majorFlag any matches for the Breaking Changes section.
Categorize each commit/PR into one of:
| Category | Conventional Commit Prefixes | Fallback (no prefix) |
|---|---|---|
| Breaking Changes | !: suffix, BREAKING | Label: breaking |
| New Features | feat: | Commit introduces new user-facing functionality |
| Bug Fixes | fix: | Commit fixes broken or incorrect behavior |
| Other Changes | chore:, docs:, ci:, refactor:, perf:, test:, style:, build: | Everything else |
Fallback classification rule — For commits without conventional prefixes, read the commit message semantically. Classify based on what the commit actually does: did it introduce new user-facing functionality (New Features)? Did it fix broken behavior (Bug Fixes)? Or is it a maintenance/improvement change (Other Changes)? Do not match individual words — understand the commit's purpose.
The word "add" in "add a new API endpoint" indicates a feature. The same word in "add missing test coverage" indicates a test (Other Changes). Context determines classification.
Rewriting rules — transform each entry from developer-speak to user-facing language:
feat:, fix(scope):, etc.)(#42)Build a contributors section:
# Get commit authors with their commit counts
git log {from_tag}..{to_tag} --format="%aN" | sort | uniq -c | sort -rn
# Resolve repo identity for GitHub username lookup
gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"'
# Map git authors to GitHub usernames via commit SHAs
git log {from_tag}..{to_tag} --format="%H" | head -100 | while read sha; do
gh api "repos/{owner}/{repo}/commits/$sha" --jq '.author.login // empty' 2>/dev/null
done | sort -u
For each contributor:
gh is not available, skip username resolution entirely — use git author namesAssemble the final release notes in this format:
# {version}
{2-3 sentence summary: what is the most important thing in this release? Written for end users.}
## Breaking Changes
- {description + migration guide}
## New Features
- {user-facing description} (#{pr_number})
## Bug Fixes
- {user-facing description} (#{pr_number})
## Other Changes
- {description} (#{pr_number})
## Contributors
{contributor list with @mentions and PR numbers}
Format rules:
@username (#42, #45) format, or Name (#42) if no GitHub usernameDisplay the complete release notes to the user in the console.
Print a summary:
Release notes generated
├─ Version: {version}
├─ Range: {from_tag}..{to_tag}
├─ Commits: {N}
├─ PRs referenced: {N}
├─ Breaking changes: {count or "none"}
├─ Contributors: {N}
└─ --post: {will publish / preview only}
If --post flag is present:
Determine the tag name:
to_tag is a specific tag: use itto_tag is HEAD: ask the user what tag to create (suggest next version)Ask user to confirm using AskUserQuestion:
On approval, write to a temp file and publish:
tmp_file=$(mktemp)
cat > "$tmp_file" << 'NOTES_EOF'
{release notes content}
NOTES_EOF
# Add --draft if user chose "Post as draft"
gh release create {tag} --notes-file "$tmp_file" --title "{version}" [--draft]
rm -f "$tmp_file"
Print result:
GitHub Release published
├─ Tag: {tag}
├─ Title: {version}
├─ Status: {published / draft}
└─ URL: {release URL from gh output}
If --post is not present, print:
To publish these notes as a GitHub Release, run again with --post flag.
--post, this command only outputs to console. No files are created or modified./afc:launch: Use launch for local artifact generation (CHANGELOG, README). Use release-notes for GitHub Release publishing.gh CLI and repository access.--post always asks for explicit approval before publishing to GitHub.gh release create completes, verify success by checking the exit code and output URL. If it fails, report the error and suggest manual creation.--post is safe to repeat. With --post, GitHub Releases for existing tags will fail (GitHub does not allow duplicate release tags).