首页
/ get-shit-done 自定义 PR Body 章节详解:用 `ship.pr_body_sections` 为 `/gsd-ship` 追加 PRD 级发布上下文

get-shit-done 自定义 PR Body 章节详解:用 `ship.pr_body_sections` 为 `/gsd-ship` 追加 PRD 级发布上下文

2026-09-08 17:22:52作者:仰钰奇

导读

get-shit-done(GSD)在阶段验证通过后,会由 /gsd-ship 依据规划工件(planning artifacts)自动生成拉取请求(PR)正文。默认正文固定包含 SummaryChangesRequirements AddressedVerificationKey Decisions 五段核心内容,但很多项目还需要在 PR 上携带用户故事、验收标准、风险、发布标准或干系人审批等更完整的发布上下文。本文基于 docs/ship-pr-body-sections.md 讲解 ship.pr_body_sections 配置项的字段语义、接入方式与校验规则,并结合 ship 工作流配置校验实现回归测试,让你能够在不修改 GSD 内置 ship 工作流的前提下,为每次发布的 PR 生成可追踪、可审批的 PRD 式增量说明。

为什么需要自定义 PR Body 章节

GSD 的 phase → execute → verify → ship 闭环中,/gsd-ship 会从 ROADMAP.mdSUMMARY.mdVERIFICATION.mdSTATE.md 等规划工件自动组装 PR 正文。这套默认正文覆盖了“做了什么、改了哪些文件、验证了什么、关键决策是什么”,但它刻意保持核心结构不可配置——团队不应因为个别项目的特殊需求而随意改动内置 ship 工作流。

实际问题在于:面向用户的功能增量往往还需要「用户故事与验收标准」「风险与依赖」「成功指标与发布标准」「干系人审批记录」这类 PRD 风格信息。这些内容有两个共性:

  1. 必须随 PR 一起发布,供审查者与审批者阅读;
  2. 内容来源分散在既有规划工件中(需求文档的 User Stories、计划文档的 Risks、验证文档的 Release Criteria),重复手写成本高且容易与工件脱节。

ship.pr_body_sections 正是为解决这一矛盾设计的纯配置扩展点:它以「源头引用 + 兜底文本」的方式,把规划工件中的章节自动抽取进 PR 正文,全程不需要触碰 get-shit-done/workflows/ship.md

GSD 内置的固定 PR 正文结构

无论是否配置自定义章节,/gsd-ship 生成的每一份 PR 正文都必然包含以下五段核心章节:

  • Summary —— 来自 ROADMAP.md 的阶段目标与 SUMMARY.md 的完成综述;
  • Changes —— 逐 Plan 列出 one-liner 与关键文件(key-files.created / key-files.modified);
  • Requirements Addressed —— Plan frontmatter 中的 REQ-ID,链接到 REQUIREMENTS.md 的条目描述;
  • Verification —— VERIFICATION.md 中自动化验证与人工验证项的勾选清单;
  • Key Decisions —— STATE.md 中累积的与本阶段相关的决策。

get-shit-done/workflows/ship.mdgenerate_pr_body 步骤中,这五段依次拼接完成之后,才会进入第 7 步「Configured project sections」——通过 gsd-sdk query config-get ship.pr_body_sections --default '[]' 读取配置并追加渲染。因此自定义章节具有严格的追加语义(append-only)

  • 渲染位置固定在 Key Decisions 之后;
  • 不能替换、删除或重排任何内置核心章节。

这一点同样被回归测试显式锁定:测试断言 ship 工作流文本中包含 append-onlycannot replace 以及五段核心标题按序出现(见 feat-3167-ship-pr-body-sections.test.cjs)。

方式一:在 /gsd-new-project 引导阶段选配

ship.pr_body_sections引导期扩展点(onboarding-time extension point)。执行 /gsd-new-project 时,GSD 会询问是否需要让 /gsd-ship 在生成的 PR 正文末尾追加可选的 PRD 风格章节,并推荐以下四个选项:

推荐选项 用途 建议 content source
User Stories & Acceptance Criteria 面向用户的用户故事与验收检查 REQUIREMENTS.md 下的用户故事与验收标准
Risks & Dependencies 发布风险、依赖与回滚说明 PLAN.md 下的 Risks / Dependencies
Success Metrics & Release Criteria 可度量的 Done 定义与发布检查 REQUIREMENTS.md 的 Definition of Done、VERIFICATION.md 的 Release Criteria
Stakeholder Review & Approval 需要签核追溯的项目审批记录 模板文本(如 {phase_name} 审批待办)

实现细节见 get-shit-done/workflows/new-project.mdPR body onboarding 的步骤描述:

  • 被选中的章节写入 .planning/config.json"enabled": true
  • 未被选中的章节也会被播种进去,但 "enabled": false——这样项目后续只需改一个布尔值即可启用,完全不需要重新编辑 /gsd-ship 工作流或重跑引导
  • 如果用户一项都不选,则写入 "ship": { "pr_body_sections": [] }

引导阶段最终通过 gsd-sdk query config-new-project '{"mode":"...",...,"ship":{"pr_body_sections":[...]}}' 一次性写入完整配置。

