第一次用 AI Coding Agent 写项目,体验往往非常爽。
你只需要说一句:
帮我做一个用户认证系统。
几分钟后,目录建好了,接口写好了,页面也能打开。两千行代码摆在面前,仿佛一个下午就完成了过去一周的工作。
但继续开发几天,问题就来了:
- 它选了你并不想用的框架;
- 登录流程能跑,却没有考虑令牌刷新和异常状态;
- 新增一个需求,旧功能突然被改坏;
- 换一次会话,之前约定的架构像从未存在过;
- 你不断补充提示词,AI 不断重写代码,时间和 Token 一起消耗。
第一天像是效率提升了 10 倍,第二周却开始集中返工。
问题未必是 AI 不够强,而是我们只告诉了它"去做什么",却没有提供足够清晰、持久、可验证的上下文。
这正是 SDD 想解决的问题。
一、什么是 SDD?
SDD 是 Spec-Driven Development,通常译为"规范驱动开发"或"规格驱动开发"。
它的核心并不复杂:先把意图写成规范,再让代码成为规范的实现。
传统开发中,需求文档和设计文档常常只是前期参考。代码一旦开始演进,文档很快就会过期,最后代码重新成为唯一事实来源。
SDD 试图反转这个关系:规范不再是写完就丢的脚手架,而是需求、设计、任务、测试与实现共同依赖的源头。GitHub 的 Spec Kit 将核心流程概括为:
text
Spec → Plan → Tasks → Implement
也就是先定义"做什么",再决定"怎么做",接着拆解"按什么顺序做",最后才进入实现。
这并不意味着开发者要在写代码前完成一本厚厚的需求说明书。真正重要的是:当 AI 准备生成代码时,关键决策已经被明确记录,而不是散落在几十轮聊天记录里。
二、Vibe Coding 为什么容易失控?
Vibe Coding 最大的诱惑,是聊天框会推动我们立刻进入实现。
想到一个功能,马上让 AI 写;发现不对,再补一句;又有新想法,继续追加。整个过程很流畅,但项目的真实需求始终只存在于人的脑中。
比如"做一个用户认证系统",至少隐藏了这些问题:
- 面向普通用户,还是企业内部员工?
- 使用邮箱密码、手机验证码,还是第三方登录?
- 前后端分别采用什么技术栈?
- 会话如何续期,退出登录后令牌如何失效?
- 是否需要多端登录、风控、审计与找回密码?
- 什么结果才算"完成"?
如果这些信息没有被提供,模型只能猜。
猜对时,我们会觉得 AI 很聪明;猜错时,我们就会进入"生成---发现问题---重新生成"的循环。更麻烦的是,即使某一轮聊清楚了,新的会话也未必保留这些背景。
所以,Vibe Coding 的问题不是"凭感觉写代码"本身,而是跳过了对目标的第一次创造,直接冲向第二次创造。
《高效能人士的七个习惯》中的"以终为始",可以很好地解释 SDD:一个结果通常会经历两次创造。第一次在头脑和方案中形成,第二次才在现实中被建造出来。建筑施工之前需要蓝图,AI 编程同样需要一份能被持续读取的"施工图"。
三、SDD 不是多写文档,而是减少 AI 的猜测
一套实用的 SDD 文档,可以围绕四个问题展开:
| 文档 | 回答的问题 | 重点内容 |
|---|---|---|
proposal.md 或 spec.md |
为什么做、做什么 | 用户、场景、范围、非目标、验收标准 |
design.md 或 plan.md |
怎么做 | 技术选型、架构、数据流、接口、异常与安全约束 |
tasks.md |
按什么顺序做 | 任务拆分、依赖关系、可并行项、验证方式 |
| 代码与测试 | 是否真的做到了 | 实现、自动化测试、人工验收、运行结果 |
大型产品可以在前面增加 PRD、调研报告和项目原则;一个周末项目则未必需要这么重。文档数量不是重点,能否消除关键歧义才是重点。
一份有效规范至少要满足三个条件:
- 可执行:AI 读完后知道下一步要修改哪些模块。
- 可验证:每个需求都有明确的成功或失败标准。
- 可追踪:需求变化时,能够找到受影响的设计、任务、代码和测试。
"界面要好看""接口要稳定""翻译速度要快"都不算合格规范,因为它们无法验收。
更好的写法是:
- 翻译结果在浏览器侧边栏中展示,正文区域可以独立滚动;
- 请求进行时显示加载状态,并禁止重复提交;
- API 返回错误时保留原文,展示可重试的错误信息;
- 用户可以一键复制完整 Markdown,复制成功后显示反馈;
- 未配置模型服务时,不发送网页内容,并引导用户完成设置。
这时,AI 不再需要猜测"做好"是什么意思。
四、用一个 Chrome 翻译插件走完 SDD
下面用一个具体需求演示这套流程:做一个 Chrome 插件,在浏览英文技术文章时,一键提取正文,调用 AI 翻译,并以 Markdown 形式展示和复制。
注意,这里不是立刻让 AI 创建项目,而是先完成第一次创造。
1. 先写 Proposal:明确 MVP 的边界
proposal.md 可以先写成这样:
markdown
# 网页文章 AI 翻译插件
## 目标
帮助中文技术读者在当前网页内完成"提取正文---翻译---预览---复制",
减少在浏览器、翻译工具和 Markdown 编辑器之间来回切换。
## 核心用户
经常阅读英文技术博客、文档和资讯的中文内容创作者。
## MVP 范围
1. 从当前网页提取标题和正文;
2. 调用用户配置的 OpenAI 兼容接口进行翻译;
3. 在侧边栏展示 Markdown 结果;
4. 支持一键复制;
5. 保存模型地址、模型名和密钥配置。
## 暂不实现
- 用户账号与云端同步;
- PDF、视频字幕和登录后受限内容解析;
- 多篇文章批量翻译;
- 自动发布到微信公众号。
## 验收标准
- 在支持的文章页面点击扩展图标后,可以打开侧边栏;
- 正文提取失败时,不调用模型,并给出明确提示;
- 翻译成功后保留标题、段落、列表和代码块;
- 用户点击复制后,剪贴板内容与 Markdown 原文一致;
- 密钥未配置时,不发起网络请求。
这份文档的价值,不是显得流程专业,而是主动说清楚"不做什么"。
AI 最容易在边界模糊时过度实现。一个 MVP 如果同时加入账号系统、云同步、多模型路由和自动发布,代码量会迅速膨胀,真正的核心链路反而迟迟无法验证。
2. 再写 Design:提前解决技术风险
需求确定后,再研究技术方案,而不是让模型随手选择依赖。
这个插件至少包含下面几个模块:
text
当前网页
↓
Content Script:读取并提取正文
↓
Background / Service Worker:组织请求与状态
↓
OpenAI 兼容模型接口:生成 Markdown 译文
↓
Side Panel:预览、重试、复制
关键选型可以记录在 design.md 中:
- 交互容器 :使用 Chrome Side Panel,而不是固定高度的 Popup。Chrome 官方提供的
chrome.sidePanel可以让扩展界面与网页并排显示,更适合承载长篇翻译结果。 - 正文提取 :优先使用 Mozilla Readability 从 DOM 中提取文章标题和正文,同时为提取失败、内容过短和非文章页面设计降级提示。
- 模型接入 :面向 OpenAI 兼容接口抽象配置层,将
baseURL、model和凭证作为配置,而不是把某个厂商写死在业务代码中。 - Markdown 渲染 :可以使用 Marked 将 Markdown 转成预览 HTML,但它本身不负责清理不安全 HTML,因此还需要配合内容净化策略,避免 XSS。
- 隐私约束:网页正文可能包含敏感内容。产品必须在发送前让用户知道数据会被提交到其配置的模型服务,并遵循最小权限原则。
这里有一个很典型的 SDD 价值:原始想法可能是"把 Popup 改成右侧全高弹窗",但 Chrome 已经提供了 Side Panel 这一正式能力。先调研再设计,可以避免让 AI 用 CSS 模拟一个脆弱的悬浮层。
设计文档还应该回答异常场景:
- 页面没有可提取正文怎么办?
- 文章超过模型上下文窗口怎么办?
- 请求超时或触发限流怎么办?
- 用户切换标签页后,侧边栏展示哪篇文章?
- Markdown 中带有原始 HTML 时如何处理?
- 密钥存在哪里,日志中是否可能泄露?
这些问题越早明确,后面返工的成本越低。
3. 拆成 Tasks:让 AI 一次只完成一个可验收单元
有了需求和设计,仍然不应该一句话让 AI "全部实现"。
tasks.md 可以这样拆:
markdown
- [ ] T01 初始化 Manifest V3 扩展骨架,验证可以本地加载
- [ ] T02 创建 Side Panel 页面,验证点击扩展图标可以打开
- [ ] T03 实现配置表单与本地存储,不接入真实模型
- [ ] T04 实现当前页面正文提取,并为失败状态添加测试样例
- [ ] T05 定义翻译服务接口,使用 Mock 响应打通完整数据流
- [ ] T06 接入 OpenAI 兼容接口,处理超时、取消和错误响应
- [ ] T07 实现 Markdown 预览、净化与复制反馈
- [ ] T08 使用短文、长文、代码文章和非文章页进行验收
- [ ] T09 清理调试日志、冗余代码和不必要权限
每个任务都应该产生一个可以检查的结果。这样做有三个好处:
- AI 的单次上下文更聚焦;
- 出现问题时,更容易定位是哪一步引入的;
- 每完成一小步就可以提交版本,回退成本更低。
如果多个任务没有依赖,例如配置页和正文提取,也可以并行推进;但"接入真实模型"显然应该在基础数据流跑通之后进行。
五、需求变化时,先改规范还是先改代码?
假设插件第一版使用 Popup,后来发现翻译内容很长,希望改成右侧全高面板。
Vibe Coding 的常见做法是直接说:
把当前弹窗改成从右侧打开,高度撑满整个页面。
AI 可能立刻修改 CSS,也可能重写页面结构,甚至引入一套新的浮层逻辑。但真正需要先确认的是:Chrome 扩展是否有原生能力?最低支持版本是什么?需要增加哪些权限?原有 Popup 是否保留?
在 SDD 中,变更流程应该是:
text
提出变更
→ 调研平台能力
→ 更新需求范围与验收标准
→ 更新技术设计
→ 标记受影响任务
→ 修改代码和测试
→ 验证文档与实现一致
也就是说,需求变更不是聊天记录中的一句补充,而是一个可追踪的规范变更。
文档和代码应该一起进入版本控制。这样才能回答:这个权限为什么新增?侧边栏方案从哪个版本开始采用?某段兼容逻辑对应哪一条需求?
如果文档写的是 Popup,代码却已经变成 Side Panel,那么文档漂移本身就是一个缺陷。
六、如何和 AI Coding Agent 配合?
SDD 并不绑定某个具体工具。Claude Code、Codex、Cursor、Copilot 或其他 Agent 都可以读取仓库中的 Markdown 文档。
关键是不要让一次对话同时承担调研、决策、实现和验收四种工作。
可以按照下面的节奏与 AI 协作。
阶段一:只讨论需求
text
阅读当前项目。围绕"网页正文提取、AI 翻译、Markdown 复制"分析用户场景,
列出范围、非目标、异常情况和可验证的验收标准。
只生成 proposal.md,不修改代码。
阶段二:只做技术调研与设计
text
基于 proposal.md 调研 Chrome 扩展的正文提取、Side Panel、模型请求、
Markdown 安全渲染方案。比较备选方案,记录取舍和风险。
只生成 design.md,不修改代码。
阶段三:拆解任务
text
根据 proposal.md 和 design.md 生成 tasks.md。
每个任务必须足够小,包含依赖关系、完成条件和验证方式,标记可并行任务。
阶段四:逐项实现
text
只实现 T04。开始前阅读规范和相关代码;完成后运行对应验证,
汇报修改文件、验证结果和仍未解决的问题。不要提前实现后续任务。
这种方式看似慢了一点,实际上减少了大段代码生成后整体推倒重来的概率。
七、别让 SDD 变成新的形式主义
SDD 也有自己的陷阱:文档可能写得很长,却没有任何有效约束;AI 同时生成三份内容高度重复的文件;代码变了,规范却没人维护。
要避免这些问题,可以坚持几条简单原则。
1. 文档规模与风险匹配
改一个按钮文案,没必要写完整 PRD;开发认证、支付、权限系统,则不能只留一句提示词。复杂度越高、影响面越大、不可逆成本越高,规范就应该越严谨。
2. 先写验收标准,再写实现方式
如果一个需求无法判断是否完成,说明它还不够清楚。验收标准会迫使我们把"好用""稳定""快速"改成可观察的行为。
3. 明确非目标
"这次不做什么"与"做什么"同样重要。非目标可以防止人和 AI 在实现过程中不断扩张范围。
4. 把研究结论写进设计,而不是只留链接
链接会失效,聊天会丢失。应该记录最终选择、放弃其他方案的原因,以及这个结论依赖的版本和约束。
5. 小步提交,随时验证
AI 生成速度越快,越需要频繁检查差异、运行测试和保存可恢复版本。版本控制不是最后上传代码时才使用的工具,而是 Agent 开发过程中的安全绳。
6. 把规范漂移当作缺陷
代码与规范不一致时,要么实现错了,要么规范过期了。两者都应该被修复,而不是默认"文档以后再补"。
八、代码越来越便宜,清晰的意图越来越贵
AI 让代码生成成本快速下降,但软件开发中真正困难的部分并没有消失:我们仍然要理解用户、划定边界、选择架构、处理异常,并判断结果是否正确。
过去,开发者的大量时间花在把明确方案翻译成代码;现在,这部分工作可以越来越多地交给 Agent。随之而来的变化是,清晰、可执行、可验证的意图,正在成为新的稀缺资源。
SDD 的意义,不是让所有人重新回到厚重的瀑布式文档,而是给 AI 一份稳定的项目记忆:
- 需求告诉它终点在哪里;
- 设计告诉它哪些道路可以走;
- 任务告诉它下一步先做什么;
- 测试告诉它是否真的到达。
Vibe Coding 可以帮助我们快速探索,SDD 则让探索出的方向能够被稳定地建造、维护和迭代。
下一次准备对 AI 说"帮我做一个系统"之前,不妨先停十分钟,写清楚四件事:为什么做、做什么、怎么做、如何证明做到了。
这十分钟,很可能会省下后面几天的返工。