关于 prd-to-plan
prd-to-plan 是面向编码 Agent 的技能,可将 PRD 转为分阶段的垂直切片实施计划,并输出到项目的 plans 目录。它还支持将计划关联到 GitHub issue,或在本地模式下工作。
主要功能
- 01按垂直切片拆分实施阶段
- 02记录跨阶段架构决策
- 03检查验收标准是否可验证
- 04将计划写入 Markdown 文件
- 05支持关联 GitHub issue
适用场景
- 01为新功能 PRD 制定实施路线
- 02把大型需求拆分为可审查阶段
- 03为编码 Agent 准备独立阶段任务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ semi-sentient/ skills-workflow --skill prd-to-plan安装后在 Claude Code 中输入/prd-to-plan确认已加载。
附带文件references/i18n-phase.md
详细介绍
PRD 转计划
使用纵向切片(示踪弹)将 PRD 拆分为分阶段实施计划。输出为项目 plans 目录中的 Markdown 文件。
流程
1. 确定 PRD 来源和 GitHub 是否可用
确定 PRD 内容的来源,以及本次调用是否会发布到 GitHub。
步骤 1a — 检测 GitHub 是否可用(开销低,只运行一次):
git remote get-url origin— 如果没有输出,或 URL 不是github.com,则 GitHub 集成不可用(纯本地模式)- 如果存在 GitHub 远程仓库,则运行
gh auth status— 如果未通过身份验证,则 GitHub 集成不可用
从远程 URL 中提取 <org>/<repo>,供后续使用。
步骤 1b — 按优先级确定 PRD 来源:
- 传递给此技能的显式 GitHub issue 参数(例如
#123或https://github.com/<org>/<repo>/issues/123) - 上下文中的 GitHub issue URL,与当前仓库的远程仓库匹配,通过扫描对话检测
- 带有 `` 页脚的本地 PRD 文件 — 如果用户指定了本地 PRD 文件(或从最近的对话中可以判断文件位置,例如
write-a-prd刚刚写入了文件),则读取该文件。如果包含页脚,则提取N,并视同显式 GitHub 参数。这是write-a-prd→prd-to-plan在不同对话之间交接时无需用户手动复制 issue 编号的方式。 - 上下文中或本地不带页脚的 PRD 内容(纯本地模式)
如果用户传递了 --no-github(或等效选项),则完全跳过 GitHub,无论上下文如何都仅在本地模式下操作——包括忽略本地 PRD 文件中的任何页脚标记。
步骤 1c — 处理每种情况:
- 存在显式参数,且 GitHub 可用:
- 运行
gh issue view <n> --json number,title,url,updatedAt(不获取正文 — 避免 PRD 已在对话中时重复内容)。这也可作为预检,确认父 issue 存在。 - 显示确认信息:
Linking plan to #<n> '<title>' — last updated <updatedAt>.被动显示时间戳;不要就此提示用户。 - 如果 PRD 尚未出现在对话中,则获取完整正文:
gh issue view <n> --json body,title,number,url - 如果对话中提到了此仓库的其他 issue 编号,则在继续前指出不匹配:
You passed #<n> but I noticed #<m> earlier. Continue with #<n>?
- 运行
- 存在显式参数,但 GitHub 不可用: 明确报错。说明是缺少
gh、未通过身份验证,还是仓库不属于 GitHub。不要静默回退。 - 检测到上下文中的 issue,且 GitHub 可用:
- 单个匹配项:
Detected GH issue #<n> '<title>' in this conversation. Link the plan as a sub-issue? (yes / specify different / skip GH) - 多个匹配项:列出它们,并询问选择哪一个(或输入
none) - 确认后,按用户传递了显式参数的情况继续
- 单个匹配项:
- 检测到上下文中的 issue,但 GitHub 不可用: 静默跳过检测;仅在本地模式下操作
- 检测到本地文件页脚,且 GitHub 可用: 按用户显式传递了页脚中的 issue 编号处理(同“存在显式参数,且 GitHub 可用”的情况)。通知用户:
Detected GH issue #<n> from PRD footer — linking plan as a sub-issue. Use --no-github to disable. - 检测到本地文件页脚,但 GitHub 不可用: 明确报错 — PRD 声明已发布,但无法访问 GitHub;不要静默取消子 issue 关系。用户需要修复
gh配置,或传递--no-github明确切换到本地模式。 - 上下文中没有相关内容,且没有显式参数: 仅在本地模式下操作。如果对话中也看不到 PRD 内容,则请用户粘贴内容或提供文件位置。
功能名称(标准化)。 在本技能中,
<feature name>指去除前缀PRD:后的源标题(不区分大小写,并去除首尾空白)。源标题是 GH issue 标题(GH 模式),或本地 PRD 中的# PRD: <Feature Name>标题(纯本地模式)——write-a-prd会为两者加上PRD:前缀,便于扫描。此此前缀不得出现在派生产物中:计划 slug(Step 7b)、计划标题(Step 7d 模板)或Plan: <feature name>子 issue 标题(Step 8b)——否则就会得到Plan: PRD: …和prd-…-plan.mdslug。仅在逐字引用实际 issue 的地方使用原始标题——上方的Linking…/Detected…确认消息,以及Source PRD:标题中的("Title")部分。
2. 探索代码库
如果你尚未探索代码库,请进行探索,以了解当前架构、现有模式和集成层。
3. 确定持久的架构决策
拆分阶段之前,确定在整个实现过程中不太可能改变的高层决策:
- 路由结构 / URL 模式
- 数据库 schema 结构
- 关键数据模型
- 身份验证 / 授权方式
- 第三方服务边界
- i18n 命名空间和可复用键引用(见 Step 3.5)
将这些内容写入计划头部,以便每个阶段都能引用。
3.5. 评估 i18n 影响
决策关卡:
- 如果 PRD 只涉及重构、测试、配置或其他不包含面向用户文案的变更,跳过此步骤。
- 如果项目未使用 i18n,跳过此步骤。
- 否则(PRD 引入或修改了面向用户的文案,且项目使用 i18n)→ 立即停止并阅读 references/i18n-phase.md。其中包含完整流程(发现配置 → 审核可复用键 → 列出新键 → 规划 Translations 阶段 → 在后续阶段接入),以及 Step 6 验证所用的验收信号。阅读之前不得继续 Step 4。
4. 起草纵向切片
将 PRD 拆分为示踪弹阶段。每个阶段都是一个贯穿所有集成层的精简纵向切片,必须端到端完成,而不是仅覆盖单个层的横向切片。
- 每个切片都要贯穿所有层(schema、API、UI、测试),交付一条精简但完整的路径 - 完成的切片应能独立演示或验证 - 优先选择多个精简切片,而不是少数几个厚重切片 - 省略各阶段间容易变化的实现细节(例如中间变量名、可能重构的内部状态结构、样式细节) - 务必包含有助于解决实现歧义且持久的实现细节(例如要使用的库或框架组件、应遵循的具体 API 模式、错误处理策略、序列化格式) - 务必包含持久的决策:路由路径、schema 结构、数据模型名称 #### 自主执行下的阶段规模当计划由 run-plan 执行时,没有人会在阶段之间停下来查看应用,因此“可独立演示”并非阶段边界的价值所在。阶段边界带来四项价值,而且都不要求阶段本身可演示:审查范围(每次判定需要评估的标准更少)、重试影响范围(每次纠正过程中丢弃的工作更少)、提交粒度,以及上下文隔离(每个阶段都在全新的 Agent 窗口中运行,因此阶段越小,单个 Agent 累积的上下文就越少)。按以下两部分规则划分阶段:
- 规模控制 — 限制阶段规模。 规划时可用标准数量作为代理指标:标准数达到两位数时,应视为需要拆分的信号。这只是一个方向性指标,并非硬性限制——审查成本随每次判定所需评估的标准数量增加,重试时会重新审查整个阶段,而固定的重试上限对 4 个标准的阶段来说较为宽裕,对 12 个标准的阶段来说却可能过于严格。如果源 PRD/issue 或 ADR 已经确定了阶段边界,则应优先遵循这一决定:将该决定记录在计划的架构决策中,并保持阶段完整,即使标准数超过十个也不例外——拆分若与既定决定相悖,就是一个问题,而非节省。
- 切分位置 — 每个拆分后的阶段都必须保留审查者可以判定失败的标准。 审查关卡会审核验收标准,因此标准的质量决定了它能否发现问题。垂直切片通常能产出可判定失败的标准(“恰好有一个重叠分配时,工位下方会显示员工姓名”);水平分层则往往会产生轻易就能满足的标准(“客户端导出
getStationAssignments”)。但要求是可判定失败,而不是垂直切片。唯一明确可以不采用垂直切片的情况:纯机械性的阶段(本地化文件、代码生成),其标准仍可证伪——“en、es 和 hi 中均存在这九个键,且位于指定位置”“没有任何 es 值是英文”——这类阶段是安全的,因为审查关卡仍能判定其失败。依赖 shell 检查的标准必须注明运行目录:在子目录中运行相对于仓库根目录的路径规范,会像真正的零命中通过一样不输出任何内容,从而使关卡形同虚设。要求记录证据的标准必须指定审查者能够读取的位置(提交说明、已提交文件、已同步的计划 issue)——“在进度说明中”没有指定任何持久位置,审查关卡会将其判为 NOT MET。只有人类才能满足的标准必须以Human verifies …开头——第 6b 步的“标准可验证性”检查项会核查这三项。
缩小阶段规模并非没有代价:每个阶段都会增加固定开销——简报、启动一次审查、提交、交接。如果所有阶段都从不失败,拆分会增加总成本;只有在阶段需要纠正处理时,拆分的收益才会显现,而且预期缺陷率越高,收益越大。风险最高的工作应优先拆分。
不属于计划内容的事项
不要在计划中加入以下阶段或步骤:
- 创建分支 —
run-plan会在开始时自动创建plan/<slug>工作分支 - 每阶段提交 —
run-plan会在每个阶段结束后,按照commit技能的格式提交 - 提交 PR —
run-plan会在运行结束时创建 PR,并链接计划子 issue 和父 PRD - 合并/部署流程 — 这些属于团队的发布流程,而非计划内容
计划描述的是工作(要构建什么、如何验证)。Git/GH 流程(分支、提交、PR)由 run-plan 统一处理。用户可以通过 --no-branch 或 --no-pr 选择跳过个别环节;计划无需针对这些覆盖选项调整——无论如何,计划都只描述工作。如果 PRD 要求合并后的验证或生产环境观察,应将其记录为描述_观察内容和决策_的阶段,而不是提交/PR 步骤。
跨阶段演进
当某个共享函数、组件或数据结构在一个阶段中引入,并在后续阶段中修改时,请明确记录其演进过程:
- 在较早阶段:说明构建了什么,并注明后续阶段会扩展它
- 在后续阶段:明确说明该阶段会修改较早阶段的实现,并描述修改前后的变化(例如:“修改第 2 阶段中的
resolveDefault(),使其在回退到硬编码默认值之前先检查缓存”) - 这样可以避免实现 Agent 从头重建,或对函数的当前状态感到困惑
向前兼容性
对于每个阶段,确定必须为后续阶段预先考虑的结构设计:
- 后续阶段将填充的扩展点(例如:“Response DTO 包含一个空的
metadata映射——第 4 阶段会在其中填充审计字段”) - 后续阶段将覆盖的抽象点(例如:“使用
resolveEndpoint(key)函数解析路径,以便第 6 阶段可以换用特定租户的路径”) - 在该阶段的“要构建的内容”部分将这些内容明确记录为说明
5. 请用户评估
以编号列表的形式展示提议的阶段划分。对于每个阶段,展示:
- 标题:简短的描述性名称
- 涵盖的用户故事:说明该阶段对应 PRD 中的哪些用户故事(如果 PRD 按编号决策而非用户故事组织,请引用决策编号,并通过 PRD 覆盖关系将决策映射到各阶段)
询问用户:
- 粒度是否合适?(太粗 / 太细)
- 是否应合并某些阶段,或进一步拆分?
持续迭代,直到用户批准阶段划分。
6. 验证计划
写入文件前,请根据实际代码库验证计划,而不是依赖记忆。审阅者需要一份可供阅读的文档,因此首先将完整计划(使用步骤 7d 的模板)写入 plans 目录之外的临时草稿——在运行时确定临时位置,并按以下顺序检查:仓库自身说明要求使用的临时目录,然后是主机的临时目录,最后是 plans 目录的同级 scratch/ 目录(如果该位置在仓库内,使用 git check-ignore 验证 Git 会忽略它;如果未被忽略,请自行将其添加到 .git/info/exclude——切勿假定已有忽略规则),绝不能使用 plans 目录本身;该目录在步骤 7 中只接收获批的成果——并将临时草稿的路径交给审阅者,在简报中说明该临时位置是有意选择的,并非发现的问题。本步骤中的每项修正都应编辑草稿;步骤 7 会将获批的草稿复制到目标位置。这样可以避免计划错误最常见的来源:依据过时的记忆,而非真实文件。起草计划的 Agent 会以善意方式解读它,因为它知道每个阶段的意图;因此,只要主机条件允许,就应由拥有全新上下文窗口的独立审阅者来完成验证,而不是让作者重新阅读自己的内容。
步骤 6a — 选择验证模式(能力门槛):
- 优先方式——独立审阅者。 如果宿主可以启动拥有独立上下文窗口的子 Agent(参考实现是 Claude Code 的 Task 工具,例如用于只读审阅的
ExploreAgent),请委托其中一个进行验证。向它提供计划和 Step 6b 检查清单,但不要提供你制定计划的理由——它必须从头阅读引用的文件,并根据证据判断每项主张。审阅者只报告发现的问题,不进行编辑。 对于大型计划,你可以安排 2–3 名审阅者并行审查(例如,一名检查源文件和可行性准确性,一名检查阶段间的一致性及 PRD 覆盖情况,一名检查 i18n)——人数宜少;大多数检查成本很低。然后由你(作者)落实修正。 - 备用方式——对抗式自我审阅。 如果宿主无法启动子 Agent,就在单独的一轮中,将 Step 6b 检查清单作为明确的 红队 审查自行执行:在实际文件证明情况并非如此之前,假定每个阶段都有误。这种方式仍会受到作者偏见影响,因此弱于独立审阅者,但远胜于宽容地重读一遍。
**无论采用哪种方式,**现在都要从磁盘重新阅读各阶段「要构建的内容」部分引用的每个源文件,而不是依赖你之前的摘要。
Step 6b——验证检查清单(由审阅者执行;作者修复发现的问题):
- 源文件准确性 — 文件路径确实存在。函数签名与计划描述一致。Provider/组件嵌套层级准确。接口和类型与计划声称要扩展的内容一致。
- 架构可行性 — 对于每个阶段,组件都确实能够访问其被描述为会使用的上下文/钩子/函数。检查 Provider 嵌套、导入路径和模块边界。
- 跨阶段连贯性 — 对于每个修改早期阶段内容的阶段,都明确记录了修改前→修改后的变化;早期阶段的测试不会因后续更改而悄然失效;共享接口的演进保持一致。
- 决策完整性 — 不得出现任何「二选一」、「或者另选方案」、「如果 > N 行」或其他未解决的表述。每项都必须明确为单一、具指示性的决策。计划要敲定决策,而不是罗列选项。
- PRD 覆盖度 — PRD 中的每个用户故事至少对应一个阶段。PRD 中的每项测试决策都对应一个 TDD 切片。
- 标准可验证性 —
run-plan的 Review Agent 必须能够仅凭仓库内容检查每条验收标准。包含三个子检查:(1)可执行性:从验收标准指定的目录运行其中列出的每条只读 shell 命令,并报告其当前返回结果与计划要求在该阶段完成后返回的结果;已经通过的命令无法证明任何内容,无法在正确实现上通过的命令会导致执行 Agent 修改有效代码,而在当前主机 shell(BSD 与 GNUgrep/sed/regcomp;\s并非通用写法)上无效的命令会造成无法区分的静默通过。(2)证据位置:要求记录输出的标准必须指定审核者可读取的位置——阶段提交说明、已提交文件或已同步的计划 issue;绝不能写「进度说明」、「摘要」或对话:这些内容并非持久记录,审核者也无法查看。(3)执行者:只有人类才能满足的标准(例如执行操作、检查控制台、观察实时流量)必须以Human verifies …/Human confirms …开头,以便执行技能的人类关卡规则能够通过机械方式识别;在包含**Known risk**: human action行的阶段中,每一条此类标准都必须标注,而不只是其中一条。 - i18n 完整性 — 如果 PRD 包含面向用户的字符串,且项目使用 i18n,则验证计划符合 references/i18n-phase.md 中的验收信号:Phase 1 是 Translations 阶段,架构决策列出 i18n 命名空间和可复用键,后续阶段不修改翻译文件,非默认语言区域有实际翻译。如有任何一项标准未通过,则返回 Step 3.5 重新修改。
Step 6c — 信心评分(必须由作者以外的人独立完成)
为每个阶段评定 0–10 分,表示 AI 编码 Agent 仅凭计划就能正确实现该阶段的可能性。评分必须由执行验证的人给出,而不是计划作者——作者给自己的计划打分毫无参考价值。在独立审核模式下,由审核者给出评分;在备用模式下,将评分视为自查清单提示,并以 Step 6d 的用户批准作为真正的关卡。
对于任何低于 9 分的评分,审核者还必须对差距进行分类:规格缺口(可通过在计划中补充细节来解决)或不可消除的风险(无论在计划中补充多少细节都无法消除)。不可消除的风险必须属于以下列出的命名原因之一:
- 该阶段需要执行编码 Agent 无法完成的人工操作,无论是验证还是设置(目视检查、实体硬件操作、在第三方控制面板中进行配置)。
- 该阶段依赖于实施前无法获知的外部系统行为(未记录的 API 响应、生产数据的形态)。
- 该阶段剩余的不确定性存在于运行时行为中,只有针对真实状态执行变更才能观察到(针对真实数据执行迁移、并发负载下的行为)——而非代码应如何编写。
只有在没有任何待处理的第 6b 步问题时,才能将风险归类为不可消除;规范含糊通常会以第 6b 步问题的形式显现,因此,清单无问题是判断“已无可修复之处”的实际标准(下方的反事实评分可兜底第 6b 步遗漏的问题)。审查者还必须报告:如果解决了所列原因,该阶段可获得的反事实评分。只有当反事实评分达到 9 分或以上,且实际评分达到 5 分或以上时,才适用例外。低于 5 分时,不可使用不可消除风险例外——返回第 5 步,将有风险的工作拆分出来,或为其设置检查点,使其成为独立的精简阶段(该下限仅适用于例外:若低于 5 分的阶段被归类为规范缺口,应按下一段进行修复,绝不能仅因评分低而拆分);若某阶段本身已是用于隔离风险的最小切片,且验收标准中包含人工检查点,则不受此下限约束(否则拆分会陷入无限循环)。在回退模式下,归类和评分一样,都是作者自行给出的判断;在第 6d 步表格中将此类行标注为自行归类,以便用户在知情的情况下批准。
标记所有低于 9 分的阶段。在继续之前,修复第 6b 步清单中的所有问题。对于被标记为规范缺口的阶段,补充具体的实施细节(代码片段、API 配置、准确的函数签名),直到评分达到 9 分或以上,或剩余差距完全由某个列明的原因造成。对任何被标记的阶段应用修复后,按第 6a 步所用的相同模式重新运行验证;第 6d 步中列出的评分和归类必须来自此次重新验证——在独立模式下,绝不能来自作者;在回退模式下,必须来自新一轮红队审查,而不能沿用修复前的结果。重新验证可以仅针对修复涉及的阶段(以及任何跨阶段引用发生变化的阶段),也可以针对一组命名的修复或单个问题(适用于修复涉及多个阶段的情况)——无论哪种方式,任务说明都必须写明范围;随后,第 6d 步表格必须为每个评分标注产生该评分的轮次,从而清楚显示未变阶段的旧评分早于当前评分,绝不将其误作当前评分。 收敛。 每轮的评审简报(包括第 1 轮)都会要求评审者将每项发现归类为 设计(第 6b 步中除标准可验证性之外的任何项目)或 标准(标准可验证性),并将每项设计发现评为 严重(按当前阶段内容会构建出错误的东西,或无法构建)、主要(执行 Agent 会停滞或只能猜测)或 次要(其他情况)。如果某轮的设计发现中没有严重或主要问题,则该轮已收敛,无论评分如何:修复其余发现,仅针对改动后的标准重新运行标准可验证性检查,然后进入第 6d 步——表格会列出收敛后的修复内容;对于评分仍低于 9 的阶段,表格会列出其评分,并注明“没有尚未解决的主要设计问题”;是否发布由用户决定。零发现不是门槛:对抗式评审者每轮都会返回一些内容,而修复轮也可能引入下一轮发现——退出条件是所有发现均为次要,而不是没有发现。未收敛的轮次按常规循环处理:作者修复其发现,评审者按照第 6c 步重新评审,其中的范围规则保持不变;收敛只决定是否跳过设计复审,不会改变由谁执行什么操作。绝不展示作者调整后的评分:无论之后作者完成了多少项修复,第 6d 步的表格都必须列出每个阶段最近一次由评审者给出的评分,并标明轮次。若发现指出现有标准存在缺陷,应通过改写或删除该标准来回应,绝不能在旁边再添加一条;若发现指出缺少必要标准,则属于覆盖缺口,可以合理地新增一条。在验证过程中新增标准,正是阶段达到分割信号阈值并重新启动循环的方式——在生产中,有两轮都在六轮中的最后两轮以这种方式完成。绝不要为了抬高评分而给阶段填入编造的细节;虚构的片段看起来像权威内容,比明确标记阶段存在问题更糟。
按例外情况接受的阶段必须将风险写入计划文件:在第 7d 步中,为该阶段添加一行 **Known risk**: <named cause>;若风险由人工操作导致,还要添加对应的验收标准(例如 - [ ] Human verifies <X>)——执行 Agent 只会阅读计划,因此只存在于本次对话中的风险,他们永远看不到。
第 6d 步——展示验证结果——向用户展示一张汇总表,列出每个阶段的置信度评分(0–10)、发现的任何问题,以及为解决问题所做的更改。如果验证改动了用户在第 5 步批准的结构(合并或拆分了阶段),表格应展示新结构,并说明改动内容及原因——无需重新征求第 5 步的批准;本次批准涵盖这些改动。对于因不可消除的风险例外而展示的任何评分低于 9 的阶段,表格必须说明具体原因(在回退模式下标明该原因由自身分类),以确保用户是在明确接受该风险,而非忽视它。未获得用户明确批准之前,绝不要进入第 7 步。如果用户要求修改,则进行修订、重新验证(模式与上文相同),并再次展示。重复此过程,直至获得批准。
7. 编写计划文件
前提条件:必须先向用户展示第 6 步的验证结果,并获得明确批准,之后才能编写计划。如果第 6 步尚未完成并获批,请现在返回并完成该步骤。
第 7a 步 — 确定计划目录,按以下优先级处理:
- 如果
.agents/plans/存在,则使用它 - 否则,如果
.claude/plans/存在,则使用它 - 否则,如果
.agents/存在,则创建.agents/plans/并使用它 - 否则,如果
.claude/存在,则创建.claude/plans/并使用它 - 否则,创建
.plans/并使用它
第 7b 步 — 派生计划 slug:
slugify 规则(与 write-a-prd 第 6a 步共用):
- 转为小写
- 将空格替换为连字符
- 删除所有非字母数字字符和非连字符
- 将连续的多个连字符合并为一个;去除首尾连字符
- 如果正在使用本地 PRD 文件(例如
.agents/plans/mui-v9-migration-prd.md),则通过替换后缀来配对 slug:mui-v9-migration-plan.md - 否则,将 GH issue 标题中的前缀
PRD:去掉(即第 1c 步的功能名称规则),然后按上述规则生成 slug:"PRD: MUI v9 Migration" → "MUI v9 Migration" →mui-v9-migration-plan.md - 在第 6d 步的审批消息中说明生成的文件名;用户的批准也涵盖该文件名(无需单独确认)
第 7c 步 — 再次调用检测(写入前执行):
检查现有状态:
- 目标计划文件是否存在于计算出的路径?
- 如果涉及 GH:父 issue 下是否存在标题为
Plan: <feature name>的子 issue?优先读取现有本地文件中的 `` 页脚(比按标题匹配更可靠)。否则,查询gh api /repos/<org>/<repo>/issues/<parent>/sub_issues并按标题匹配。
根据状态选择分支:
| 本地文件 | 子 issue | 提示 |
|---|---|---|
| 否 | 否 | 正常继续 |
| 是 | 否 | Plan file exists. Overwrite (regenerate) / re-publish existing file as sub-issue / cancel? |
| 是 | 是 | Plan file and sub-issue #N both exist. Regenerate file / update sub-issue body / cancel? |
| 否 | 是 | Sub-issue #N exists but no local file. Fetch its body as the local file / regenerate from scratch / cancel? |
如果用户选择了仅发布或仅更新的路径,则跳过下方的文件写入,直接跳到第 8 步并使用现有文件。否则继续。
第 7d 步 — 使用以下模板编写计划。
Source PRD: 标题有两种形式——不可混用:
- 涉及 GH:
> Source PRD: #123 — https://github.com/<org>/<repo>/issues/123 ("Title") - 纯本地:
> Source PRD: .agents/plans/<slug>-prd.md
涉及 GH issue 时,省略任何本地 PRD 文件引用——GH issue 是规范来源,本地 PRD 文件通常尚未提交(在 GitHub 上阅读计划的人看到本地路径可能会感到困惑)。
# Plan:Source PRD: <以下形式之一:>
- 涉及 GH:
#123 — https://github.com/<org>/<repo>/issues/123 ("Title")- 纯本地:
.agents/plans/<slug>-prd.md
架构决策
适用于所有阶段的长期决策:
- Routes:...
- Schema:...
- Key models:...
- i18n:使用的命名空间/范围、可复用的键引用(来自第 3.5 步;如果没有面向用户的字符串或不涉及 i18n,则省略)
- (根据需要添加/删除章节)
阶段 1:<标题>
用户故事:<来自 PRD 的列表>
已知风险:<第 6c 步中列出的原因——仅适用于因不可消除风险例外而被接受且得分低于 9 的阶段;其他情况省略此行>
要构建的内容
简要描述此垂直切片。描述端到端行为,而不是逐层说明实现。
验收标准
- 标准 1
- 标准 2
- 标准 3
阶段 2:<标题>
用户故事:<来自 PRD 的列表>
要构建的内容
...
验收标准
- ...
8. 发布到 GitHub(仅当涉及 GH 时)
如果在仅本地模式下操作,则完全跳过此步骤。
步骤 8 — 确定操作,根据步骤 7c 的处理结果:
- 创建 — 不存在现有子议题(首次发布,或重新调用矩阵中的“重新发布现有文件”)。遵循步骤 8a–8e。
- 更新 — 应原地更新现有子议题(来自重新调用矩阵中的“更新子议题正文”分支)。跳过 8b–8e,仅遵循步骤 8f。
步骤 8a — 确认环节:
- 创建路径:
Ready to create sub-issue under #<parent> from <path>. Review the file (and edit if needed), then reply 'create' to proceed, or 'cancel' to stop. - 更新路径:
Ready to update existing sub-issue #<n> from <path>. Review the file (and edit if needed), then reply 'update' to proceed, or 'cancel' to stop.
等待明确确认。用户可以在确认前编辑文件。
步骤 8b — 创建子议题:
首先确保存在 plan 标签,因为如果标签不存在,gh issue create --label plan 会因 HTTP 422 而失败:
gh label create plan \
--color bfd4f2 \
--description "Phased implementation steps and technical rollout details" \
2>/dev/null || true
此操作具有幂等性:如果标签已存在,gh label create 会报错,而 2>/dev/null || true 会忽略该错误,因此已有的 plan 标签会保持不变。不要添加 --force — 这会覆盖现有标签的颜色和描述。如果此命令因真实原因(身份验证、网络)失败,下面的 gh issue create 会显示错误。然后创建子议题:
gh issue create \
--title "Plan: <feature name>" \
--body-file <path> \
--label plan
同时获取新议题编号(用于显示)和议题的整数数据库 ID(用于步骤 8c 中的关联调用)。REST sub_issues 端点需要整数数据库 ID,而不是 GraphQL 节点 ID — 传入节点 ID 会返回 HTTP 422 is not of type 'integer'。使用以下命令获取:
CHILD_DB_ID=$(gh api /repos/<org>/<repo>/issues/<child_number> -q .id)
不要使用 gh issue view <n> --json id — 它返回 GraphQL 节点 ID(以 I_kw… 开头的字符串),端点会拒绝该 ID。
步骤 8c — 关联子议题:
gh 2.88.1 没有 --parent 标志,也没有 sub-issue 子命令。请使用 REST API。注意 -F(大写)标志 — gh api 会将 -f 的值作为字符串发送,但 sub_issue_id 必须是数字:
gh api --method POST /repos/<org>/<repo>/issues/<parent>/sub_issues \
-F sub_issue_id=<child_db_id>
失败时最多重试 3 次,并使用退避间隔:250ms、1s、3s(大多数故障是临时的速率限制或最终一致性问题)。
步骤 8d — 成功时:
- 将 `` 作为页脚追加到本地计划文件
- 向用户报告子议题 URL
步骤 8e — 故障处理:
-
创建失败(步骤 8b):本地文件完好无损。原样报告错误,并告知用户重新运行
/prd-to-plan #<parent>以重试 — 步骤 7c 中的重新调用矩阵会检测到现有文件,并提供仅发布路径。 -
重试后关联失败(步骤 8c):子议题已创建,但没有父级链接(即孤立议题)。不要自动删除。报告部分完成状态,并提供准确的修复命令:
Plan written to <path>. Sub-issue #<n> created: <url> Failed to attach as sub-issue of #<parent>: <error> To fix the relationship manually: CHILD_DB_ID=$(gh api /repos/<org>/<repo>/issues/<n> -q .id) gh api --method POST /repos/<org>/<repo>/issues/<parent>/sub_issues \ -F sub_issue_id="$CHILD_DB_ID" To start over: gh issue delete <n>, then re-run /prd-to-plan #<parent>.
步骤 8f — 更新路径(用户在步骤 7c 的重新调用矩阵中选择“更新子议题正文”时):
不执行创建和关联,而是运行:
gh issue edit <n> --body-file <path>
此操作会整体替换正文,同时保留议题编号、评论历史和子议题关系。不会添加变更日志前言 — 本地文件是唯一真实来源。
文件中已有 `` 页脚,这是首次创建时添加的;不要重复追加。成功后,只需向用户报告子议题 URL。