DeepDojo.AI发布 2026-11-12English

Claude Code 修复循环的五个停止条件

Claude CodeAI 编程

认证集成测试一直失败,你交代了一句:“一直修到测试通过为止。”几轮之后,Claude Code 报告测试全部通过。你打开 diff 一看,有一条断言被改宽了,另一个用例被标成了跳过。测试确实绿了,缺陷还在。

“一直修到通过”听起来是个清楚的目标,实际上只给了一个成功条件,没有给任何停止条件。循环里可能发生的事远不止“修好”一种:

  • 失败原因在环境,比如本地数据库没启动,改代码永远修不好;
  • 连续几轮失败数量都没减少,只是在同一个方案上打转;
  • 最省事的“通过”方式,是弱化断言或跳过用例;
  • 修着修着,改动范围超出了原来的计划。

没有边界的循环,会把这些情况都当成“继续修”。办法是在启动前就约定停止条件:检查成功时停,连续两轮没改进时停,达到轮次或成本上限时停,需要你做决定或外部条件变化时停,范围超出计划时回到计划阶段。停下来时,要报告进展、证据、原因和需要的输入。下面逐条说明,最后讲用 Stop Hook 强制检查时怎样避免死循环。

01 表面的通过从哪里来

循环应有成功、无改进、预算和外部依赖边界。“一直修到测试通过”可能把环境问题混入代码修改,甚至通过弱化断言或跳过用例得到表面的通过。

测试失败的原因也要先看清。客户端根本连不上服务,证明的是环境有问题;请求到了目标接口、仍然返回错误结果,才是代码缺陷。原因分不清就进入修复循环,Claude 只能在代码里反复尝试。分阶段推进时怎样给每一步设完成条件,见用 Claude Code 开发大功能的分阶段做法。

02 启动前约定五个停止条件

启动前先约定:

  • 检查成功时停止。
  • 连续两轮没有减少失败时停止并报告阻塞。
  • 达到最大轮次或成本预算时停止。
  • 发现需要用户决策、凭证或外部环境变化时停止。
  • 修改范围超出原计划时回到计划阶段。

这几条可以直接写进任务说明。轮次和预算还可以交给工具来管:Claude Code 最佳实践把“花多少”列为可以由 Claude Code 强制执行的一类,在 -p 非交互模式下可以用 --max-turns 或 --max-budget-usd 设上限,也可以设置用量上限;不设的话,就由 Claude 自己的节奏决定。

03 停下来时报告什么

达到停止条件就停下来,报告进展、证据、原因和所需输入。继续尝试要有新的依据,重复同一方案本身并不代表有进展。

例如认证集成测试因本地数据库未启动而失败,修改代码未必有帮助。若同一连接错误持续存在,应报告环境证据,确认能否启动服务;不能以跳过该测试作为成功。恢复依赖后,再回到原验收。

一份停下来时的报告,至少要让你看到:

内容例子
进展撤销字段和退出写入已完成,单元测试通过
证据集成测试连续三轮报同一个数据库连接错误
原因本地数据库服务未启动,与代码修改无关
所需输入需要你启动数据库,或确认使用测试容器

04 往回退到哪一步

阶段证据决定下一步:关键事实不足就回研究,范围变化就回计划,外部条件缺失则等待对应变化。机制只在有实际用途时加入。

最后一步的验收,仍然要回到开始时定下的证据要求。测试通过只是其中一类证据,行为、兼容和审查证据都要齐,见Claude Code 说修好了,你该怎么验收。

05 用 Stop Hook 强制检查时防止死循环

想让“检查不通过就别结束”变成强制规则,可以用 Stop Hook。最佳实践文档给的例子是一条类型检查:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "pnpm tsc --noEmit 1>&2 || exit 2" }
        ]
      }
    ]
  }
}

Stop 表示一次回复结束,包括提出澄清问题后结束回复。Hook 以退出码 2 阻断时,Claude 会收到 stderr 里的编译错误,回去继续修,直到检查通过。

这正是要设停止条件的地方。阻断会要求 Claude 继续,因此必须检查 stop_hook_active,避免同一结束条件反复触发。Hooks 参考文档对这个字段的说明是:Claude Code 已经因为 Stop Hook 在继续工作时,它的值为 true;检查它,或者处理对话记录,避免在一个永远不会满足的条件上反复阻断。官方另外设了一道上限:Stop Hook 连续让回合继续八次后,Claude Code 会忽略下一次阻断、结束这一轮;每次 Claude 调用工具,计数就会清零。

只检查文件存在时,使用脚本即可;涉及完成质量的语义判断,才考虑带标准与超时的模型处理器。单纯提醒用 Notification。Stop 事件的含义和其他事件怎样选,见Claude Code Hook 不触发怎么排查。

回到开头那次“全部通过”:如果启动前约定了“连续两轮失败没减少就停”“不能以跳过测试作为成功”,Claude 会在第三轮停下来,告诉你数据库连不上,而不是去改断言。继续尝试要有新的依据,重复同一方案不算进展。