refactor(releaser): 将 manage-release 改名为 releaser

- skills/manage-release -> skills/releaser(git mv,内容不变)
- releaser 的 frontmatter/标题改名,description 保留旧名作为触发词
- skills/manage-release/ 保留为纯弃用占位(SKILL.md + README.md,指向 releaser),
  已装软链与旧项目 .pouch.yaml 不再悬空或失效
- 同步或引用:AGENTS.md、README.md、docs/getting-started.md、orc(routing/SKILL/README)、
  ack delivery、builder(SKILL/README/contract)、memory-distill、pouch onboard 与
  suggest_skills
- 测试:catalog 需列出旧名占位,新增弃用占位断言,orc children 纳入旧名占位
This commit is contained in:
2026-09-16 15:14:12 +08:00
parent ca3156ed93
commit d791f5584c
24 changed files with 465 additions and 403 deletions
@@ -0,0 +1,83 @@
# 代码托管平台适配
## 区分 Git 与 Forge 能力
fetch、查询 remote refs、推送分支和推送单个 tag 属于 Git transport 能力,可直接通过
已配置的 Git remote 完成。创建或查看 PR/MR、合并以及创建 Forge Release 才需要平台
CLI。只发布 tag 时,不要因为缺少 Forge CLI 而停止;仍要验证 remote、认证目标和推送
授权,并在 push 后读回远端 ref。
## 选择 Forge 适配器
从 push remote URL 识别平台,并使用对应官方 CLI:
| 平台 | CLI | PR/MR 命令域 | Release 命令域 |
|---|---|---|---|
| GitHub | `gh` | `gh pr` | `gh release` |
| GitLab | `glab` | `glab mr` | `glab release` |
| Gitea / Forgejo | `tea` | `tea pulls` | `tea releases` |
先运行 CLI 的版本、认证状态和只读查看命令。记录匹配 remote host 的活动账号;存在多
个账号或 profile 时,必须唯一确定本次使用的身份。CLI 版本之间的 flags 可能不同,
每次执行写操作前读取对应子命令的 `--help`,不要凭记忆拼接参数。
直接从目标 worktree 的当前 shell 运行 `git` 与平台 CLI,让它们使用各自正常的登录机制。
Gitea/Forgejo 使用 `tea whoami` 和 `tea` 对应子命令;不要由 Agent 读取 tea 配置文件、
调用 credential helper 导出 token,或把 token 转存到命令参数、环境文件和发布说明。
当请求确实涉及 PR/MR、合并或 Forge Release,且 remote host 无法识别、CLI 缺失、认证
失败或 CLI 指向另一个实例时,停止对应平台阶段并报告:
- host、owner/repository、remote 名称。
- base、head 和当前 commit。
- 已完成的本地验证。
- 尚需人工执行的创建 PR/MR、合并或 release 步骤。
不要自动安装 CLI,也不要把 token 放进命令行后改用 `curl`。用户明确提供受支持的其他
集成时,可以使用该集成,但仍遵守同一套授权和验证闸门。
## 创建 PR/MR
使用显式的 repository、base、head、title 和 body,避免交互式默认值改变目标。把动态
值作为独立 argv 或结构化输入传递,不拼接 shell 命令。创建前:
1. 确认当前分支已经推送到计划中的 remote。
2. 查询同一 head/base 是否已有 open PR/MR,有则复用并更新状态,不重复创建。
3. 确认 head commit 与本地已验证 commit 相同。
4. 确认 CLI 不会隐式创建 fork 或推送到另一个 remote。
5. 再次读取活动账号,向用户展示 host、repository、账号和授权的最远阶段。
PR/MR body 包含目标版本、变更摘要、验证命令与结果、发布后续。创建后读取平台返回的
URL、编号、head/base 和状态,不以命令退出码代替远端读回。
## 检查和合并
用结构化输出读取 draft、head commit、base、review、required checks、冲突或
mergeability、允许的合并方式。平台字段缺失时,使用平台提供的只读详情命令补足;不能
证明闸门通过时保持未合并。
GitHub 使用 `gh pr view`、`gh pr checks` 和 `gh pr merge`;GitLab 使用
`glab mr view`、pipeline 状态和 `glab mr merge`;Gitea 或 Forgejo 使用
`tea pulls` 的查看、检查和合并能力。实际参数以当前 CLI 的 `--help` 为准。
若用户要求检查通过后自动合并,优先使用仓库已经启用的 auto-merge 或 merge queue。
不要用管理员选项绕过 review、CI、conversation resolution 或 protected branch。
合并后重新读取 PR/MR,取得平台确认的 merged commit。随后 fetch 远端 base,并验证该
commit 已进入远端 base。只看到本地 merge commit 或分支关闭不足以证明平台已合并。
## 创建 Forge Release
把 Git tag 和 Forge Release 当成两个独立状态。先创建、推送并验证包含完整更新说明的
annotated tag,再创建 release。Forge Release 正文复用已经冻结并验证的 tag 更新说明,
不要重新生成另一份内容。
- GitHub 创建 release 时使用能够拒绝缺失 tag 的选项,例如当前 CLI 支持的
`--verify-tag`。
- GitLab、Gitea 或 Forgejo 创建 release 前,先用只读命令证明 tag 已存在并指向计划的
commit、tag object 包含计划的更新说明;不要使用会顺便创建 tag 的默认行为。
- 预发布版本按项目规则标记 prerelease,不要自动把它标为 latest 或 stable。
- 发布后重新读取 release URL、tag、正文和可见性,确认正文与 tag 更新说明一致。
Forge Release 创建失败但 tag 已成功推送时,保留 tag 并从 release 阶段恢复,不要重新
合并或创建另一个 tag。
@@ -0,0 +1,77 @@
# 项目发布策略
## 策略优先级
按以下顺序确定规则,并在来源冲突时停止说明,不要静默覆盖:
1. 用户本次请求中明确给出的目标和授权范围。
2. 项目 `AGENTS.md`、`CLAUDE.md`、发布文档和可选的 `.release-policy.yaml`。
3. 构建脚本、包清单、CI 工作流和历史发布使用的实际入口。
4. 代码托管平台当前的默认分支、保护规则、检查和允许的合并方式。
5. 本 Skill 的默认值。
用户请求若与项目硬规则或平台保护冲突,展示冲突并请求处理方式。不要借用户的一句
“直接发布”绕过仓库声明的检查或保护。
开始流程时记录 base commit,并读取该提交对应的项目策略。本次发布分支对策略文件的
修改不应改变正在执行的流程;新策略从下一次发布开始生效。
项目策略不能授予外部写权限。即使配置声明创建 Forge Release 或删除远端分支,也必须
由用户本次请求明确授权相应动作。
## 可选配置
项目反复出现同一种歧义时,用户可以要求创建 `.release-policy.yaml`。从
`templates/release-policy.template.yaml` 复制后,只保留项目真正需要固定的字段。
配置只保存可提交的项目策略:
- `schema`:配置结构版本,当前为 `1`。
- `base_branch`:发布 PR/MR 的目标分支。
- `branch_pattern`:需要准备仓库修改时使用的版本分支格式,支持无展示前缀的规范
`{version}`;直接发布不因此创建分支。
- `version.scheme`:`semver` 或项目已经使用的其他方案。
- `version.sources`:构建和运行实际读取的权威版本文件;项目明确从 Git tag 派生版本时
可以省略,不要为了发布新增无消费方的版本文件。
- `tag_pattern`:release tag 格式,支持无展示前缀的规范 `{version}`。
- `merge_method`:`squash`、`merge` 或 `rebase`。
- `forge_release`:项目是否建议在 tag 后创建 Forge Release;它不授予创建权限。
- `tag_signing`:`off`、`optional` 或 `required`。
- `delete_remote_branch`:发布完成后是否建议清理远端源分支;它只是计划偏好,不是删除
权限或自动执行指令,仍需用户在本次请求中明确授权。
不要在配置中保存 token、账号、私钥路径、个人工作目录或一次性发布状态。不要加入任意
shell 命令字段;本地验证继续从项目文档、CI 和构建入口发现。
读取配置后校验字段集合、类型和枚举值,遇到未知字段时停止。`branch_pattern` 和
`tag_pattern` 展开后分别用 Git branch/tag ref 规则校验;不要把配置值拼进 shell 字符串。
`version.sources` 中每一项必须是仓库相对路径,拒绝绝对路径和 `..`。规范化并解析
symlink 后,目标必须仍在当前 worktree 内;权威来源通常还应由 Git 跟踪。
先按版本方案把用户输入规范化。默认 SemVer 接受 `1.6.0` 或作为用户输入的 `v1.6.0`,
但内部 `{version}` 固定为 `1.6.0`;版本文件写入规范值,branch/tag pattern 分别负责添加
展示前缀。自定义版本方案按项目文档定义规范值,不能从 pattern 猜测后重复添加前缀。
## 无配置时的发现顺序
1. 从 remote HEAD 和平台信息确定默认 base,不能确定时询问。
2. 从项目文档、CI 和构建入口找版本文件及更新方式。
3. 仅当发布需要修改仓库内容时,从已有分支和已合并 PR/MR 识别命名与合并方式。
4. 从稳定 tag 识别前缀、版本方案和更新说明范围;项目由 tag 派生版本时,把实际构建
入口和 tag 历史共同作为版本来源证据,否则只把 tag 当作交叉验证。
5. 无项目约定时使用 SemVer 和 `v<version>` annotated tag;需要准备仓库修改时再使用
`release/v<version>` 和 squash merge。默认不创建 Forge Release,不删除远端分支。
## 每次执行的计划快照
在第一次写操作前列出以下事实:
- base 分支、远端 commit 和 tag 将指向的目标 commit。
- 当前版本、目标版本、版本来源和升级依据。
- 更新说明的提交范围、来源和拟发布内容。
- 是否需要修改仓库内容;需要时再列出 worktree 路径与分支名。
- PR/MR 托管平台和合并方式。
- tag 与 Forge Release 计划。
- 用户授权的最远阶段和清理范围。
任何事实在执行中改变时刷新计划。改变会影响已授权的远端写目标时,再次获得确认。
+55
View File
@@ -0,0 +1,55 @@
# 中断恢复与安全清理
## 恢复原则
每次重入都从 Git 和代码托管平台读取状态,不依赖上一轮聊天结论。先记录准确的
base、head、PR/MR、merged commit、tag 和 release,再执行唯一缺失的下一步。
网络或平台调用返回超时、未知状态或非结构化错误时,先用只读命令刷新远端状态。不要把
重试当成默认动作;创建 PR/MR、合并、推 tag 和创建 release 都可能已经成功。
## 常见部分状态
| 当前状态 | 继续方式 | 禁止事项 |
|---|---|---|
| 远端 release commit 已准备,没有 tag | 核对版本与更新说明后直接创建 annotated tag | 不创建无必要的分支或 worktree |
| 本地 annotated tag 已创建但未推送 | 核对对象类型、commit 和完整说明后只推送该 tag | 不因重入重复创建或改写 tag |
| worktree 已创建,无改动 | 继续开发,或经授权移除干净 worktree | 不使用强制删除 |
| 本地发布分支已存在,没有 worktree | 核对版本身份、tip、upstream 和 base 后挂载现有分支 | 不用 `-b` 覆盖分支 |
| 分支已推送,没有 PR/MR | 确认 head/base 后创建一次 PR/MR | 不重复推送新分支 |
| PR/MR 已存在,未合并 | 复用 URL,刷新 checks、review 和冲突状态 | 不创建第二个 PR/MR |
| PR/MR 已合并,没有 tag | 获取 merged commit,生成并确认更新说明后继续发布 | 不重新合并 |
| tag 已推送,没有 release | 验证 tag 的 commit 和更新说明后创建 Forge Release | 不创建替代 tag |
| tag 指向正确 commit 但为 lightweight 或说明不符 | 停止并交由维护者决定撤销或发布修订版本 | 不移动、覆盖或补写远端 tag |
| release 已创建,验证未完成 | 读回 release、tag 和可见性 | 不直接声称发布完成 |
| 同名资源身份不匹配 | 停止并报告差异 | 不覆盖、关闭或删除未知资源 |
## 并发冲突
两个 Agent 或维护者可能同时准备相同版本。创建分支、PR/MR、tag 或 release 前都重新查询
目标是否存在。推 tag 前立即检查远端引用;push 因同名引用失败时保持失败,不要 force。
base 在开发期间前进时,让 PR/MR 和仓库规则决定是否需要更新分支。已经推送的发布分支
不在本 Skill 中重写历史;需要更新时优先创建普通提交,或交给平台的 update branch、
merge queue 和 auto-merge。任何 force push 都是硬停止条件。
## 回滚边界
- 未推送的本地版本提交可以在用户授权下修改或放弃,但不要覆盖其他工作。
- 已推送但未合并的 PR/MR 可以关闭,分支默认保留。
- 已合并变更通过新的 revert PR/MR 回滚,不重写 base 历史。
- 已发布 tag 默认不可变。commit 或更新说明错误时停止,由维护者决定撤销发布或发布新版本。
- Forge Release 失败不回滚已经正确推送的 tag;从 release 阶段恢复。
## 清理规则
清理始终放在发布验证之后:
1. 确认 worktree 没有修改、暂存或未跟踪文件。
2. 确认分支提交已从远端 base 或已验证 tag 到达。
3. 仅移除目标 linked worktree,不操作主 worktree,不使用 `--force`。
4. 删除本地分支前再次确认已合并。
5. 删除本地或远端分支都必须有用户本次请求的明确授权;项目策略不能代替授权。
6. 使用 `git worktree prune --dry-run` 查看陈旧记录;不要把 prune 当作普通清理步骤。
任何清理条件不满足时保留现场,并报告路径、分支、未提交状态和后续人工动作。
+132
View File
@@ -0,0 +1,132 @@
# 版本号与 tag
## 确定权威版本来源
按项目实际构建链路寻找版本来源,不要遍历到一个看起来像版本号的字符串就修改。优先级:
1. 项目发布文档或 `.release-policy.yaml` 明确声明的文件。
2. 项目明确由 Git tag 或 VCS metadata 派生构建版本时,以 tag 规则作为发布版本来源,
不要为了发布凭空新增或修改版本文件。
3. 构建、打包或运行入口直接读取的清单,例如 `VERSION`、`package.json`、
`pyproject.toml`、`Cargo.toml` 或语言工具链的版本配置。
4. 由权威文件生成的镜像文件、锁文件或发布元数据。
5. 最近稳定 tag,用于确定当前已发布版本、更新说明范围和发布历史。
记录每个权威文件的当前值和更新方式。多个权威来源不一致时停止,不要选择修改时间最新
的文件,也不要只改其中一个。
配置声明了版本文件时,它们必须使用仓库相对路径。拒绝绝对路径、`..` 和解析后逃出目标
worktree 的 symlink;修改前确认规范化后的准确路径。不要用 glob 或模糊搜索结果执行
批量替换。
## 选择目标版本
项目已有 CalVer、单调构建号、独立包版本或自定义方案时继续使用,不要迁移到 SemVer。
项目没有规则且只有一个协调版本时使用 SemVer:
- 不兼容的公开 API 或行为变化增加 major。
- 向后兼容的新功能增加 minor。
- 向后兼容的修复增加 patch。
根据实际兼容性判断,不要只凭 commit 前缀自动升级。项目明确采用 Conventional Commits
或已有版本工具时,可以把它们的结果作为项目规则。破坏性影响无法确定时给出建议并请
用户确定准确版本。
预发布版本沿用项目格式;没有格式时使用 `-alpha.N`、`-beta.N` 或 `-rc.N`。正式 tag
默认不加入 build metadata。不要从带 build metadata 的 tag 推断兼容性顺序。
独立多包版本、多个维护分支和 release train 不属于默认单版本流程。无法确定一个目标
版本时停止并说明需要增加包或发布线维度。
## 规范化与渲染
内部始终分别记录规范版本、分支名和 tag 名。默认 SemVer 的规范版本不含 `v`,例如
用户输入 `v1.6.0` 时规范化为 `1.6.0`;版本文件写入 `1.6.0`,再将它代入
`release/v{version}` 和 `v{version}`。不要把完整 tag 名直接代入 `{version}`。
项目采用自定义前缀或非 SemVer 时,以项目版本来源定义规范值,以 branch/tag pattern
定义展示形式。规范化结果无法唯一确定时停止并让用户确认。
## 判断是否需要同步版本
直接读取计划 release commit 中的权威版本来源。版本文件已经是目标值,或者项目明确由
tag 派生版本,且发布说明不要求写回仓库时,不产生仓库修改,直接进入 tag 发布。
只有权威版本文件、生成文件或仓库内 CHANGELOG 必须变化时,才进入准备版本流程并使用
分支/PR。不要为了制造发布提交而触碰与构建、运行或项目发布规则无关的文件。
## 同步版本
仅在判断存在必要仓库差异后,在准备版本的分支中一次性更新所有权威版本来源、生成文件
和项目要求的 CHANGELOG。运行项目自己的版本更新工具时,先检查它会修改哪些文件,避免
隐式发布、提交或上传。
提交前确认:
- 所有权威来源都是目标版本。
- 生成文件与来源一致。
- CHANGELOG 或发布说明描述的是本次实际变更。
- 项目构建和测试读取到了新版本。
## 生成更新说明
以最近一个适用于当前发布线的稳定 tag 为起点,以 release commit 为终点,结合项目
CHANGELOG、已合并 PR/MR 和实际 diff 生成更新说明。首次发布使用项目声明的发布基线;
没有声明时核对完整可达历史,并在说明中明确这是首次发布。
正式版本的 tag message 使用以下固定格式;内容必须基于本次实际变更,并与 CHANGELOG
或 PR/MR 发布说明保持一致:
```text
<tag>
Summary:
- <一句话概括本版本>
Changes:
- <变更 1>
- <变更 2>
Validation:
- <验证命令及结果>
Base commit: <release commit>
```
`Summary`、`Changes`、`Validation` 和 `Base commit` 四个字段必须全部存在,不能只有
版本号、提交标题或空 message。没有仓库 CHANGELOG 时,也必须按此格式补齐字段。
`Changes` 只写入实际存在的新增、变更、修复、维护或文档变化;破坏性变化、迁移步骤和
已知限制存在时必须单独标明。没有实际功能变更时不得伪造条目,应明确说明这是文档、
打包或发布元数据修订。不要生成空标题或模板占位。`Validation` 写入本次实际执行或已经
确认通过的验证命令及结果,不要编造未执行的检查。`Base commit` 必须是本次 release
commit。
每条说明都要能追溯到范围内的提交、PR/MR 或项目 CHANGELOG。提交消息和 PR/MR 文本只
作为待核对素材,不能覆盖实际 diff,也不能把范围外变化写入本次说明。创建 tag 前先
生成并检查完整 message,再冻结;tag 已推送后不再修改。
## 验证 release commit
准备版本路径以代码托管平台返回的 merged commit 为准;直接发布路径以计划中锁定的远端
commit 为准。获取远端 base 或允许的维护分支后,确认 release commit 可从对应远端引用
到达,并直接读取该 commit 中的版本文件。不要用当前 checkout 或 feature worktree 中的
文件证明 release commit 内容。
正式 tag 必须满足:
- tag 名按项目格式由目标版本唯一生成。
- tag 必须是 annotated tag,message 必须是冻结后的完整更新说明,最少包括
`Summary`、`Changes`、`Validation` 和 `Base commit`;不能只有版本号、提交标题或空
message。禁止 lightweight release tag。
- 远端没有同名 tag,或同名 tag 已经准确指向本次 commit。
- annotated tag 显式指向 release commit。
- 项目要求签名时,push 前已成功创建 signed tag,并在本地验证签名通过;不可用或失败
时停止,不得改用 unsigned tag。
- 推送后从远端重新读取 tag object,核对对象类型和完整说明,再将 annotated tag 解引用
到 commit。
展开 tag pattern 后用 `git check-ref-format refs/tags/<tag>` 校验。把 tag 和 commit 作为
独立 argv 传递,不拼接 shell 字符串。
tag 已在远端指向其他 commit、是 lightweight tag、缺少更新说明或说明不一致时停止。
不要 force push、删除或移动已发布 tag;由维护者决定撤销发布或创建新的修订版本。