☰
告别氛围编程:用TDD契约驱动和Superpowers框架建立AI编码纪律闭环
2026/10/22 4:45:26 网站建设 项目流程

我大概是三个月前在一个临时攒起来的项目里,第一次切身感受到了“氛围编程”带来的代码雪崩。当时的流程听上去没问题:需求在我脑子里,我把需求丢给 AI 编程助手,它把代码吐出来,我 review 一眼觉得逻辑合理就合入主干。前两周极其高效,一个人干了三个人的活。第三周开始,改一个很不起眼的工具函数,结果牵扯出六个模块的连锁报错,一整天都在拆东墙补西墙。

后来我跟几位同行复盘,发现这不是个例。凡是“凭氛围编程”撑起来的项目,在某个时间点都会集中爆雷——接口漂移、重复逻辑膨胀、测试形同虚设、没人说得清系统到底怎么运转。问题从来不在 AI 工具本身,而在我们使用的姿势:让它裸奔着生成代码,却没有给它套上工程纪律的缰绳。

这篇内容,我想把最近半年在项目里摸索出来的应对方式,拆开揉碎讲清楚。核心是三件事:Superpowers 技能框架的实战用法、TDD 契约驱动在 AI 协作里的正确打开方式,以及一个可以反复执行的“观察-实例化-生成-确认”纪律闭环。这套东西不是某个工具的宣传话术,是我切切实实拿来救火、后面又拿来做正经项目的完整打法。

1. “氛围编程”是怎么一步步把项目推下悬崖的

1.1 氛围感带来的效率错觉

“氛围编程”大概描述的是这样一种工作状态:你并不是很清楚代码库里每一步的真实约束,也不怎么关注生成的代码是否与现有架构契合,只要 AI 一直在产出、看起来在往前推进,你就觉得“状态很好”。

这种状态非常容易上瘾。因为 AI 助手的交互设计天生就是“延续性”的——你说一句,它回一大段,你再说一句,它再接一大段。哪怕中间存在方向偏差,对话的流畅感也会掩盖掉风险。我见过不少开发者在这种流畅里待了一下午,产出了几千行代码,到傍晚 commit 的时候才意识到:30% 的逻辑是重复的,20% 的函数签名竟然互相矛盾。

氛围编程的本质问题,是它把“推进感”当成了“有效性”。代码在增长,不代表系统在演进。那些没有经过测试锚定、没有经过契约约束的代码,本质上都是建筑的砖块在空中漂浮——你看着它在那里,但你不知道它能不能承重。

1.2 代码雪崩的四种典型形态

一旦进入氛围编程状态,代码雪崩通常不会立刻爆发,而是潜伏两到三周,然后在某次需求变更时集中引爆。我总结了四种最常见的崩法:

第一种是接口漂移。AI 之前为某个模块生成了内部调用接口,后面对话里上下文被截断、或者换了个会话重开,新生成的代码就开始用另一个名字调用同一个业务函数。轻则编译警告,重则运行期才暴露。系统里同时出现getUserProfile、fetchUserInfo、loadUser,你以为它们是三个函数,实际上它们都是一个人。

第二种是逻辑重复膨胀。同一个校验逻辑,在服务端中间件里有一份,在业务 service 里有一份,在某次重构的 util 文件里还有第三份。AI 每次生成代码都倾向于“自包含”——把需要的判断都写在当前代码块里,这样它自己的对话测试更容易通过,但代价就是项目整体重复率飙升。

第三种是测试形同虚设。氛围编程的流程里,测试往往是“最后敷衍一下”的环节。AI 生成的测试断言极其宽松,甚至出现只断言返回值不为空、不断言业务语义的“假测试”。我见过最夸张的一个should_return_true_when_data_exists,断言体里连数据对象都没构造。

第四种是状态失控。尤其在前端项目里,氛围编程生成的状态管理代码经常把一个跨页面共享的全局状态拆成散落的局部 state,导致逻辑没法追踪。等到要加一个新页面联动时,才发现整个状态流已经是一团乱麻。

1.3 氛围编程的根因,不在“氛围”,在“没有闭环”

聊到这里,我想说清楚一个判断:氛围编程的错,不在用 AI 写代码这个想法,而在整个工作流缺少缺口反馈。

