1. 这套组合到底是什么,以及为什么值得搭
先说结论:OpenSpec 加 Superpowers 搭建的 SDD+TDD 工作流,本质上是在 AI 辅助编程时代,替你把"需求怎么描述、任务怎么拆解、产出怎么验证"这三件事标准化。用 OpenSpec 管需求和规格,用 Superpowers 给 AI 补上"先规划、再执行、后验证"的工程习惯,再用 TDD 给每一次代码改动装上安全网。这套东西最适合两类人:一类是重度使用 Claude Code、Codex CLI 这类 AI 编程工具的开发者,另一类是想在团队里推广 AI 开发流程、但苦于 AI 产出不可控的技术负责人。
先说我的实际感受。过去我用 AI 写代码,最头疼的不是它写不出来,而是它"太听话"——你说加个 URL 校验,它把整个工具类重写了;你说优化一下性能,它顺手改了接口签名。改完你觉得不太对,又说不清楚哪里不对。这套工作流的核心价值,就是把"我觉得不太对"变成"这里有明确的验收标准,测试没过"。
SDD(Spec-Driven Development)管的是"做什么":需求必须是结构化、可校验、有验收标准的文档,而不是聊天框里的几段话。TDD(Test-Driven Development)管的是"怎么证明做对了":每个任务先写测试,测试红了才允许写实现,实现到测试绿了才算完。Superpowers 则是这套流程的"搬运工",它把 plan、test-driven-development 这些方法论封装成 AI 客户端能直接调用的技能(Skills),让 AI 按照规范一步步执行,而不是自由发挥。
说实话,这套组合并不复杂,也没有引入什么重型框架。它的底层逻辑非常朴素:把好团队的开发纪律,翻译成 AI 能理解的指令。下面我按搭建顺序,把每一步的来龙去脉和实操细节都拆开讲。
2. 三层架构:SDD 管方向,TDD 管验证,Superpowers 管执行
2.1 为什么先说 OpenSpec,它到底解决了什么
OpenSpec 是一个基于 Markdown 的规格管理工具,它最大的特点就是"轻"。不需要建设独立的规格管理系统,不需要学习专门的规格语言,就是用 Markdown 文件管理需求,用 CLI 命令校验规格的完整性。它的目录结构一般是这样的:
specs/ url-validator/ spec.md proposal.md tasks.mdspec.md 是这个功能模块的"宪法",里面写了这个模块要解决什么问题、有哪些需求点、每个需求点的验收标准是什么。proposal.md 记录变更提案,tasks.md 是拆解出来的开发任务列表。CLI 会校验这些文档之间的引用关系是否完整,验收标准是否可追踪。
OpenSpec 解决的核心痛点是"需求漂移"。在没有 OpenSpec 的时候,你给 AI 的描述是这样的:"帮我写一个 URL 校验函数,要支持 http 和 https,还要能处理国际化域名。"这句话看着清楚,实际上充满了歧义——要不要自动加上协议前缀?校验不通过是返回 false 还是抛异常?超长 URL 算不算非法?AI 每次理解的都不一样,你每次都要重新解释。一旦把这些内容写进 spec.md,变成"输入参数是什么、输出是什么、哪些情况必须返回 false"这种明确条文,AI 的执行稳定性立刻上一个台阶。
我在实践中发现一个特别有意思的现象:OpenSpec 的收益不只是给 AI 看的,更是给自己看的。当你被迫把需求写成"验收标准:当输入包含中文字符时,校验结果为 false"这种句子时,你才会发现自己原本的需求有多模糊。很多时候需求不清,不是产品经理没说清楚,是开发自己就没想清楚。
2.2 TDD 为什么在 AI 时代反而更重要了
传统观点认为 TDD 会拖慢开发速度,这种说法在人工开发时代还有讨论空间,但在 AI 编程时代完全站不住脚。AI 生成代码的速度极快,但它生成的代码质量方差极大——上一秒还在写优雅的闭包,下一秒就可能写出一个遗漏边界条件的循环。人肉 review 每一行 AI 代码既不现实也不高效,更可靠的方式是:让测试来验收。
TDD 的标准循环是 Red-Green-Refactor,也就是先写一个失败的测试,再写让测试通过的最小实现,最后在测试保护下重构。这个循环对人类开发者来说是一种纪律,对 AI 来说则是一种极强的约束。因为 AI 在自由发挥时会倾向于"多做"——你说要校验 URL 格式,它顺手把 URL 规范化也做了,结果行为超出了你的预期。但如果你先写好测试,AI 就会倾向于"只做让测试通过的事",因为测试就是它的验收单。
举个例子,给 URL 校验工具写测试时,我会写出这样一组成熟用例:合法 URL 返回 true、无协议 URL 返回 false、包含空格的 URL 返回 false、只传一个空字符串返回 false、传入 null 返回 false。然后让 AI 对着这组测试写实现。AI 看到测试里明确写了"无协议也返回 false",它就不会自作主张加上自动补全协议的逻辑。测试就是需求的编码化表达,表达能力比自然语言强得多。
2.3 Superpowers 在这套组合里扮演的角色
Superpowers 来源于开发社区,是一组开放技能集(Skills),它把工作流封装成 AI 客户端可调用的模块。其中最核心的两个技能是 Plan 和 Test-Driven Development。Plan 技能负责在动手写代码前,先产出任务列表和实施计划;TDD 技能负责执行测试先行的开发循环。
你可以把 Superpowers 理解成一个"项目经理":它不直接替你写业务代码,而是负责把需求拆成有序任务、在每个任务开始前选取合适的执行策略、在任务结束时提醒你进行验收。它的价值在于把 SDD 和 TDD 的流程"固化"到 AI 的执行逻辑里。没有 Superpowers 时,你需要用口述的方式要求 AI"先写规格、再拆任务、先写测试、再写实现",AI 大概率做着做着就乱了;有了 Superpowers,AI 会按照预设的技能逻辑自动走完整条流水线。
从实际使用体验看,Superpowers 对 Claude Code 的适配度最高,因为 Claude Code 原生支持 Skills 目录。Codex CLI 等其他工具也可以通过配置文件加载,但体验略有差异。我建议先把 Claude Code 跑通整套流程,熟练后再迁移到其他环境。
3. 环境搭建:从零开始把所有工具接起来
3.1 安装 OpenSpec CLI 与初始化项目
OpenSpec 的最新版本是作为 CLI 工具分发的,安装方式取决于你的 Node.js 环境。在 macOS 和 Linux 上,我一般直接通过 npm 全局安装:
npm install -g openspec openspec --version需要注意的是,OpenSpec 迭代速度很快,不同版本的命令可能有细微差异。安装完成后,先执行初始化命令让当前项目生成标准的 specs 目录结构:
openspec init这条命令会在项目根目录创建 specs 文件夹以及必要的模板文件。如果是在已有代码仓库里初始化,OpenSpec 不会动你的代码,它只添加规格管理相关的目录和配置,这一点可以放心。
初始化完成后,建议先跑一遍空校验,确认规格体系本身是健康的:
openspec validate此时应该有"校验通过"或类似的提示。如果在这里就报错,大概率是 Node.js 版本太低或者目录权限有问题。后面写规格文档踩坑时,validate 命令会是你的主要排查工具。
3.2 把 Superpowers Skills 装进 AI 客户端
Superpowers 的安装相对简单,它本质上是把一组 Markdown 格式的技能说明文件放到 AI 客户端指定的目录里。以 Claude Code 为例,技能目录通常在项目的 .claude/skills 下,或者用户级目录 ~/.claude/skills 下。安装步骤是:先把 Superpowers 仓库克隆到本地,再把其中的 skills 目录内容复制到上述位置。
git clone https://github.com/your-superpowers-repo mkdir -p ~/.claude/skills cp -r your-superpowers-repo/skills/* ~/.claude/skills/复制完成后,重启 Claude Code,在会话里输入斜杠命令检查技能是否加载成功。如果技能列表里出现了 plan、test-driven-development 等名称,就说明安装成功。如果没出现,优先检查目录路径是否正确,以及技能文件是否为 Markdown 格式。
这里有一个我踩过的坑:如果你同时配置了项目级技能目录和用户级技能目录,AI 可能会优先加载项目级目录里的同名旧版本技能,导致新版本不生效。所以安装新版本前,先检查两处目录是否有同名文件,重复了就清理掉旧的一侧。
3.3 验证整套环境是否可用
环境装好了,别急着写正式需求,先跑一个最小验证。我习惯用"写一个加法函数"这种题目来做冒烟测试。具体做法是:先创建 specs/add-function/spec.md,描述一个接收两个数字并返回和的函数,写明验收标准;然后启动 AI 会话,调用 plan 技能让它拆解任务;再调用 TDD 技能让它执行"先测试后实现"。
如果这些步骤都能在无人干预下完成,并且最终测试通过,说明 SDK + TDD + Superpowers 的组合已经可以跑起来了。这个冒烟测试听起来简单,但它能一次性暴露 80% 的环境问题:CLI 没装好、技能目录不对、提示词没有生效、测试框架缺失等等。
整套环境的复杂度不算高,但容错率也不高。组件之间的关系是链式的——SDD 依赖 OpenSpec 管理文档,TDD 依赖测试框架提供红绿反馈,Superpowers 依赖 AI 客户端的技能加载机制。任何一环断了,工作流就退化回普通的"聊天写代码"模式。这也是为什么我建议老老实实先跑一遍冒烟测试,不要一上来就处理复杂业务。
4. 实操走查:从写规格到测试通过,完整做一遍
4.1 第一步:把需求写进 specs 文档
我拿一个很常见的场景举例:给现有系统增加一个 URL 校验工具函数。这个需求听起来很简单,但用它作为演练足以覆盖 SDD+TDD 的完整流程。
打开 specs/url-validator/spec.md,我会这样描述需求:
--- name: URL Validator description: 提供 URL 格式校验能力 --- # URL Validator ## 背景 系统需要对外部输入的 URL 进行校验,防止无效 URL 进入下游逻辑。 ## 需求 - 支持校验 http 和 https 协议的 URL - 输入为空字符串或 null 时返回 false - 输入包含空格时返回 false - 输入缺少协议前缀时返回 false - 校验结果以布尔值返回,不抛异常这个 spec.md 看起来只是几行文字,但里面每一句话都对应一条可执行的验收标准。写完 spec 后,执行:
openspec validateOpenSpec 会检查 spec.md 的格式是否符合规格,以及是否有足够的结构支撑后续任务拆解。这个校验过程就是 SDD 和普通文档写作的本质区别:普通文档写错字不影响什么,规格文档写得不完整会直接导致 AI 无法拆解任务。
4.2 第二步:用 Plan 技能拆解任务
规格写完后,启动 AI 会话,对 AI 说:"请使用 plan 技能,根据 specs/url-validator/spec.md 生成任务清单。"此时 Plan 技能会读取规格文档,输出类似这样的任务列表:
## Task 1: 创建 URL 校验函数骨架 目标: 创建 urlValidator 函数,输入字符串返回布尔值 步骤: 1. 创建 src/urlValidator.js 2. 导出 urlValidator 函数 验收: 函数存在并可以调用 ## Task 2: 实现协议校验逻辑 目标: 仅接受 http/https 协议开头的 URL 步骤: 1. 解析协议部分 2. 与白名单比对 验收: 非法协议返回 false注意 Plan 技能生成的任务列表是有依赖顺序的:Task 1 是函数存在的骨架,Task 2 才是具体逻辑。这种渐进式拆分对 AI 很有必要——如果直接让 AI"实现完整功能",它大概率会一次性把边界情况和业务逻辑混在一起写,出错了极难定位。Task 列表的意义就是把大问题切成 AI 每次只需要思考一件小事的小块。
拿到任务列表后,把它保存到 specs/url-validator/tasks.md。这一步很重要,因为后续执行阶段 AI 需要反复参照任务列表,而不是凭空回忆。
4.3 第三步:按 TDD 循环逐个完成任务
现在进入最核心的环节——执行 TDD。在 AI 会话里,对 AI 说:"使用 test-driven-development 技能,完成任务列表中的 Task 1。"
TDD 技能会要求先写测试。于是 AI 先生成一个测试文件,内容类似:
import { urlValidator } from "../src/urlValidator"; import { describe, it, expect } from "vitest"; describe("urlValidator", () => { it("should be a function", () => { expect(typeof urlValidator).toBe("function"); }); });运行测试,结果是红色的(失败),因为 src/urlValidator.js 还不存在。然后 TDD 技能才会指导 AI 创建这个文件,实现最基础的函数声明,让测试变绿。第一次跑这个循环时,你会明显感受到它和普通 AI 编程的区别:AI 不再一口气写完所有代码,而是老老实实地"测试失败 -> 最小实现 -> 测试通过"这样推进。
Task 2 和后续任务的流程完全一样,只是测试内容更复杂。以 Task 2 为例,AI 会先把测试写成:
it("should reject URL without protocol", () => { expect(urlValidator("example.com")).toBe(false); });等到实现做完,测试通过后,再把所有测试整体跑一遍,确保前面的任务没有被后续修改破坏。
4.4 第四步:验收闭环与规格变更
所有任务完成后,需要做两件事:一是跑一遍完整的 openspec validate,确认规格文档和实现状态一致;二是手动检查一下验收标准里是否有覆盖不到的场景。为什么要做这个人工巡检?因为 AI 写的测试有可能"自我满足"——它严格按照需求条目设计了测试,但如果需求本身就遗漏了场景,测试也测不出来。这是 SDD+TDD 工作流的天花板,所有验证都依赖于规格文档本身的质量。
至于规格变更,这是几乎一定会发生的事。需求变了不要慌,OpenSpec 的 proposal 机制就是为变更设计的。每当你需要修改 spec.md 的行为描述时,应该先创建 proposal,比如 specs/url-validator/proposal.md,记录"变更原因、变更内容、影响范围",再更新 spec.md 和 tasks.md。这套机制的好处是变更全程留痕,AI 在后续任务中不会读取到互相矛盾的规格描述。我见过很多团队工作流跑崩,就是因为直接改了 spec.md 但没同步 tasks.md,AI 按新规格拆任务、按旧任务做开发,整个流程就乱了。
5. 这套工作流常见的问题与排查实录
5.1 问题速查表:从环境故障到流程崩坏的排查路径
工作流跑久了,问题会集中在几个固定的位置。我把高频问题整理成速查表,按出现频率排序:
| 症状 | 可能原因 | 排查思路 |
|---|---|---|
| AI 会话里找不到 plan 技能 | Skills 目录路径不对 | 检查技能文件是否在 ~/.claude/skills 下,重启客户端 |
| openspec validate 报 YAML 解析错误 | spec.md 头部格式写错 | 检查 frontmatter 的键值是否有冒号结尾、缩进是否一致 |
| AI 不先写测试,直接写实现 | TDD 技能没有被触发 | 在提示词里明确指出"必须先写测试再写实现" |
| 测试永远红,实现改不完 | 测试与实现耦合过强,或需求描述有歧义 | 检查测试是否在断言一个未定义的中间状态 |
| 任务列表与规格不一致 | 修改 spec.md 后未同步 tasks.md | 重新运行 Plan 技能,让任务列表重新生成 |
| 技能加载了但行为不符合预期 | 项目级与用户级目录存在旧版本 | 清理旧版本技能文件,保留单一版本 |
其中最隐蔽的问题是这个:TDD 技能明明加载了,AI 却不按 TDD 走。我排查过很多次,发现根源往往是提示词里包含了"快速实现""一次完成"这类诱导性词汇,或者你在规格文档里把任务描述得过于像实现指令。AI 的服从性很强,但它遵循的是"当前提示和技能约束的合力"。如果技能说"先写测试",你的提示词却说"请直接实现全部功能",AI 会倾向于完成更具体的指令。所以使用这套工作流时,提示词一定要克制:不要给 AI 更多实现层面的指令,让它完全按技能流程走。
5.2 避坑心得:AI 工作流里最贵的错误是流程错误
在具体执行层面,我最想分享的一条经验是:不要让 AI 同时推进多个任务。Plan 技能拆出来的 Task 是有依赖关系的,但 AI 在执行时会有"顺手把下一个问题也解决了"的冲动。比如 Task 2 在做协议校验,它可能会顺手把空字符串校验也实现了,正好这是 Task 3 的内容。如果这次"顺手"没有对应测试保护,一旦行为偏离预期,你根本不知道是哪个 Task 引入的问题。
所以我会在每个任务开始前明确提示 AI:"只完成当前任务,不要提前实现其他任务的目标。"这句提示看着啰嗦,但它能把 TDD 的红绿反馈保持干净:每个任务的红绿切换对应一个明确的行为变化,出问题时定位成本极低。
第二个心得是关于测试粒度的。AI 写的测试容易走两个极端:要么一个测试函数里断言了十几个场景,要么每个场景拆成一个 it() 但所有 it() 都是同一类断言。这两种方式都不利于排查。一个经验法则是"一个 it() 只断言一个行为"。行为是什么?就是你验收标准里的一句话。验收标准写了几条,测试就至少有几个 it()。这样当某个测试红掉时,你能精确地说出是哪个需求点出了问题。
第三个心得涉及一个反直觉的坑:不要为了让测试通过而让 AI 修改规格文档。TDD 的红绿循环中,AI 面临压力会倾向于"低成本过关"——比如测试要求"无协议 URL 返回 false",AI 可能认为改成"所有 URL 都返回 false"也能让这个测试通过。这种行为在单个测试内无懈可击,但会在整体验收时漏洞百出。防范方法是:在触发 TDD 技能时,同时强调规格文档是唯一权威,测试和实现都必须向规格看齐,而不是向彼此的临时状态看齐。
5.3 这套流程覆盖不到的盲区
说句公道话,SDD+TDD 工作流也不是银弹。它最大的盲区在"探索性需求"——当你完全不知道解决方案长什么样,需要反复实验和推翻时,严格的规格先行反而会拖慢节奏。比如你刚上手一个新框架,连 API 都不熟悉,这时候强行写验收标准,写出来的东西大概率会在实验中被推翻。我的建议是:探索阶段随便跑,跑通了、理解了,再补 spec,再用 TDD 重写关键路径。SDD 的本质是文档化已理解的逻辑,而不是替代人对未知的探索。
另一个盲区是 UI 和交互层面的验证。目前这套组合最顺手的场景是纯逻辑、纯函数、纯 API 服务这类"输入输出明确"的模块。UI 层面因为涉及视觉断言、交互时序、浏览器环境,TDD 的反馈回路会变得很长,AI 执行起来的稳定性也会下降。如果你要处理前端界面,可以把业务逻辑抽成纯函数纳入这套流程,UI 部分用人工 review 兜底。
6. 一些扩展想法:CI 集成和团队协作层面的玩法
这套工作流跑顺之后,可以往两个方向扩展。第一个方向是把 openspec validate 加进 CI 流水线,在每次合并代码前自动校验规格文档是否完整、任务列表是否更新、测试是否全部通过。这一步能把 SDD+TDD 从"开发者的自选动作"变成"团队的强制规范",约束力完全不一样。第二个方向是用它来批量处理遗留代码:拿旧的业务模块练手,先补 spec,再补测试,再重构实现。这个过程会比较痛苦,但对代码库健康度的提升非常明显。
我个人在实际使用中还有个体会:OpenSpec 加 Superpowers 这套组合,真正的价值不是让你"更快地写代码",而是让你"更清楚地知道自己要写什么"。很多开发问题,表面上是写代码慢、bug 多,实际上的根源是想不清楚需求边界。这套工作流用温和的强制力,把"想清楚"这一步前置了。如果你也在为 AI 产出不可控而头疼,不妨按上面的步骤搭一遍,先跑通一个小功能,再逐步扩大使用范围。