/pdlc-ship
发布工作流(收评审通过的功能 → 跑测试 → bump VERSION → 更 CHANGELOG → tag)
Claude Code
$ npx -y skills add kanfu-panda/pdlc-skills --skill pdlc-ship --agent claude-code
Codex
$ npx skills add kanfu-panda/pdlc-skills --skill pdlc-ship -a codex -y
Cursor
$ npx skills add kanfu-panda/pdlc-skills --skill pdlc-ship -a cursor -y
Gemini CLI
$ npx skills add kanfu-panda/pdlc-skills --skill pdlc-ship -a gemini-cli -y
GitHub Copilot
$ npx skills add kanfu-panda/pdlc-skills --skill pdlc-ship -a github-copilot -y
OpenCode
$ npx skills add kanfu-panda/pdlc-skills --skill pdlc-ship -a opencode -y
Windsurf
$ npx skills add kanfu-panda/pdlc-skills --skill pdlc-ship -a windsurf -y
SKILL.md
pdlc-ship.SKILL.mdname: pdlc-ship
description: 发布工作流(收评审通过的功能 → 跑测试 → bump VERSION → 更 CHANGELOG → tag)
argument-hint: "[--version <x.y.z>] [--skip-tests (仅 hotfix)] | --tag-after-merge [v<x.y.z>]"
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
layer: 2
stage: ship
produces:
- VERSION
- CHANGELOG.md
- docs/05_deployment/releases/v<version>-release-notes.md
- .git/refs/tags/v<version>
requires:
- docs/.pdlc-state/
next_step: pdlc-deploy
terminal_state: ship_done
发布工作流
串联发布一个版本所需的所有步骤:收评审通过的功能 → 跑测试 → 升级 VERSION → 更新 CHANGELOG → 写发布说明草稿 → 创建 tag。CI 配置默认不动(见 §1.6)。
<!-- @include templates/prompts/iron-law.md(已内联于下方,无需另读) --> ⛔ **IRON LAW · 不可违反的硬门禁**
以下规则为**不可协商**的执行约束:
1. **文件必须落盘**:所有带编号(功能ID / 缺陷ID)的文档,必须作为实际文件写入磁盘,不可仅在对话中输出。 2. **阶段必须落章**:每个阶段完成后必须在状态机 `docs/.pdlc-state/<feature-id>.json` 追加 history,不可跳过。 3. **测试必须存在**:进入 `/pdlc-implement` 前,对应测试必须存在且处于红灯状态。违反则中止。 4. **自检必须执行**:段二自检为强制步骤,不得以"已经很好了"为由跳过。 5. **防循环**:段三修复为单次,不递归。无法自动修复的问题记录到报告,继续往下走。 6. **状态必推进**:成功执行某 phase 后 `current_stage` 必须变更。收尾时若发现 `current_stage` 未推进,视为失败并报错,**不得静默返回**(防止外层循环拿滞后的状态空转烧额度)。唯一例外:命中人工点主动 block 时,`current_stage` 保持不变但必须写 `last_phase_result.ok=false` + `blocked_reason`。
**违反任一条 = 立即中止当前命令,输出违规详情,等待人工介入。** <!-- @include-end templates/prompts/iron-law.md -->
> ⛔ **发布是破坏性·不可逆操作**:打 tag / bump 版本 / 触发 CI/CD 属破坏性范畴。**`--autonomous` 对本命令无效**——即使带该参数,§1.1(未完成功能)与 §1.2(测试门)的人工确认仍必须真实由人应答。自主循环(`/pdlc-loop-run`)停在「评审通过、`next_step` 为 `pdlc-ship`」(循环文档里称 `review_done`),永不进入本命令。
段一:执行
> 参数带 `--tag-after-merge`:只做「合并后补打」(见 1.5 末尾),跳过下面全部步骤。
1.1 前置检查
1. 确认当前分支不是 `master` / `main`(参考 CLAUDE.md §5) 2. 确认工作区干净(`git status` clean) 3. 盘点 `docs/.pdlc-state/` 下的功能(跳过 `_` 前缀的索引文件与 `statusline.json`),逐个归入四类:
- **可发布**:`next_step` 为 `pdlc-ship`,且 `last_phase_result.ok` 不是 `false`——评审(或功能编排)已通过、等着发布。这一类**纳入本次发布**
- **已发布**:`current_stage` 为 `ship_done` 或 `deploy_done`——上一次发布已纳入,本次不再收
- **旧版终态写法**:`current_stage` 以 `_done` 结尾但不是上面两个(如 `feature_done` / `fix_done` / `review_done`)——旧版本写入,分不清是「已发布」还是「评审通过、待发布」。逐个列出,**请人确认**归入可发布还是已发布;`--autonomous` 也不替人判
- **进行中**:其余全部(含 `last_phase_result.ok` 为 `false` 的阻塞功能)
- 有进行中的功能 → 列出来并询问是否继续(用户明确同意才继续;进行中的功能不纳入本次发布)
- 可发布为空 → 告知「没有评审通过、待发布的功能」,询问是否仍要发布(如只发文档 / 依赖升级)
4. **质量闸门检查**(若项目有 `docs/00_standards/quality-targets.yml`): 读 `docs/07_reviews/quality/` 下**最近一份 `.md` 报告**(同名 `.html` 只是视图, 闸门一律以 `.md` 为准——两者若不一致,信 `.md`):
- 无任何报告 → 提示先跑 `/pdlc-quality`,询问是继续还是先出报告
- 报告**总判定未达标** → **默认不放行**;要发必须由人**显式 override 并写明理由**,
该理由需记入本次发布的 CHANGELOG 或发布说明(不允许无声跳过)
- 报告**过期**——分两档处理,**不是所有过期都等价**(见下)
- 达标且未过期 → 在发布报告里引用该报告路径、日期与 commit SHA 作为质量证据
过期判定:按「改动了什么」分两档
报告头部记着生成时的 `<!-- 仓库版本: <commit SHA> -->`(由 `/pdlc-quality` 落盘时写入)。 取该 SHA,跑 `git diff --name-only <SHA>..HEAD` 看这期间动了什么:
| 这期间改动命中 | 判定 | 理由 | |---|---|---| | `docs/01_requirements/prd/`、`docs/00_standards/quality-targets.yml`、`docs/00_standards/e2e-flow-map.yml`、`docs/00_standards/test-commands.yml` | **硬闸·不放行** | 报告里的 PRD ↔ `core_flows` 对账与 E2E 覆盖矩阵的**输入变了**,结论不再成立。重跑单测补不回对账——必须重跑 `/pdlc-quality` | | 只有其它代码 / 文档 | 提示已过期,**建议**重跑 | 对账仍成立,测量数字可能略旧 | | 报告里没有 `仓库版本` 字段,或该 SHA 在本仓库解析不了 | **按「不可判」处理**:明确告知无法核对新鲜度,建议重跑 | 与三态语义同一条纪律——「查不了」不等于「没问题」,不得静默当作未过期 |
> ⛔ 硬闸同样允许人**显式 override 并写明理由**(与「总判定未达标」同一条通道,理由须记入 > CHANGELOG 或发布说明),但**不得无声跳过**。
`quality-targets.yml` 变动要单独看一眼「闸门是不是被调松了」
若上表命中的文件里**包含 `quality-targets.yml`**,除了要求重跑,还必须把 `git diff <SHA>..HEAD -- docs/00_standards/quality-targets.yml` **原样展示给人**, 并逐条点出下列「变松」信号——**命中任何一条都要人明确确认,不得只当作普通过期**:
- 覆盖率目标数字**下降**(如 85 → 70)
- `core_flows` 条目**减少**(核心流被移出闸门视野)
- lint 策略**放宽**(如 zero-warnings 改为允许若干 warning)
- 新增了**豁免声明**(把某些 PRD / 流程排除在对账之外)
> **为什么单列**:报告达标之后把目标调低,重跑一次照样是绿的——日期新、SHA 新、结论"达标", > 但**尺子本身变短了**。这与 `/pdlc-test-setup --refresh` 的「严向自动、松向人确认」是同一条 > 原则换个位置:**放松闸门永远是人的决定,不能由流程默默吸收。**
1.2 发布前测试门(参考 CLAUDE.md §6)
**必须主动询问用户**(不得默认跳过,也不得默认强制跑):
📦 发布前测试门检查:是否先跑全量单测 + E2E 测试?
[选项 A] 跑测试(推荐)
→ 后端:./gradlew test 或 mvn test
→ 前端:pnpm test 或 npm test
→ E2E:pnpm exec playwright test(如有)
[选项 B] 跳过测试 —— 仅适用于生产 hotfix
→ 理由:<请说明>
→ 自动记录到 commit 消息
请选择 A 或 B。
若选 B:本命令的参数必须含 `--skip-tests` 且有理由说明,否则中止。
1.3 版本号处理
1. 读取当前 `VERSION` 文件 2. 若本命令的参数带 `--version x.y.z`,用指定值;否则按语义化规则建议:
- 本次发布含 fix 且无 feature → 补丁号 +1
- 含 feature 且无 breaking → 次版本号 +1
- 含 breaking → 主版本号 +1
3. 写回 `VERSION`
1.4 更新 CHANGELOG.md
1. 取 §1.1 盘点出的**可发布**功能(含人工确认归入可发布的旧版终态写法) 2. 分组:缺陷(`B` 开头的 ID)→ "修复";history 里有 `refactor` 阶段的功能 → "重构";其余 → "新增" 3. 每条用"- <简要描述>(<feature-id>)"格式写入 CHANGELOG 的 `[未发布]` 段(开发各阶段可能已按同一格式为该功能追加过条目——`[未发布]` 段里已有同一 ID 的,不重复写) 4. 把 `[未发布]` 改为 `[<new-version>] - <今日日期>`
1.4.1 发布说明草稿(可直接作 PR 描述)
按 `assets/release-notes-template.md` 写 `docs/05_deployment/releases/v<new-version>-release-notes.md`,把这次发布散在各处的结论汇到一页, 开 PR 时直接 `gh pr create --body-file <这个文件>`,发 Release 时也能用。**只写这个文件,不开 PR、不合 PR、不推送。**
- **来源**:本次纳入的功能(§1.1 的可发布清单)各自的 PRD「背景与目标」、`docs/07_reviews/code/<ID>-*-review.md` 的评审总结与「需人工处理」项、
状态文件里 `last_phase_result.checks`(读的是推进到 `ship_done` **之前**的那份,即评审阶段的结果),以及 §1.1 的质量报告结论、§1.2 测试门的选择、§1.5 的 tag 去向
- **数字照抄**:问题数、`checks` 的值原样搬,不重算、不美化;`null` 照写 `null`。某项产物不存在就写「无」,不要补写一份
- **「需要人跟进」不能省**:评审里的需人工项、质量闸门 override、过期提示,本次发布交给人的事都列在这里;真的一项都没有才写「无」
- **不加工具署名**:草稿是给人发出去的文字,不写「由某某工具生成」之类的署名或链接
- tag 去向此时还没定(§1.5 才判断):先写「待定」,§1.5 判断完回来改成「已打 v<new-version>」或「待合并后打」,再一起提交
1.5 提交,按合并方式决定何时打 Tag
**先推进状态机,再提交**:对每个纳入的功能按段四的规则运行状态推进脚本(`--stage ship --next pdlc-deploy --done`),让 `ship_done` 随发布提交一起进库。先提交后推进的话,状态文件的改动留在发布提交之外——squash 合并时就丢了,主干上这些功能会一直显示「待发布」。
git add VERSION CHANGELOG.md docs/05_deployment/releases/v<new-version>-release-notes.md docs/.pdlc-state/<纳入的功能ID>.json
git commit -m "release: v<new-version>"
若选项 B(跳过测试):commit 消息末尾追加 `[skip-tests: <理由>]`。
**tag 必须指向最终留在主干上的那个提交。**本命令跑在发布分支上,分支怎么合进主干决定了现在打的 tag 还算不算数:
| 合并方式 | 发布分支上的提交会不会原样进主干 | 本命令的做法 | |---|---|---| | 普通合并(merge commit)/
Read more
name: pdlc-ship description: 发布工作流(收评审通过的功能 → 跑测试 → bump VERSION → 更 CHANGELOG → tag) argument-hint: "[--version <x.y.z>] [--skip-tests (仅 hotfix)] | --tag-after-merge [v<x.y.z>]" allowed-tools: Read, Write, Edit, Bash, Glob, Grep layer: 2 stage: ship produces: - VERSION - CHANGELOG.md - docs/05_deployment/releases/v<version>-release-notes.md - .git/refs/tags/v<version> requires: - docs/.pdlc-state/ next_step: pdlc-deploy terminal_state: ship_done
发布工作流
串联发布一个版本所需的所有步骤:收评审通过的功能 → 跑测试 → 升级 VERSION → 更新 CHANGELOG → 写发布说明草稿 → 创建 tag。CI 配置默认不动(见 §1.6)。
<!-- @include templates/prompts/iron-law.md(已内联于下方,无需另读) --> ⛔ **IRON LAW · 不可违反的硬门禁**
以下规则为**不可协商**的执行约束:
1. **文件必须落盘**:所有带编号(功能ID / 缺陷ID)的文档,必须作为实际文件写入磁盘,不可仅在对话中输出。 2. **阶段必须落章**:每个阶段完成后必须在状态机 `docs/.pdlc-state/<feature-id>.json` 追加 history,不可跳过。 3. **测试必须存在**:进入 `/pdlc-implement` 前,对应测试必须存在且处于红灯状态。违反则中止。 4. **自检必须执行**:段二自检为强制步骤,不得以"已经很好了"为由跳过。 5. **防循环**:段三修复为单次,不递归。无法自动修复的问题记录到报告,继续往下走。 6. **状态必推进**:成功执行某 phase 后 `current_stage` 必须变更。收尾时若发现 `current_stage` 未推进,视为失败并报错,**不得静默返回**(防止外层循环拿滞后的状态空转烧额度)。唯一例外:命中人工点主动 block 时,`current_stage` 保持不变但必须写 `last_phase_result.ok=false` + `blocked_reason`。
**违反任一条 = 立即中止当前命令,输出违规详情,等待人工介入。** <!-- @include-end templates/prompts/iron-law.md -->
> ⛔ **发布是破坏性·不可逆操作**:打 tag / bump 版本 / 触发 CI/CD 属破坏性范畴。**`--autonomous` 对本命令无效**——即使带该参数,§1.1(未完成功能)与 §1.2(测试门)的人工确认仍必须真实由人应答。自主循环(`/pdlc-loop-run`)停在「评审通过、`next_step` 为 `pdlc-ship`」(循环文档里称 `review_done`),永不进入本命令。
段一:执行
> 参数带 `--tag-after-merge`:只做「合并后补打」(见 1.5 末尾),跳过下面全部步骤。
1.1 前置检查
1. 确认当前分支不是 `master` / `main`(参考 CLAUDE.md §5) 2. 确认工作区干净(`git status` clean) 3. 盘点 `docs/.pdlc-state/` 下的功能(跳过 `_` 前缀的索引文件与 `statusline.json`),逐个归入四类:
- **可发布**:`next_step` 为 `pdlc-ship`,且 `last_phase_result.ok` 不是 `false`——评审(或功能编排)已通过、等着发布。这一类**纳入本次发布**
- **已发布**:`current_stage` 为 `ship_done` 或 `deploy_done`——上一次发布已纳入,本次不再收
- **旧版终态写法**:`current_stage` 以 `_done` 结尾但不是上面两个(如 `feature_done` / `fix_done` / `review_done`)——旧版本写入,分不清是「已发布」还是「评审通过、待发布」。逐个列出,**请人确认**归入可发布还是已发布;`--autonomous` 也不替人判
- **进行中**:其余全部(含 `last_phase_result.ok` 为 `false` 的阻塞功能)
- 有进行中的功能 → 列出来并询问是否继续(用户明确同意才继续;进行中的功能不纳入本次发布)
- 可发布为空 → 告知「没有评审通过、待发布的功能」,询问是否仍要发布(如只发文档 / 依赖升级)
4. **质量闸门检查**(若项目有 `docs/00_standards/quality-targets.yml`): 读 `docs/07_reviews/quality/` 下**最近一份 `.md` 报告**(同名 `.html` 只是视图, 闸门一律以 `.md` 为准——两者若不一致,信 `.md`):
- 无任何报告 → 提示先跑 `/pdlc-quality`,询问是继续还是先出报告
- 报告**总判定未达标** → **默认不放行**;要发必须由人**显式 override 并写明理由**,
该理由需记入本次发布的 CHANGELOG 或发布说明(不允许无声跳过)
- 报告**过期**——分两档处理,**不是所有过期都等价**(见下)
- 达标且未过期 → 在发布报告里引用该报告路径、日期与 commit SHA 作为质量证据
过期判定:按「改动了什么」分两档
报告头部记着生成时的 `<!-- 仓库版本: <commit SHA> -->`(由 `/pdlc-quality` 落盘时写入)。 取该 SHA,跑 `git diff --name-only <SHA>..HEAD` 看这期间动了什么:
| 这期间改动命中 | 判定 | 理由 | |---|---|---| | `docs/01_requirements/prd/`、`docs/00_standards/quality-targets.yml`、`docs/00_standards/e2e-flow-map.yml`、`docs/00_standards/test-commands.yml` | **硬闸·不放行** | 报告里的 PRD ↔ `core_flows` 对账与 E2E 覆盖矩阵的**输入变了**,结论不再成立。重跑单测补不回对账——必须重跑 `/pdlc-quality` | | 只有其它代码 / 文档 | 提示已过期,**建议**重跑 | 对账仍成立,测量数字可能略旧 | | 报告里没有 `仓库版本` 字段,或该 SHA 在本仓库解析不了 | **按「不可判」处理**:明确告知无法核对新鲜度,建议重跑 | 与三态语义同一条纪律——「查不了」不等于「没问题」,不得静默当作未过期 |
> ⛔ 硬闸同样允许人**显式 override 并写明理由**(与「总判定未达标」同一条通道,理由须记入 > CHANGELOG 或发布说明),但**不得无声跳过**。
`quality-targets.yml` 变动要单独看一眼「闸门是不是被调松了」
若上表命中的文件里**包含 `quality-targets.yml`**,除了要求重跑,还必须把 `git diff <SHA>..HEAD -- docs/00_standards/quality-targets.yml` **原样展示给人**, 并逐条点出下列「变松」信号——**命中任何一条都要人明确确认,不得只当作普通过期**:
- 覆盖率目标数字**下降**(如 85 → 70)
- `core_flows` 条目**减少**(核心流被移出闸门视野)
- lint 策略**放宽**(如 zero-warnings 改为允许若干 warning)
- 新增了**豁免声明**(把某些 PRD / 流程排除在对账之外)
> **为什么单列**:报告达标之后把目标调低,重跑一次照样是绿的——日期新、SHA 新、结论"达标", > 但**尺子本身变短了**。这与 `/pdlc-test-setup --refresh` 的「严向自动、松向人确认」是同一条 > 原则换个位置:**放松闸门永远是人的决定,不能由流程默默吸收。**
1.2 发布前测试门(参考 CLAUDE.md §6)
**必须主动询问用户**(不得默认跳过,也不得默认强制跑):
📦 发布前测试门检查:是否先跑全量单测 + E2E 测试? [选项 A] 跑测试(推荐) → 后端:./gradlew test 或 mvn test → 前端:pnpm test 或 npm test → E2E:pnpm exec playwright test(如有) [选项 B] 跳过测试 —— 仅适用于生产 hotfix → 理由:<请说明> → 自动记录到 commit 消息 请选择 A 或 B。
若选 B:本命令的参数必须含 `--skip-tests` 且有理由说明,否则中止。
1.3 版本号处理
1. 读取当前 `VERSION` 文件 2. 若本命令的参数带 `--version x.y.z`,用指定值;否则按语义化规则建议:
- 本次发布含 fix 且无 feature → 补丁号 +1
- 含 feature 且无 breaking → 次版本号 +1
- 含 breaking → 主版本号 +1
3. 写回 `VERSION`
1.4 更新 CHANGELOG.md
1. 取 §1.1 盘点出的**可发布**功能(含人工确认归入可发布的旧版终态写法) 2. 分组:缺陷(`B` 开头的 ID)→ "修复";history 里有 `refactor` 阶段的功能 → "重构";其余 → "新增" 3. 每条用"- <简要描述>(<feature-id>)"格式写入 CHANGELOG 的 `[未发布]` 段(开发各阶段可能已按同一格式为该功能追加过条目——`[未发布]` 段里已有同一 ID 的,不重复写) 4. 把 `[未发布]` 改为 `[<new-version>] - <今日日期>`
1.4.1 发布说明草稿(可直接作 PR 描述)
按 `assets/release-notes-template.md` 写 `docs/05_deployment/releases/v<new-version>-release-notes.md`,把这次发布散在各处的结论汇到一页, 开 PR 时直接 `gh pr create --body-file <这个文件>`,发 Release 时也能用。**只写这个文件,不开 PR、不合 PR、不推送。**
- **来源**:本次纳入的功能(§1.1 的可发布清单)各自的 PRD「背景与目标」、`docs/07_reviews/code/<ID>-*-review.md` 的评审总结与「需人工处理」项、
状态文件里 `last_phase_result.checks`(读的是推进到 `ship_done` **之前**的那份,即评审阶段的结果),以及 §1.1 的质量报告结论、§1.2 测试门的选择、§1.5 的 tag 去向
- **数字照抄**:问题数、`checks` 的值原样搬,不重算、不美化;`null` 照写 `null`。某项产物不存在就写「无」,不要补写一份
- **「需要人跟进」不能省**:评审里的需人工项、质量闸门 override、过期提示,本次发布交给人的事都列在这里;真的一项都没有才写「无」
- **不加工具署名**:草稿是给人发出去的文字,不写「由某某工具生成」之类的署名或链接
- tag 去向此时还没定(§1.5 才判断):先写「待定」,§1.5 判断完回来改成「已打 v<new-version>」或「待合并后打」,再一起提交
1.5 提交,按合并方式决定何时打 Tag
**先推进状态机,再提交**:对每个纳入的功能按段四的规则运行状态推进脚本(`--stage ship --next pdlc-deploy --done`),让 `ship_done` 随发布提交一起进库。先提交后推进的话,状态文件的改动留在发布提交之外——squash 合并时就丢了,主干上这些功能会一直显示「待发布」。
git add VERSION CHANGELOG.md docs/05_deployment/releases/v<new-version>-release-notes.md docs/.pdlc-state/<纳入的功能ID>.json git commit -m "release: v<new-version>"
若选项 B(跳过测试):commit 消息末尾追加 `[skip-tests: <理由>]`。
**tag 必须指向最终留在主干上的那个提交。**本命令跑在发布分支上,分支怎么合进主干决定了现在打的 tag 还算不算数:
| 合并方式 | 发布分支上的提交会不会原样进主干 | 本命令的做法 | |---|---|---| | 普通合并(merge commit)/
Author: kanfu-panda Repo: github.com/kanfu-panda/pdlc-skills License: MIT pdlc-skills is built on one rule: an AI saying "done" doesn't count — exit codes do.
Other skills on pdlc.
pdlc-adopt
已有代码、还没有 PDLC 文档的老项目接入——只读扫描后逆向生成基线文档并做健康检查,不改代码;空目录新项目用 /pdlc-bootstrap
pdlc-bootstrap
空目录从一句话描述初始化新项目(服务 / 应用拆分、技术栈、目录骨架与 PDLC 文档目录);已有代码的项目用 /pdlc-adopt
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about pdlc-ship.
- Which coding agents can use pdlc-ship?
- pdlc-ship installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