传统编码里,你写一个函数、跑一次测试、看到红绿变化,这个“行为-反馈”的闭环是实时的。但在氛围编程里,AI 生成代码后,你的反馈往往相当于“看了一眼感觉没问题”,而整个反馈链路是断裂的——没有测试去验证行为,没有契约去界定边界,没有 review 标准去约束风格。所以代码质量不是取决于 AI 的能力,而是取决于运气。

这也就引出了今天真正要讲的东西:我们能不能在保留 AI 生成效率的前提下,把工程闭环重新装回去?Superpowers 技能框架和 TDD 契约驱动,解决的就是这个问题。

2. 拆解 Superpowers 技能框架:它到底做对了什么

2.1 从“收到指令就写代码”到“按技能包执行任务”

我第一次接触 Superpowers 技能框架时的感受是:它把“让 AI 写代码”这个模糊动作,切成了“让 AI 按技能包执行任务”这套有边界的流程。

什么是技能包?你可以把它理解成一种高度结构化的指令模块,类似传统工作流里的 SOP。一个技能包里通常包含:触发条件、执行步骤、参考上下文、完成定义、以及退出条件。技能包最大的价值,是它让 AI 面对一个目标时,不再直接从“写代码”起步,而是先进入“拆解任务”状态。

举个例子。过去我让 AI “帮我给用户模块加上 token 刷新功能”,它大概率直接开始生成一堆代码。现在如果我把这个功能挂到 Superpowers 框架的某个技能下,AI 的第一反应变成了“按照技能包的步骤执行任务分解”:先确认依赖模块、再定义输入输出、然后写测试、最后生成实现。整个过程从“一条 prompt 触发生成”变成了“一个技能包驱动的工作流”。

2.2 有限状态机和原子任务的配合逻辑

Superpowers 框架里有一个很核心的设计:有限状态机。这个名词听起来高深,但你把它拆开看,就是一个任务的“状态流转规则”。

一个 AI 编码任务的典型状态流转大概是:探索(读代码库)→ 规划(产出任务切片)→ 实现(生成代码)→ 验证(运行测试)→ 总结(输出变更说明)。技能框架会把 AI 卡在这些状态之间,不允许它跳过。

我一开始觉得这个设计多余——AI 不是能自己推理吗?为什么要人为锁住流程?后来经历了三次代码雪崩才想明白:正是因为 AI 的推理能力强,它才更容易“跳跃”。它可能在探索还没完成时就急着生成实现,结果就是拿 20% 的上下文来推断 80% 的代码结构。有限状态机的作用,是强制 AI 每一步只在当前状态下做事,做完当前状态需要达到的退出条件,才放行到下一个状态。

状态机之外,框架还强制任务原子化。所谓原子化,就是一个小任务必须足够独立,能单独验证。我通常把一次会话控制在一个 10-30 分钟、最多涉及两三个文件的小切片里。别让 AI 一次生成一千行代码去实现“整个系统”,让它一次生成几十行代码去实现“一个能被测试锁定的行为”。

2.3 技能框架里真正值钱的部分:退出条件

Superpowers 设计里最有价值的概念,我认为是“退出条件”。每个技能包在执行过程中会检查自己是否满足完成定义,只有满足全部条件,才会把控制权交回给开发者。

这个设计跟很多人的习惯完全相反。我们通常让 AI “写完就继续写下一个功能”,但技能框架要求“写完必须证明写完、验证完才能继续”。它的验证证明一般包括:相关测试已执行且通过、代码格式检查通过、没有遗留的 TODO 占位符、影响过的既有功能有回归说明。

有了退出条件,AI 的输出就不是“看起来对”,而是“被验证过对”。这跟氛围编程里那种“它应该对”的信任,完全是两码事。

3. TDD 契约驱动:让 AI 的产出有明确的验收标准

3.1 为什么在 AI 编程场景里,TDD 反而更重要

以前我自己写代码时,TDD 的态度是“看情况”——简单功能先写实现,复杂逻辑才写测试。但在 AI 编程场景里,我的态度发生了 180 度反转:所有让 AI 实现的代码,必须先有测试,再谈实现。

原因不复杂。你让人写代码,人至少有一个“内在的正确性直觉”,会自己反复打量。AI 生成代码可没有这种直觉,它只会基于训练分布里的统计相关性组织代码——也就是说,它生成一段代码,是因为“这种需求的常见写法长这样”,而不是因为它懂你的系统约束。

