一、SDD:一种让 AI 先读规范再写代码的方法论
SDD(Specification-Driven Development,规约驱动开发)的核心主张很简单:先写规范,再写代码——所有实现必须从规范推导而来,规范是系统的唯一事实源。
这个理念本身并不新鲜。API-first、Design-first 都是类似思路。SDD 的不��之处在于,它是专门为 AI 辅助开发 设计的——通过结构化的规范文档来约束 LLM 的行为,让 AI 不再"自由发挥",而是"按规范执行"。
二、speckit:五阶段流水线
speckit 是 SDD 方法论的开源参考实现,提供了一套完整的 Claude Code 命令工具链。它将开发过程强制划分为五个顺序执行的阶段:
Constitution(宪法)→ Specify(规约)→ Plan(计划)→ Tasks(任务)→ Implement(实现)
| 阶段 | 产物 | 作用 |
|---|---|---|
| Constitution | constitution.md | 定义项目不可变的架构原则和约束,所有后续阶段必须遵守 |
| Specify | spec.md | 用自然语言 + 结构化模板描述功能需求、验收标准、成功标准 |
| Plan | plan.md | 基于 Spec 生成技术方案,包含架构决策、组件划分、依赖关系 |
| Tasks | tasks.md | 将 Plan 拆解为有序的实施任务列表,每个任务有明确的输入输出 |
| Implement | 代码 | 按 Tasks 逐个实现,每个任务完成后校验是否符合规范 |
2.1 Constitution:项目宪法
Constitution 是 speckit 最有特色的设计。它扮演"项目宪法"的角色:
- 所有后续阶段产物必须遵守 Constitution 中定义的原则
speckit.plan命令会加载 constitution.md 做合规检查speckit.analyze命令将 Constitution 冲突自动标记为 CRITICAL 级别- 通过 Governance 章节规定修订流程,版本语义化管理
这个设计的出发点很好——给 LLM 一个"不可违背的约束集合",防止 AI 在生成方案和代码时偏离项目的核心架构原则。
2.2 阶段顺序约束:双层保障
speckit 通过脚本前置检查 + 命令模板内流程约束两层机制,确保阶段不被跳过:
脚本层:不同阶段使用不同的前置脚本。/speckit.specify 使用 create-new-feature.sh 创建分支和目录;/speckit.plan 使用 setup-plan.sh 初始化方案模板;/speckit.tasks、/speckit.implement、/speckit.analyze 通过 check-prerequisites.sh 检查前序产物是否存在。
命令模板层:每个命令明确要求加载前序产物作为输入:
| 命令 | 必须加载的前序产物 |
|---|---|
/speckit.specify | spec-template.md |
/speckit.plan | constitution.md + spec.md |
/speckit.tasks | spec.md + plan.md(+ 可选产物) |
/speckit.implement | tasks.md + plan.md(+ 可选产物) |
/speckit.analyze | spec.md + plan.md + tasks.md + constitution.md |
值得注意的是,Implement 阶段并不直接加载 spec.md 和 constitution.md——需求和原则约束仅通过 tasks.md 和 plan.md 间接传递,这意味着信息衰减不可避免。
2.3 三个核心理念
speckit 代表的 SDD 方法论可以归纳为三个核心理念:
- 规范即代码:Spec 文档的详细程度接近代码本身,是系统行为的权威描述
- 宪法最高权威:Constitution 是不可违背的约束,所有阶段产物必须与之对齐
- 强制线性:五个阶段通过脚本前置检查强制顺序执行
三、上下文窗口:speckit 绕不开的物理极限
speckit 的每个阶段都通过 command(命令模板)实现——本质上是一段注入 LLM 对话的 Markdown 指令。每次调用阶段命令时,命令模板 + 前序产物会被注入到 LLM 的上下文中,与用户输入、项目代码共同竞争有限的上下文窗口。
3.1 窗口里到底装了什么?
以 /speckit.implement 为例:
graph TB
subgraph CTX["LLM 上下文窗口(固定容量)"]
direction TB
A["命令模板(~200 行)<br/>阶段指令 + 执行步骤 + 校验规则"]
B["必需产物<br/>tasks.md + plan.md"]
C["可选产物<br/>data-model.md + contracts/<br/>+ research.md + quickstart.md"]
D["项目代码上下文<br/>需要读取和修改的源文件"]
E["对话历史<br/>本轮交互的累积上下文"]
end
style A fill:#ff9999
style B fill:#ffcc99
style C fill:#ffcc99
style D fill:#99ccff
style E fill:#cccccc
红色是"约束开销"——每次必须占用;橙色是"产物开销";蓝色才是"有效信息"——真正帮助 LLM 做出正确决策的代码上下文。约束和产物占据的空间越大,留给实际代码的空间越小。
3.2 阶段推进,窗口压力递增
graph TD
S1["Constitution<br/>命令模板 + constitution 模板<br/>窗口占用:低"]
S2["Specify<br/>命令模板 + spec-template<br/>窗口占用:低"]
S3["Plan<br/>constitution + spec.md<br/>窗口占用:中高"]
S4["Tasks<br/>spec.md + plan.md + 可选产物<br/>窗口占用:中高"]
S5["Implement<br/>tasks.md + plan.md + 可选产物<br/>+ 大量代码读写<br/>窗口占用:高"]
S1 --> S2 --> S3 --> S4 --> S5
style S1 fill:#c8e6c9
style S2 fill:#c8e6c9
style S3 fill:#ffcc80
style S4 fill:#ffcc80
style S5 fill:#ef9a9a
Implement 阶段的窗口压力最大,原因有二:一是 tasks.md 通常比 spec.md 更长(展开的详细任务列表),二是 implement 还需要大量读写实际代码文件。
3.3 窗口溢出的四个症状
| 现象 | 原因 |
|---|---|
| AI 生成的代码不符合 Constitution 原则 | Implement 阶段不加载 constitution.md,原则约束仅通过 plan.md 间接传递,信息衰减不可避免 |
| Implement 阶段产出与 Spec 不一致 | Implement 不直接加载 spec.md,需求信息仅通过 tasks.md 间接传递,细节丢失 |
| 多步骤流程后期质量下降 | 执行多个 task 时对话历史累积,命令模板中的执行规则在窗口中的"权重"逐轮稀释 |
| 复杂项目几乎无法使用 | 仅"理解现有代码"就需要大量窗口,留给约束和产物的空间不够 |
四、speckit 的价值与局限
值得借鉴的设计
- Constitution 机制:给 AI 一个不可违背的约束集合,这个思路在任何 AI 辅助开发场景都有价值
- 阶段门控:通过脚本 + 模板双层机制确保流程不被跳过,降低了 AI"跳步"的风险
- Analyze 命令:提供了一个独立的质量审查阶段,可以对全部产物做一致性检查
核心局限
- 上下文窗口是物理极限:再精妙的流程设计,也无法绕开 LLM 上下文窗口的容量限制。当产物 + 约束占据过多窗口空间时,留给实际代码的空间不足,AI 输出质量必然下降
- 信息间接传递导致衰减:Implement 不加载 spec 和 constitution,需求和原则通过 plan/tasks 间接传递,细节丢失是结构性问题
- 强制线性 vs 真实开发的非线性:speckit 假设需求稳定、方案一次成型。虽然提供了
/speckit.clarify处理歧义,但一旦进入 Plan 阶段就没有回头修正 spec 的机制 - 缺少"理解现有系统"的阶段:对于存量项目,每个需求的第一步都是"摸清现状",speckit 没有这个阶段
五、总结
speckit 是一个有思想的工具。它试图用"规范文档"来驯服 LLM 的不确定性,用"强制线性流程"来保证工程质量。在新项目、需求清晰、复杂度可控的场景下,它确实能带来结构化的开发体验。
但 LLM 的上下文窗口是一个硬约束。speckit 的"全量加载前序产物"策略,在复杂项目中会导致约束和产物挤占代码上下文的空间,最终反而降低 AI 输出质量。这不是 speckit 的 bug,而是当前 LLM 架构下所有"重文档"方法论都会面临的结构性矛盾。
理解这个矛盾,才能更好地在实践中取舍。