关于 release-changelog
用于编写 Paperclip 稳定版用户更新日志的技能,遵循项目的日历版本规则和发布流程;具备 API 上下文时还可更新发布 Case。
主要功能
- 01依据 Beta 源提交生成说明
- 02收集提交、changeset 和已合并 PR
- 03识别并记录破坏性变更
- 04按面向用户的章节组织内容
- 05条件允许时更新发布 Case
适用场景
- 01在 Beta 浸泡期起草更新日志
- 02准备稳定版升级指南
- 03发布签核前审查版本变更
MCP 相关
具备 Paperclip API 上下文时,该技能会创建或更新发布 Case,并将更新日志写入其正文文档。Cases 不可用时仍可准备更新日志文件。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ paperclipai/ paperclip --skill release-changelog安装后在 Claude Code 中输入/release-changelog确认已加载。
详细介绍
Release Changelog 技能
为 Paperclip 稳定版生成面向用户的变更日志。
版本号模型
Paperclip 使用日历版本号(calver):
- 稳定版:
YYYY.MDD.P(例如,2026.318.0) - Canary 版:
YYYY.MDD.P-canary.N(例如,2026.318.1-canary.0) - Git 标签:稳定版使用
vYYYY.MDD.P,Canary 版使用canary/vYYYY.MDD.P-canary.N
版本号不分主版本、次版本和修订版本。稳定版版本号根据预定发布日期(UTC)和当天下一个稳定版修订槽位确定。
输出:
releases/vYYYY.MDD.P.md- 启用 Cases 时,按
(caseType, key)对releaseCase 执行新增或更新,并在其中创建包含变更日志正文的body文档修订
重要规则:
- 即使有
2026.318.1-canary.0这样的 Canary 版,变更日志文件仍为releases/v2026.318.1.md - 不要根据 semver 升级类型推导版本号
- 不要创建 Canary 版变更日志文件
发布渠道流程 — 源提交与文件位置
稳定版由经过验证的 beta 版晋升而来,因此变更日志描述的是 beta 版的源提交,而不是 master 的最新提交:
-
发布源提交是最新的
beta/v<beta-version>标签所指向的提交(下文的{beta-src})。使用以下命令解析:git fetch origin --tags npm view paperclipai dist-tags # the beta dist-tag names the version git rev-parse 'beta/v{beta-version}^{commit}' -
{beta-src}之后master上的提交将在下一次发布中包含。 切勿将其纳入;它们是“后续计划”部分的输入,不属于变更日志。 -
验证期间,文件位于分支
release-notes/v{beta-version}的releases/beta/v{beta-version}.md中(PR 合并到master)。beta 版发布时,发布工作流会将该分支推送上去,并生成初始模板;请在该分支上编辑,并直接改写模板内容。如果分支不存在(自动化启用前创建的 beta 版),则从origin/master创建分支并填入初始模板:./scripts/draft-stable-notes.sh {beta-version} -
PR 必须在稳定版发布之前合并到
master:稳定版发布前检查会从master读取文件,若文件不存在则会失败。 -
在此流程中,切勿自行创建
releases/vYYYY.MDD.P.md——稳定版发布后,工作流会创建规范化 PR,将以 beta 版本号命名的文件重命名为该文件。 -
修复版本例外情况(从
candidate/release-*分支发布的修订版):此时,说明必须直接提交到候选分支上的releases/vYYYY.MDD.P.md,并与挑拣过来的修复一同提交。
步骤 0 — 幂等性检查
生成任何内容之前,先检查变更日志是否已存在:
ls releases/beta/v{beta-version}.md 2>/dev/null # soak-window home
ls releases/vYYYY.MDD.P.md 2>/dev/null # canonicalized / fix path
git ls-remote origin 'refs/heads/release-notes/v{beta-version}'
release-notes/v{beta-version} 分支中只有自动生成的初始模板属于正常起始状态,不构成冲突——直接改写即可。
如果文件已存在:
- 先阅读文件
- 向审阅者展示文件
- 询问是保留、重新生成,还是更新特定章节
- 切勿在未告知的情况下覆盖文件
步骤 1 — 确定稳定版范围
查找上一个稳定版标签和 beta 版源提交:
git tag --list 'v*' --sort=-version:refname | head -1
beta_src="$(git rev-parse 'beta/v{beta-version}^{commit}')"
git log v{last}..${beta_src} --oneline --no-merges
变更日志的范围始终为 v{last}..{beta-src}——绝不使用 ..HEAD 或 ..origin/master。
稳定版版本号来自以下其中一项:
- 维护者的明确要求
./scripts/release.sh stable --date YYYY-MM-DD --print-versiondoc/RELEASING.md中已达成一致的发布计划
不要根据 Canary 标签或预发布后缀推导变更日志版本号。 不要根据 API 意图推导主版本、次版本或修订版本的升级;calver 使用日期和当天的稳定版修订槽位。
步骤 2 — 收集原始输入
从以下来源收集发布数据:
- 自上一个稳定版标签以来的 Git 提交
.changeset/*.md文件- 在可用时,通过
gh获取已合并的 PR
实用命令:
git log v{last}..{beta-src} --oneline --no-merges
git log v{last}..{beta-src} --format="%H %s" --no-merges
ls .changeset/*.md | grep -v README.md
gh pr list --state merged --search "merged:>={last-tag-date}" --json number,title,body,labels
步骤 3 — 检测破坏性变更
查找以下内容:
- 具有破坏性的迁移
- 已移除或更改的 API 字段/端点
- 重命名或移除的配置键
BREAKING:或BREAKING CHANGE:提交标记
关键命令:
git diff --name-only v{last}..{beta-src} -- packages/db/src/migrations/
git diff v{last}..{beta-src} -- packages/db/src/schema/
git diff v{last}..{beta-src} -- server/src/routes/ server/src/api/
git log v{last}..{beta-src} --format="%s" | rg -n 'BREAKING CHANGE|BREAKING:|^[a-z]+!:' || true
如果检测到破坏性变更,请醒目地标出——必须在“破坏性变更”章节中说明,并提供升级路径。
第 4 步 — 面向用户分类
使用以下稳定版更新日志分区:
Breaking ChangesHighlightsImprovementsFixesUpgrade Guide(需要时)
排除纯内部重构、CI 变更和仅涉及文档的工作,除非它们会实质影响用户。
指南:
- 将相关提交归并为一条面向用户的条目
- 从用户视角撰写
- 精简、具体地撰写重点内容
- 明确说明破坏性变更需要执行的升级操作
- 从第一稿起就按完整稳定版深度撰写:以 beta 版本为基础的草稿会原样作为稳定版说明发布,因此,首次撰写草稿时,上一个稳定版的文件就是衡量详尽程度的标准——在稳定期内,绝不能让草稿停留在自动生成的骨架式简略程度。骨架中嵌套的 PR 摘要是改写素材,不应保留为原有格式。
- 描述变化,而非重复已有内容:撰写前先阅读上一稳定版的说明(
releases/v<last-stable>.md)。若其中已经介绍某项功能,本次发布的条目只涵盖发生的变化——例如默认值切换、强化或功能完善;应以对照上一版本的方式表述(“上个版本引入了 X;本次发布将其设为默认值”),而不是将该功能描述为首次推出。若某个主题曾是上一版本的重点,对于后续完善工作,不要再次将其列为重点;将其归入 Improvements。
内联 PR 和贡献者署名
当某条目明显对应一个已合并的拉取请求时,请在条目末尾按以下格式添加内联署名:
- **Feature name** — Description. ([#123](https://github.com/paperclipai/paperclip/pull/123), @contributor1, @contributor2)
规则:
- 只有在能够有把握地将条目对应到某个特定的已合并 PR 时,才添加 PR 链接。使用合并提交消息(
Merge pull request #N from user/branch)来对应 PR。 - 列出 PR 的作者。使用 GitHub 用户名,不要使用真实姓名或电子邮件地址。
- 如果一条目由多个 PR 共同贡献,请全部列出:
([#10](url), [#12](url), @user1, @user2)。 - 如果无法确定 PR 编号或贡献者,请省略署名括号部分,不要猜测。
- 没有外部 PR 的核心维护者提交可以省略署名括号部分。
步骤 5 — 写入文件
文件路径使用 Channel Process 部分中的 beta 版本路径
(releases/beta/v{beta-version}.md),但内容的标题应使用计划中的稳定版本。使用
./scripts/release.sh stable --date {planned-promotion-date} --print-version 解析该版本
(推广日期通常为 beta 发布日期加上 3 天的观察期)。如果推广日期推迟,版本会在派发时重新解析——beta 版本文件名可以避免因此产生问题;发生这种情况时,请更新标题。
变更日志的开头必须是格式为 # Paperclip {version} 的 H1 标题(不带花括号),例如 # Paperclip v2026.618.0。务必包含 Paperclip 前缀和版本号中的 v。
模板:
# Paperclip vYYYY.MDD.P
> Released: YYYY-MM-DD
## Breaking Changes
## Highlights
## Improvements
## Fixes
## Upgrade Guide
## Contributors
Thank you to everyone who contributed to this release!
@username1, @username2, @username3
除 Highlights、Improvements 和 Fixes 外,空章节应省略;这几个章节通常应保留。
应始终包含 Contributors 章节。列出发布范围内所有提交的作者,并使用他们的 GitHub 用户名(而非真实姓名或邮箱)通过 @ 提及。查找 GitHub 用户名的方法:
- 从合并提交消息中提取用户名:
git log v{last}..{beta-src} --oneline --merges——分支前缀(例如from username/branch)即为 GitHub 用户名。 - 对于
[email protected]这类 noreply 邮箱,@前的部分就是用户名。 - 如果贡献者的用户名不明确,请检查
gh api users/{guess}或 PR 页面。
绝不要暴露贡献者的邮箱地址。 只能使用 @username。
排除机器人账号(例如 lockfile-bot、dependabot)。
排除特定人员——Contributors 章节只列出社区贡献者。规范排除列表(请保留在此处;
Discord 技能会遵循此列表):
cryppadotta、forgottendev、devinfoley、sockmonster、scotttong、
nguyenm7、nickyleach、tonio-alucema
按 GitHub 用户名的字母顺序排列贡献者(不区分大小写)。
如果排除后没有剩余贡献者,则跳过此章节,不要提及。
步骤 5b — 更新发布案例
写入 releases/vYYYY.MDD.P.md 后,如果本次运行包含 Paperclip API 上下文,则创建或更新顶层发布案例。将 skills/paperclip/references/cases.md 作为 API 规范。如果 API 返回 403 Cases are disabled,请说明必须启用 Cases,然后仅继续处理变更日志文件。
请求:
POST /api/companies/:companyId/cases
{
"caseType": "release",
"key": "paperclip-release:vYYYY.MDD.P",
"title": "Paperclip vYYYY.MDD.P release",
"summary": "Stable Paperclip release notes for vYYYY.MDD.P.",
"status": "in_progress",
"fields": {
"schema_version": 1,
"version": "vYYYY.MDD.P",
"release_date": "YYYY-MM-DD",
"release_patch": 0,
"stable": true,
"channels": ["changelog", "blog_post", "tweet_storm"],
"artifacts": {
"changelog_path": "releases/vYYYY.MDD.P.md",
"github_release_url": null
},
"verification": {
"typecheck": "unknown",
"tests": "unknown",
"build": "unknown",
"smoke": "unknown"
},
"notes": null
}
}
此字段架构有意涵盖所有通用字段值类型:字符串、数字、布尔值、数组、对象和 null。每次运行都要保持键名不变,并在每次更新时发送完整对象,因为字段会被替换,而非深度合并。
然后将变更日志写入案例正文文档:
PUT /api/cases/:releaseCaseId/documents/body
{
"title": "Paperclip vYYYY.MDD.P changelog",
"format": "markdown",
"body": "<contents of releases/vYYYY.MDD.P.md>",
"changeSummary": "Initial stable changelog"
}
如果要更新现有正文文档,请先获取案例并传入最新的 baseRevisionId。如果遇到 409 stale_base_revision,请重新获取、谨慎合并,然后重试一次。
步骤 6 — 发布前检查
交接之前:
- 确认 H1 标题为
# Paperclip {version}(例如# Paperclip v2026.618.0),且只使用稳定版本 - 确认标题或文件名中没有
-canary字样 - 确认任何重大变更都有升级路径
- 确认
release案例已创建,或说明 Cases 不可用的原因 - 提交草稿供人工审批
此技能不会发布任何内容,只负责准备稳定版变更日志文件。