方式二:手动配置(CLI 或直接编辑 JSON)

对于已存在的项目,可通过 SDK 查询命令写入:

gsd-sdk query config-set ship.pr_body_sections '[{"heading":"Risks & Dependencies","enabled":true,"source":"PLAN.md ## Risks || PLAN.md ## Dependencies","fallback":"- No known high-risk rollout dependencies."}]'

也可以直接编辑项目根目录下的 .planning/config.json,一个完整的三段配置示例:

{
  "ship": {
    "pr_body_sections": [
      {
        "heading": "User Stories & Acceptance Criteria",
        "enabled": true,
        "source": "REQUIREMENTS.md ## User Stories || REQUIREMENTS.md ## Acceptance Criteria",
        "fallback": "- Acceptance criteria are covered by the linked requirements and verification evidence."
      },
      {
        "heading": "Risks & Dependencies",
        "enabled": true,
        "source": "PLAN.md ## Risks || PLAN.md ## Dependencies",
        "fallback": "- No known high-risk rollout dependencies."
      },
      {
        "heading": "Stakeholder Review & Approval",
        "enabled": false,
        "template": "- Product owner approval pending for {phase_name}."
      }
    ]
  }
}

需要注意,配置存放在项目的 .planning/config.json 中,由 sdk/src/config.tsloadConfig 负责读取并与默认值合并;其中 ship: { pr_body_sections: [] } 是声明的默认形状(见 sdk/src/config.ts),默认模板文件中同样体现为空数组(get-shit-done/templates/config.json)。

Section 字段语义与校验规则

每个章节是一个 JSON 对象,支持如下字段:

字段 是否必填 说明
heading 渲染为 Markdown ## {heading}。必须为单行文本,不能包含换行
enabled 默认 true。设为 false 表示保留在配置中但不渲染
source 规划工件标题的兜底选择链(fallback chain),命中后整段拷贝进 PR 正文
template 字面量 Markdown,支持一组封闭的 token(见下文)
fallback source 未找到内容且没有 template 时使用的字面量 Markdown

每个 section 必须至少提供 sourcetemplatefallback 三者之一,否则配置会被校验拒绝。

这些规则在 get-shit-done/bin/lib/config.cjsvalidateShipPrBodySections 中有完整的代码级落地:

  • 顶层必须是 JSON 数组,否则报 Expected a JSON array of section objects
  • 每项必须是对象,且只允许预定义的字段白名单 SHIP_PR_BODY_SECTION_KEYS,出现未知字段即拒绝;
  • heading 必须是非空字符串,且通过 /[\r\n]/ 检测禁止换行
  • enabled 出现时必须为布尔值 true/false,字符串 "true"/"yes" 会被拒绝;
  • source/fallback/template 若出现则必须是字符串;
  • 三者至少一个为非空字符串;
  • source 的每个选择器都必须匹配 SHIP_PR_BODY_SOURCE_RE:即以允许的工件文件开头、后跟 ## 和标题文本。

违规时配置写入会整体失败,而不是部分生效——测试验证了畸形值不会写进 .planning/config.json(见 feat-3167-ship-pr-body-sections.test.cjs)。

Source 选择器:从规划工件抽取章节

source 指向规划工件中的标题,使用 || 提供逐级兜底:

REQUIREMENTS.md ## User Stories || REQUIREMENTS.md ## Acceptance Criteria

语义为:先从 REQUIREMENTS.md## User Stories 找内容,若为空则尝试 ## Acceptance Criteria,再不行才轮到 fallback

允许作为 source 的工件文件(白名单,配置校验的正则即来源于此):

  • ROADMAP.md
  • PLAN.md
  • SUMMARY.md
  • VERIFICATION.md
  • STATE.md
  • REQUIREMENTS.md
  • CONTEXT.md

这条白名单意味着 source 不可能引用 package.json、任意 .txt 或其他未经允许的文件——回归测试专门用 package.json ## Scripts 验证了这一点会被拒绝(见 feat-3167-ship-pr-body-sections.test.cjs)。从源码结构可以推断,这一限制是为了让 PR 正文始终可追溯到官方规划工件,避免引入无结构、易过期的内容源。

当所有选择器均未命中、而 templatefallback 也都不存在时,该 section 的最终正文为空,会在渲染后整体省略

Template Token:受控的占位符命名空间

template 字段是字面量 Markdown,但出于安全与可预测性考虑,只支持以下 5 个 token

  • {phase_number}
  • {phase_name}
  • {phase_dir}
  • {base_branch}
  • {padded_phase}

其余任何 {...} 形式——包括环境变量、shell 展开、项目自定义 token——都会被配置校验显式拒绝。校验实现遍历 template 中全部 \{([a-zA-Z][a-zA-Z0-9_]*)\} 匹配项,凡不在白名单内即报 Unsupported template token(见 get-shit-done/bin/lib/config.cjs)。

