关于 release
面向 Worktrunk 维护者的发布工作流技能,涵盖版本调整、验证、变更日志审查、合并与打标签,并强调发布前的数据丢失风险和文档检查。
主要功能
- 01将发布分支同步到 main
- 02运行本地及跨平台测试
- 03审查变更与库兼容性
- 04准备版本号和变更日志
- 05审查数据丢失与文档风险
- 06合并、打标签并监控发布
适用场景
- 01准备 Worktrunk 版本发布
- 02检查累计变更中的数据丢失风险
- 03打标签前核对变更日志覆盖情况
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ max-sixty/ worktrunk --skill release安装后在 Claude Code 中输入/release确认已加载。
详细介绍
原文在翻译后有更新,译文可能不是最新。
Release Workflow
Steps
-
将发布分支与
main同步:发布工作树的分支在两次发布之间会落后于main,只有发布完成后才会重置到main。从过时的分支切出会悄悄漏掉此后合并的所有内容。先快进到main的最新提交:git fetch origin git merge --ff-only origin/main--ff-only会在该分支是origin/main的严格祖先时推进分支;如果两者已分叉,则会失败(而不是创建合并提交或丢弃工作),必须先手动协调再继续。这相当于发布分支上的wt up,但这里明确写出操作,因为up别名会将每个分支变基到各自的上游(origin/release),而不是main。记下最终的提交 SHA:这是变更日志所涵盖的提交;第 12 步会在打标签前检查变更日志是否涵盖所有进入main的内容。 -
运行测试:两道关卡——本地测试套件和完整的跨平台测试套件。
- 本地:
cargo run -- hook pre-merge --yes。 - 跨平台:在切出时的提交上触发
nightly工作流,并等待其通过。这是发布进行完整 linux/macos/windows 验证的环节:PR 路径(ci.yaml)正在转向基于 cargo-affected 的选择,并将停止运行完整的test矩阵;nightly则运行full-tests(完整的 3-OS 套件),以及 feature-powerset、release-target、nix-flake 和 minimal-versions。基准测试不属于nightly,它们在独立的benchmarks.yaml中运行,且不作为任何关卡。
启动 ci-reporter,监控gh workflow run nightly.yaml --ref main # 注册会落后于触发操作,而且之前的发布可能留下了 # 已完成的旧 workflow_dispatch 运行 — 仅筛选正在运行的任务。 sleep 5 RUN=$(gh run list --workflow=nightly.yaml --event=workflow_dispatch --branch=main --limit 5 --json databaseId,status --jq 'map(select(.status != "completed")) | .[0].databaseId')$RUN直至完成(避免使用gh run watch,它可能会卡住)。继续之前修复所有失败。
- 本地:
-
检查当前版本:读取
Cargo.toml中的version -
审查提交:检查上次发布以来的提交,了解变更范围。审查累计差异中的数据丢失风险面(参见数据丢失风险面审查)和文档(参见文档审查)。
-
检查库 API 兼容性(仅供参考):运行
cargo semver-checks check-release -p worktrunk(如果尚未安装,则使用cargo install cargo-semver-checks --locked安装),将结果作为版本升级级别的参考,而不是兼容性关卡——worktrunk 可以自由发布含有破坏性变更的库版本。如果报告了破坏性变更,也没关系;按照 semver,版本升级仍必须是次版本(1.0 之前)或主版本(1.0 之后)。参见下文“库 API 兼容性”。 -
致谢贡献者:检查外部 PR 作者和问题报告者(参见下文“致谢外部贡献者”和“致谢问题报告者”)
-
确定发布类型:根据变更(包括 semver-checks 的结果)选择版本升级类型。只有在选择确实存在歧义时才询问用户(见下文)。
-
升级版本(必须在干净的工作树上运行——在编辑 CHANGELOG 之前):
cargo release X.Y.Z -p worktrunk -x --no-publish --no-push --no-tag --no-verify --no-confirm && cargo check这会升级
Cargo.toml和Cargo.lock,然后自动提交。第 10 步会重置此提交,以便将 CHANGELOG 一并纳入。 -
更新 CHANGELOG:顶部部分包含本次发布的变更(见下文的强制验证)。如果标题是
## Unreleased,将其改为## X.Y.Z,并将其余条目合并到该部分中——在其上方插入新标题会导致发布说明中残留过时的## Unreleased。否则,顶部部分就是上次发布的版本:在它上方添加## X.Y.Z部分,绝不要追加到其中。 -
提交:重置第 8 步自动创建的提交,暂存所有内容,并创建最终发布提交:
git reset --soft HEAD~1 && git add -A && git commit -m "Release vX.Y.Z" -
合并到 main:先完成对最终候选版本的文档审查,然后推送发布分支、创建 PR、等待 CI 并合并。保留工作树,剩余步骤将在其中运行。然后将分支移到已合并的提交上:
git fetch origin && git reset --keep origin/mainPR 会通过 squash 合并,因此该分支不再是
main的祖先,第 1 步的--ff-only无法推进它;--keep会将其移过去,并且在有未提交内容时仍会失败。等待 CI 期间main可能继续前进;第 12 步会检查打标签前进入的内容。 -
确认变更日志涵盖
main,然后打标签并推送:标签决定发布内容——release.yaml会根据标签对应的树构建二进制文件和 GitHub 发布说明,因此所有能从该标签到达的内容都会包含在发布中。合并时会将 PR squash 到当时main的最新提交上,因此 PR 等待 CI 期间进入的提交已经是发布提交的祖先,无论变更日志是否提及它,都会随发布一同发布(容易漏掉的是:后续提交重做了本次发布已记录的功能)。列出自切出时的提交(第 1 步)以来进入main的内容:git fetch origin git log --oneline <cut-from-commit>..origin/main检查通过意味着
origin/main上的变更日志记录了所列出的每个面向用户的提交。没有偏移时,列表只有一行,即Release vX.Y.Z (#NNNN)squash 提交。审查此期间进入的其他偏移内容,并将面向用户的变更纳入一个后续 squash PR,然后重新获取并再次运行检查。列表只会逐轮增长——偏移的提交会保留,并加上后续 PR 自己的 squash 提交——因此每一轮都会重新检查更长列表的覆盖情况。 将文档审查扩展到其已审查 SHA 之后的所有更改,包括修正内容和 CI 期间产生的提交。记录最终审查的 SHA,并在打标签前解决所有问题。确认无误后,为
origin/main打标签。检查和标签指向同一个引用,且它是 main 的最新提交,因此该标签可从main访问:git tag vX.Y.Z origin/main && git push origin vX.Y.Z -
等待发布工作流:推送标签会触发
release.yaml。启动 ci-reporter Agent 监控运行,直到完成(避免使用gh run watch——它可能会卡住);运行 ID 可通过以下命令获取:gh run list --workflow=release.yaml --event=push --branch=vX.Y.Z --limit 1 --json databaseId --jq '.[0].databaseId'
release.yaml 会自动构建二进制文件并发布到 crates.io、Homebrew 和 winget。
数据丢失风险面审查
Worktrunk 最严重的故障,是悄无声息地破坏用户的工作。每个 PR 的审查(running-tend,“数据丢失风险面”)是第一道关卡;发布是第二道关卡,此时上次发布以来的所有差异会一次性呈现。
这项审查以尽可能全面为目标:找出所有可能触及删除风险面的更改,接受误报,然后逐一评估候选项。漏掉一条真实的数据丢失路径,其代价远高于审查一条误报。
单靠关键词 grep 不够。它只能找到有人想到要匹配的内容,而让 Agent 依据 grep 锚点审查,会继承其盲区。因此,应并行启用彼此独立的查找 Agent,其中大多数不使用 grep,并分析它们找出的每个候选项。
查找:使用独立查找 Agent,以覆盖面优先于准确率
并行启动 3-5 个查找子 Agent,检查累计差异(git log v<last-version>..HEAD -p)及其涉及的代码,包括调用已更改代码或被已更改代码调用的内容。每个 Agent 独立工作:在此阶段不要让它们共享发现,也不要让它们都采用同一种方法。每个 Agent 都应返回候选位置及一句理由,宁可多报。
为每个 Agent 指定不同的任务。至少两个不提供 grep 或关键词列表,让它们基于代码推理,而不是进行模式匹配:
- 行为分析(不使用 grep): 阅读每项更改,并思考它可能破坏什么:文件、分支、工作树、未提交或未跟踪的工作、已提交但尚未推送的提交。标记任何最坏情况下会导致用户数据丢失的更改。
- 影响范围分析(不使用 grep): 对差异涉及的每个函数和文件,追踪其调用方和被调用方。标记任何现在可能触及破坏性原语的路径(删除分支、移除工作树、删除文件系统内容、重写历史),即便相关调用位于差异范围之外。
- 自动化差异分析(不使用 grep): 比较发布前后的自动化内容:
plugins/*/hooks/hooks.json、hooks/hooks.json、hooks/wt.sh,以及用户会复制使用的技能或别名示例。标记任何新添加或更改的、会删除或强制覆盖内容的调用。 - 关键词扫描(使用 grep): 一个查找 Agent 对完整差异运行模式过滤,作为交叉检查,绝不能作为主要方法。不要给它任何路径规范;路径允许列表会重现不使用 grep 的查找 Agent 旨在避免的盲区(破坏性代码最密集的部分——
src/commands/process.rs中的垃圾清理——位于src/git/之外)。git log v<last-version>..HEAD -p \ | grep -nE -- '--force-delete|--force| -D| -f |branch -[dD]|worktree remove|reset --hard|checkout -f|clean -[fdx]|remove_dir_all|remove_file|rm -rf'
分析:逐一评估候选项
汇总候选项、去重,并根据 AGENTS.md 中的数据安全不变量和 FAQ“Worktrunk 可以删除什么?”清单逐一分析:它是否能在失败时保留数据、是否要求对破坏性操作征得明确同意,以及是否避免悄无声息地删除副作用。为每项标记为真实风险/可接受/需要更改,并说明理由。
展示完整的评估结果,并在打标签前取得明确批准。即使某个候选项看起来可以接受,只要删除风险面候选项尚未解决,就不要为发布打标签。
文档审查
本次发布会审查自上次发布以来的所有文档变更,包括已合入 main 的变更,以及发布准备期间所做的编辑。面向公众的文档是经过筛选的产品指南:每段内容都应帮助读者了解或使用 Worktrunk,详略程度应与需要这些内容的读者人数相称。
从完整的发布差异开始,盘点文档所在的所有位置:
git diff --name-status v<last-version> HEAD
git diff v<last-version> HEAD
将上一个标签、候选 SHA 和完整清单交给独立审查者。审查网站页面、README 文件、CLI 帮助、配置和命令示例、随产品发布的技能,以及发布说明。每份权威源只审查一次,并检查其生成的副本是否一致;docs/AGENTS.md 定义了所有权和同步规则。
审查者应结合每段变更的上下文阅读,并检查:
- 目的与详略: 这段内容是否会改变读者的理解或做法?删去冗余说明,以及应放在测试或 PR 中的实现或回归细节。只有在使用方式发生变化或现有说法变得不再正确时,正确性修复才需要配套说明文案。
- 清晰简洁: 使用具体且一致的术语;先介绍概念,再依赖这些概念;在原处改写定义,而不是层层添加注意事项。精简内容时,必须保留必要的说明和限定条件。
- 准确易用: 根据实际行为核实说法,根据对应命令核实示例。检查链接,并以读者实际阅读的顺序查看受影响的渲染章节。
对于每项发现,说明其位置、对读者的影响,以及具体的替换内容或删除建议。在权威源中应用修正,重新生成镜像,并运行 docs/AGENTS.md 中的检查。关闭发现前,请审查者检查修正后的内容。在发布审查记录中记下审查范围和 SHA、覆盖范围、发现及其处理结果;未解决的发现会阻止打标签。变更日志中的说法和致谢也必须接受下文所述的核实。
CHANGELOG 审阅
自上次发布以来提交的草稿条目:
git log v<last-version>..HEAD --oneline
重要:不要轻信提交说明。 提交说明往往会淡化或错误描述变更。对于可能影响用户的提交:
- 运行
git show <commit> --stat,查看哪些文件发生了变更 - 如果涉及面向用户的代码(命令、CLI、输出),阅读实际差异
- 留意打包在一起的变更——一条“重命名标志”的提交可能也添加了新功能
提交说明具有误导性的常见情况:
- “重构 X”的提交同时改变了行为
- “重命名标志”的提交添加了新功能
- “修复 Y”的提交同时改进了错误消息或添加了提示
- CI/测试提交包含生产代码修复
需要记录的重要变更:
- 新功能或命令
- 用户可见的行为变更
- 用户可能遇到的错误修复
章节顺序: 改进、修复、文档、内部。文档包括帮助文本、网页文档和术语改进。内部包括精选的重要内部变更(并非所有变更)。
每个章节内按读者关注度排序。 章节是第一个排序维度,顺序固定;读者关注度是第二个维度,决定章节内的排名。变更类型不影响排序:没人要求的行为变更,排名应低于用户提出的功能需求;所有用户都会遇到的修复,排名应高于仅针对特定平台的修复。关注度取决于变更影响的读者数量,以及每位读者需要采取行动的程度,绝不考虑构建该变更所花费的精力——精力与关注度最不一致的时候,往往正是刚完成变更、正在撰写说明的时候。因此,破坏性变更仍应排在所属章节的靠前位置:影响的读者不多,但每位受影响的读者都必须采取行动。(/writing-prose 将此称为“根据受众比例调整显著程度”;此处重述是因为该技能属于个人配置,不在此仓库中。)
破坏性变更: 在条目中内联注明,而不是单独设立章节:
- **Feature name**: Description. (Breaking: old behavior no longer supported)
跳过:内部重构、添加测试(面向用户的测试除外,例如 Shell 补全测试)。
长度和语气
合并相关条目。 几个主题相同的 PR——例如,三个性能改进合起来带来一项用户可感知的提速——应放在一个条目中,而不是分成三个。读者关心的是整体变化,而不是 PR 的边界。将所有 PR 都列在末尾的 ([#a](...), [#b](...), [#c](...)) 列表中。
简明扼要——限制的是字数,不是句数。 每个条目以 35 个词为目标;内容较密的条目可到 60 个词,最重要的两三条可到 80 个词;Internal 部分的条目限一句话。删去“为什么要这样做”的细节,除非它会改变用户对这项变化的理解;代码示例以及 Cmd::stream / OnceCell / DashMap 这类内部细节应留在 PR 描述中,因为解释原因属于那里。
句子可以不断延长,以容纳你想说的内容;字数上限不会。所以要计算,不要凭感觉判断:
awk '/^## /{if (f) exit; f=1} f' CHANGELOG.md \
| awk '/^- \*\*/ {n=split($0,_," "); t+=n; c++; if (n>60) o++; printf "%4d %.58s\n", n, $0} END {printf "\n%d entries, %d avg, %d over 60\n", c, c?t/c:0, o}'
以字数上限为准,而不是以上一版发布为准。 篇幅会逐渐膨胀:每次起草新版本时都会对照上一节,而抽象规则总会输给身边具体的范例。尽管这项规范始终要求“简明”,五个版本间的条目平均字数还是从 49 增长到了 101。先看看上一节的篇幅偏到了什么程度,然后不要理会它,按上限来写。
条目只描述变化。 条目应记录旧行为是什么,以及现在变成了什么。只有当问题影响了相当多用户且确实需要特别处理时,才给出祈使性指导;这种情况很少见。其他补救方法应放在 PR 描述中。
不要加入主观评价。 描述发生了什么变化,不要用主观措辞评价以前的决定。避免用“蛮力”“丑陋”“吵闹”“错误”等词来形容过去的代码。中立地说明原先的行为,并明确说明现在的行为。
好:“已将 .pi/ 从默认排除列表中移除;需要排除它的用户可以通过 [step.copy-ignored] 添加。”
不好:“已移除 .pi/——这是一次无关调试会话中采用的蛮力修复,不应成为与项目无关的默认设置。”
修复的显眼程度应与影响范围相称。 读者会略读粗体标题,因此标题以及修复是否单独成条,会在读者看到正文前告诉他们问题有多严重。正确性或数据丢失修复通常需要满足一些特定条件——例如,使用非默认的 git 配置、从特定位置运行命令,或进行特定形式的更改。应在标题中写明这些条件,并在正文中说明后果:如果标题直接陈述后果,所有读者都会以为自己也可能遇到;之后再补充条件也无法消除这种印象。用“且”连接条件:“设置了 X 且 从 Y 运行”表示边缘情况,而“X 或 Y”会让人觉得有两个常见触发条件。应通过上一版发布的二进制文件复现,逐一确认每个条件,而不是只看差异内容——未经验证的假设会导致条目夸大问题;夸大数据丢失问题本身也是一种失实。
好:“设置了 ignore 的子模块:当 submodule.<name>.ignore 隐藏了子模块中的未提交更改时,wt remove 会将工作树视为干净状态,并连同这些更改一起将其移除。”
不好:“wt remove 不再删除被配置隐藏的子模块更改:设置了 submodule.<name>.ignore 且 子模块中存在未提交更改时,……”——条件都写出来了,但标题已经让所有读者以为发生了数据丢失问题。
几乎不会引起读者关注的修复(参见上文的排序规则)——名称以 - 开头、非 UTF-8 路径,或某个平台上的特殊环境——不要单独成条。将它们合并到结尾的条目中,例如“针对特殊环境的修复”,并在分句中列出每种情况。将多项粗体修复分开列出,会让人觉得工具有这么多种出错方式,无论正文如何解释都一样。
致谢外部贡献者
对于由外部贡献者(非仓库所有者)编写提交的任何变更日志条目,请添加其 GitHub 用户名以示致谢:
- **Feature name**: Description. ([#123](https://github.com/user/repo/pull/123), thanks @contributor)
查找外部贡献者:
git log v<last-version>..HEAD --format="%an <%ae>" | sort -u
然后,对于每位外部贡献者的提交,从提交中查找其 GitHub 用户名(通常在电子邮件或 PR 中)。
致谢问题报告者
当修复或功能解决了用户在此仓库中报告的问题时,请感谢报告者,而不只是 PR 作者。用户花时间报告错误、请求功能或提供复现步骤,值得获得认可。(不要致谢上游或外部仓库的问题报告者——只致谢在此处提交问题的用户。)
- **Feature name**: Description. ([#456](https://github.com/user/repo/pull/456), thanks @reporter for reporting)
对于引用了问题的修复:
- **Bug fix**: Description. Fixes [#123](https://github.com/user/repo/issues/123). (thanks @reporter)
查找报告者——以下三个步骤都要执行:
问题可能在修复前几个月就已提交。错误报告也可能出现在 PR 评论中,而不只是问题中。这些步骤相辅相成;每一步都能找到其他步骤遗漏的内容。
-
从每个提交中提取所有问题/PR 引用(主要步骤):
git log v<last-version>..HEAD --format="%B" | grep -oE '#[0-9]+' | sort -t'#' -k2 -n -u对每个引用编号运行
gh issue view N --json title,author,state。这样可以查到几个月前提交的问题——这是最常被遗漏的致谢。 -
检查 PR 评论中的错误报告(查找从未成为问题的报告): 对提交中引用的功能 PR,检查评论串,查找报告问题的用户:
gh pr view NNN --json comments --jq '.comments[] | "\(.author.login): \(.body[:150])"' -
查看自上次发布以来创建或关闭的所有问题(查找未被引用但相关的问题):
git log -1 --format=%cs v<last-version> gh issue list --state all --search "created:>=<date>" --json number,title,author --limit 100 gh issue list --state closed --search "closed:>=<date>" --json number,title,author --limit 100将每个问题标题与本次发布中的更改进行交叉比对。
应致谢的情况:
- 提供了明确复现步骤的错误报告(在问题或 PR 评论中)
- 影响了实现方式的功能请求
- 提供了测量数据的性能报告(例如“需要 15 秒”)
- 在讨论中协助诊断问题的用户
以下情况无需致谢:由仓库所有者提交的问题、无关紧要的报告,或与实际实现内容差异很大的问题。
为重要功能添加文档链接
对于有专门文档的主要功能,请添加文档链接。使用完整 URL,确保链接在 GitHub 发布页面中也能正常使用:
- **Hook system**: Shell commands that run at key points in worktree lifecycle. [Docs](https://worktrunk.dev/hook/) ([#234](https://github.com/user/repo/pull/234), thanks @contributor for the suggestion)
如果有值得用户阅读的大量文档,请添加链接,例如新命令、功能页面或“技巧与模式”部分。小幅改进则无需添加。
必须:核实每条变更日志条目
起草完变更日志条目后,必须启动一个子 Agent 来核实每个项目符号是否准确。 此标签会将这段文本发布为 GitHub 发布说明,因此之后若要更正,就需要向 CHANGELOG.md 提交后续 PR,并手动编辑发布页面;届时可能已经有人读到了错误内容。这项检查值得投入所需的全部时间。
把关需要双向检查。 如果只检查准确性,每条内容都会越写越长:“低估”和“未涵盖”没有相反方向的制衡因素,因此每轮检查只会增加内容,而不会删减。这种不对称正是上述情况不断加剧的原因。过长、过于内部化或排名高于读者更关注内容的条目,与错误条目一样,都应被指出。
子 Agent 提示词模板:
Verify these changelog entries for version X.Y.Z are accurate. They publish with
the tag, and by the time anyone corrects a wrong line, readers have acted on it.
Spend the time to read a source for each one: reading the entry and finding it
plausible is not a check, because the entry was written from the same commits you
are about to read.
Previous version: [e.g., v0.1.9]
Commits to check: git log v<previous>..HEAD
Entries to verify: the top section of CHANGELOG.md as it stands on disk. Read it
there rather than from a paste:
awk '/^## /{if (f) exit; f=1} f' CHANGELOG.md
Verify claim by claim, not entry by entry: an entry carries several independent
claims, and one verdict over the whole entry waves through every claim that is not
its headline.
1. Find the relevant commit(s) using git log and git show
2. Read the diff, not the commit message. The diff settles what changed, and
nothing else: not what the behavior was before, not what the user sees, not
what a file it doesn't touch does. Settle a "previously" / "no longer" / "so X
broke" claim by reading the old file (`git show <sha>^:<path>`) and confirming
the old behavior there. The new code's handling of the old case is not that
confirmation: a case added together with a comment about why it produces
nothing reads in a diff exactly like a case that used to produce something.
Some claims have no source in the commit at all — a version floor, what a
rendered page shows, how another component behaves. Read that source: the
rendered output, the other component's own file, the upstream project's own
releases
3. Flag any claim its source does not support, whether it overstates,
understates, or misdescribes
4. Flag if the entry runs over 60 words (80 for one of the two or three headline
entries), restates the PR description, or explains mechanism the reader cannot
act on — report these as seriously as an inaccuracy, and quote a shorter
rewrite that keeps every user-facing claim
Also check:
- Are there user-facing changes NOT covered by these entries?
- Verify each "thanks @..." attribution (right person, right role — author vs reporter)
- Within each section, is any entry ranked above one that more readers will notice?
- Read each headline alone, as a skimming reader does. Flag one that states the
consequence (what was lost or broken) rather than the situation it needed, and a
fix almost no reader will notice that has its own bullet rather than a clause in
a closing roll-up.
Report format:
- Entry: [entry text]
Status: ✅ Accurate / ⚠️ Needs revision / ❌ Incorrect
Length: [word count] — ✅ / ⚠️ over ceiling
Evidence: [for each claim, the source you read and what it said]
Suggested fix: [if needed]
检查应以顺利通过为终点,而非停留在首次检查的发现上。 核查者建议的改写并不比你自己写的内容更有依据,而你在检查进行期间编辑的条目也处于同样状态——这两种情况都会使该条目仍未得到核实。请根据当前版本重新检查整个部分,只有检查顺利通过后才能定稿。
此技能旁边的 evals/README.md 中列出了已发布版本的四个条目,其中三个有误,可用于评估对这个模板的修改是否解决了上次措辞遗漏的问题;其中还包含一个关于突出程度规则的起草示例。
如果核实发现问题: 请向用户升级处理。向他们展示子 Agent 的发现,并询问如何继续。不要自行尝试解决含糊不清的变更日志条目——用户比你更了解其更改背后的意图。
确定发布类型
根据变更选择版本号增量。只有一种级别合理时,跳过提问;仅在确实存在歧义时才提问。
答案显而易见时,无需提问,直接继续:
cargo semver-checks报告存在破坏性变更 → 次要版本(发布前 1.0;发布前不允许使用补丁版本,处于成熟期的项目在发布前 1.0 时也没有理由使用主版本增量)。告知用户并继续:“将升级次要版本 — semver-checks 报告了 N 个破坏性变更;发布前 1.0 不允许使用补丁版本。”- 自上次发布以来只有错误修复和内部提交,没有新功能,也没有 semver 破坏性变更 → 补丁版本。用相同格式告知用户。
仅在确实存在歧义时提问 — 例如,加入了新功能但没有 semver 破坏性变更(选择补丁版本还是次要版本需要判断),或用户对变更的解读可能与你不同的边界情况。使用 AskUserQuestion,提供实际选项(补丁版本 vs. 次要版本);不要添加跳过版本号之类的新选项。
提问时,请列出:
- 当前版本(例如
0.2.0) - 变更的简要摘要(新功能、错误修复、破坏性变更)
- 你的建议及理由
示例:
Current version: 0.2.0
Changes since v0.2.0:
- Added `state clear` command (new feature)
- Added `previous-branch` state key (new feature)
- No breaking changes
Recommendation: Minor release (0.3.0) — new features, no breaking changes
版本指南
- 第二位数字(0.1.0 → 0.2.0):向后不兼容的变更
- 第三位数字(0.1.0 → 0.1.1):其他所有变更
当前项目状态:成熟期(参见 AGENTS.md › 项目状态)。外部接口 — 配置文件格式(wt.toml、用户配置)以及 CLI 标志/参数 — 涉及兼容性,因此此类破坏性变更需要有充分理由(确实能带来改进,而非仅仅清理代码),并且应优先使用弃用警告,而不是静默破坏。其他所有内容,包括内部 API 和库 API,都保持灵活:worktrunk 可以自由发布会造成破坏性变更的库更新,并在每次发布时升级版本号,不必顾及现有内部 API。
库 API 兼容性
Worktrunk 是一款 CLI 工具。Cargo.toml 中的 [lib] crate 确实公开了 API,但它不是兼容性界面 — 根据 AGENTS.md › 项目状态,无需考虑 Rust 库兼容性问题;项目可以自由发布会造成破坏性变更的库更新,并在每次发布时升级版本号(参见 CHANGELOG.md 中“Breaking library API”条目)。下游 crate 预期会固定版本。
因此,cargo-semver-checks 是一个仅供参考的版本增量依据,并非要求我们承诺为下游 crate 保持 API 稳定的门槛。它会将当前公开 API 与上一个发布到 crates.io 的版本进行比较,并报告与 semver 相关的变更 — 这是选择版本增量时有用的参考信号:
cargo semver-checks check-release -p worktrunk
结果解读:
- 未报告问题:没有来自库层面的版本增量信号。根据 CLI 变更和新功能来选择。
- 报告了破坏性变更:这是预期且可接受的 — 此处无需避免破坏库 API。但按照 semver,在发布前 1.0 时,破坏性变更仍至少需要升级次要版本(例如,0.37.0 → 0.38.0),而不是补丁版本。相应地升级版本;这是版本号规则,并非需要保留旧 API 的信号。
- 工具无法运行(例如,缺少基线):可能是 crate 尚未发布,或注册表缓存已过期。尝试运行
cargo semver-checks check-release -p worktrunk --baseline-version <last-published>。
此检查用于验证所选的版本增量 — 在不存在破坏性变更时,它无法区分补丁版本和次要版本。继续通过提交审查来决定使用补丁版本(仅修复)还是次要版本(新功能)。