The Strict CI/CD Agent

行业软件开发规模研发团队

背景

CI/CD 与自动化测试已是现代研发的标配;将「修 bug」也交给 AI 的尝试并不少见,但常见失败模式是:AI 自信地声称「已修复」并尝试提交,而实际代码无法通过编译或测试,甚至引入回归。业界与社区对此有大量讨论:若没有以测试结果为唯一准绳的闸门,AI 的修改无法被信任。

本案例中的团队在智能体工具链中加入了停止钩子(Stop Hook):仅在测试全部通过时才允许执行「提交 PR」类动作,否则将失败日志回灌给智能体,驱动其反思并再次尝试,形成「修—测—再修」的闭环,直至通过。

问题

表象问题(开发者能直接感知)

让 AI 自动修 bug 时,AI 常回复「已修复」,但本地或 CI 一跑测试仍失败;有时 AI 修改了无关文件或引入了新问题;开发者不得不自己再看日志、再改一遍,对 AI 的信任度下降。

根本原因(技术与流程层面)

智能体缺少「成功」的客观定义:它依赖自身输出或模型推理判断「修好了」,而不是以测试运行结果为准。没有闸门阻止「测试未通过就提交」的行为,错误信息也未系统性地反馈给智能体做下一轮修正。

核心痛点

  • 误报「已修复」:模型可能幻觉式地认为修改正确,而实际编译/测试失败
  • 无闭环:失败日志未自动回到智能体上下文,无法驱动针对性重试
  • 信任缺失:人工不得不二次验证,自动化修 bug 的价值大打折扣

解决方案:测试闸门 + 日志回灌 + 反思重试

阶段一:提交前拦截(The Stop Hook)

当智能体尝试调用「提交 PR」或「标记完成」类工具时,系统不直接执行,而是先触发一次确定的测试运行(如同一套本地/CI 测试)。若任一项失败,Stop Hook 阻止提交,并将测试失败时的 STDERR/日志作为新上下文回传给智能体,不给予「完成」信号。

阶段二:读码、改码、跑测(Tool Use)

智能体使用 Tool Use 读文件、编辑代码、在隔离环境中执行测试。它只能通过「测试通过/不通过」来判断是否修好,而非自我声称。每次失败后,新日志被追加到上下文中,供下一轮推理使用。

阶段三:反思与再试(Reflection)

收到失败日志后,智能体先进行 Reflection:归纳失败原因(编译错误、断言失败、超时等),再制定更针对性的修改策略(如只改某文件、只调某条件),然后再次编辑与跑测。此循环持续直到测试全部通过,此时 Stop Hook 放行,允许提交。

实施难点

难点 1:测试稳定性(Flaky Tests)

若测试本身存在不稳定(如依赖时间、网络),可能造成「其实修对了但测试偶发失败」而被误判。需要在 Stop Hook 侧区分确定性与 flaky,或对关键路径做重试/去 flaky 处理。

难点 2:修复策略的完备性

复杂 bug 可能需要多文件、多轮修改;智能体有时会陷入局部策略。通过限制最大迭代轮次、或人工在关键轮次介入,可避免无限循环。

难点 3:与现有 CI 的对接

Stop Hook 触发的测试需与团队现有 CI 用例一致,否则「通过」仍可能在上游 CI 失败。通常做法是复用同一套测试脚本或调用同一 CI 接口。

效果(估算,非精确数字)

指标变化
提交质量仅当测试通过才放行,避免「声称修好却未过测」的 PR 进入主分支
人工介入预计减少部分「看日志再自己改」的重复劳动;复杂 bug 仍可能需人工收尾
迭代轮次单次修 bug 可能经历多轮试错,实际轮次因问题复杂度而异

以上为基于案例设计的预期效果。实际效果取决于测试覆盖度、测试稳定性(flaky 比例)与 bug 类型;复杂架构或跨模块问题仍可能需人工参与。

用到的模式及其在本案例的具体作用

模式在本案例解决的具体问题
The Stop Hook在「提交/完成」前强制跑测,仅当通过才放行,在本案例中直接解决「AI 声称修好但未过测」的信任问题
Tool Use读文件、改代码、执行测试均通过工具完成,保证行为可复现且结果可验证
Reflection根据失败日志归纳原因并调整修复策略,避免盲目重试,提高后续轮次命中率
The Stop HookTool UseReflection

参考依据

来源具体内容年份
CI/CD 最佳实践测试作为发布闸门、Green build 文化
业界讨论AI 辅助修 bug 时「以测试为准」的实践与工具设计