token

Cyber-GE

Article • 10 min read

Spec 驱动开发:让 AI 编程助手真正理解你的意图

GE

TL;DR: Spec 驱动开发是一种与 AI 编程助手协作的方法论。核心思想是「先想清楚,再动手做」——通过规范、设计、任务、实现四个阶段,将模糊的需求逐步细化为可执行的代码。所有中间产物以 Markdown 文件形式保存在项目中,实现跨会话记忆和跨工具协作。

前置知识:本文假设读者使用过 Cursor、Claude Code、Kimi Code 等 AI 编程助手,了解 prompt 工程的基本概念。


问题:AI 编程助手的「失忆症」

使用 AI 编程助手时,你可能遇到过这些问题:

每次新会话都要重新解释项目背景。昨天讨论过的架构决策,今天 AI 完全不记得。你说「继续昨天的工作」,AI 一脸茫然。

复杂功能开发到一半,上下文窗口爆了。AI 开始「幻觉」,生成与之前讨论矛盾的代码。你不得不开新会话,然后又要重新解释一遍。

多人协作时更糟糕。你和同事用同一个 AI 助手开发同一个功能,但 AI 对你们说的话完全不一致。没有共享的「记忆」,协作变成了各自为战。

这些问题的根源在于:AI 的上下文是临时的,而软件开发是持续的。


解决方案:把「记忆」写进项目

Spec 驱动开发的核心思想很简单:既然 AI 没有持久记忆,那就把记忆写成文件,保存在项目里。

每次会话开始时,AI 读取这些文件,恢复上下文。每次会话结束时,AI 更新这些文件,保存进度。文件跟着项目走,换一个 AI 工具也能继续工作。

这不是什么新发明。软件工程早就有类似的实践:需求文档、设计文档、任务看板。Spec 驱动开发只是把这些实践标准化,让 AI 能够理解和操作。


四阶段工作流

整个方法论分为四个阶段,每个阶段都有明确的输入、输出和验证标准。

Spec 驱动开发四阶段流程

阶段一:规范(Specify)

这个阶段回答「做什么」的问题。输入是模糊的需求描述,输出是结构化的需求规格文档。

触发词是「规范功能」。比如你说「规范功能:用户登录」,AI 会生成一个 spec.md 文件,包含用户故事、功能需求、验收标准和边界情况。

# 功能:用户登录

## 用户故事
作为用户,我希望通过邮箱和密码登录,以便访问我的个人数据。

## 功能需求
1. 支持邮箱+密码登录
2. 登录成功后返回 JWT Token
3. 密码错误时返回模糊提示(不透露是邮箱不存在还是密码错误)
4. 支持「记住我」功能(Token 有效期 7 天)

## 验收标准
- [ ] 正确的凭据返回 200 + Token
- [ ] 错误的密码返回 401
- [ ] 不存在的用户返回 401(与密码错误一致)
- [ ] Token 包含用户 ID 和过期时间

## 边界情况
1. 邮箱格式不合法 → 返回 400
2. 密码为空 → 返回 400
3. 账户被禁用 → 返回 403 + 提示信息

这个阶段的价值在于:强迫你把需求想清楚。很多 bug 不是代码写错了,而是需求没想清楚。

阶段二:设计(Design)

这个阶段回答「怎么做」的问题。输入是需求规格,输出是技术设计文档。

触发词是「设计功能」。AI 会基于 spec.md 生成 design.md,包含 API 设计、数据模型、安全方案和错误处理策略。

# 设计:用户登录

## API 设计
POST /api/v1/auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "secret",
  "remember": true
}

## 数据模型
- 复用现有的 `users`
- 新增 `refresh_tokens` 表存储长期 Token

## 安全考虑
1. 密码使用 bcrypt 验证(cost factor = 12)
2. 速率限制:5 次/分钟/IP
3. JWT 使用 RS256 签名,私钥存储在环境变量

## 错误处理
| 场景 | HTTP 状态码 | 响应体 |
|------|------------|--------|
| 凭据错误 | 401 | `{"error": "invalid_credentials"}` |
| 账户禁用 | 403 | `{"error": "account_disabled"}` |
| 请求过频 | 429 | `{"error": "rate_limited"}` |

如果你在现有项目中开发,AI 会先读取代码库分析文档(后面会讲),确保设计与现有架构一致。

阶段三:任务分解(Tasks)

