> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# SDD 规格驱动开发简明教程
- URL: https://www.hubwiz.com/blog/sdd-concise-tutorial/
- Published: 2026-05-12T01:28:11.000Z
- Updated: 2026-10-13T15:57:38.000Z
- Description: 五种具有不同生命周期的规格文档类型 — 以及为什么"维护所有文档"是对"规格束之高阁"问题的错误答案。
- Author: admin
- Tags: CODING AGENT, #Import 2026-10-14 14:41

周五，六点。一位开发者在用编码智能体完成一个冲刺后合上了笔记本电脑。三十个生成的Markdown文件与通过代码审查并部署到生产环境的代码并排而立。

两周后，他回到了同一个功能。那些文件中没有一份反映现实。智能体添加了验证，有人在热修复中引入了租户作用域，一个库更改了其签名。**上一个冲刺的Markdown已经是考古学了。**

这并非因为他缺乏纪律性。**这是他在不知不觉中选择的架构所固有的特征。**

> *"我认为构建软件最困难的部分是对这个概念构造的规格说明、设计和测试，而不是表示它的劳动。"*

规格束之高阁不是纪律失败。它是大多数团队从未有意识地做出的架构决策的后果。**正确的答案不是维护一份文档 — 而是将规格说明拆分为五种具有不同生命周期的文档类型。** 这就是本文的主题。

## 1、PRD、SRS和LLD是为人类编写的

LLM需要不同的信息架构。

当你写下"系统应该对用户进行身份验证"时，你的团队成员知道你的意思。你们使用Postgres，你们切换到了JWT，三月份的一条Slack讨论决定了用Auth0。这个人能读懂言外之意，有疑问时会在咖啡机旁询问。

LLM没有咖啡，也没有Slack。**智能体根据其训练数据中的统计分布来选择OAuth、JWT还是会话cookie** — 偏向于2023年GitHub上流行的任何东西。这不是模型缺陷。这是接收者本质上的差异。

PRD、SRS和LLD是委员会时代的遗产。模糊性在它们中是一种特性 — 它为协商、走廊澄清和演示后的修订留下了空间。这些文档假设存在**隐性知识**：团队中填补空白的未成文知识。而给LLM的规格说明不能假设任何东西。