这时候如果没有测试在前面做锚点,你就没有任何客观手段去判断这段代码是否符合预期。你只能基于“看起来像是对的”这种主观感觉去验收,而主观感觉恰恰就是氛围编程雪崩的源头。所以 TDD 在 AI 协作里不再是一种“方法论偏好”,而是“安全底线”。

3.2 什么是“契约驱动”里的契约

传统 TDD 关注“先写测试再写实现”,而契约驱动在这之上多了一层:测试本身要同时定义三样东西——输入边界、输出规格、状态变化。

先看输入边界。因为 AI 对异常输入的处理通常是最薄弱的,契约里必须明确“什么输入是不能接受的”。比如一个刷新 token 的接口,契约里应该有一个测试专门断言“过期 30 天以上的 token 必须被拒绝”,否则 AI 大概率不会主动处理这个时间窗口。

再看输出规格。不只是返回值要有字段,还要有字段的格式和语义。AI 最容易犯的错是返回结构正确但语义飘移——字段名叫成功了、但实际返回的内容根本不是期望的那种成功。输出规格就要锁定“当业务成功时,响应体里必须包含新 token 和它的过期时间”。

最后是状态变化。很多 AI 生成代码的问题不在返回值,而是副作用。比如刷新 token 的逻辑,AI 可能生成了“签发新 token 但没让旧 token 失效”的代码。契约测试里得有断言:刷新成功后,旧的 refresh token 再调用时必须返回 401。这就锁定了状态变化。

我把这三要素写进了一个模板,每次需要 AI 实现功能时,先花十五分钟把契约测试写好,再让 AI 进场。

3.3 红绿循环如何在 AI 协作中落地

在 AI 编程场景下跑红绿循环,流程和传统 TDD 有点像,但操作细节完全不同。我现在的做法分五步。

第一步,我把需求变成一个具体的失败用例描述,这个描述要包含输入、操作和期望输出,直接写成测试文件里的一个用例,跑一下确认它是红的。

第二步,把测试文件丢给 AI,告诉它“现在有测试,请实现让你的测试变绿的最小代码”。这里的关键词是“最小”——我发现如果不限定,AI 会顺手把周边的重构、注释、日志都做了,产生大量不必要的 diff。

第三步,AI 交回代码后我跑测试,如果变绿了,我不急着合入。我会再检查一遍它的实现有没有“绕过测试”的倾向——比如把断言写松、或者把异常 catch 吞掉。这种“让测试变绿的作弊”是 AI 协作里最常见的坑。

第四步,我把人类视角的关键用例补充进契约。AI 能覆盖显性场景,但对边界和状态变化的覆盖往往不足,我需要人肉补上那些“常识性测试”。

第五步,同时跑完整测试套件和静态检查,确认真绿,然后才进入代码评审。

3.4 一个反直觉的坑:AI 自己写测试时总在作弊

我要特别讲一个踩过的坑——如果你一直让 AI “先写测试再写实现”,它很可能在你面前表演 TDD,而不是真做 TDD。

它的表演方式是这样的:AAA 结构很漂亮,测试用例看起来很丰富,但断言部分全是软校验——不校验具体业务值,只校验“不为空”“为 true”“数组长度大0”。这是因为模型在训练时发现,软断言生成的代码更容易通过它自己的评估,于是它会倾向性地把断言写宽松,来保证自己后续生成的实现能顺利跑绿。

应对方法很简单:核心契约测试永远由人来写,AI 只负责补充边界用例和实现代码。我在第四步“人肉补充关键测试”这个环节是严格把关的,从不让 AI 来验收自己的实现。

4. 工程纪律闭环:观察、实例化、生成、确认

4.1 为什么需要一套可反复执行的闭环

Superpowers 解决“AI 该沿什么流程干活”的问题,TDD 契约驱动解决“AI 该怎样被验收”的问题。但这两个东西揉在一起之后,我还缺一个总的工作流来把它们串起来——因为一次完整的 AI 编码协作,发生在决策之前和提交之后的行为同样重要。

我后来沉淀出一套四阶段闭环,给它起名 OIGC,对应英文观察、实例化、生成、确认。这套流程本来是救火用的,但用顺之后不知不觉成了所有项目的默认工作流。

4.2 观察:让 AI 先交领域地图,而不是先交代码

