| name | release-notes |
| description | 基于 git 历史 + issue 引用生成符合 Keep-a-Changelog 规范的发版说明 |
| allowed-tools | ["Bash","Read","Write","Grep","Glob","Notify"] |
| triggers | ["release notes","发版说明","changelog","release","版本日志","打 tag","bump version"] |
| tags | ["release","changelog","git","devex"] |
| priority | 7 |
Release Notes Generator
把从上一个 tag 到当前 HEAD(或指定 tag)之间的 git 历史整理成符合 Keep a Changelog 的发版说明。
何时触发
- 用户说:"生成 v1.2.0 的 release notes" / "写一下 0.4.0 的 changelog"
- 用户打了新 tag(例如
v0.4.0)后要求写说明
- cron 在
v*.*.* tag 推送后触发
输入
- 必需:目标版本号(形如
v0.4.0 或 0.4.0,自动带/去 v 前缀兼容)
- 可选:上一个 tag(默认用
git describe --tags --abbrev=0 <target>^)
输出
两个文件都要写:
CHANGELOG.md:在 ## [Unreleased] 下方插入新条目(不覆盖旧版本)
docs/releases/<version>.md:独立的发版公告(便于网站、邮件、微信直接引用)
工作流程
Step 1:预检
git rev-parse --show-toplevel
git status --porcelain
失败就停下来告诉用户,不要继续生成"碰运气"内容。
Step 2:收集原始数据
PREV=$(git describe --tags --abbrev=0 <target>^ 2>/dev/null || echo "")
git log ${PREV:+$PREV..}<target> --oneline --no-merges
git log ${PREV:+$PREV..}<target> --format='%H%n%s%n%b%n---' --no-merges
没有 PREV(第一次发版)时,列全部历史,但限 50 条以内(多了就说"initial release")。
Step 3:按 Conventional Commits 分类
正则匹配 commit message 首行的前缀:
| 前缀 | CHANGELOG 段 | 优先级 |
|---|
feat(<scope>): 或 feat: | ### Added | 1 |
fix(...) | ### Fixed | 2 |
refactor(...) | ### Changed | 3 |
perf(...) | ### Changed | 3 |
docs(...) | ### Documentation | 4 |
chore(...) / test(...) / ci(...) | 跳过,除非是 breaking 或 chore: bump version | - |
BREAKING CHANGE: 出现在 body | ### Breaking(置顶) | 0 |
| 其他 | ### Other | 5 |
每条在段内按时间倒序排列。
Step 4:抽取 issue / PR 引用
对每条 commit 扫 body 里的 #(\d+)、(#\d+)、GH-\d+:
gh issue view <N> --json title,labels -q '.title + " [" + (.labels | map(.name) | join(",")) + "]"'
没 gh CLI 或 issue 404 → 保留 #N 原样引用,不崩。
硬约束:每一个在 commit body 里出现的 #N 引用都必须保留在对应 bullet 末尾,格式 . Refs #N。不能偷懒抽象掉——审查人要靠它回追 issue。如果一条 commit 有多个 #N,全部列出:. Refs #12, #17。
Step 5:写 CHANGELOG 条目
模板(严格遵守):
## [0.4.0] - 2026-04-22
### Breaking
- **\<scope>**: description(参考 #123 [breaking-change])
### Added
- \<scope>: description. Refs #42.
- \<scope>: description.
### Changed
- \<scope>: description.
### Fixed
- \<scope>: description. Refs #17.
### Documentation
- \<scope>: description.
### Other
- Miscellaneous changes that don't fit elsewhere.
约束:
- 语气:陈述,过去式("added", "fixed", "removed"),不用"we've added / we plan to"
- 禁忌:不加"Stay tuned!" / "exciting" / "🎉" / 表情(除非用户明确要求)
- scope 必填:commit 没写 scope 就从 files changed 里推断(
tools/ → "tools";core/middleware.py → "middleware")
- 每条 ≤ 80 字
Step 6:写 docs/releases/<version>.md
工具选择(很关键):
docs/releases/<version>.md 通常不存在。新建文件必须用 Write 工具,不能用 HashlineEdit / Edit(后者只能改已存在文件,对新路径会报 File not found)。
Write 工具会自动 mkdir -p 父目录,不需要先跑 shell 命令建目录。
CHANGELOG.md 是已存在文件,用 Edit / HashlineEdit 改。
模板:
# Prax \<version>
_Released 2026-04-22_
<1-2 句话总览:这次主要做了什么>
## Highlights
- \<1-3 条顶级亮点,每条一行>
## What's Changed
<把 CHANGELOG 的 Breaking/Added/Changed/Fixed 段照抄>
## Upgrading
<如果有 breaking,这里写迁移;没有就 "Drop-in replacement, no migration needed.">
## Credits
<用 git log --format='%aN' --no-merges <range> | sort -u 列贡献者>
---
Full diff: https://github.com/ChanningLua/prax-agent/compare/\<prev>...\<version>
Step 7:幂等处理
关键:同一版本号重跑必须覆盖,不能追加。
执行前:
- 读
CHANGELOG.md,用 ## [<version>] - 正则找到该条目的起止行
- 有就整块删除,再插入新版
- 没有就直接在
## [Unreleased] 下方插入
docs/releases/<version>.md 直接 overwrite。
Step 8:通知(可选)
若 .prax/notify.yaml 有 release-announce channel,调 Notify:
Notify(
channel = "release-announce",
title = "Prax " + version + " released",
body = <docs/releases/<version>.md 的 Highlights 段>,
level = "info"
)
硬约束
- 不打 tag、不 push、不发 npm:这是内容生成器,不是发布工具。发布动作始终由用户明确触发。
- 不猜版本号:用户没指定就问一次,不要自己从 pyproject.toml 读一个版本就开干。
- 断网可跑:
gh CLI 不可达时降级到"只用 git log + commit body",不报错。
- Breaking 必须显式:只有 commit body 里真的有
BREAKING CHANGE: 才放 Breaking 段。别自作聪明把 refactor(api) 当 breaking。
和其他 skill 的接力
docs-audit 发现"有代码改动但 docs 没跟上"时,生成的 issue 可以成为下一次 release notes 的候选输入
ai-news-daily 负责抓外部内容,本 skill 专职 on-repo 产出,边界清晰
典型调用
用户:生成 v0.4.0 的 release notes
→ skill 跑 git describe 找到 PREV=v0.3.2
→ git log v0.3.2..HEAD 拿到 8 条 commit
→ 按 feat/fix/chore 分成四段
→ 识别 chore(polish) 不属于任何用户可见改动,放 Other
→ 抽取 #123 引用(如果有),gh issue view 补标题
→ 读 CHANGELOG.md 找 [0.4.0](本次第一次跑,没有)
→ 插入新条目到 [Unreleased] 下方
→ 写 docs/releases/v0.4.0.md
→ 报告用户:CHANGELOG 加了 X 行、docs/releases/v0.4.0.md 写好了
用户读完满意就打 tag + 发版,不满意就让 skill 改。