![两栏对比图，展示了为人类编写的PRD文档与LLM规格说明的根本区别：前者容忍模糊性，后者要求明确性。](https://www.hubwiz.com/blog/content/images/2026/05/1-j2-J3Wj1GNGar8S3X1laZw.png)

*PRD与LLM规格说明的对比 — 这不是风格上的差异，而是本质上的差异。右栏中的每一层都关闭了一个缺口，而在左栏中，这些缺口默认由人类来填补。*

关键洞察：**这不是关于一个更好的PRD版本。** 而是关于一个完全不同类别的文档。幻觉是合乎逻辑的结果：智能体收到了一份为拥有它所缺乏的上下文的读者设计的文档。

术语澄清：**氛围编码（vibe coding）** — 一位著名AI研究员在2025年提出的术语，描述在没有计划的情况下与智能体对话进行软件开发。**规格驱动开发（SDD）** 是一种工作流，你在开始指导AI之前，先编写一份描述"做什么"和"为什么"的文档。

结论：**我们必须从零开始为LLM设计规格说明，而不是继承PRD和SRS的惯例。**

## 2、七个信息层：跨领域需求

在我介绍具体的文档类型之前，有一个观察：**无论你在编写哪种文档，它都必须包含七个信息层。** 这些不是章节 — 它们是品质。每份SDD文档都以某种比例包含它们。

- **第1层：语言精确性。** "系统应该加密密码"意味着一切也意味着虚无。"系统应使用bcrypt以≥12的开销因子加密所有密码"则是一个契约。**EARS**（Easy Approach to Requirements Syntax）— 一种由五种句子模式组成的格式，由劳斯莱斯于2009年开发 — 强制要求精确性。在LLM时代之前很久就被航空和汽车行业采用 — 事实证明这也是为智能体做的准备。
- **第2层：负面需求。** 没有明确的"系统不做X"这一节，智能体会添加社交登录，因为"这是最佳实践"。**智能体默认的乐观主义是一个缺陷，而不是一个特性。**
- **第3层：可衡量的成功标准。** "实现JWT认证"意味着二十行或两百行代码。没有验收标准，智能体会随意决定。这是它知道何时停止的唯一方式。
- **第4层：硬性技术约束。** 什么是**禁止的** — 库、模式和API。没有这一层，智能体根据训练数据中的流行度来选择技术 — 有时选择的库已经被废弃了两年。
- **第5层：架构上下文 — 代码库锚定。** 一份锚定在现有仓库中的规格说明：智能体知道具体的文件和依赖关系；它不会"在真空中"编写。没有锚定，智能体会构建一个平行世界 — 这就是它创建重复类然后试图"统一"的方式。
- **第6层：作为显式场景的边缘情况。** 没有命名的边缘情况，智能体只会生成快乐路径。这种模式随处可见：场景是被命名的，而不是暗示的。
- **第7层：经过验证的库规格 — 反幻觉。** 经过验证的库规格说明描述的是实际的API签名，而不是统计猜测。功能规格说明应包含具体的库版本和关键API约束。

![七个信息层作为跨领域需求的堆叠图：每种规格文档类型包含各层的不同比例。](https://www.hubwiz.com/blog/content/images/2026/05/1-a5UJ-9VwiKE6U2ZYiefHpA.png)

*七个信息层。它们不是章节，而是品质 — 五种文档类型（第3节）中的每一种都以不同比例包含它们。*

2022年的独立研究发现，安全关键上下文中超过**40%的代码**存在漏洞 — 其中很大一部分可以直接追溯到这七个层级中某一层的缺失。**这些层级是需求。下面的五种文档类型是表达它们的机制。**

## 3、你需要的五种规格文档类型

要让智能体生成生产代码，你需要**五种不同的文档**。每种回答不同的问题，具有不同的生命周期，由不同的负责人维护。它们共同构成了与LLM的完整契约。

对于每种类型，我将介绍：**用途**、**生命周期**、**必须包含的内容**和**可复制的模板**。

### 3.1 项目宪章

**用途。** 团队与智能体之间的永久协议。不可协商的规则 — 安全、技术栈和基本架构模式。智能体在每次会话、每个层级都会读取。

**生命周期。** 数年。每季度编辑一次，语义化版本控制。宪章变更是可审计事件。

**必须包含的内容。**

- **技术栈** — 允许列表（附具体版本）和禁止列表。一个条目就能省去数百次纠正。
- **架构模式** — 必需的（"数据库访问仅通过仓库层"）和禁止的（"禁止全局可变状态"）。
- **安全** — 锚定于既定标准（OWASP Top 10、CWE）的自定义规则。映射到CWE-ID使宪章成为可审计的合规制品。
- **测试门禁** — 覆盖率阈值和测试分类（单元/集成/端到端）。最小化即可，因为智能体处理了大部分工作。
- **代码风格底线** — 命名约定和目录结构。LLM默认处理大多数约定 — 不要过度复杂化。
- **执行级别** — CRITICAL（阻止合并）、SHOULD（警告）和MAY（信息性）。

**模板。**

```
# 项目宪章 — vX.Y.Z

## 第一条 — 技术栈 [CRITICAL]
ALLOWED: TypeScript ≥5.3, React ≥18, PostgreSQL ≥15
FORBIDDEN: jQuery, class components, CommonJS modules

## 第二条 — 架构模式 [CRITICAL]
系统应仅通过仓库层访问数据库。
在控制器中直接调用ORM是PROHIBITED的。

## 第三条 — 安全 [CRITICAL]
系统应对所有数据库查询进行参数化（CWE-89）。
系统应使用bcrypt以cost ≥12对密码进行哈希（OWASP A02）。

## 第四条 — 测试门禁 [SHOULD]
变更文件的覆盖率在合并前≥80%。

## 第五条 — 代码风格 [MAY]
仓库模式: src/repositories/{Entity}Repository.ts

```

九到十二条。不少于（太抽象），不多于（合规过载 — 智能体会迷失在指令中）。

### 3.2 功能规格说明

**用途。** 描述单个功能的"做什么"和"为什么"。用户得到什么、为什么，以及你如何验证它已完成。

**生命周期。** 按功能分支。合并后可以消亡（故意为之）— 这是它的权利。

**必须包含的内容。**

- **业务目标** — 一段话。为什么存在这个功能。
- **用户故事** — 作为{角色}，我希望{操作}，以便{收益}。
- **功能需求** — 使用EARS格式（SHALL）。编号：FR-001和FR-002。
- **成功标准** — 可衡量、可验证。SC-001："登录在<2s p95内完成。"
- **非目标** — 这个功能不做的事情。没有这一节，智能体会添加功能。
- **边缘情况** — 显式、命名的。"如果登录失败5次，则账户被锁定15分钟。"
- **代码库锚定** — 哪些文件、哪些模式、在哪里接入。
- **开放问题** — 一个"\[NEEDS CLARIFICATION\]"部分用于标记模糊之处。让智能体停下来比让它猜测更好。

**模板。**

```
# 功能规格说明: {名称}

## 目标
[1段 — 为什么需要这个功能]

## 用户故事
- US-1: 作为注册用户，我希望使用邮箱+密码登录
        以便我能访问我的账户。

## 功能需求
FR-001: 系统应通过邮箱+密码对用户进行身份验证。
FR-002: 当登录失败5次时，系统应锁定账户15分钟。

## 成功标准
SC-001: 95%的登录在<2s内完成。
SC-002: 登录失败不应透露邮箱是否存在。

## 非目标
- 社交登录（计划v2）
- 密码重置流程（单独功能，FR-XXX）

## 边缘情况
- 如果邮箱存在但未确认，则阻止登录 + 发送确认邮件。
- 如果账户被锁定，则返回423 + Retry-After头。

## 代码库锚定
- src/auth/AuthService.ts — 扩展
- src/middleware/rateLimit.ts — 复用模式
- src/db/schemas/User.ts — 无变更

## [NEEDS CLARIFICATION]
- 2FA策略: TOTP vs SMS vs 无 [NEEDS CLARIFICATION]

```

### 3.3 技术计划

**用途。** 描述"怎么做"。架构决策、带版本的库、实现阶段和风险。这是智能体在开始生成之前阅读的文档 — 以了解它所工作的技术上下文。

**生命周期。** 按功能，比功能规格说明更短。执行后，它成为历史记录。

**必须包含的内容。**

- **技术栈和版本** — 具体的。不是"Node ≥18"，而是"Node 20.11 LTS"。
- **架构决策** — 关键选择及其理由。如果选择重大，链接到单独的ADR。
- **依赖** — 哪些库、哪些版本，以及为什么选这些而不是其他。
- **阶段/里程碑** — 实现顺序。
- **性能目标** — 具体的。"1000 req/s p95 <200ms，每个实例<100MB内存。"
- **风险** — 什么可能出错以及你将如何检测到。

**模板。**

```
# 技术计划: {名称}

## 技术栈
Node 20.11 LTS, TypeScript 5.4, Fastify 4.26, PostgreSQL 16.

## 架构决策
- AD-1: JWT (jose) + httpOnly cookie. 刷新令牌存储在单独的表中。
        理由: 无状态API，但可以通过DB删除实现令牌失效。
- AD-2: bcrypt (cost=12) 而不是 argon2。
        理由: 宪章第三条，OWASP A02。

## 依赖
- jose@5.2 (JWT)
- bcrypt@5.1 (哈希)
- @fastify/rate-limit@9.1 (现有模式)

## 阶段
1. 数据库迁移 (users.password_hash, users.locked_until)
2. AuthService (注册/登录/锁定逻辑)
3. 路由 + 中间件
4. 测试 (单元 + 集成)

## 性能目标
- 登录 p95 <2s, p99 <5s.
- bcrypt cost=12 → 每次哈希约250ms。可接受。

## 风险
- bcrypt阻塞事件循环 → 如果p95 >2s则使用工作线程。
- 端点上的暴力破解 → 速率限制已存在，但需要审计规则。

```

### 3.4 任务列表

**用途。** 原子工作单元。每个任务都是确定性的、可验证的，可独立提交。智能体逐个执行列表中的任务，每次使用全新的上下文。

**生命周期。** 按功能。执行后，它成为git中的历史（每个任务一次提交）。

**每个任务必须包含的内容。**

- **ID + 名称** — T001和T002。简短、可操作的标题。
- **文件路径** — 它涉及哪些文件。
- **操作** — 具体要做什么。如果可能，提供完整代码。
- **验证** — 确认任务完成的命令或测试。
- **完成定义** — 可衡量的。
- **\[P\]** — 并行安全任务（独立任务）的标记。
- **依赖** — 有依赖关系任务的顺序排列。

**模板。**

```
# 任务列表: {名称}

## T001: Users数据库迁移
**文件:** db/migrations/2026_05_15_login.sql
**操作:** ALTER TABLE users ADD COLUMN password_hash TEXT NOT NULL,
          ADD COLUMN locked_until TIMESTAMP NULL.
**验证:** psql -c "\\d users" — 显示新列。
**完成:** 迁移在本地DB上运行；回滚通过。

## T002 [P]: 测试 AuthService.hashPassword
**文件:** src/auth/__tests__/AuthService.test.ts
**操作:** [完整测试代码，包含bcrypt cost=12 + 空密码的边缘情况]
**验证:** npm test -- AuthService.test
**完成:** 测试失败（TDD的RED阶段）。

## T003 [依赖: T002]: 实现 AuthService.hashPassword
...

```

`[P]`标记允许智能体在没有依赖关系时并行执行任务。**每个任务一次原子提交** — 使回滚和审查更容易。

### 3.5 变更规格说明 — 增量和错误修复

**用途。** 描述对现有系统的**变更**。可以是迭代（增量）或缺陷修复（bug修复）。格式是语义差异，而不是完整的重新规格说明。

**生命周期。** 按变更。带时间戳归档（审计跟踪）。

**增量必须包含的内容。**

- **ADDED** — 新需求或功能。
- **MODIFIED** — 变更的需求，以"旧→新"格式。
- **REMOVED** — 弃用的需求。
- **对其他组件的影响** — 系统的哪些部分需要审查。

**模板 — 增量。**

```
# 增量: 为登录添加2FA (2026-05-20)

## ADDED
- FR-010: 当用户启用2FA时，系统应在每次登录时要求TOTP验证码。
- SC-010: TOTP设置流程端到端在<60s内完成。

## MODIFIED
- FR-001 (先前版本): "系统应通过邮箱+密码对用户进行身份验证"
- FR-001 (新版本): "系统应通过邮箱+密码对用户进行身份验证，
                    如果启用了2FA，则随后要求TOTP验证。"

## REMOVED
- (无)

## 影响
- AuthService.login — 添加2FA挑战步骤。
- LoginRoute — 添加步骤状态机。

```

**错误修复必须包含的内容。**

- **当前行为** — 系统 NOW 的行为方式（不正确的）。
- **预期行为** — 修复后应如何表现。
- **不变行为** — 哪些必须保持不变。**最重要的部分。** 没有它，修复会在远程模块中引入回归。
- **复现步骤** — 重现问题的步骤。
- **根本原因** — 原因，而不仅仅是症状。

**模板 — 错误修复。**

```
# 错误修复: 速率限制器忽略X-Forwarded-For (BUG-2026-042)

## 当前行为
当请求通过负载均衡器到达时，速率限制器使用
  负载均衡器的IP，而不是终端客户端的IP → 所有客户端共享
  一个IP的限额。

## 预期行为
当请求包含来自受信任代理的X-Forwarded-For头时，
  速率限制器应使用原始客户端IP。

## 不变行为
- 当请求没有X-Forwarded-For时，速率限制器使用
  socket IP（与当前相同）。
- 当X-Forwarded-For来自不受信任的源时，忽略它
  （安全：防欺骗保护）。

## 复现步骤
curl -H "X-Forwarded-For: 1.2.3.4" localhost/login (循环执行) →
  第一个客户端在5次尝试后被阻止（应为：各自独立的限额）。

## 根本原因
速率限制中间件在配置中没有trustedProxies列表。

```

**不变行为**部分是区分"修复了问题的bug修复"和"引入了新问题的bug修复"的关键。没有它，智能体会将整个模块视为"需要重写"。

![五种规格文档类型作为具有不同生命周期的层次结构图：项目宪章在底部（数年），功能规格说明+技术计划+任务列表的三元组（按功能），变更规格说明（按变更，归档）。](https://www.hubwiz.com/blog/content/images/2026/05/1-6wP7M-9-1bfLQW0cmmBTcg.png)

*五种文档类型。每种回答不同的问题，具有不同的生命周期，由不同的负责人维护。它们共同构成了与LLM的完整契约。*

五份文档看起来像是额外开销。**它们不是** — 因为每份文档只有一个职责和一个生命周期。试图将所有这些塞进一个文件中，产生的恰恰是让开发者头疼的漂移混乱。

## 4、生命周期：什么消亡，什么存活

在每个国家，宪章很少变更，而普通法律每周都在变。**你的项目需要同样的分离。** 宪章：数年，罕见变更，语义化版本控制。按功能的三元组（功能规格说明、计划、任务）：数周，合并后故意消亡。变更规格说明：带时间戳的归档和审计跟踪。

Thoughtworks的Birgitta Böckeler（2025年10月）引入了关于合并后规格说明发生什么的经典分类法：**规格优先（spec-first）、规格锚定（spec-anchored）和规格即源（spec-as-source）**。大多数开发者通过工具选择而非刻意决策，不知不觉地选择了第一条路径。本文讲述的是规格优先。

在规格优先模型中，按功能的三元组（规格+计划+任务）在合并后**故意消亡** — 这是它的权利。宪章存活下来。变更规格说明被归档。澄清一下：另外两条路径是规格锚定（规格与代码并存）和规格即源（代码是编译器的二进制输出）。两者都是小众用法，不在本文讨论范围内。

![时间线图，展示了五种文档类型的不同生命周期：项目宪章为连续的水平线（数年），按功能的三元组为每隔几周出现和消失的三角形，变更规格说作为时间轴上归档的单个点。](https://www.hubwiz.com/blog/content/images/2026/05/1-LE86J9LhjnW-m3Xvh_otAQ.png)

*五种规格文档类型的生命周期。宪章经受一切。按功能的三元组故意消亡。变更规格说明被归档 — 可用于审计，不会膨胀对话上下文。*

Yegge在2025年花了一个月时间淹没在数百个Markdown文件中。没有一个被再次阅读。**那不是因为缺乏纪律性 — 而是规格优先路径缺少一个专门的持久层。** 一份能够存活下来的宪章。

机制很简单。**宪章在每次会话开始时被智能体读取** — 一次基于文件的交接，独立于对话上下文。它经受住了**上下文腐化**（随着上下文窗口填满，生成质量下降），因为它不在对话历史中。文件在第二十次会话中与第二次会话中一样可读。

## 5、决策树：为你的团队选择规格组合

五种类型是完整集合。**大多数团队不需要从一开始就使用全部五种。**

- **个人/小团队/新项目：** 宪章（轻量级，5-7条规则）+ 功能规格说明（与技术计划合并为一个部分）+ 任务列表。变更规格说明仅作为bug修复模板，仅当项目超过6个月时才使用增量。**大多数情况。**
- **个人/棕地/兴趣项目：** 最小宪章（3-5条规则 — 主要是技术栈）+ 临时功能规格说明。更多时候重写而非维护。跳过正式的任务列表。
- **团队/长期项目：** 所有五种类型。扩展的宪章（9到12条规则），技术计划中的正式阶段，带有`[P]`标记的显式任务列表，以及每次迭代的增量规格说明。边缘情况被显式命名，因为没有任何智能体会原谅你在远程模块中的回归。
- **企业/受监管行业**（金融科技、医疗、国防）：所有五种类型 + 映射到既定标准（OWASP、CWE）的重型宪章，作为每次生成的硬性门禁。在这里，仅规格优先作为唯一模式已经不够 — 但这是另一篇文章的主题。就本文而言，宪章是无论其他选择如何都将整个制度维系在一起的基础。

![选择规格组合的决策树：个人/团队/企业 × 新项目/棕地。每个叶节点指示使用五种文档类型中的哪些以及什么权重。](https://www.hubwiz.com/blog/content/images/2026/05/1-GlVULarhN2glo3auf54TOg.png)

*SDD决策树。大多数团队落在个人/新项目 → 轻量级宪章 + 功能规格说明组合 + 任务列表。受监管领域和棕地项目需要所有五种类型配合重型宪章。*

走一遍决策树只需要两分钟。这个决策可以在未来两年中节省三十小时对抗规格漂移的时间。**跳过这个决策的团队得到的是工具的默认组合 — 然后纳闷为什么审计师不接受Slack讨论作为合规文档。**

## 6、结束语

让我们回到周五六点的那位开发者。两周后，他的仓库有五种文档类型：一份包含九条规则的宪章，智能体在每次会话中都会读取；一个按功能的三元组（功能规格说明、技术计划和任务列表），在合并后故意消亡；以及一个增量归档，保留了变更历史。上一个冲刺的Markdown仍然是考古学 — 但在归档中，而不是在根目录中。**一旦你接受按功能的规格说明注定要消亡 — 并将必须存活的内容分离出来 — 规格束之高阁就不再是问题了。**

带走五件事：

- **PRD、SRS和LLD是委员会时代的遗产** — 从零开始设计信息架构。
- **七个信息层**是跨领域需求 — 它们以不同比例出现在所有五种文档类型中。
- **你需要的五种规格文档类型：** 宪章、功能规格说明、技术计划、任务列表和变更规格说明（增量+错误修复）。每种只有一个职责和一个生命周期。
- **宪章比其他一切存活得都久** — 这是对规格束之高阁问题的经验性答案。
- **热修复友好的SDD不存在**，这是一个事实，不是一个缺陷。宪章就是你的热修复门禁。

![文章总结信息图：五种规格文档类型位于中心（宪章在底部，按功能的三元组在中间，变更规格说明在顶部），周围是4个象限，展示文章的主要概念 — PRD与LLM规格说明的对比、7个信息层、生命周期、决策树。](https://www.hubwiz.com/blog/content/images/2026/05/1-2-dFv8KpezUw2ofQ3_Kz0g.png)

*规格优先的解剖图，一图概括。五种具有不同生命周期的文档类型。宪章存活 — 其他一切都可以故意消亡。*

从宪章开始。九到十二条规则，每季度编辑一次。然后为第一个真正的功能创建按功能的三元组。当第二次合并到来时添加变更规格说明。**三十分钟的决策可以节省未来两年中三十小时对抗漂移的时间。**

---

原文链接: [SDD — Designing a Spec That Survives Code Generation — Spec-First — Spec-Driven Development](https://medium.com/@wasowski.jarek/sdd-designing-a-spec-that-survives-code-generation-spec-first-spec-driven-development-b61fdc234493?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处

> **这是「AI 编程 / Vibe Coding」专题的一部分。**完整地图见：[AI 编程 / Vibe Coding 完全指南](https://www.hubwiz.com/blog/vibe-coding-stack/)