SDD 规格驱动开发
Spec-Driven Development:以结构化规格作为唯一真实来源,AI 编码 Agent 按规格实现,而不是靠一句自由提示词碰运气。 一句话概括:规格是源头,代码是产物。
一、什么是 SDD
1.1 定义
SDD(Spec-Driven Development)是一种 AI 辅助开发工作流:先写出一份结构化规格(目标、非目标、约束、验收标准),把它作为唯一真实来源(Single Source of Truth),再让 AI Agent 依据规格来实现代码。
1.2 三种范式的对比
| 范式 | 真实来源 | 工作方式 | 典型问题 |
|---|---|---|---|
| 传统开发 | 代码 | 人写代码,文档是附属品 | 文档滞后、知识在个人脑中 |
| Vibe Coding | 提示词 | 一句话描述,AI 自由发挥 | 结果不可控、风格漂移、反复重来 |
| SDD | 规格 | 规格约束解空间,AI 在约束内实现 | 前期投入高、需维护规格 |
1.3 为什么是现在(2026)
AI Agent 把「写代码」变得前所未有地便宜,于是「定义清楚要写什么」成了新的瓶颈:
- 代码生成成本 ↓ → 返工成本成为主要成本
- 提示词质量参差 → 输出质量方差极大
- 决策隐性化 → 设计决策散落在代码评审和生产事故里
SDD 的应对方式:把隐性的设计决策前移到规格评审阶段,在成本最低的时候做决策。
二、核心理念
2.1 Prompt-only 为何失效
| 问题 | 表现 |
|---|---|
| 缺项目上下文 | 生成的代码与既有架构冲突 |
| 缺全局约束 | 命名不统一、重复逻辑、安全策略被绕过 |
| 意图靠猜 | AI 自行脑补需求,返工率高 |
| 无法复用 | 同一需求换端(Web → App)要重新描述一遍 |
2.2 三大价值
- 可控性:规格限定了允许的解空间,AI 不会自由发挥到不可审查的规模。
- 可追溯性:每条代码都能追溯到规格条目;反过来规格变更可定位受影响代码。
- 可复用性:规格与语言无关,同一份 spec 可喂给 iOS / Android / Flutter / 后端。
2.3 质量左移
传统「测试左移」停在 CI 阶段;SDD 推动的是质量左移到规格评审:
传统: 需求 → 设计 → 编码 → 测试 → 上线 → 发现问题SDD: 需求 → 【规格评审】→ 方案 → 编码 → 测试 → 上线 ↑ 错误在这里被拦截,成本最低一份经过产品、技术、安全共同确认的规格,能在编码之前拦掉大部分设计缺陷——因为改一份 Markdown 比改十个文件便宜得多。
三、标准流程
以 GitHub Spec Kit 的实现为准,SDD 分五个核心阶段:
constitution(项目宪法,每项目一次) ↓specify(写规格:what & why) ↓ clarify(澄清模糊点,可选) ↓ plan(技术方案:how) ↓ tasks(拆解任务) ↓ analyze(跨工件一致性检查,可选) ↓ implement(执行实现) ↓ converge(评估差距,追加剩余任务)→ 循环直到 Converged3.1 命令与产出对照
| 阶段 | Spec Kit 命令 | 产出文件 | 关键约束 |
|---|---|---|---|
| 项目宪法 | /speckit.constitution |
constitution.md |
每项目一次,全局准则 |
| 写规格 | /speckit.specify |
spec.md |
只写 what & why,严禁谈技术栈 |
| 澄清 | /speckit.clarify |
补充 spec | 消解歧义(建议在 plan 之前) |
| 技术方案 | /speckit.plan |
plan.md |
此阶段才决定 how |
| 拆任务 | /speckit.tasks |
tasks.md |
有序、可勾选、标依赖 |
| 一致性检查 | /speckit.analyze |
分析报告 | 跨工件覆盖度检查 |
| 实现 | /speckit.implement |
代码 | 按 tasks 逐条执行 |
| 收敛 | /speckit.converge |
追加任务 | 循环直至 Converged |
3.2 为什么「写规格时不准谈技术栈」
这是 SDD 最重要的一条纪律:把「要什么」和「怎么做」彻底分开。
- 如果在 spec 阶段就写「用 Redis 做缓存」,等于提前锁死了方案,探索其他解的空间被关闭;
- 分开之后,同一份 spec 可以生成多套 plan(性能优先版、成本优先版、可维护优先版),对比后再选。
这条纪律的价值在于:需求是稳定的,实现是可替换的。混在一起写,需求变更会污染方案,方案变更会污染需求。
四、规格的分层结构
实践中团队收敛出的四层结构:
specs/001-feature/├── spec.md # 需求:用户可见行为、验收标准、non-goals├── plan.md # 方案:架构、数据模型、关键权衡├── data-model.md # 数据模型细节├── tasks.md # 有序任务清单└── contracts/ # 契约:OpenAPI / JSON Schema / Gherkin4.1 spec.md 必备要素
| 要素 | 说明 | 反例 |
|---|---|---|
| 目标 | 一句话说明这个功能解决什么问题 | 「做一个收藏功能」(太泛) |
| 用户可见行为 | 用户能看到、能操作什么 | 「后端存到 Redis」(用户不可见) |
| 验收标准 | 逐条可测试的检查项 | 「体验流畅」(不可测) |
| Non-goals | 明确不做什么 | 缺失 → AI 会自行扩大范围 |
| 约束 | 技术栈、需遵循的既有模式、禁止改动的文件 | 缺失 → AI 动不该动的代码 |
| Open questions | 未决问题集中列出 | 缺失 → AI 悄悄替你决定 |
Non-goals 是 spec 里最容易被忽略、又最有价值的一节。它直接封住了 AI「顺手多改一点」的倾向。
4.2 验收标准的写法
好的验收标准是可机械验证的:
## 验收标准- [ ] 已登录用户在详情页点击「收藏」,按钮变为「已收藏」- [ ] 未登录用户点击收藏,跳转登录页并携带 redirect 参数- [ ] 重复点击收藏返回 code=1001(已收藏),不产生重复记录- [ ] 收藏列表按收藏时间倒序,分页每页 20 条- [ ] 取消收藏后,详情页按钮恢复为「收藏」坏的例子:
- [ ] 收藏功能好用 ← 不可测- [ ] 性能良好 ← 不可测,应改为「列表接口 P95 < 300ms」4.3 契约层
契约是「规格 → 代码」之间可被机器校验的桥梁:
| 类型 | 用途 |
|---|---|
| OpenAPI 3.1 | HTTP 接口结构与 Schema |
| JSON Schema | 请求/响应体校验 |
| Protobuf | gRPC 接口 |
| Gherkin / Cucumber | 行为场景 |
| Pact | 消费者驱动的契约测试 |
五、工具生态(2026)
| 工具 | 形态 | 特点 |
|---|---|---|
| GitHub Spec Kit | 开源工具包(MIT) | 13 万+ stars,38 个 Agent 集成(Copilot / Claude Code / Cursor / Codex / Gemini / Kiro / Zed…),157 个社区扩展;核心流程开箱可用 |
| Amazon Kiro | Agentic IDE | 规格原生,自动产出 requirements / design / tasks;用 EARS 语法写验收标准 |
| Tessl | 规格注册表 + 工具链 | 用 @test 注解从规格直接生成测试套件 |
5.1 Spec Kit 安装与初始化
# 依赖:Python 3.11+、uvuv tool install specify-cli# 初始化项目(以 Copilot 为例)specify init my-project --integration copilotcd my-project# 查看所有可用集成specify integration list换成
--integration后面的值即可切换 Agent(claude / cursor / codex / gemini 等), 规格工件与 Agent 无关,换工具不用重写规格——这是 Spec Kit 的核心卖点(无锁定)。
5.2 Spec Kit 的三种流程入口
Spec Kit 并非只有 SDD 一条路,它提供三个独立的入口(不是三个必走的阶段):
| 流程 | 用途 | 命令序列 |
|---|---|---|
| 规格驱动开发 | 开发新功能/应用 | constitution → specify → plan → tasks → implement → converge |
| Bug 修复 | 诊断与修复缺陷 | bug-assess → bug-fix → bug-test |
| 想法评估 | 判断一个想法值不值得投入 | assess-intake → research → define → shape → decide |
Bug 修复流程值得单独说明——它刻意把「诊断」「修复」「验证」三步分开,避免 Agent 直接改代码而不查根因:
specify extension add bug/speckit-bug-assess "提交空密码时登录页崩溃" slug=login-crash/speckit-bug-fix slug=login-crash/speckit-bug-test slug=login-crash最终判定为 verified / partial / failed 三档——缺少验证不算修复成功。
六、实战示例:走一遍完整流程
以「旅游线路收藏」功能为例(多端项目场景)。
6.1 阶段一:项目宪法
/speckit.constitution制定以下项目原则:- 代码质量:遵循项目既有分层(Controller → Service → Repository),不跨层调用- 测试:新增业务逻辑必须有单元测试;接口必须有契约测试- 一致性:所有接口返回统一格式 { code, message, data },错误码集中定义- 安全:所有写操作必须鉴权;用户只能操作自己的数据- 可维护性:单函数不超过 50 行;不新增依赖需说明理由产出 constitution.md,后续所有功能都受它约束。
6.2 阶段二:写规格(只谈 what & why)
/speckit.specify为线路详情页增加「收藏」能力。## 目标让用户能把感兴趣的线路存起来,稍后在「我的收藏」里查看。## 用户可见行为- 线路详情页显示「收藏」按钮,已收藏时显示「已收藏」- 点击收藏/取消收藏后,按钮状态即时变化- 「我的收藏」页面按收藏时间倒序展示线路卡片- 收藏列表支持分页## 验收标准- [ ] 已登录用户点击收藏 → 按钮变为「已收藏」,再次点击恢复- [ ] 未登录用户点击收藏 → 跳转登录页,登录后回到原页面- [ ] 重复收藏同一线路不会产生重复记录- [ ] 「我的收藏」列表按收藏时间倒序,每页 20 条- [ ] 取消收藏后,该线路从列表移除## Non-goals(本次不做)- 不做收藏分组 / 标签- 不做收藏数展示与排行- 不做收藏分享- 不改动现有线路列表与下单流程## 约束- 遵循既有分层结构与统一响应格式- 不得修改 `OrderService` 相关代码- 移动端与 PC 端表现一致## Open questions- 收藏上限是否需要限制?(暂定不限,待产品确认)6.3 阶段三:澄清
/speckit.clarifyAgent 会追问,例如:「收藏是否需要软删除?」「列表接口是否需要返回线路的实时价格?」——这些答案回填进 spec,而不是让模型自行决定。
6.4 阶段四:技术方案
/speckit.plan技术选型:- 新增 line_favorite 表:id, user_id, line_id, created_at,user_id+line_id 建唯一索引- 新增 FavoriteController / FavoriteService / FavoriteRepository,遵循现有分层- 接口:POST /api/favorites、DELETE /api/favorites/:lineId、GET /api/favorites?page=1- 收藏状态在详情页接口中附带返回 isFavorited 字段- 前端:复用现有卡片组件;Vue 端用 Pinia 管理收藏状态,uni-app 端用同一套 API 封装产出 plan.md + data-model.md。
关键点:同一份 spec 可以产多套 plan。比如还可以生成一套「用 Redis 缓存收藏状态降低详情页延迟」的性能优先方案,对比后择优。
6.5 阶段五:拆任务
/speckit.tasks产出示例([P] 表示可并行):
- [ ] T1 创建 line_favorite 表与迁移脚本- [ ] T2 [P] 定义 Favorite 实体与 Repository- [ ] T3 实现 FavoriteService(收藏 / 取消 / 列表 / 批量查状态)- [ ] T4 [P] 实现 FavoriteController 与路由注册- [ ] T5 详情页接口附带 isFavorited 字段- [ ] T6 [P] 前端 API 封装(favorites.ts)- [ ] T7 PC 端详情页收藏按钮- [ ] T8 [P] uni-app 端详情页收藏按钮- [ ] T9 「我的收藏」列表页(分页)- [ ] T10 单元测试:Service 层收藏去重逻辑- [ ] T11 契约测试:三个接口的响应结构6.6 阶段六:实现与收敛
/speckit.implementAgent 按 T1 → T11 顺序执行,每个任务完成即打勾。执行完后:
/speckit.convergeconverge 会拿代码库对照 spec / plan / tasks,找出遗漏项并追加为新任务,循环直到报告 Converged。
这一步是 SDD 相对纯 Prompt 开发的关键差异:它有一个独立的"自查差距"环节,而不是靠人肉眼比对。
七、三个失败模式(比宣传材料更重要)
这是实践者跑了一个月真实产品后总结的教训。
7.1 Spec drift(规格漂移)
现象:代码往前走了,规格没跟上。两周后规格开始主动误导人——新人和 AI 都会相信它。
对策:
- 功能上线后若不再维护,直接删除规格;
- 陈旧的规格比没有规格更糟;
- 或用 CI 强制规格与代码对齐(契约测试失败即构建失败)。
7.2 Over-specifying(过度规格化)
现象:规格写得细到成了「散文版实现」,等于把代码写了两遍。
对策:
- 规格应约束解空间,而不是画完整张图;
- 一个自检信号:规格比它产出的 diff 还长,就是坏味道。
7.3 Review fatigue(审查疲劳)
现象:审规格 → 审方案 → 审 diff,三轮。大改动值得,中等改动会开始「盖章通过」,而盖章通过的规格会给你虚假的安全感。
对策:
- 完整仪式只留给值得的变更(大、贵、不熟悉);
- 中等改动可只做 spec + diff 两轮。
7.4 判断准则
变更超出你的脑容量时写规格;装得下就不写。
| 场景 | 是否写规格 |
|---|---|
| 单文件小修、错别字、样式微调 | ❌ 不写,写规格只是抄写 |
| 探索性试验(还不知道要做什么) | ❌ 不写,先做原型 |
| 新功能(跨多文件、跨端) | ✅ 写 |
| 大规模重构(行为不能变) | ✅ 写,重点写「必须保持不变的行为」 |
| 高风险改动(支付、权限、数据迁移) | ✅ 必须写 |
| 接手陌生代码库的改动 | ✅ 写,spec 本身就是理解过程 |
八、与 TDD / BDD / MDD 的关系
| 实践 | 核心 | 与 SDD 的关系 |
|---|---|---|
| TDD | 测试先行,验证函数级计算 | 互补:SDD 定边界(输入输出、错误码、验收标准),TDD 验内部逻辑 |
| BDD | 行为场景(Given-When-Then) | 可作为 SDD 的契约层(Gherkin) |
| MDD | 模型驱动,从模型生成代码 | 理念相近,但 SDD 面向 AI Agent 而非代码生成器 |
| 瀑布 | 阶段严格串行 | 不同:SDD 的规格是活文档,代码可从规格重新生成,不是一次性签字 |
成熟架构里的分工
SDD:定义边界 —— 契约、输入输出、错误码、验收标准TDD:验证中间 —— 领域逻辑、算法、边界条件两层配合,既保证「做的是对的东西」,也保证「东西做对了」。
九、渐进式落地路径
不要一上来全面铺开。五个层级,按需爬升:
| 层级 | 做法 | 时间 | 价值 |
|---|---|---|---|
| L1 规格即文档 | 用 OpenAPI 描述现有接口,不改任何代码,生成文档 | 第 1 周 | 消除「文档在哪」的问题;AI 很擅长从旧代码反推第一版规格 |
| L2 规格即检查关卡 | CI 加 Spectral / Redocly,强制命名规范、必填描述与示例 | 第 2-3 周 | 规格质量提升,工作流不变 |
| L3 规格即契约 | 引入契约测试(Schemathesis / Pact)跑在 CI | 第 1-2 月 | 第一次因「改字段没改规格」而构建失败时,团队才真正理解价值 |
| L4 新服务规格先行 | 新服务强制 spec PR 先于实现 PR 合并 | 第 2 月起 | 从源头保证一致性 |
| L5 规格驱动 Agent | 选一个工具(Spec Kit / Kiro / Tessl)接入 Agent 工作流 | 第 3 月起 | 本次讨论的完整形态 |
落地建议
- 从窄开始:挑一个绿地功能或一个高风险变更,不要给每个 CRUD 都写规格。
- 规格进仓库、进 CI:与代码同仓,用 PR 评审规格,用 CI 校验契约。
- 先评审规格:把资深工程师的注意力从 diff 上移到 spec 上——错规格早发现的成本远低于错合并。
- ADR 写短:每个决策一页纸,胜过一份被遗忘的 wiki。
十、常见问题(FAQ)
Q1:写规格会不会拖慢进度?
不会,只是把决策提前到成本更低的时候。设计决策本来就要做,SDD 只是把它从「代码评审或线上排障时才发现」变成「规格评审时就定下」。在 Agent 工作流里这个交换更划算:30 分钟写规格,常能省下几小时反复重问与返工。
Q2:我们的 API 变化很快,规格跟不上怎么办?
如果接口变化快到规格无法维护,那是设计稳定性问题,不是规格问题。SDD 的作用恰恰是把这种不稳定暴露出来。
Q3:生成的代码质量差怎么办?
质量杠杆在规格本身:
- 模糊的规格 → 模糊的代码
- 结构化的验收标准 → 可验证的代码
另外要区分两类生成:样板代码生成(路由、校验、类型定义)质量通常很好;业务逻辑仍需人把关。
Q4:这不就是瀑布 / MDD 回归吗?
不是。区别在于:
- 瀑布:一次性签字,文档冻结,变更代价高;
- SDD:规格是活文档,随功能演进,代码可随时从规格重新生成;规格变更的代价很低。
Q5:小团队值得吗?
值得,但要选择性使用。两人团队在绿地功能和大规模多文件重构上收益明显;对一行修复和探索性试验,写规格反而更费时间。
Q6:遗留系统能用吗?
能,而且 L1 就是为遗留系统设计的:先让 AI 从现有代码反推出一版规格,人工校正后作为基线,再逐步升级到契约与规格驱动。
Q7:Agent 说它满足了规格,怎么确认?
必须有可执行校验。「满足规格」只有在有验收测试、契约测试或 schema 校验通过时,才是一个机械可验证的事实,否则只是模型的自述。
十一、最佳实践清单
写规格时
- 只写 what & why,技术栈留到 plan 阶段
- 写明 Non-goals(不做什么)
- 验收标准逐条可测试,禁止「体验流畅」这类描述
- 未决问题集中放
Open questions,不让模型替你决定 - 规格短于它将要产出的 diff(长度是自检信号)
做方案时
- 明确列出不允许改动的文件/模块
- 关键权衡记录成 ADR(一页纸)
- 重要功能可生成多套 plan 做对比
实现与验收
- 任务拆到「一次能审查完」的粒度
- 每个任务完成即打勾,避免批量完成
- 跑
converge做差距自查 - 验收标准逐条用测试或手工验证过,不采信 Agent 的自我声明
长期维护
- 规格与代码同仓、同 PR 评审
- 契约进 CI,spec 与代码不一致时构建失败
- 功能稳定后若不再维护规格,主动删除而不是留着误导人
十二、总结
SDD 的本质是一次重心转移:
过去:程序员的价值 = 会写代码现在:程序员的价值 = 会定义清楚要写什么三条核心认知:
- 规格是源头,代码是产物——把「要什么」和「怎么做」分开,需求才能稳定、方案才能替换。
- 只有可执行校验才算合规——没有测试的「已满足规格」是自述,不是事实。
- SDD 是给大变更用的工具,不是普适流程——「变更超出脑容量才写规格」是最实用的判断标准。
对你当前的场景(多端项目 + AI 协作开发),最值得落地的两点是:
- 把已有的「先方案后改代码」规则固化成 spec / plan 工件,从口头约定升级为可追溯的文档;
- 用一份 spec 驱动多端实现(PC / H5 / 小程序 / App),从「每端分别对齐」变为「规格统一、实现分头」。
完