1. 为什么要把 SDD、OpenSpec、SuperPowers 放在一起用
大家有没有发现,2025 年的 AI 编程圈,聊得最多的已经不是“提示词写得好不好”,而是“怎么让 AI 别把项目改乱”。我自己的项目从 vibe coding 一路走过来,最后收敛到一套组合:SDD(Spec-Driven Development,规范驱动开发)作为方法论,OpenSpec 作为规范仓库和流程骨架,SuperPowers 作为编码 Agent 的技能增强层。今天这篇文章就把这套搭配的完整玩法和踩坑记录整理出来。
先说结论:这不是某个玩具框架的试用报告,而是一套已经能在真实全栈项目里稳定交付的协作方式。适合谁?适合被 AI 写出来的代码反复返工的个人开发者,也适合想让 AI 参与交付的 3 到 10 人小团队。整套东西没有一个环节依赖玄学,安装成本也不高,后面我会一步步演示。
1.1 从 vibe coding 到“写得越多,返工越多”
2025 年初我还挺迷 vibe coding 的,打开编辑器,给 Claude 丢一句话,看着它噼里啪啦生成几百行代码,那种爽感确实上头。但项目一复杂,问题就来了。你让 AI 加一个“用户备注”字段,它可能顺手改了列表页的排序逻辑,或者把另一个接口的返回结构给动掉,而且它不会主动告诉你。返工几次之后你会发现,问题不在于 AI 能力不够,而在于缺少一个约束它的“基准线”。
这个基准线,就是规范。规范不是写给人看的文档,而是给 AI 的行动边界。你定义好输入、输出、验收条件,它才不会在自由发挥的道路上越走越远。SDD 做的事情,就是把“先写规范,再写代码”这件事变成工程纪律,而不是靠运气。
我见过不少团队一开始对“写规范”特别抵触,觉得是流程绑架。但放到 AI 编程的场景下,规范其实是帮 AI 节省上下文、帮人节省返工时间的东西。AI 的上下文窗口再大,也装不下整个项目。如果有一个结构良好的规范文件,它只需要读那一个文件,就知道该动哪些文件、不该动哪些文件、做到什么程度算完成。
1.2 Birgitta Böckeler 的三级分类框架
SDD 不是新概念,但因为 AI 编程,它重新火了起来。今年我认真读了一遍 Thoughtworks 工程师 Birgitta Böckeler 提出的 SDD 三级分类框架,收获其实挺大。这个框架把“写规范”从“凭感觉”变成“分级别”,让团队可以根据功能风险选择到底写多细。
第一级,把“要做什么”写清楚。这是最基础的描述型规范,解决的是业务需求到功能列表的翻译问题。对 AI 来说,这一级能让它不跑题。比如“增加用户备注功能”,背后要包含字段、接口、页面入口,这些写清楚,AI 就不会把备注做成一个独立模块。
第二级,把“怎么实现”定下来。包括技术选型、模块划分、接口约定、数据模型。这一级解决的是多个文件、多个服务之间的协作问题。尤其在全栈项目里,AI 经常出现“前端调用的接口路径和后端定义的不一致”这类问题,根本原因就是实现层面的规范缺失。
第三级,把“怎么验收”变成可执行的检查。具体到测试用例、契约测试、性能指标。AI 实现完之后,可以自己跑检查,而不是靠人肉 Review 猜它有没有做对。我在实际操作中的习惯是:内部工具页面用第一二级,核心支付链路用第三级,甚至会把验收条件直接写成测试用例的标题。
1.3 SDD 到底解决了什么工程问题
SDD 这套方法论之所以在 AI 编程时代变得重要,是因为它精准踩中了几个痛点。
第一,上下文窗口有上限。AI 看不到整个代码库,它只能看到你喂给它的内容。规范文件相当于一张地图,让 AI 知道当前任务在全局中的位置。没有地图的 AI 就像只拿了几个文件就开始施工的装修队,很容易拆错墙。
第二,验收标准常常缺失。传统开发里,“做完”的定义经常在人的脑子里。AI 写代码时,如果 spec 里没有明确的验收条件,它就会用“看起来对”来代替“确实对”。比如字段长度限制、鉴权逻辑、边界条件,这些不写清楚,AI 基本不会主动处理。
第三,变更历史不可追溯。代码 diff 只能告诉你改了什么,不能告诉你为什么这么改。SDD 的 spec 文件记录了决策过程,将来 AI 再改这块代码时,可以直接读当时的 proposal,避免把别人有意设计的逻辑当成冗余代码删掉。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. OpenSpec:把规范变成可维护的工程资产
2.1 OpenSpec 是什么,为什么选它
OpenSpec 是一个基于 Markdown 的规范驱动开发框架,准确说是围绕 SDD 方法论打造的一套工程工具。它把规范文件组织成有结构的目录,再用命令行工具提供创建、校验、汇总的能力。你用纯文本写规范,它帮你管理规范的版本和流转。
我一开始也犹豫过,为什么要多引入一个工具,直接用 Markdown 文件夹不行吗?后来发现,OpenSpec 真正值钱的是它定义了规范的组织方式。它把规范拆成 proposal、task、change、capability 这些概念,让每一份规范都有明确的归属和生命周期。AI 读取起来很轻松,人能 review 的粒度也刚刚好。
选择 OpenSpec 还有几个实际原因。它是 Markdown 而不是自定义 DSL,AI 不需要额外解析器,人看起来也不费劲。它的文件结构天然适合 Git 做 diff,规范变更可以跟代码变更一起走 Code Review。CLI 还提供脚手架,可以快速生成 proposal 模板,省掉从零开始排版的时间。
2.2 目录结构与核心概念
OpenSpec 的目录结构在不同版本里会有细微差别,但核心思路一致。我拿一个实际项目举例,初始化之后大致长这样:
text复制specs/
projects/
add-user-notes/
proposal.md
tasks/
001-schema-and-api.md
002-frontend-form.md
capabilities/
auth/
capabilities.md
changes/
2025-07-15-add-refresh-token.md
projects 目录放的是“一次性功能交付”,比如“增加用户备注”。每个项目有自己的 proposal 和 task 列表。capabilities 目录放的是“系统长期能力快照”,比如认证能力、支付能力,后面每次对这个能力的修改都会追加一条 change 记录。
这种拆分的价值在于:AI 在开发一个功能时,只需要读 projects/add-user-notes 下的内容;在修改既有能力时,只需要读对应 capability 的当前状态和变更记录。它避免了一个常见问题——把所有规范堆在一个大文档里,最后谁也不想看,AI 也不知道该看哪段。
2.3 一份能直接用的 Proposal 模板
OpenSpec 的 proposal 文件不要求统一模板,但我强烈建议至少包含几个部分。给你看一份我在真实项目里用过的:
markdown复制# Proposal: 增加用户备注
## Why
用户希望在自己的资料里记录一段私人备注,方便自己识别账号。
## What
- 用户表增加 note 字段,varchar(500),默认空字符串
- GET /me 返回 note 字段
- PATCH /me 支持更新 note 字段
- 前端个人资料页增加备注输入框
## Acceptance Criteria
- 没有备注时,GET /me 返回 note=""
- 输入超过 500 字时,PATCH /me 返回 400
- 用户只能更新自己的备注,不能影响其他用户
- 前端保存成功后展示成功提示,失败时保留输入内容
## Out of Scope
- 不做备注的富文本编辑
- 不做备注的搜索与分享
## Risks
- 用户表新增字段可能影响现有序列化逻辑,需要同步更新
Why 段落给 AI 讲清楚业务背景,What 段落圈定改动范围,Acceptance Criteria 段落给出可验证的完成标准,Out of Scope 段落明确告诉 AI “这些事不要做”。最后面 Risks 是给 AI 提醒容易踩坑的地方。
我实际用下来,Out of Scope 是最容易被忽略但最有用的一节。AI 特别容易在实现过程中自己加戏,比如顺手做了一个备注搜索功能。没有这一节,你就要在 code review 时一条条驳回。
2.4 写规范时的三条红线
规范写得好不好,直接影响 AI 的执行质量。我总结了三条红线,每一条都是踩过坑之后才总结出来的。
第一,别写形容词。“界面友好”“体验流畅”“性能良好”这类描述,AI 无法验证,写了等于没写。验收条件必须是可观测的:返回什么状态码、字段值是什么、耗时小于多少毫秒。如果一句话没法转成测试用例,就应该改写成可验证的描述。
第二,范围要写反例。只写“做什么”还不够,一定要写“不做什么”。AI 的默认行为是尽量多做,你不拦着,它就会顺手重构周边代码。明确写出“本次不改动列表页排序逻辑”“本次不引入新的状态管理库”,AI 才会收敛手脚。
第三,规范必须进版本库。写在聊天记录里的规范不算规范,写在某个在线文档里的规范也会很快过期。规范要和代码放在同一个仓库里,跟随代码一起变更、一起 review、一起合并。这样每条代码改动都能对应到一份规范变更,将来回溯时也有据可查。
3. SuperPowers:给 AI 编码 Agent 加装技能包
3.1 SuperPowers 是什么,不是什么
SuperPowers 是社区里流行的一套 Claude Code 技能集,可以理解为给编码 Agent 安装的“职业技能包”。它把 brainstorm、planning、TDD、subagent 驱动开发这些工作流,做成一个个结构化的 skill 文件。Agent 在对话中会根据任务描述自动选择合适的技能来调用。
它不是魔法。SuperPowers 的本质是用 Markdown 文档把高级工作流固化下来,让模型按照 SOP 执行。模型本来就会写代码,但有了技能包之后,它更像一个有经验的老工程师:先做方案,再拆任务,再写测试,最后实现功能,而不是抓起键盘就写。
这正好和 SDD 形成互补。SDD 解决的是“做什么、为什么做、怎么验收”,SuperPowers 解决的是“开发过程中用哪套标准动作去执行”。一个偏工程管理,一个偏个人工作法。
3.2 安装和接入项目的三种方式
SuperPowers 的安装方式在不同版本里有变化,我建议以官方 README 为准。这里分享我常用的项目级接入方式,对团队协作更友好。
先把技能仓库 clone 下来,再把需要的技能复制到项目的 .claude/skills 目录:
bash复制git clone https://github.com/obra/superpowers.git
mkdir -p .claude/skills
cp -r superpowers/skills/* .claude/skills/
如果你用的是新版 Claude Code,也可以在对话中输入 /install-skill,然后选择本地技能路径,让工具自己完成安装。还有一种做法是把技能放到个人全局目录,这样所有项目都能用,但我更建议放项目级目录,因为版本可控、成员同步方便。
接入项目后,记得在项目根目录的 CLAUDE.md 或者 AGENTS.md 里写一句“本项目已启用以下技能”,让 AI 知道这些技能存在。这一步很多人会漏掉,结果技能装好了但 AI 从来不用。
3.3 核心技能拆解
我把 SuperPowers 里几个核心技能的功能和适用场景整理成了一张表,方便你对照使用。
| 技能 | 典型用途 | 什么时候用 |
|---|---|---|
| brainstorm | 需求分析、方案头脑风暴 | 写 spec 之前,先让 AI 帮忙补全思考盲区 |
| planning | 将大任务拆解成可执行步骤 | spec 被接受后,正式开发前 |
| tdd | 测试驱动的实现循环 | 写代码阶段,强制先写测试再写实现 |
| subagent-driven-development | 把子任务派发给子 Agent 处理 | 任务复杂、上下文窗口紧张、需要并行处理时 |
拿 tdd 技能来说,它不只是告诉 AI“要写测试”,而是定义了一整套循环:先写一个失败测试,再运行测试确认失败,再写最小实现让测试通过,最后重构。这套节奏如果靠人肉在提示词里描述,每一轮都要重复一遍。做成技能之后,AI 自己知道下一步该干什么。
3.4 和 OpenSpec 组合时的调用策略
OpenSpec 和 SuperPowers 的配合,可以理解成“规范层”和“行为层”的嵌套。OpenSpec 负责告诉 AI 要交付什么、验收标准是什么;SuperPowers 负责告诉 AI 开发过程中应该按什么步骤走。
我现在的固定流程是这样:先用 OpenSpec 写 proposal,再由 SuperPowers 的 planning 技能把 proposal 转成任务清单,然后进入 tdd 技能循环实现功能,最后用 subagent 技能做一次反向 review。每一层各司其职。
为了让 AI 自动遵循这个流程,我通常在项目根目录放一份 AGENTS.md,内容很简单:
markdown复制# Agent 工作规则
- 动代码前,先阅读 specs/ 下与任务相关的 proposal 和 task。
- 如果任务缺少验收标准,必须向用户确认,禁止自行假设。
- 开发功能时优先使用 tdd 技能。
- 修改范围严格按照 proposal 的 What 和 Out of Scope 执行。
这样每次开新会话,AI 第一件事就是读取这份规则,相当于把方法论固化在项目里。
4. 实操:一次全栈功能从规范到提测的完整过程
4.1 场景定义与项目初始化
光讲概念不够,我拿一个非常常见的场景走一遍完整流程。假设现在要给一个 React + Express 项目增加“用户备注”功能。需求是:用户在个人资料页可以保存一段备注,最长 500 字,只对自己可见。
项目还没初始化,先建目录、初始化 Git、再初始化 OpenSpec:
bash复制mkdir sd-demo
cd sd-demo
git init
openspec init
OpenSpec 初始化会在项目根目录生成 specs 文件夹。这个文件夹很快就会变成整个开发流程的事实标准,后续所有规范都往这里放。
4.2 用 OpenSpec 写“用户备注”规范
初始化完成后,创建一个新的 proposal:
bash复制openspec proposal create add-user-notes
这个命令会生成一个空的 proposal 文件,我直接填入前文展示过的内容。注意我把验收条件写得特别具体,因为后面 AI 实现时,我会要求它把每一条验收条件映射到测试用例上。
这里有一个很关键的细节:task 拆分最好在 proposal 里就规划好。我的做法是拆成两个任务,一个是后端接口与数据库,一个是前端交互。拆完 AI 实现的时候不会一把抓,而是分步执行,每一步都有独立的完成标准。
4.3 用 SuperPowers 加 Claude Code 实现功能
spec 写好后,在项目里启用 SuperPowers 技能,然后开一个 Claude Code 会话。我使用的提示词有固定套路:
text复制请先阅读 specs/projects/add-user-notes/ 下的 proposal.md 和 tasks/ 目录下的任务拆分。
严格按照 Acceptance Criteria 实现功能,使用 tdd 技能,先写测试再写实现。
不要修改 spec 中没有提到的文件和逻辑。
这一步相当于告诉 AI:你的工作依据是规范,不是自由意志。实际操作中,AI 会先读 proposal,然后执行 tdd 技能。它会先写一个类似这样的后端测试:
ts复制describe("PATCH /me note", () => {
it("updates the current user's note", async () => {
const res = await request(app)
.patch("/me")
.send({ note: "hello" });
expect(res.body.note).toBe("hello");
});
it("rejects notes longer than 500 chars", async () => {
const res = await request(app)
.patch("/me")
.send({ note: "a".repeat(501) });
expect(res.status).toBe(400);
});
});
测试先红后绿,AI 才会去实现数据库迁移和接口逻辑。整个过程中我基本不需要盯着每一步,只需要在阶段结束时 review diff。
4.4 验证、Review 和提交
实现完成后,进入验证环节。我会手动跑一遍测试,再让 AI 自己总结改动列表。命令大致是这样:
bash复制npm test
npm run build
git add -A
git commit -m "feat: add user notes"
提交前,我会再看一眼 spec 和代码是否一致。OpenSpec 的命令行工具在较新版本里提供了变更汇总能力,可以自动基于最近一次提交生成 PR 描述。不同版本命令有差异,你装好之后可以先跑 openspec --help 确认一下。
Review 时重点看三样东西:数据库迁移是否符合规范中的字段定义;接口是否严格处理了 500 字限制;前端把错误状态处理好没有。只要 spec 写得到位,这三个问题 AI 一般都能自己处理掉,剩下的只是一些样式细节。
4.5 过程中真实发生过的翻车现场
这套流程并不是第一次就完美跑通的。我最开始做类似功能时,AI 在数据库里用了 TEXT 类型而不是 VARCHAR(500),测试全绿但没满足字段长度限制。原因是验收标准写在 spec 里,但 AI 生成的测试根本没有覆盖长度边界。后来我改了策略,在 spec 里的每一条验收标准后面加上“对应测试用例”,要求 AI 保证每一个验收标准都有测试兜底,这个问题就很少再出现。
另一类翻车是 AI 在实现后端时,顺手把 PUT /me 也加上了,理由是“ PUT 更符合幂等语义”。规范里写的是 PATCH,它自己加了额外接口。虽然不影响功能,但多了没有 review 过的 API 面,长远看是隐患。这就是为什么 Out of Scope 一定要写清楚,并且在 AGENTS.md 里明确“不要实现规范之外的接口”。
5. 常见问题与排查技巧实录
5.1 AI 不按规范执行怎么办
这是被问得最多的问题。规范写了,AI 不读,或者读了不遵守。我的排查顺序是固定的。先确认规范文件有没有真正进入 AI 的上下文。在 Claude Code 里,AI 只会看你明确打开或读取的文件,不是仓库里所有文件它都知道。如果提示词只是说“项目里有规范”,AI 未必会去找。
解决办法是在 AGENTS.md 里写上“动代码前,阅读 specs/ 对应的 proposal 和 task”,并在每个会话的提示词里直接点出具体路径。如果 AI 还是不执行,多半是验收条件写得不够可验证,或者范围太模糊。把问题描述从“优化用户体验”改成“当请求参数缺失时返回 400”,AI 的执行准确率会显著提升。
5.2 SuperPowers 技能不触发怎么办
技能装的没问题,但 AI 就是不调用,通常是因为技能的 description 写得太泛。Claude Code 的技能选择依赖描述和当前任务的相关性,如果 description 写着“Use this skill for development”,AI 很难判断什么时候触发。
我现在的做法是把 description 写成带触发条件的句子,例如“用户要求开始写功能代码时,必须先使用本技能生成测试计划,并按测试驱动开发循环执行”。这样 AI 在遇到写代码类任务时,就很容易选中这个技能。另外检查一下技能目录是否真的在 .claude/skills 下,层级不要多套一层,装完重启会话让它重新扫描。
5.3 上下文窗口爆掉的三种解法
全栈项目一复杂,AI 的上下文很容易被塞满。我现在常用三种解法。
第一种,OpenSpec 的规范文件尽量精简。proposal 控制在 50 到 100 行以内,task 再拆细,每次只让 AI 读当前 task,而不是整个 proposal 加所有历史变更。第二种,使用 SuperPowers 的 subagent 技能,让主 Agent 把任务派发给子 Agent,子 Agent 独立处理后把结果汇总回来,这样主 Agent 的上下文只留关键信息。第三种,及时使用 /compact 压缩历史对话,压缩前把规范和 AGENTS.md 的路径重新强调一遍,避免压缩后 AI 丢失工作依据。
5.4 多人协作时规范漂移怎么防
一个人用的时候,规范漂移问题不严重,因为你自己能记住。多人协作时,AI 生成的代码经常先合到了主分支,spec 却还停留在 proposal 状态。要防这个问题,得从流程上卡。
我的做法是在 PR 模板里加一个必选 checkbox:“本次改动是否同步更新了 specs/ 下对应文档”。同时在 code review 时,如果发现代码里出现了 spec 没有定义的行为,直接打回。还有一个土办法但很有效:把规范变更和代码变更放在同一个 commit 里。这样 review 时看到代码 diff 旁边就有 spec diff,两个不一致一眼就能看出来。
5.5 问题速查表
| 问题 | 可能原因 | 解决办法 |
|---|---|---|
| AI 不读规范 | 规范没进入上下文 | 在提示词和 AGENTS.md 中明确给出 spec 路径 |
| AI 改超出范围 | Out of Scope 缺失或太简单 | 在 proposal 中明确写出不做什么 |
| 规范写了但测试没覆盖 | 验收标准不可验证 | 每条验收标准都要能映射到测试用例 |
| SuperPowers 技能不触发 | description 缺少触发条件 | 重写 description,加入明确的触发场景 |
| 上下文爆掉 | 一次塞入过多任务文件 | 拆小 task,用 subagent 分发 |
| 多人协作 spec 和代码不一致 | 缺少流程约束 | PR 模板加 checkbox,规范和代码同 commit 提交 |
6. 最后想分享的一点习惯
最后再说一个我自己的感受。SDD 不是万能药,它会有文档成本,小到一行配置的改动也去写 proposal 确实夸张。我的习惯是:判断标准看“这次改动是否会改变外部行为或数据模型”。如果是,就值得写规范;如果只是改文案,那就直接改。但不管哪种,我都会在 commit 时问自己一句:如果 AI 明天要改这块代码,它能找到依据吗。
这套 OpenSpec 加 SuperPowers 的组合,本质上就是把依据留在了代码旁边。规范不是给 AI 找麻烦,而是让 AI 在没有你随时盯着的时候,仍然按同一个标准干活。这个习惯帮我省下的返工时间,远比写规范花掉的时间多。