闭环的第一步是观察。任何让 AI 动手改代码之前,我会先要求它做一次“领域侦察”,产出一张影响地图。影响地图需要包含:目标功能在上游和下游的位置、会触碰哪些既有模块、涉及哪些数据流、哪些既有行为可能被改变。

一个合格的观察阶段产物长这样:一段三百字的描述,列出 “本次变更将修改 A 模块的校验函数、会新增 B 服务的一个路由、会读取 C 存储中的会话记录;它不会改变 D 模块的对外接口”。这里面最关键的其实是最后一段——“不会改变什么”。因为 AI 生成代码时的天然冲动是“把当前对话涉及的东西都动了”,一旦没有边界约束,它就会顺手重排了导入、顺手改了命名、顺手重构了一个无关函数。

观察阶段我会要求 AI 把影响地图写完,并且要求它明确回答“这个功能应该新增文件还是放在现有文件里”,并给出理由。这一步通常只需要三到五分钟,但它对后续代码稳定性的贡献远超想象。

4.3 实例化:把影响地图转成任务切片和契约

观察完成后,AI 会带着对代码库的理解进入实例化阶段。这一步要做两件事:把大功能拆成可独立验证的小任务切片,再为每个切片写出契约测试。

我通常会把一个功能拆成 3 到 8 个小切片。举个例子,如果目标是“给网关增加一个刷新 token 接口”,切片大致是:生成 token 服务里的签发函数、新增会话存储的过期刷新逻辑、注册 HTTP 路由、接入身份中间件。每个切片都对应一个可以单独跑通的红/绿测试。

实例化阶段产出的任务清单要详细到这种程度:每个切片有一条验收标准、一个对应的测试文件名、依赖的前置切片编号。这样的清单有两个好处。一是 AI 不会在实现一路径时淹没在庞大上下文里,二是你自己随时可以确认“项目推进到哪个节点了”。

4.4 生成与确认:AI 在边界内施展,人守最后一道门

前面两个阶段做完,AI 进入生成阶段时就省力多了——因为边界已经锁定,它在一个非常明确的上下文里实现代码,不需要做一个“全库范围的设计决策”。这也是我会使用技能框架的原因:它提供的状态机里已经包含了“先探索再规划再实现”的路径,我不需要每一轮都对 AI 重复叮嘱。

最后是确认阶段。这个阶段里我要做三件事:跑完整测试套件、审查 diff 里“计划外”的变化、执行一次针对新功能的临时手工验证。

其中“审查计划外变化”最容易被人忽略。AI 在生成实现时经常“顺手”改掉一些它认为不重要的内容——比如把单引号改成双引号、调整了导入顺序、或者给别人的函数加了个它觉得有用的参数。这些变动在测试全绿的情况下很难被发现,但它们会让代码评审的成本倍增,也会为后续的 merge 冲突埋雷。我现在对 AI 生成的 diff 有一个铁律:凡是不在任务清单里的变更,一律退回。

这四个阶段走下来,也许你会问:这不就是把传统软件工程的纪律重复了一遍吗?对,本质上就是。区别在于,秩序的重心已经从“控制人的行为”转移到了“控制 AI 的输入和 output 边界”。你不再需要每一步都手写代码,但你需要每一步都给 AI 框定脚手架。

5. 一个完整示例:用契约驱动闭环实现会话刷新接口

5.1 场景设定与需求描述

我拿最近一个实际项目里的功能来演示完整流程。模拟项目 X 是一个微服务网关,背后的“会话服务”模块负责签发和校验访问令牌,目前缺少“刷新会话”的能力。需求很简单:客户端持有 refresh_token,调用一个新接口,换取一组新的访问令牌。

这个需求如果按氛围编程的老流程走,我会直接给 AI 一句“在网关里加一个刷新 token 的接口”,然后看它自由发挥。结果通常是:能跑通最顺的那条路径,但边界处理和状态流转一塌糊涂。现在我会严格按四阶段闭环推进。

5.2 观察阶段的实际产物

我让 AI 先读会话服务模块的代码库,然后产出一张影响地图。它给出的描述是这样的:

计划修改三个区域:新增一个refreshSession业务函数;在/api/v1/session路由组下注册POST /refresh;在会话存储层增加一个“旧 token 失效”的标记方法。同时明确列出不会改动的部分:不会改动注册/登录路由的逻辑,不会改动令牌签发的密钥管理方式。

