OpenSpec + Superpowers:构建SDD+TDD工作流实战指南
2026/9/14 23:09:59 网站建设 项目流程

OpenSpec + Superpowers 搭建 SDD+TDD 工作流教学文档

先说个直觉:现在的 AI 编程工具写代码确实快,但写出来的东西经常跑偏——你说要做个导出功能,它顺手给你改了配置文件;你说要加个缓存,它把整个查询逻辑重写了。问题不出在 AI 本身,出在我们没有给它一个可执行的流程约束。OpenSpec 和 Superpowers 这套组合,就是冲着这个痛点去的:OpenSpec 负责把需求写成机器可读的规格文档,Superpowers 负责在 Codex CLI 里注入一套能"照着规格干活"的技能,SDD(规格驱动开发)管设计,TDD(测试驱动开发)管验证,两条线拧成一条流水线。这篇文章我会从环境准备、流程设计、实际踩坑三个层面,完整介绍这套工作流的搭建方法,适合已经在用 AI 辅助编程、但对代码质量有要求的开发者和技术团队参考。

1. 从混乱到有序:这套工作流到底解决了什么问题

1.1 AI 编程的失控点不在代码,在上下文

我踩过最典型的坑是这样的:让 AI 帮我实现一个"通过搜索关键词筛选文件列表"的功能,它确实把搜索逻辑写对了,但顺手把结果排序从"按修改时间"改成了"按文件名"。单看代码没问题,单测也能过,但产品经理看一眼就炸了。这种问题反复出现的根源在于,传统对话式编程把需求藏在聊天记录里,AI 只能靠上下文猜测"什么该做、什么不该做",一旦上下文窗口滚上去,前面的约束就变成了模糊记忆。

OpenSpec 的思路是把需求从对话里拿出来,变成仓库里的 Markdown 文件。每个功能需求、每条验收标准、每个边界条件都被写成明确条目,AI 在动手前会先读这些文件,所有决策都基于规格文档而不是对话记忆。规格即契约,代码和测试都围绕这份契约展开,AI 的"自由发挥空间"被压缩到可控范围。

1.2 SDD 管"做什么",TDD 管"对不对"

SDD 和 TDD 并不是二选一的关系,而是上下游关系。SDD(Specification-Driven Development)关注的是需求定义:这个功能要解决什么问题、有哪些输入输出、边界条件是什么、怎么验收。TDD(Test-Driven Development)关注的是代码验证:先写一个肯定会失败的测试,再写最小代码让测试通过,最后重构。前者回答"做什么",后者回答"有没有做对"。

把两者组合起来以后,整个流程变成了这样:规格文档定义需求和验收标准 → AI 根据规格拆解任务并生成失败测试 → AI 写最小代码让测试通过 → 重构消除重复代码。每一步都有明确输出物,每一步都有验证手段。这跟我们以前手动写需求文档、写测试用例、写实现代码的顺序完全一样,但全部交给 AI 按流程执行,人只负责审查关键节点。

这套流程适合谁?适合所有用 AI 写代码、但不想被 AI 的"过度自信"坑到的人。不管你是独立开发者还是团队协作,只要代码要上线、要维护,规格先行就值得做。它不能替代你的判断力,但它能逼你在让 AI 动手之前先把需求想清楚。

2. 环境准备:OpenSpec 和 Superpowers 的安装与初始化

2.1 安装 Codex CLI 并注入 Superpowers 技能

Superpowers 是 Davin Reed 发布的一套 Codex CLI skills 集合,本质上是给 AI 预装了一套工作技能包,里面包含 TDD workflow、plan writing、debugging 等多个可复用的技能模块。安装方式取决于你用的 CLI 客户端,如果你用codex作为交互终端,命令是这样的:

# 1. 确保 Codex CLI 已安装并完成登录 codex --version # 2. 把 Superpowers 技能克隆到 Codex 的 skills 目录 git clone https://github.com/workflow-superpowers/book-codex.git ~/.codex/skills # 3. 用 workbuddy 批量安装 skill 包(可选,推荐) npx workbuddy@latest install skill superpowers

用 workbuddy 安装的好处是它会自动处理 skill 之间的依赖关系,并且注册到一个统一的技能管理列表里。安装完成后,进入 Codex 交互界面,输入superpowers关键字,如果能看到对应的技能加载信息,就说明安装成功。

