BMAD-METHOD 实战:把计划拆成故事并持续追踪(Story Breakdown + Sprint Planning 完整工作流)
【免费下载链接】BMAD-METHODBreakthrough Method for Agile Ai Driven Development项目地址: https://gitcode.com/gh_mirrors/bm/BMAD-METHOD
导读
本指南讲解 BMAD-METHOD 中"计划落地"的核心环节:如何把一份已完成的规划(spec 或 PRD)拆解为可在一个会话内实现的故事单元,并用sprint-status.yaml追踪它们的生命周期。读完本文你将掌握两条路径的完整流程——spec 驱动的 Story Breakdown 与 PRD 驱动的bmad-create-epics-and-stories+bmad-sprint-planning,以及就绪门禁(readiness gate)、状态生成、状态查看、追踪文件修复和方向纠正(correct course)五大操作的具体命令与判定逻辑,所有结论均有仓库源码与测试佐证。
两条路径:先想清楚"拆什么"
BMAD-METHOD 把"把计划变成故事"分成两种形态,取决于你的计划是什么。原文 break-work-into-stories-and-track-it.md 用一张表给出了决策入口:
| 计划形态 | 要做的事 | 追踪产物 |
|---|---|---|
由SPEC.md支撑的单个 epic | 请bmad-spec做 Story Breakdown | 位于SPEC.md旁边的有序stories.yaml |
| 带 PRD(以及 UX 或架构)的项目 | 先运行bmad-create-epics-and-stories,再运行bmad-sprint-planning | epic 文件 +sprint-status.yaml |
路径一:spec 支撑的 epic ——stories.yaml即全部追踪
在 spec 路径下,stories.yaml是整个追踪文件,不涉及 sprint-status 文件。bmad-spec 的 "Story Breakdown" 一节明确:输出物是与SPEC.md同级的stories.yaml,通过固定文件名发现(与SPEC.md、.memlog.md同一约定),不列入companions:也不会被前端配置引用——它是"派发故事"的输入,而非下游消费的契约。
Story Breakdown 是纯交互式操作(headless 运行永远不会执行它),它逐个能力(capability)与约束(constraint)和用户对话,按"可独立评审的切片"提议故事,并为每个故事收集三个关键字段:spec_checkpoint、done_checkpoint,以及可选的invoke_dev_with派发备注——这正是"开发者可照着实现"的来源。字段定义、合法性与校验规则见 assets/stories-schema.md。构建流程会把每个故事的实现记录写到 spec 文件夹下,而 Finish an Epic 把stories.yaml当作清单来读取。
路径二:PRD 项目 —— epic 文件 + sprint-status
对完整项目,bmad-create-epics-and-stories以"产品合伙人"身份与用户协作,把 PRD 的需求和架构决策转化为按用户价值组织的 epic 文件,每个故事都带有开发者可以对照实现的验收标准。该技能采用步骤文件架构(step-file architecture):按 step-01-validate-prerequisites.md → step-02-design-epics.md → step-03-create-stories.md → step-04-final-validation.md 顺序执行,每次只加载一个步骤文件,不允许跳步,最终文档通过 frontmatter 的stepsCompleted数组记录进度(见 SKILL.md 的 WORKFLOW ARCHITECTURE 一节)。
本文之后的所有内容都围绕路径二展开。
就绪门禁(Readiness Gate):用"老手读交接单"的眼光审计划
bmad-sprint-planning运行在规划与实现的分界线上。在任何追踪文件存在之前,它先像一位持怀疑态度的资深开发者在读交接单那样审视计划。关键点在于(见 references/readiness-gate.md):
- 按内容盘点,不按文件名:它扫描
{planning_artifacts}与{project_knowledge},识别 brief、PRFAQ、PRD、spec、UX 产出、架构、epics 等文档——靠"读内容判断是什么",而不是靠文件名模式匹配,因为不同项目的产物组合与命名各不相同。 - 只问一个问题:开发者能否实现这些 epic,而无需凭空发明任何没有记录在案的决策?
具体的评审维度包括:意图文档中的需求与决策能向前追溯到故事,故事也能回溯到已记录的意图(双向检查孤儿);epic 交付用户价值且没有前置依赖,故事彼此独立可完成;故事依赖的架构与 UX 决策有记录而非假设;产物之间的冲突(如 spec 与 epic 意见不一)被显式暴露而非默默解决。
判定与处理
- PASS—— 一句话给出结论;若是完整 sprint-planning 意图,继续进入生成追踪阶段。
- CONCERNS—— 简要列出每个缺口所在位置,询问用户是继续还是先修复。
- FAIL—— 按严重程度排序给出发现,为每个发现指名能修复它的技能(相关规划技能,或跨切变更用
bmad-correct-course),并提供将发现保存为{planning_artifacts}/implementation-readiness.md的选项,然后停止。
注意:缺失某种文档类型只有在其内容被故事依赖时才构成发现——没有 UX 文档、也没有 UI 故事的纯后端项目完全没问题。
触发方式:说 "check implementation readiness" 只运行门禁;Product Manager 与 Architect 菜单上的IR触发器效果相同。在 SKILL.md 的 On Activation 中,readiness 是五种意图之一:只加载references/readiness-gate.md、跑门禁、报告、停止。
生成追踪:sprint_plan.py generate的确定性部分
门禁通过后,同一个技能继续生成sprint-status.yaml。这里体现了 BMAD-METHOD 的职责切分哲学——SKILL.md 开篇就说:"你的判断力用在脚本无法处理的地方:决定哪些文件是 epic、权衡就绪度、调和脚本标记的问题";而解析 epic、派生 key、合并状态、写入sprint-status.yaml这些是确定性工作,交给脚本。
发现 epic 文件是你的判断
先生成追踪时,epic 文件通常是epics.md、epic-*.md,或是{planning_artifacts}下的分片epics/文件夹——但依然以内容为准。如果整份文档和分片版本同时存在,询问用户哪份是当前的,而不是猜。
generate 命令与参数
uv run {skill-root}/scripts/sprint_plan.py generate \ --epic-file <path> [--epic-file <path> ...] \ --status-file {implementation_artifacts}/sprint-status.yaml \ --stories-dir {implementation_artifacts} \ --project "{project_name}" --date "{date}"可追加的参数(来自 sprint_plan.py 的build_parser(),第 710–737 行):
| 参数 | 作用 |
|---|---|
--project-key | 覆盖/设置project_key字段,默认NOKEY |
--tracking-system | 覆盖/设置追踪系统标识,默认file-system |
--story-location | 覆盖/设置故事文件位置,默认取--stories-dir |
--dry-run | 只报告不同步情况,不写入任何文件 |
--fresh | 无视既有状态做一次干净重建(修复路径使用) |
--set KEY=STATUS | 应用用户确认的显式状态,是唯一允许降级的路径 |
{date}必须是MM-DD-YYYY HH:MM格式——这是过期检查(staleness check)解析的格式(脚本中DATE_FORMAT = "%m-%d-%Y %H:%M";同时接受%Y-%m-%d %H:%M与%Y-%m-%d两种手写漂移格式)。
脚本到底做了什么(源码级)
从 sprint_plan.py 的cmd_generate(第 372–468 行)可以看到完整的确定性链条:
- 解析:
parse_epics()(第 170–209 行)用两条正则识别标题——EPIC_RE(## Epic 1:形态)与STORY_RE(### Story 1.1:形态),支持2.6a这类拆分故事编号;代码围栏(```/~~~)内的内容被跳过;"长得像 Epic/Story 但解析失败"的标题会进入warnings供 LLM 处理。 - key 派生:故事 key 形如
1-1-user-authentication(epic序号-故事序号-slug)。_slug()(第 131–140 行)是Unicode 感知的:非拉丁标题会保留自身字符而不是塌缩成同一个占位符;纯标点/emoji 标题则退化为 8 位内容哈希,保证 key 确定性且互不重复。 - 合并(绝不降级):
_merge_status()(第 240–252 行)比较计算值与既有值,按状态等级取更高者——backlog(0) < ready-for-dev(1) < in-progress(2) < review(3) < done(4)(故事),epic 为backlog(0) < in-progress(1) < done(2),retro 为optional(0) < done(1)(第 57–60 行)。 - legacy 归一化:v6 时代的
drafted/contexted在每次读取时被映射为现代含义(drafted→ready-for-dev、contexted→in-progress,第 66 行),报告但永不重置——所以旧文件既不会被判非法也不会丢失进度。 - 故事文件检测:
--stories-dir下存在{key}.md的故事,其状态会被托底到ready-for-dev(第 278–279 行),并记入报告upgraded_from_disk。 - 安全写入:原子写(临时文件 +
fsync+os.replace),保留原文件权限位;写后回读校验development_status与关键字段,校验失败则原子恢复原文件字节(第 325–350、443–467 行)。 - 只输出 JSON:无论成败,stdout 只输出 JSON——连 argparse 错误都是 JSON(
JsonArgumentParser.error(),第 116–128 行),保证机器可消费。
读 JSON 报告并行动(判断力重新登场)
报告的in_sync、new_entries、dropped_orphans、illegal、legacy_mapped、upgraded_from_disk字段回答了"追踪是否同步":
warnings中出现未解析的 Epic/Story 类标题 → 展示给用户,一起修正标题后重跑;dropped_orphans是旧文件中与现有 epics 匹配不上的条目(通常是改名),每条都携带旧状态 → 与用户对账后,用--set <新key>=<旧状态>重跑移植;- 若 epic 格式彻底超出正则能力 → 退回到对照 sprint-status-template.yaml 手工构建文件,并明确告知确定性路径不适用。
重新生成是安全的:已完成的工作保持完成、action items 与手写注释原样穿过、--dry-run只报告漂移不写入。这也是 epic 变更后随时刷新追踪的方式。
状态词汇表(sprint-status.yaml 的完整契约)
sprint-status-template.yaml 定义了完整词汇,脚本内嵌的HEADER_COMMENT(sprint_plan.py 第 77–108 行)与之逐字节一致,且测试套件断言两者永不漂移:
- Epic 状态:
backlog(未开始)、in-progress(进行中)、done(全部故事完成); - Story 状态:
backlog(只存在于 epic 文件)、ready-for-dev(故事文件已创建)、in-progress(开发中)、review(实现完成待评审)、done(完成); - Retrospective 状态:
optional(可选完成)、done(已完成); - Action Item 状态:
open(已承诺未处理)、in-progress(处理中)、done(完成)。
工作流要点也写在模板里:epic 在其首个故事开始时自动转in-progress(由 build 的 sprint 同步完成);开发者通常在上一故事done之后创建下一故事以吸收经验;开发把故事移入review后运行 code review(建议用全新上下文、不同 LLM)。时间戳统一用MM-DD-YYYY HH:MM。测试夹具 test_sprint_plan.py 中的EPICS_FIXTURE直观展示了输入 epic 文件的规范格式。
查看状态:'show sprint status'
说 "show sprint status"(或 "where are we")会跳过门禁直接看现状。命令:
uv run {skill-root}/scripts/sprint_plan.py status \ --status-file {implementation_artifacts}/sprint-status.yaml --date "{date}"--stale-days可调过期阈值,默认 7 天(STALE_DAYS_DEFAULT = 7)。脚本计算出(见cmd_status,sprint_plan.py 第 482–618 行):
- 各状态计数(故事/epic/retro 分开统计,legacy 值透明映射并在
legacy_mapped中报告); - 风险标志:文件过期(stale)、孤儿故事(有故事 key 但无对应 epic 条目)、进行中的 epic 却没有故事、等待评审的故事(提示运行
bmad-code-review)、未识别 key; - 来自回顾的未处理 action items(
open与in-progress); - 一条推荐的下一步动作及其故事 key。
下一步推荐的固定优先级
推荐动作遵循固定优先级(sprint_plan.py 第 559–591 行),与原文档一致:
- 恢复进行中的工作(
bmad-build,取第一个in-progress故事); - 评审等待中的内容(
bmad-code-review,取第一个review故事); - 开始下一个就绪故事(
bmad-build,取第一个ready-for-dev); - 开始第一个 backlog 故事(
bmad-build,取第一个backlog); - 运行未完成的回顾(
bmad-retrospective,当故事全部完成而epic-N-retrospective仍为optional); - 全部完成(无推荐)。
刻意不提供时间估算——只有状态、风险与下一步。渲染时若脚本报错(YAML 损坏、手工改坏结构等),不要停在错误上:自己读sprint-status.yaml用最佳判断给出同样的摘要,说明确定性路径失败的原因,并引导走修复流程。
修复追踪文件:validate 与 fix
validate:只检查,不改动
说 "validate sprint status" 检查文件格式而不改动它:
uv run {skill-root}/scripts/sprint_plan.py validate \ --status-file {implementation_artifacts}/sprint-status.yaml不写文件,无论是否合法都以 0 退出(详见 references/validate.md)。校验内容:文件存在性、YAML 可解析性、顶层是否为映射、必需 key(generated/last_updated/project/development_status)、时间戳格式、key 语法(epic-N、N-M-slug、epic-N-retrospective)、状态是否属于该类型的合法词汇、action_items是否为结构合法的列表(见cmd_validate,sprint_plan.py 第 621–707 行)。若legacy_mapped非空,说明文件仍在使用 v6 状态名,任何重新生成都会把它们改写为现代词汇——无论哪种方式进度都被保留。
fix:先推断真相,再让用户确认,最后写干净
说 "fix sprint status" 处理文件损坏或与现实漂移的情况。核心纪律是:推断决定状态"应该"是什么,用户确认,脚本写入;未经确认绝不写入(references/fix-sprint-status.md)。六步流程:
- 评估损坏范围:跑
validate并共享结果;若 epic 文件本身缺失或不可解析,直接说明——在规划产物存在之前没有可重建的对象。 - 并行推断真实状态:派出多个子代理并行收集证据,各自返回带证据的
key=status提议——epic 文件(权威工作分解)、故事文件(磁盘上有哪些、内容透露的进度)、git 历史与代码(引用故事 key 的提交)、以及当前文件本身(抢救一切可信内容,尤其action_items)。 - 汇合成一张提议状态表:key → 提议状态 → 证据 → 不确定项。证据冲突或单薄时倾向更低的状态并标记——"虚假的 done 比虚假的 in-progress 代价更高"。
- 与用户确认:展示表格,高亮所有与当前文件不同的条目(尤其是降级)和低置信度判断;Headless 模式不确认,直接以
blocked状态停住。 - 写干净文件:一条命令,基于已确认的表格:
uv run {skill-root}/scripts/sprint_plan.py generate \ --epic-file <path> [...] \ --status-file {implementation_artifacts}/sprint-status.yaml \ --stories-dir {implementation_artifacts} \ --project "{project_name}" --date "{date}" \ --fresh --set <key>=<status> [--set <key>=<status> ...]--fresh干净重建文档(规范词汇、标准头部)但保留action_items;--set应用已确认状态,且是唯一允许降级的路径——只有与 fresh 默认值不同的已确认条目才需要--set。 6.验证:再跑validate(期望valid: true),并给出状态视图摘要让用户看到修复后的样子。
修复是唯一能把故事标记为"比原来更不完整"的路径,因为它反映的是经确认的现实。
兼容旧名称
旧名称仍然可用:bmad-check-implementation-readiness与bmad-sprint-status都会转发到这里。任何_bmad/custom/bmad-sprint-status.toml覆盖项需迁移到bmad-sprint-planning.toml。
纠正方向(Correct Course):变化大到单故事装不下时
运行bmad-correct-course的场景:需求被证明是错的、架构决策必须改变、或依赖发生了变化。它会读取 PRD、epics、架构与 UX 文档,评估影响,产出一份sprint 变更提案——什么变、什么不变、按什么顺序变。批准后,它更新sprint-status.yaml并把文档编辑移交出去;应用这些编辑后,再创建新增或变更的故事。
bmad-correct-course/SKILL.md 的流程细节:提案文档默认写到{planning_artifacts}/sprint-change-proposal-{date}.md,包含五节——问题摘要、影响分析(epic/故事/产物冲突/技术影响)、推荐路径(直接调整 / 潜在回滚 / MVP 复审)、详细变更提案(每个都带 old → new 与理由)、实现移交。变更按范围分三类路由:Minor(开发者直接实现)、Moderate(需要 backlog 重组,PO/DEV 协作)、Major(需要 PM/架构师参与的根本性重规划)。PRD 与 epics 是必需输入,缺一则 HALT;交互模式支持 Incremental(逐条审批)与 Batch(一次性审阅)两种模式。
已完成的工作保持已完成——correct course 不会把 done 的故事打回。对于大规模重构,更推荐对受影响的 epic 重新运行 Story Breakdown 或bmad-sprint-planning。
接下来做什么
- 用
bmad-build逐故事实现; - 当决策稳定后,改用
bmad-build-auto进入自主开发循环; - 实现过程中,build 会通过 sprint 同步把故事状态写回
sprint-status.yaml,code review 把故事推进到review(见模板 WORKFLOW NOTES),而 bmad-retrospective 使用与sprint_plan.py相同的 key 语法读写同一文件、把 action items 追加进action_items段——这正是状态视图能持续浮现"来自回顾的未处理项"的原因; - 当 epic 的故事全部完成,用 Finish an Epic 收尾关闭。
整个闭环(bmad-create-epics-and-stories产出 epic →bmad-sprint-planning门禁与追踪 →bmad-build推进 →bmad-retrospective沉淀 →bmad-correct-course纠偏)形成了一个可审计、可恢复、状态永不倒退的交付追踪体系:判断力始终留给人与 LLM,而解析、合并、校验这些"确定性苦活"全部由 sprint_plan.py 以原子写入、JSON 输出、绝不降级的方式可靠完成。
【免费下载链接】BMAD-METHODBreakthrough Method for Agile Ai Driven Development项目地址: https://gitcode.com/gh_mirrors/bm/BMAD-METHOD
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考