
Loop Engineering:让 AI Coding 持续正确
AI 编程真正的难点,不是让模型写出一次正确代码,而是让正确目标、正确实现、独立验证和经验改进持续发生。这是「vibe coding 工程化」系列第一篇:为什么需要 Loop,它改变了什么,以及什么时候不值得用。
「vibe coding 工程化」系列第一篇。本篇是科普:讲清楚 为什么需要 Loop、它改变了什么、 什么时候值得用。具体的施工单字段、门禁配置和脚本细节,留给后面几篇。
单次生成能力由模型决定,长期交付质量由工程系统决定。
这句话是我做了几个月 AI Coding 之后最实在的体会。模型一年比一年强,但**「这次写对了」和「这个项目一直是对的」之间,隔着的东西跟模型没什么关系**。
一、AI Coding 的真实问题
先说清楚:不是模型不会写代码。它写得很好。
问题出在别处,而且只在任务变大之后才出现。
目标会漂。 你让它加个限流,它顺手把注册接口、两个重置接口一起改了——因为「这些看起来也该限」。改得不算错,但那不是你要的这一轮。等你发现时,diff 已经跨了三个模块,你分不清哪些是本轮该做的。
上下文会丢。 长任务里,前天定的架构语义,今天的会话已经不记得了。它会重新推理一遍,推出一个同样合理但不一样的结论。
它会自圆其说。 这是最要命的一条。同一个模型既实现又自审,你问它「这样对吗」,它会用刚才生成代码的同一条推理链回答你「对」。自审在这里是同义反复,不是检查。
你看不懂它在干什么。 一个跨模块的任务跑到第三天,你想知道「现在到哪了、下一步为什么是它」,得去读它的输出——而它的输出永远是自信、完整、看起来很有道理的。
这四条有个共同点,值得单独说:
它们都不报错。
不会编译失败,不会测试变红,不会有任何一个工具跳出来说「等一下」。小任务里你依赖的那套反馈——编译器、测试、类型检查——在这些问题面前全部沉默。
它们不是「AI 不够好」的产物。恰恰相反,是 AI 足够好的产物:它写得太通顺了,通顺到每一行都看不出破绽。
人的错误通常带语气。一个人写「据某某确认」的时候,心里多少有一丝犹豫,那丝犹豫会渗进文字里。AI 的错误没有语气。
二、什么是 Loop Engineering
先说它不是什么:不是让两个 AI 无限互相聊天,也不是无限重试。
它是一套闭环交付方法:
权威文档(需求 / 架构 / 方案)
│
▼
┌──► ① 目标对齐:本轮施工单
│ │
│ ▼
│ ② 分阶段实施(执行方)
│ │
│ ▼
│ ③ 机器验证:范围门禁 + 测试
│ │
│ ▼
│ ④ 独立审查(另一方,只读真实 diff)
│ │
│ ┌──────┴──────┐
│ │ │
└──────┤ 有问题 │ 通过
再来一轮 ▼
⑤ 证据收口(冻结 diff/测试/结论)
│
▼
⑥ 经验反馈 → 规则演进
关键在那个回箭头。
它不是「写完 → review 一下 → 合并」的流水线,是一个逼近过程。这个区别不是修辞,我有数据。
一次审查为什么不够
一份架构设计,交给独立审查方,连着跑了五轮:
| 轮次 | 发现的 MAJOR | 说明 |
|---|---|---|
| 第 1 轮 | 6 条 | 红线冲突、设计与代码矛盾、未决事项被定稿… |
| 第 2 轮 | 5 条 | 全是新的 |
| 第 3 轮 | 4 条 | 全是新的 |
| 第 4 轮 | 4 条 | 全是新的 |
| 第 5 轮 | 4 条 | 全是新的 |
23 条实质问题,49 分钟,没有一条重复。
这才是「为什么必须是 Loop」的答案。修完第一轮那 6 条,第二轮冒出 5 条全新的——因为第一层被清掉之后,第二层才暴露出来。
而且越往后越深。第 1 轮的问题在文档层面就能看出来(红线冲突、术语不一致);第 5 轮的问题得把方案在脑子里跑起来才看得见——比如「候选领取的 CAS 冲突被错误地等同于候选耗尽」,那是并发语义,第 1 轮根本轮不到它。
如果只审一遍,你会拿到一份修好了 6 个问题、还剩 17 个的设计,而且你会以为它通过了。
三、为什么普通 Prompt 不够
很多人的第一反应是:这些在 prompt 里说清楚不就行了?「不要越界」「不要自己下结论」「测试要覆盖真实路径」。
不够,原因有三个。
Prompt 表达期望,不表达约束。 「请不要越界」和「机器真的阻止越界」是两件事。前者是一句话,后者是一道会返回非零退出码的门禁。
长会话里指令权重会衰减。 开头那句「只改这三个文件」,到第 40 轮对话时,跟当前上下文里的一百件事在争夺注意力。它没有忘记,它只是不再是最重要的那句。
执行方无法验证自己是否遵守了约束。 你可以让它自查,但那还是同一条推理链。
所以 Loop 做的事是:把关键约束从「文字提醒」提升为机器边界——路径白名单变成 diff 门禁,「必须测试」变成命令退出码,「不能自己批准」变成另一个不共享推理链的审查方。
一条经验:凡是有代码机制的约束,修完就不再犯;凡是靠文档、靠记性的,会一直犯。 我自己就栽过——一条规则上午刚写进文档,下午写新内容时照样违反,两小时后才发现。
四、角色分工
Loop 里有四个角色,边界很清楚:
| 角色 | 负责 | 不负责 |
|---|---|---|
| 人 | 目标优先级、架构语义、风险接受、发布授权 | 逐条转发两个 AI 的输出、替 AI 判断代码细节 |
| Claude | 按施工单实施、跑测试、汇报进度、按 findings 修复 | 自审批准、扩大范围、擅自提交或部署 |
| Codex | 读真实 diff 独立审查、给机器可读的结论 | 替代编译器、决定产品风险 |
| Harness | 路径范围、危险操作、证据完整性的机器边界 | 判断复杂业务语义 |
这里最重要的一条:Claude 的解释和进度汇报是线索,不是证据。
它说「测试通过了」不算数,命令的退出码才算数。它说「这个之前定过」不算数,翻出当时的决议记录才算数。
可信链条只有这几样:
权威文档 + 真实 diff + 命令退出码 + 独立审查 + 冻结证据
五、五个核心对象
用生活化的话讲,Loop 里只有五样东西:
1. 权威文档 —— 图纸 需求、架构、方案。它回答「为什么做、目标长什么样」。它不记录每次工具怎么跑的。
2. 施工单(Task Packet)—— 本次派工单 这一轮唯一的目标是什么、允许动哪些文件、验收标准是什么、哪些明确禁止。 它是执行会话的唯一主线指针——执行方跑偏了,拿它对一下就知道。
3. 范围门禁(Guard)—— 工地围栏 只管「你有没有走出这块地」,不管「你在这块地上盖得好不好」。它不判断业务语义,只比对路径。
4. 审查提纲(Review Prompt)—— 这次验收重点看什么 不是把全部历史复制一遍,是「这一轮最关键的问题是什么」。
5. 证据包(Run Evidence)—— 竣工资料 当时的 HEAD、diff、门禁结果、测试输出、审查结论。三个月后有人问「为什么这么设计」,你翻这个,而不是翻聊天记录。
六、一次任务怎么流动
举个简化的例子。
架构师定规矩:异步请求失败后,必须沿一个固定的候选序列依次重试,不能随便挑。
写施工单:本轮唯一目标是实现这个重试序列;允许动路由器和状态机两个文件;验收标准是正常、失败、回退三条路径都有测试;明确禁止改动计费相关代码。
Claude 实施:写代码,跑测试。正常路径过了,失败路径过了,回退路径也过了。它汇报:完成。
门禁比对:真实 diff 只碰了允许的两个文件。通过。
Codex 独立审查:它拿到的是真实 diff,不是 Claude 的自述。它发现——并发条件下,两个 worker 可能同时认领同一个候选,造成双提交。测试没覆盖这个,因为测试是单线程跑的。
Claude 只修这个:不顺手重构,不「既然改到这里了不如把那个也优化一下」。修完,跑回归。
审查通过,证据收口:冻结这一刻的 diff、测试输出、审查结论。这一轮结束。
注意这里发生了什么:测试全绿,门禁通过,执行方汇报完成——但代码有一个并发缺陷。 抓住它的不是更严格的测试要求,是一个没参与生成、只读真实 diff 的第二方。
七、Loop 带来了什么
| 没有 Loop | 使用 Loop | |
|---|---|---|
| 主线 | 目标随对话漂移,diff 跨了三个模块才发现 | 施工单声明唯一目标,门禁比对真实 diff |
| 验证 | 执行方说「测试通过了」 | 命令退出码 + 独立审查读真实 diff |
| 缺陷暴露时机 | 上线后 | commit / deploy 之前 |
| 并发/回退/安全问题 | 单线程测试测不出来 | 独立审查方按语义反推 |
| 换会话 | 靠聊天记录,前天定的今天忘了 | 施工单 + 证据包,跟会话无关 |
| 三个月后问「为什么这么设计」 | 翻聊天记录,翻不到 | 翻证据包:当时的 diff、测试、结论 |
| 经验 | 留在某个人脑子里 | 沉淀成规则,跨项目复用 |
最实在的一条:缺陷在 commit 之前暴露。上面那 23 条 MAJOR,如果没有这道缝,其中相当一部分会变成线上问题,或者变成三个月后没人敢动的「当初就是这么设计的」。
八、Loop 不是什么
这一节比上一节重要。大部分把流程搞砸的人,是搞错了这几条。
不是项目管理看板。 它不追踪谁在做什么、进度百分之多少。主线状态还是以你原有的计划和台账为准。
不是所有改动都要走的审批流程。 改个文案也要写施工单、拉审查——那是自残。
不是让 AI 完全自治。 恰恰相反,它把人的裁决点收窄并固定:只在架构语义、风险接受、发布边界上做决定,其余交给机器边界。
不是用文档数量衡量质量。 连续两轮只在改规则、改提纲、改台账,没有代码增量——那不是流程严谨,那是空转。
不是 Codex 审查越多越好。 审查只剩措辞和排版问题时,继续审是浪费。
不是替代测试、架构师和生产责任人。 独立审查不是编译器,它不能替你跑测试;它也不决定产品风险——那是人的活。
九、成本和适用边界
Loop 是有成本的,而且成本不小。所以要分强度:
| 强度 | 适用 | 最小做法 |
|---|---|---|
| 快速处理 | 读代码、查 bug、明确的小修、低风险单文件改动 | 直接干完 + 跑针对性验证。不写施工单,不拉审查 |
| 标准 Loop | 跨文件、架构实现、重要设计、多 agent 接力 | 一个施工单、一次门禁、必要测试、一次独立审查 |
| 严格 Loop | 集群写操作、数据/模型、安全、发布、不可逆迁移 | 标准 Loop + 环境授权、回滚证据、人工风险裁决 |
判断不清时用标准 Loop。但出现下面这些信号,应该降低强度而不是继续加文档:
- 改动可以在一个低风险文件内完成;
- 连续两轮只改规则、提纲、台账,没有代码增量;
- 审查只剩措辞和排版问题;
- 流程建设时间开始接近实际实现时间。
最后这条是硬线。流程的成本必须明显小于它防住的损失,否则它就是个仪式。
十、Loop 怎么自我进化
这是我认为最容易被忽略、也最关键的一层。
一个很自然的冲动是:每发现一次流程问题,就往规则里加一条。三个月后你会得到一份没人读的规则集——而没人读的规则等于没有规则。
所以规则的晋升要走这条路:
实践中发现问题
↓
先进轻量收件箱(只记事实,不当场立规矩)
↓
周期性聚合:这个问题重复出现了几次?
↓
达到阈值 → 才考虑升级为通用规则
↓
规则可测试、可衡量,且**允许降级和退役**
核心边界是:问题自动发现,规则人工晋升。
这里有个我自己踩到的坑,值得说:收件箱本身也会出问题。我的收件箱跑了一段时间后,里面 96% 的记录是「护栏正常拦了一次」——那不是问题,那是护栏在按设计工作。真正的信号被埋在噪音里。
记录「系统正常」等于制造噪音,而噪音会让人学会无视这个收件箱,连真信号一起无视。这个坑我会在后面单独写一篇。
十一、怎么判断 Loop 是否健康
不看文档数量。看这些:
- 执行方大部分时间在实现和验证,而不是在维护流程文档;
- 人只处理真正的架构、风险和发布裁决,不做二传手;
- 审查能抓住跨文件、并发、回退和安全问题——如果它只会挑错别字,那这道缝没起作用;
- 每个阶段的进度能用一句业务语言说清;
- 普通操作不反复弹确认;
- 规则建设时间明显小于交付时间;
- 相同的问题越来越少——重复问题经过聚合才进规则,规则也允许退役。
长期做不到,优先缩小阶段、降低强度、修正施工单,而不是继续加约束文本。
结尾:从「生成代码」到「持续正确」
回到开头那句话。
单次生成能力由模型决定。 这一年模型进步得非常快,而且还会更快。
长期交付质量由工程系统决定。 这部分不会因为模型变强而自动变好——恰恰相反,模型越强,它的错误越通顺、越自洽、越没有语气,也就越需要一道不共享推理链的缝。
那条被抓住的假授权是 Claude 写的,抓住它的是 Codex。但真正起作用的不是哪个模型更聪明——换成两个 Claude、或者两个 Codex,只要中间那道缝还在,效果一样。
人类团队几十年前就懂这个道理,所以有 code review,所以有「作者不能 approve 自己的 PR」。Loop 只是把同一条规矩,搬到一个写得更快、更自信、也更没有语气的作者身上。
它写得越好,这道缝就越必要。
Loop 的价值,是把偶然的正确变成可重复的正确。
下一篇:施工单到底怎么写——一份好的施工单和一份没用的施工单差在哪,以及为什么「允许修改范围」这一栏比「目标」那一栏更重要。