注意:Superpowers 本质上是外置技能包,不同版本对 Codex CLI 的兼容性略有差异。我用的版本要求 Codex CLI 在 0.42 以上,如果你的版本太旧,技能包注册后可能不会被读取。遇到这种情况先升级 CLI,不用急着排查技能文件本身。

2.2 初始化 OpenSpec 规范目录

OpenSpec 本身是一个轻量级命令行工具,核心是"目录即规范"。在你的项目根目录下执行:

# 安装 OpenSpec CLI npm install -g openspec # 在项目根目录初始化规范目录 cd /path/to/your/project openspec init

初始化过后,项目里会生成一个openspec/目录,默认结构如下:

openspec/ ├── specs/ # 存放当前有效的规格文档 ├── changes/ # 存放工作中的变更提案 └── proposals/ # 存放历史提案归档

这个结构跟 Git 的.git目录有点像——它不参与业务代码编译,但所有 AI 编程流程都以它为准。每个新功能启动前,你需要新建一个change提案,提案里写清楚"要改什么、为什么改、验收标准是什么",AI 会根据这份提案去拆任务、写测试、写实现。规格腐化成摆设,本质上是大家嫌写文档麻烦,但 OpenSpec 的粒度足够小,一个提案一页纸就够,成本完全可控。

2.3 环境变量的额外配置

为了让 Codex CLI 在读取规格后能自动执行"先测试后实现"的流程,我建议在 shell 配置文件里加一个变量,让 AI 的高风险操作默认进入审查模式:

# ~/.zshrc 或 ~/.bashrc export CODEX_HIGH_RISK_OPERATIONS="plan"

这样 AI 在准备执行规格任务时,会先生成一份详细计划供你确认,而不是直接开始改代码。对团队协作来说,这一步能极大减少"AI 改了不该改的文件"这类事故。

3. 核心实操流程:从一个真实功能跑通 SDD+TDD 闭环

3.1 写规格:把需求变成可验收的 Markdown

理论讲再多不如跑一遍真实流程。我选了一个有代表性的小功能来做演示:给一个命令行书签管理工具增加"通过关键词搜索书签并按时间排序"的能力。需求描述看起来很简单,但信息量挺大——有输入、有输出、有排序规则、有时间字段。

先创建一个变更提案:

openspec new add-search-to-bookmark

这会生成openspec/changes/add-search-to-bookmark/spec.md,我在此基础上填入了完整规格:

# 变更提案:add-search-to-bookmark ## 变更类型 新增功能 ## 原因说明 用户目前无法快速从大量书签中找到目标条目, 需要通过关键词过滤并以可预期的方式排序结果。 ## 规格详情 ### 需求描述 新增一个 `bookmark search` 子命令,按关键词过滤现有书签, 结果按"创建时间倒序"排列。 ### 实现要点 - 支持大小写不敏感的关键词匹配,匹配范围包括标题和 URL。 - 输出内容包括:ID、标题、URL、创建时间。 - 无匹配结果时返回空列表并给出友好提示。 - 排序顺序固定为创建时间倒序,即最新创建的排在最前面。 - 不得修改现有书签创建、删除、列表命令的行为。 ### 验收标准 - [ ] `bookmark search keyword` 返回所有标题或 URL 中包含关键词的书签。 - [ ] 输出内容按创建时间倒序排列。 - [ ] 关键词匹配不区分大小写。 - [ ] 不改变其他子命令的现有行为。 - [ ] 无匹配结果时输出提示信息,退出码为 0。

规格里那句"不得修改现有行为"是我特别加的。AI 在改代码时经常顺手"优化"掉其他逻辑,验收标准里明确写出来,运行时才有依据去约束它。写完规格后保存,这份文档就是后续所有 AI 操作的地图。

3.2 让 AI 拆解任务并生成失败测试

打开 Codex CLI,进入项目目录,给 AI 明确指令:

请阅读 openspec/changes/add-search-to-bookmark/spec.md, 按 TDD 方式完成该功能。先拆分任务,再对每个任务编写失败测试, 不要开始写实现代码。

如果 Superpowers 加载正常,AI 会调用 TDD 工作流技能,输出一份任务清单,类似这样:

  1. 创建bookmark search命令入口和参数解析。
  2. 实现关键词过滤逻辑(标题 + URL,忽略大小写)。
  3. 实现创建时间倒序排序。
  4. 实现空结果提示。
  5. 添加或调整测试,覆盖上述行为。