这个阶段把设计拆成可执行的原子任务。输入是技术设计,输出是任务清单。

触发词是「分解为任务」。AI 会生成 tasks.md,每个任务都有明确的完成标准和验证方法。

# 任务:用户登录

## 任务 1:创建数据库表
- [ ] 创建 `refresh_tokens`
- **验证**:运行 migration,检查表结构

## 任务 2:实现登录 API
- [ ] 创建 POST /api/v1/auth/login 端点
- [ ] 实现密码验证逻辑
- [ ] 实现 JWT 生成
- **验证**
  - 单元测试覆盖正常流程和边界情况
  - 手动测试 API 响应

## 任务 3:添加安全机制
- [ ] 实现基于 IP 的速率限制
- [ ] 配置 bcrypt cost factor
- **验证**:连续发送 6 次请求,第 6 次返回 429

任务的粒度很重要。太大了 AI 容易跑偏,太小了又浪费时间。经验法则是:一个任务应该能在 10-30 分钟内完成,产出可验证的结果。

阶段四:实现与验证(Implement + Validate)

这个阶段才开始写代码。触发词是「实现任务 N」。

AI 会读取对应的任务描述,生成代码,然后按照验证标准检查结果。完成后自动更新任务状态。

"实现任务 1:创建数据库表"
→ AI 生成 migration 文件
→ 运行 migration
→ 验证表结构
→ 标记任务 1 为 done

"实现任务 2:实现登录 API"
→ AI 生成 controller、service、测试
→ 运行测试
→ 验证覆盖率
→ 标记任务 2 为 done

每个任务完成后,tasks.md 中的状态会更新。下次会话时,AI 读取这个文件就知道做到哪里了。


项目结构

所有文档都保存在项目根目录的 .specs/ 文件夹中:

.specs/
├── project/
│   ├── PROJECT.md      # 项目愿景与目标
│   ├── ROADMAP.md      # 功能路线图
│   └── STATE.md        # 会话状态(当前进度、阻塞、决策记录)
├── codebase/           # 现有代码库分析(可选)
│   ├── STACK.md        # 技术栈
│   ├── ARCHITECTURE.md # 架构
│   ├── CONVENTIONS.md  # 编码规范
│   ├── STRUCTURE.md    # 目录结构
│   ├── TESTING.md      # 测试策略
│   └── INTEGRATIONS.md # 外部集成
└── features/           # 功能规格
    └── user-login/
        ├── spec.md     # 需求规格
        ├── design.md   # 技术设计
        └── tasks.md    # 任务清单

这个结构有几个设计考量:

project/ 目录存放项目级信息,每次会话都会加载。STATE.md 是跨会话记忆的核心,记录当前进度、阻塞项和历史决策。

codebase/ 目录是可选的,用于在现有项目中开发。通过「映射代码库」命令生成,帮助 AI 理解现有架构。

features/ 目录按功能组织,每个功能一个子目录。这样可以按需加载,避免上下文爆炸。


上下文管理策略

大语言模型的上下文窗口是有限的。即使是 200k token 的模型,也不能把所有文档一股脑塞进去。Spec 驱动开发采用分层加载策略:

基础层(每次会话必加载,约 15k tokens)

  • PROJECT.md — 项目愿景,让 AI 知道在做什么
  • ROADMAP.md — 功能列表,让 AI 知道整体规划
  • STATE.md — 当前状态,让 AI 知道做到哪里了

按需层(根据当前任务加载)

  • 处理现有项目时加载 codebase/ 目录
  • 处理特定功能时加载对应的 spec.md
  • 按设计实现时加载 design.md
  • 执行任务时加载 tasks.md

绝不同时加载

  • 多个功能的规格文档
  • 多个架构分析文档

目标是把总上下文控制在 40k tokens 以内,给实际工作预留 160k+ 的空间。


跨会话记忆

STATE.md 是实现跨会话记忆的关键。它的结构大致如下:

# 项目状态

## 当前会话
- **最后工作**:用户登录功能的任务 3
- **状态**:进行中
- **阻塞**:等待安全团队确认速率限制策略

## 决策记录
- 2026-02-28: 选择 PostgreSQL 而非 MySQL
  - 原因:JSON 字段支持更好,适合存储用户偏好
- 2026-02-27: 选择 JWT 而非 Session
  - 原因:支持多端登录,便于水平扩展

