SDD 变更提案模板
当一个需求不能只靠一句话交给开发,但还没到写实现细节的时候,用这份模板先把行为、边界、负责人和评审证据写清楚。
# Change Proposal Owner: Status: Draft | Review | Approved Date: ## Problem - 现在什么行为不清楚、缺失或需要改变? ## Goal - 这次上线后,用户或系统必须发生什么变化? ## Non-goals - 本次明确不做什么? ## Acceptance Criteria - Given ... When ... Then ... ## Open Questions - [ ] ... ## Evidence Required - Test: - Log or metric: - Manual check: - Rollback signal:
什么时候使用这份模板
- 需求会影响多个页面、服务或角色。
- 产品或负责人需要工程在开工前确认范围。
- AI 编码代理需要一个可追溯的上下文包。
- 评审者需要先看到非目标,避免实现阶段扩范围。
填好后应该是什么样
模板只有在写入真实决策、负责人和证据后才有价值。下面是一个可评审的片段。
## Goal - 90 天内可退款的已捕获支付,不会产生重复退款。 ## Non-goals - 本次不更换支付渠道。 - 不做批量退款。 ## Acceptance Criteria - Given 同一个 idempotency key 被重复提交 When 退款接口再次收到请求 Then 返回已有 refund_id,且不发送第二条事件。
场景笔记:先把退款范围写清楚
客服团队在渠道超时后出现过重复退款,于是提出“给 checkout 加退款能力”。这个需求看起来小,真正需要先决定的是重放行为、客服权限,以及 pending 退款何时阻止二次操作。
容易出错的地方:如果提案只写“避免重复”,AI 编码代理可能只加唯一约束,却留下事件发送、客服 UI 状态和超时恢复这些关键行为。
- 评审动作:评审者应该先确认 90 天限制、幂等响应,以及批量退款不在本次范围内。
- 证据要求:最强证据是一条重放测试,加一个客服 UI 检查,证明 pending_provider_confirmation 期间不能再次退款。
怎样把模板改成真实项目内容
不要只替换标题和日期。真正有价值的版本,应该把每个占位字段都变成一个可评审决定:谁负责、什么行为必须成立、哪些范围明确不做、合并前需要看到什么证据。如果某个字段暂时无法填写,就把它保留为开放问题,而不是用含糊段落盖过去。
使用这份 spec.md 时,先写当前最可能导致返工的部分。对很多团队来说,那不是实现步骤,而是边界、例外、兼容性或发布证据。模板越早暴露这些问题,AI 编码或人工实现时越不容易顺手扩大范围。
- 推荐场景:需求会影响多个页面、服务或角色。
- 评审重点:目标是一个行为结果,而不是任务清单。
- 强写法参考:已捕获支付在 90 天内允许退款。相同 idempotency key 的重放请求返回已有 refund_id,不创建第二行记录,也不发送第二条 refund_requested 事件。
建议的评审路径
第一轮只看范围:目标是否单一,非目标是否能阻止常见扩张,影响系统是否被点名。第二轮看可验证性:验收标准是否描述了状态、触发和可观察结果,而不是“应该更好用”这类愿望句。第三轮看证据:测试、截图、日志、指标或手工检查是否能证明每条标准。
把这份模板交给 AI 编码工具前,应该先让人类评审者确认允许修改的文件、不可改动的接口、迁移顺序和停止信号。这样 AI 得到的是一份可执行规格,而不是一段看起来很完整但仍然模糊的提示词。
- 实现前:确认开放问题没有阻塞行为判断。
- 实现中:每个任务都回到这份模板里的标准或约束。
- 合并前:用证据证明结果,而不是只写“测试通过”。
实现前先检查这些点
- 目标是一个行为结果,而不是任务清单。
- 非目标至少阻止一个常见的范围扩张。
- 每条验收标准都能被测试或观察。
- 证据写明测试、日志、指标、截图或手工检查。
弱写法 vs 强写法
弱写法
允许用户退款,并确保不会重复退款。
强写法
已捕获支付在 90 天内允许退款。相同 idempotency key 的重放请求返回已有 refund_id,不创建第二行记录,也不发送第二条 refund_requested 事件。
什么时候可以认为它不是空模板
这类页面最容易变薄的地方,是只提供一个漂亮骨架,却没有说明如何判断填写质量。一个合格版本至少要能回答三件事:这个变更为什么需要现在做;哪些范围被明确排除;合并前用什么证据证明行为没有偏离。
如果你把模板用于真实工作,建议在 PR 描述里附上最终文件,并标出哪些段落在实现中发生过变化。规格不是一次性文档,它应该随着实现证据一起更新。读者复制这份模板时,也应该复制这种习惯:所有看起来像决定的内容,都要能被评审和追踪。
- 最低证据:至少一条自动化测试或契约 fixture。
- 高风险证据:补截图、日志查询、指标或回滚信号。
- 后续证据:对已知缺口写负责人和复查日期。
它在完整 SDD 包里负责什么
不要把所有内容都塞进同一个文件。spec.md 只负责它最擅长的那一层:把某一类决定写到可以评审、可以引用、可以更新的地方。范围、设计、任务和证据应该彼此连接,但不应该互相吞掉。这样做的好处是,当实现过程中发现新事实时,团队能准确知道应该更新哪一个文件。
实际使用时,可以把这份模板和相关资源串成一条很短的链路:先写规格或提案,再补设计或任务,最后把证据回填到 PR。读者复制模板时,也应该复制这条链路。单独一个漂亮模板不会提高交付质量;可追溯的文件链路才会。
如果页面被拿来做团队规范,建议在仓库里保留一个填好后的样例,而不是只放空模板。样例能告诉新成员什么算“足够具体”,也能让 AI 编码工具学习团队真正接受的边界和证据格式。
- 上游输入:明确的用户问题、系统约束和已知失败模式。
- 下游输出:可执行任务、评审问题、测试证据或发布门禁。
- 维护方式:每次实现改变决定时,同步更新对应规格文件。
FAQ
它和 PRD 有什么不同?
PRD 说明产品意图;变更提案把意图转成工程行为、验收标准和证据。
应该写多长?
多数提案一页就够。如果需要架构权衡,链接设计文档,不要把这份模板无限加长。
什么时候可以进入实现?
当评审者对范围、非目标、影响系统和合并前证据达成一致时。
相关资源
编辑说明
这份模板面向 spec-driven development 工作流,示例用于展示结构,不代表特定公司的内部流程。
- 作者: Daniel Marsh
- 编辑政策: 我们如何审阅和更新内容
建议把它放在仓库的 /docs/specs/ 或 /.specs/ 下,并在实现过程中持续更新。最后更新:2026 年 5 月 19 日。