随后它会为每个任务生成测试文件。以 Node.js 项目为例,测试代码会是这个样子:

import { describe, it, expect } from 'vitest'; import { searchBookmarks } from '../src/search.js'; describe('bookmark search', () => { const bookmarks = [ { id: 1, title: 'OpenAI Blog', url: 'https://openai.com/blog', createdAt: '2024-01-10' }, { id: 2, title: 'Dev.to', url: 'https://dev.to', createdAt: '2024-02-15' }, { id: 3, title: 'GitHub Docs', url: 'https://docs.github.com', createdAt: '2024-03-01' } ]; it('应按关键词过滤标题和 URL,且不区分大小写', () => { const result = searchBookmarks(bookmarks, 'open'); expect(result).toHaveLength(2); }); it('应按创建时间倒序排列', () => { const result = searchBookmarks(bookmarks, ''); expect(result[0].id).toBe(3); expect(result[1].id).toBe(2); }); it('无匹配结果时返回空数组', () => { const result = searchBookmarks(bookmarks, 'not-exist'); expect(result).toEqual([]); }); });

这时候跑测试,结果一定是失败的,因为实现文件还不存在。这个"红灯"状态非常重要,它是 TDD 的起点,证明测试真的在起作用。

实操心得:让 AI"先写测试再写实现"这个顺序,如果你不明确说明,它十有八九会反过来。Superpowers 的 TDD skill 会自动约束这个顺序,但如果你没装 Superpowers,就必须在提示词里强调"不得先写实现代码,测试通过前不得编写业务逻辑"。

3.3 最小化实现与绿灯通行

测试写好后,给 AI 下第二阶段指令:

现在实现业务逻辑,目标是让现有测试通过。不要添加测试未覆盖的功能。 每通过一个测试就汇报一次进度。

AI 会开始逐步实现代码,每次实现后运行测试。如果某个测试挂了,它会根据失败信息修正实现,直到全部变绿。这里有个细节值得注意:最小化实现阶段,AI 往往会把代码写得很简陋。比如为了满足"关键词不区分大小写",它可能直接写了toLowerCase()硬比较,没考虑 URL 解码之类的边界情况。这其实是 TDD 的正常节奏——先让行为正确,再回来优化结构。绿灯之后,代码结构问题用重构阶段解决。

实测中这一步最耗时的地方往往是"AI 写的测试和实现相互印证但都理解偏了需求"。比如我们规定"匹配范围包括标题和 URL",但 AI 写测试时只测了标题,实现也只过滤了标题。这时候规格文档就派上用场了,我会直接指出"规格第 3 条明确写了 URL 也要匹配,请补充对应测试用例"。如果规格里没写,AI 可能永远意识不到自己漏了什么。

3.4 重构与回归:用规格文档守住边界

全部测试通过后,进入重构阶段。我给 AI 的指令是:

测试已全部通过。现在在不改变行为的前提下重构代码, 重点是消除重复逻辑、提升可读性,同时保持测试全绿。

这个阶段 AI 可能做的事情包括:把过滤和排序拆成独立函数、提取常量、统一错误提示格式。每次重构后都必须跑一遍完整测试,确认没有破坏已有行为。我们的规格里写了"不得修改现有书签创建、删除、列表命令的行为",所以重构结束后我会手动跑一遍回归测试,确保其他命令一切正常。

到这里,一个功能已经从"需求描述"变成了"有规格、有测试、有实现、有重构"的完整闭环。整个过程里我做的最重要的事情不是写代码,而是在每个阶段确认 AI 的输出没有偏离规格。规格文档是唯一的事实来源,测试是唯一的验收标准,剩下的执行交给 AI。

4. 常见问题与排查技巧实录

4.1 高频问题对照速查表