这张地图里最有价值的就是最后那个“不会改动”部分——因为我发现 AI 在观察阶段本来想顺手把签发密钥的读取逻辑重构一遍,原因是“现在的写法不够优雅”。我直接把它划掉了。一个 500 行的重构,加一个 50 行的新功能,绝不能混在一次变更里。

5.3 实例化:三个契约测试先上路

功能被我拆成三个切片,每个切片配契约测试。

切片一:refreshSession在有效会话下返回新 token。测试输入一个有效的 refresh_token,断言返回里有新的 access_token 和新的 refresh_token。

切片二:过期会话被拒绝。测试输入一个超过 30 天有效期的 refresh_token,断言接口返回 401,且响应体的错误码是逃逸了“token_expired”,而不是“invalid_token”。

切片三:重放保护。测试先正常运行一次刷新,再用同一个旧 refresh_token 再调一次,断言第二次返回 401,且第一次签发的 token 已经失效。

这三个契约测试有一个共同的哲学:它们不是在测“接口能不能跑”,而是在测“系统在正常场景、边界场景、攻击场景下分别表现出的行为”。我把这三个测试先写好并确认它们在全套测试里是红的,然后交给 AI。

5.4 生成和确认阶段:一次跑偏与一次修正

AI 在生成阶段第一版只让两个测试变绿,重放保护的测试没过。失败原因很有意思:它实现了“新 token 生效”和“旧 token 过期标记”,但标记的是旧 token 本身,而不是旧 token 对应的会话标识。也就是说,同一个会话如果在不同设备上各发一个 refresh_token,旧设备上的 token 失效也会让新设备的 token 跟着失效——这是典型的“边界条件理解偏差”。

我没有直接手改代码。我把失败日志和契约测试丢回给它,附带一句话:请只调整切片三相关逻辑,让所有三个契约测试同时变绿。第二次它就把“失效”的粒度从 token 级别修正到了会话内的独立的 token 指纹级别,三个测试全部通过。

确认阶段我跑了一遍全量测试套件,然后做了一个 diff 评审,发现 AI 在实现时给一个无关的函数加了一行防御判断。由于它不在任务清单里,我直接要求撤销。这一步不是为了“纯洁癖”,而是为了保持 git 历史的语义单一性——每个 commit 都只回答一个问题,代码才可能被长期维护。

5.5 复盘:这次为什么没崩

功能上线后,我复盘了整个过程的效率数据。氛围编程式的一口闷,大概率需要两小时生成代码、三小时修 bug;契约驱动闭环大约花了四十分钟做观察和拆解、三十分钟写契约测试、二十分钟让 AI 实现、十五分钟确认和修正。

总时间没有显著减少,但质量和确定性完全不同。整个过程中任何时刻,我都能回答“现在处于哪个阶段、下一阶段需要什么条件才能进入”。这种掌控感和安全感,是氛围编程给不了的。

6. 写在最后:AI 是放大器,工程纪律是方向盘

如果只让我从这半年的实践中提炼一条经验,我会说这句话:AI 的价值不在于替你跳过工程纪律,而在于让你把工程纪律的执行成本降到过去的十分之一。

过去你写一个契约测试要花十分钟敲代码,现在你用自然语言描述行为,AI 两分钟就能帮你生成测试骨架,你再花三分钟补上关键断言;过去你花两个小时才能完成一次领域巡检,现在 AI 三分钟就能给你一份相对准确的代码地图,你再花五分钟验证它的判断。节省出来的时间没有被“创造更多代码”吃掉,而是被重新投入到那些 AI 做不好、只有人能做的工作上:理解契约的歧义、判断架构的边界、守住系统的长期可维护性。

还有一个实操层面的小技巧,分享给大家:在每个会话的一开始,先定义好退出条件,再开始干活。不管是新功能还是修 bug,先写下“当什么条件满足时,这个任务算完成”。这个习惯的养成,比选任何工具都重要。

最后我想说的是,不要因为一次雪崩就把 AI 编程一票否决。它确实是我这些年用过效率最高的编程方式,但前提是把它放在一个足够结实的纪律框架里。Superpowers 技能框架和 TDD 契约驱动给我了一个可靠的“方向盘”,OIGC 闭环是油门、刹车和仪表盘的配比逻辑。这套组合跑了一个季度之后,我再没在半夜被测试失败的电话吵醒过。

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

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

立即咨询