设计意图明确:封闭 token 命名空间可以避免意外的 prompt 注入或 shell 展开,保证 PR 正文生成过程的确定性。这些 token 的实际取值在 ship 流程初始化阶段已就绪——init.phase-op 会返回 phase_numberphase_namepadded_phasephase_dir 等字段,base_branch 则由 config-get git.base_branch 或远端默认分支解析而来(见 get-shit-done/workflows/ship.md 的 initialize 步骤)。

典型用法示例:

{
  "heading": "Stakeholder Review & Approval",
  "enabled": true,
  "template": "- Product owner approval pending for {phase_name}."
}

精益 Agile PRD 实战配置

对于需要「轻量 agile PRD 轨迹」的团队,推荐把章节映射到本次增量(increment)本身,让 PR 正文成为可直接使用的发布工件。下面是两个开箱即用的完整示例:

示例 1:用户故事与验收标准

{
  "heading": "User Stories & Acceptance Criteria",
  "enabled": true,
  "source": "REQUIREMENTS.md ## User Stories || REQUIREMENTS.md ## Acceptance Criteria",
  "fallback": "- Acceptance criteria are covered by the linked requirements and verification evidence."
}

示例 2:成功指标与发布标准

{
  "heading": "Success Metrics & Release Criteria",
  "enabled": true,
  "source": "REQUIREMENTS.md ## Definition of Done || VERIFICATION.md ## Release Criteria",
  "fallback": "- Release when automated verification and required manual checks pass."
}

这两个 section 组合的效果是:PR 正文在保持核心五段简洁可审的同时,把「功能增量从用户视角是什么、完成标准是什么、何时可以发布」的 Done 语义显式化。审查者不必翻阅整个工作区即可完成评审,而每一步都能向上追溯到需求与验证证据——这正是它被称为 release artifact 的原因。

生成与创建流程中的实际位置

自定义章节的真正落点可从 get-shit-done/workflows/ship.md 的生成链路确认:

  1. 五段内置章节按序拼接成 PR_BODY
  2. 通过 gsd-sdk query config-get ship.pr_body_sections --default '[]' 读取配置(读取失败时安全回退到空数组,保证无配置项目不受影响);
  3. 对每个 enabled !== false 的 section 解析 source / template / fallback 并追加到正文末尾;
  4. 若某 section 渲染后 trim 为空则省略;
  5. 把完整正文写入临时文件(mktemp .../gsd-pr-body.XXXXXX.md)后执行 gh pr create --body-file,以避免超大 PRD 段落撞上 shell 参数长度限制。

其中「用 --body-file 而非 --body」是关键工程细节:大段 PRD 内容可能超过命令行参数上限,而文件方式不受此约束;trap 保证临时文件在流程结束或异常时自动清理。

Troubleshooting:常见问题排查

ship.pr_body_sections 配置被拒绝

按以下清单逐项核验配置值:

  • 必须是 JSON 数组[...]),不能是单个对象;
  • 每项的 heading单行非空字符串;
  • enabled 必须是布尔值 truefalse不能是字符串(如 "true""yes");
  • 每项至少包含 sourcetemplatefallback 三者之一;
  • 只允许 headingenabledsourcetemplatefallback 这些受支持字段,其余字段名会被整体拒绝;
  • source 中的每个选择器必须是「白名单工件文件 + ## + 标题」的合法形式。

某个 section 没有出现在 PR 正文中

按顺序检查这些条件:

  • enabled 不是 false(配置了 false 的章节会被跳过,且不产生警告——这是为引导期预置预留的预期行为);
  • 所选 source 标题确实存在于对应允许的工件中;
  • 当 source 内容可能缺失时,该 section 提供了 fallbacktemplate
  • 渲染后的正文 trim 后不为空——空正文的 section 会被省略。

template token 被拒绝

只使用上文列出的 5 个受支持 token。任意环境变量(如 $HOME${VAR})、shell 替换与项目自定义 token 都刻意不支持,配置校验会直接报错,这正是为了把 PR 正文生成约束在可控范围内。

小结

ship.pr_body_sections 是 GSD 面向真实发布协作设计的纯配置、可追溯的 PR 正文扩展机制

  • 零侵入:不修改任何内置 ship 工作流,仅在核心五段之后追加内容;
  • 来源可溯源:章节内容优先从 ROADMAP.mdPLAN.mdREQUIREMENTS.mdVERIFICATION.md 等官方工件抽取,配以 fallback 兜底,杜绝无源文本;
  • 封闭与安全:字段白名单、工件白名单、token 白名单三层校验全部落在 get-shit-done/bin/lib/config.cjsvalidateShipPrBodySections 中,由 feat-3167-ship-pr-body-sections.test.cjs 全程守护;
  • 引导友好/gsd-new-project 可一次播种四个 PRD 风格章节并以 enabled 开关控制,项目生命周期内随时启用,无需重跑引导。

如果你正在管理一个需要用户故事、审批签核或发布标准随代码一起评审的仓库,为 .planning/config.json 补上 ship.pr_body_sections,是最低成本的发布工件增强路径。相关完整工作流实现可继续查阅 ship 工作流new-project 引导 以及 SDK 配置模块

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391