问题现象可能原因解决方式
AI 直接写实现代码,忽略"先写测试"指令所用 skill 包未加载或未安装 TDD skill执行npx workbuddy@latest install skill superpowers重新安装,并在提示词里重复强调 TDD 顺序
测试通过了,但功能行为明显与需求不符规格文档里的验收标准写得太模糊,AI 只按自己理解实现回到spec.md补全边界条件,增加具体示例,然后让 AI 补充测试用例再重跑
AI 改动范围超出本次规格,连带修改了别的模块开了过大的文件读取权限,或上下文里有其他模块的代码片段用 OpenSpec 的变更边界约束 AI 只能读写当前变更涉及的文件,必要时在提示词里声明"只允许修改与 add-search-to-bookmark 相关的文件"
Superpowers 技能未被 Codex 识别Codex CLI 版本过老或 skills 目录路径不对升级 Codex CLI 到最新版本;确认 skills 目录为~/.codex/skills;重启 CLI 会话
测试用例本身写错了,实现跟着测试一起错测试是在实现代码之前由 AI 生成的,但生成时依赖了实现细节测试应基于规格编写,而非基于实现。要求 AI 对照spec.md的验收标准逐条映射测试用例,避免"测试为了通过而通过"
想让 AI 终止当前操作但总是继续执行交互模式下的中断信号被忽略按两次 Ctrl+C 强制中断;或在提示词中明确"停止当前操作,等待我的下一步指令"

4.2 独家避坑心得

这套流程跑了两个月,我总结出三个最值得说的经验。

第一个经验是规格文档一定要包含"不要做什么"。人写需求时默认"没提到的就是不该做的",但 AI 恰恰相反——它倾向于把没提到的都当作"可以做"。在验收标准里明确写"不得修改现有行为""不得更换现有的数据结构""不得引入额外依赖",看起来有些多余,却能少踩很多坑。

第二个经验是不要让 AI 一次性写太多测试。我试过让它为一个大功能一次生成 20 多个测试用例,结果有一半都在测无关紧要的细节,另一半因为依赖了未实现的中间状态而反复报错。后来我改成"每个任务生成 3 到 5 个针对性测试",流程顺畅多了。小型化测试包还有一个好处:红灯出现时能更快定位到具体是哪个行为没实现。

第三个经验是定期把openspec/changes里已完成的变更归档到openspec/proposals。这个动作很多人嫌麻烦会跳过,但归档后的提案沉淀了"当初为什么这么设计"的决策记录。等三个月后你自己回来看代码,或者新同事接手项目,这些提案比任何代码注释都更有价值。OpenSpec 的设计初衷就是让规格文档和代码共同演进,变更被合并、提案被归档,项目历史就变成了一条完整的决策链。

4.3 当 AI"玩忽职守"时,手动兜底方案

偶尔会遇到 AI 无论如何都无法理解需求的情况。这时候不要在一个会话里反复纠缠,我通常的做法是把它看作一个执行器而不是协作者:手动把任务拆分得更细,比如把"实现搜索功能"拆成"第一步:创建命令入口;第二步:读取书签数据;第三步:实现过滤逻辑;第四步:实现排序逻辑",然后一条一条发给它。

这其实也是 SDD 理念的延伸——规格的粒度越细,AI 的自由度越低,执行结果就越可控。手动拆分看起来多花了几分钟,但省掉了后面调试和返工的时间,整体效率反而更高。

5. 写在最后的实践经验

这套 OpenSpec + Superpowers 的 SDD+TDD 工作流,本质上是在 AI 编程时代重新引入了工程纪律。以前我们靠人脑记忆需求约束,靠代码评审兜底,现在则可以靠规格文档和测试用例把约束固化在流程里。AI 的能力波动不可控,但流程可以做到可控。用这套流程跑了一段时间后,我最直观的感受是代码 review 的争议少了很多——大家不再争论"这个函数应该叫什么名字"这类主观问题,而是先对齐规格,再讨论实现。

最后再分享一个小的操作技巧:每次让 AI 开始一个新变更时,我都会在项目根目录建一个AGENTS.md文件,里面写清楚"请先阅读openspec/changes/当前变更名/spec.md,所有实现必须满足该文档的验收标准,测试通过前不得进入下一步"。这个文件会让 Codex 在每次会话开始时就自动加载工作流约束,相当于给 AI 装了一个"开机自启"的流程导航。我实测下来,加上这个文件之后,AI 跑偏的概率至少下降了一半。

如果你也在用 AI 写代码,我建议你从一个小功能开始尝试这套工作流。不用一开始就追求完整规范,先跑通一遍,感受一下"规格先行"和"测试先行"带来的变化。等你跑顺了两个变更,再回来补齐团队规范也会更容易落地。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询