## 用户偏好
- 使用中文回复
- 代码注释用英文
- 测试框架:Jest

每次会话结束时,AI 会更新这个文件。下次会话开始时,AI 读取这个文件就能恢复上下文。

你也可以手动编辑这个文件。比如记录一个重要决策,或者标记某个任务被阻塞了。


跨工具协作

这套方法论的一个意外收获是:它让你可以在不同的 AI 工具之间无缝切换。

因为所有状态都保存在项目文件中,而不是某个工具的云端。你可以用 Cursor 开始一个功能,用 Claude Code 继续,再用 Kimi Code 收尾。每个工具读取同样的 .specs/ 目录,看到同样的进度。

这在实践中很有用。不同的 AI 工具有不同的优势:有的擅长代码生成,有的擅长调试,有的擅长文档。你可以根据任务选择最合适的工具,而不用担心上下文丢失。


实践建议

应该做的

每次会话先读 STATE.md。这是恢复上下文的第一步。如果你使用的 AI 工具支持自动加载,配置好让它自动读取。

一个功能走完完整流程。不要跳过设计直接编码。每个阶段都有价值:规范阶段帮你想清楚需求,设计阶段帮你想清楚方案,任务阶段帮你想清楚步骤。

及时更新任务状态。完成一个任务就标记一个。这不仅是给 AI 看的,也是给自己看的。

记录关键决策。为什么选择方案 A 而非 B?这个技术债务是有意为之还是无奈之举?这些信息对未来的你(和未来的 AI)都很有价值。

应该避免的

一次处理多个功能。这会导致上下文爆炸,降低输出质量。专注于一个功能,完成后再开始下一个。

跳过验证步骤。每个任务都要有验证标准。没验证等于没完成。AI 生成的代码不一定正确,验证是质量保证的最后一道防线。

在实现阶段改设计。如果发现设计有问题,回到设计阶段修改 design.md,然后重新分解任务。保持各阶段职责清晰。


与传统开发的对比

维度传统方式Spec 驱动
需求管理口头沟通或零散文档结构化的 spec.md
设计评审会议讨论,记录分散design.md 可追溯
任务跟踪Jira/Trello 等外部工具tasks.md 与代码同仓库
AI 协作每次重新解释上下文自动加载项目状态
跨工具状态锁定在特定工具文件级别的可移植性

Spec 驱动开发不是要取代传统的项目管理工具,而是在 AI 协作场景下提供一个轻量级的补充。对于个人项目或小团队,它可能就够用了。对于大团队,它可以作为 AI 协作的「接口层」,与现有工具并存。


局限性与权衡

这套方法论不是银弹,有几个明显的局限:

前期投入。写规范和设计需要时间。对于简单的功能,这个投入可能不值得。经验法则是:如果一个功能能在 30 分钟内完成,直接写代码可能更快。

文档维护。代码改了,文档也要改。如果不及时更新,文档会变成误导。这需要纪律。

学习曲线。团队成员需要学习这套流程和触发词。初期可能会觉得繁琐。

不适合探索性开发。如果你还不知道要做什么,先写规范是没意义的。这套方法论更适合需求相对明确的场景。


快速开始

如果你想尝试这套方法论,可以从以下步骤开始:

新项目

"初始化项目"
→ 创建 PROJECT.md(愿景、目标、成功标准)

"创建路线图"
→ 创建 ROADMAP.md(功能列表、优先级)

"规范功能:[功能名称]"
→ 进入功能级开发流程

现有项目

"映射代码库"
→ 生成 codebase/ 目录下的 6 个分析文档

"初始化项目"
→ 创建 PROJECT.md + ROADMAP.md

"规范功能:[功能名称]"
→ 进入功能级开发流程

暂停与恢复

"暂停工作"
→ 自动更新 STATE.md,记录当前进度

"继续工作"
→ 读取 STATE.md,从上次位置继续

进一步阅读


一句话总结:Spec 驱动开发 = 想清楚 + 写下来 + 按步骤执行 + 验证完成

它不会让 AI 变得更聪明,但会让你和 AI 的协作更高效。

edit_note

"Code is poetry written for machines, but read by humans. Optimize for the latter."

Related Trigrams

Qián - The Creative

卦辞 · Judgment

"元亨利贞。"

象曰 · Image

天行健,君子以自强不息。

今日启示 · Insight

创造力与领导力的时刻。保持正直,大事可成。