【AI Native开发-08】一次改 14 个文件,为什么 AI 交付会失控?
30 秒看懂这篇
Plan 通过后,真正危险的不是 AI 不会写,而是一次写太多:越界文件、顺手重构、改宽松断言全混在一个 Diff 里,评审变成考古。
flowchart TB
A["取 Plan 的一小步"] --> B["声明允许 / 禁止修改范围"]
B --> C["实现 + 同步测试"]
C --> D["跑当前相关检查"]
D --> E{"Diff 与契约一致?"}
E -- "是" --> F["记录结果,进入下一小步"]
F --> A
E -- "范围越界" --> G["撤回或回 Plan 补授权"]
E -- "Spec / Plan 冲突" --> H["暂停,报告事实与选项"]核心方法是 小步 + 红线 + 每步验证 + Diff 审查。每一步应小到容易审、能独立验证、出错可单独回滚。遇到契约冲突时先暂停,不用猜测绕过前期评审。
本篇给出执行纪律、指令模板、冲突处理协议,以及“禁止靠削弱测试修绿”的规则。
一个典型场景
Plan 通过后,你对 AI 说:“按 Plan 实现删除文章功能吧。“然后去开了个会。
回来发现,AI 确实做完了,但 Diff 里有 14 个文件被改动:
- 核心删除功能做了,没问题;
- 但它把
ArticleList.astro里列表加载逻辑整个重写了(Plan 明确说”不改列表加载”),理由是”原来的写法和新按钮不太搭”; - 它”顺便”给文章详情页也加了个删除入口(Spec 非目标:只在列表页删除);
- 它发现
auth.ts里一个函数”看起来有 bug”,顺手改了——而那个函数被发布流程依赖; - 有个测试红了,它把断言改宽松了,让测试通过。
14 个文件里,只有 5 个在 Plan 的清单上。你无法判断这 9 个计划外改动哪些安全、哪些埋了雷。code review 变成考古。
这不是 AI 能力问题,是执行方式问题。你给了它一个大任务、没有中间检查点、没有文件红线,它就用”看起来最完整”的方式填满了整个空间。
核心问题:为什么实现阶段最容易失控
Plan 是纸面的,Implement 是动真格的。这个阶段有三个固有风险:
风险一:改动空间是开放的。 Spec 和 Plan 阶段只产出文字,写错了改字就行;Implement 阶段 AI 能触碰代码库里的任何文件,一次越界就可能破坏无关功能。
风险二:AI 倾向于”把事情做完”而不是”只做要求的事”。 它被训练成提供完整、周到的解决方案。当它发现代码里有”更好的写法”或”顺手能修的问题”时,会倾向于一起改掉——哪怕你没要求、哪怕 Plan 禁止。
风险三:错误在这个阶段开始变贵。 沿用第 01 篇的教学相对成本示意,Plan 阶段改方案记为 3,实现或测试阶段再发现问题记为 8 到 20;这些不是行业测量值,只用于说明越界改动会增加后续回滚与排查成本。
对策不是”别让 AI 写代码”,而是把一次大爆炸式的实现,拆成一连串受约束的、可检查的小步。
正确流程:小步、红线、每步验证
原则一:一次只执行 Plan 里的一小步
不要说”按 Plan 全部实现”。要说”只完成 Plan 的第 1 步”。
当前阶段:Implement
请只完成 Plan 中的第 1 步:
"写 src/lib/article-delete.ts 的权限与状态校验函数"。
允许修改:
- src/lib/article-delete.ts(新增)
禁止修改:
- 任何其他文件
- 不要写接口、不要写前端、不要写测试(那是后面步骤)
完成后请报告:
1. 新建 / 修改了哪些文件
2. 关键校验逻辑是什么
3. 有没有遇到 Plan / Spec 里和代码对不上的地方
(如果有,停下来报告,不要自己决定怎么处理)一小步的判定标准:Diff 小到能在 2 分钟内看完,且只对应 Plan 里的一个步骤。 这一步只写校验函数,就绝不碰接口和前端。
为什么这么拆?因为:
- 每步的 Diff 极小,越界一眼可见(这一步只该出现一个新文件,出现第二个就是越界);
- 出错能单独回滚这一步,不影响其他;
- 冲突能在最早的步骤暴露,而不是等 14 个文件改完才发现。
原则二:每一步完成后立即检查 Diff
每完成一小步,不要急着让它继续。先看 Diff:
# 每步之后必做
git status # 改了哪些文件?是否都在允许清单内?
git diff # 具体改了什么?有没有计划外的改动?检查三件事:
- 文件范围对不对:改动的文件是否都在这一步的”允许修改”清单里?出现清单外的文件,立即追问。
- 有没有无关改动:即使是允许的文件,里面有没有夹带”顺手重构""顺便改格式""觉得是 bug 就修了”的改动?
- 有没有临时代码:
console.log、注释掉的代码、写死的测试数据、TODO——这些在准出前必须清掉。
发现越界,当场处理:让 AI 把计划外改动撤回,而不是”先留着回头再说”——回头你就忘了。
原则三:测试和实现同步推进,禁止用改测试来”修绿”
实现里有一条铁律:
测试红了,先判断是实现错了还是测试错了;永远不允许通过改宽松断言 / 删断言 / 删测试来让它变绿。
AI 在实现阶段有个强烈倾向:测试一红,它的第一反应是调整测试让它通过——因为”让测试通过”是它被训练出的目标。但这会彻底摧毁测试的意义。
正确处理:
测试红了。停下来,按这个顺序判断:
1. 测试断言的行为,Spec 里是怎么规定的?
2. 如果 Spec 规定的行为和测试一致 → 是实现错了,改实现。
3. 如果 Spec 规定的行为和测试不一致 → 是测试理解错了,
回到测试设计阶段改测试,并说明为什么。
4. 如果 Spec 压根没规定这个行为 → 这是 Spec 缺口,
回到 Spec 补规则,重过 Gate 1,而不是现场拍一个行为。只有第 3、4 种情况才动测试,且必须说清依据是 Spec。“改完测试就绿了”永远是危险信号,不是完成信号。
原则四:冲突时暂停,不要自作主张
实现中可能遇到两类不同问题:
- 业务冲突:Spec 要求的行为与现状或其他规则矛盾,需要人重新决定;
- 技术映射错误:Spec 已明确
hide: true为未公开,Plan/Implement 却读了不存在的article.status。
第二种不是“Spec 与代码冲突”,而是实现没有忠实映射 Spec。无论哪类,都不该靠猜继续:
重要:如果你发现 Spec / Plan 与真实代码不一致,
停止修改并报告:
- Spec / Plan 原文与代码事实分别是什么
- 冲突属于业务规则、技术方案,还是实现映射
- 可选处理方式及影响
等待对应闸门作出决定。暂停的价值,是防止实现悄悄偏离已评审契约。第 02 篇假想事故的根因正是 Plan/Implement 把 hide 错映射成 article.status;正确修复是改 Plan 和实现,并保留回归测试。
还有一条更精细的经验法则:如果新增分支改变了业务语义,先回 Spec;如果只是实现既定契约所需的技术细节,更新 Plan/代码即可。 不必把每一个实现 if 都提升成业务需求。
Implement 指令模板
当前阶段:Implement
关联:Spec <路径>,Plan <路径>,本次执行 Plan 第 N 步
【本步目标】
<Plan 第 N 步的原文>
【允许修改的文件】
- <路径> — <改什么>
【禁止修改的区域】
- <路径 / 目录> — <原因>
- 不做任何 Plan 之外的重构、优化、"顺手修 bug"
【执行纪律】
- 只做这一步,不提前做后续步骤
- 测试和本步代码同步写
- 测试红了:先对照 Spec 判断是实现还是测试错,
禁止通过放宽 / 删除断言让测试变绿
- 发现 Spec / Plan 与代码冲突:停止,报告冲突和备选方案,等决定
【完成后报告】
1. 新建 / 修改的文件清单
2. 本步关键逻辑
3. 本步运行了什么检查、结果如何
4. 未解决的问题或冲突(如有)Implement 准入准出
准入:
- Plan 已过 Gate 2 评审;
- 实现拆成了有顺序、可独立验证的小步;
- 每一步都有明确的”允许修改 / 禁止修改”清单;
- 实现分支独立(feature branch),可随时整体回滚。
准出(进入 Verify 前必须满足):
- Plan 的所有步骤都完成,每个 REQ 都有对应实现;
- Diff 全部落在 Plan 批准的文件范围内,没有未解释的计划外改动;
- 类型检查、静态检查通过;
- 所有测试通过,且没有通过改宽松断言得来的”绿”;
- 无
console.log、注释代码、写死数据、TODO等临时残留; - 关键异常路径(权限失败、状态非法、重复操作)都有实现;
- 实现中发现的 Spec / Plan 冲突都已回流修正,契约和代码一致;
- 不可逆操作按 Plan 的缓解措施处理(如权限与状态校验、二次确认、临时目录测试,以及已验证的 Git 历史或备份恢复路径);不得临时改成 Spec 已排除的
.trash/ 软删除方案。
三种 Implement 反模式
反模式一:大爆炸式交付。 一句话”按 Plan 全做了”,回来 14 个文件。无法 review、无法定位、无法安全回滚。对策:强制小步,每步单独检查。
反模式二:善意重构。 AI”贴心地”改进了它路过的所有代码——重命名变量、调整格式、重构它觉得不合理的函数。每个改动单独看都”没错”,合在一起让 review 寸步难行,还可能破坏被依赖的行为。对策:禁止修改清单 + 每步 Diff 检查,计划外改动一律撤回。
反模式三:修到绿色。 测试红了就改断言、加 try/catch 吞掉错误、甚至删掉测试。表面全绿,实际把唯一能发现 bug 的东西关掉了。对策:把”测试变红后的处理顺序”写进指令,任何断言改动都必须引用 Spec 依据。
回退与检查
业务语义缺失回 Spec,技术映射或方案错误回 Plan / Implement,测试误解回测试设计。人重点检查每步 Diff、计划外改动、断言变更和不可逆操作;越界已混在一起时,整体回滚分支再按小步执行,不在难以审查的 Diff 上继续修补。
结语
Implement 阶段的纪律只有一句话:让 AI 在一个看得见边界、每步都能被检查的空间里行动。边界越清晰,AI 的能力越能被安全地放大;边界越模糊,它的”周到”就越容易变成事故。
小步实现走完了,代码和测试都在。但”AI 说它做完了、测试也绿了”并不等于”改动是安全的”。下一篇讲代码评审与变更控制:怎么系统性地审查一份 AI 产出的 Diff、怎么发现藏在合法文件里的越界逻辑、怎么给变更分级并让高风险改动强制经过人眼——这是代码合入主干前的最后一道防线。
