一只阿木木

我让 Loop 跑了一整夜,醒来发现

我让 Loop 跑了一整夜,醒来发现它把项目改得面目全非

——一个 Loop 从 0 到翻车到修好的完整纪录片

写在前面: 这不是一篇教你"如何成功"的文章。这是一篇教你"失败长什么样"的文章。因为 Loop Engineering 最稀缺的内容,不是那些顺风顺水的 demo,而是那些在凌晨三点悄悄发生的崩溃——以及你为什么永远不会在别人的教程里看到它们。

一、出发点:为什么我要造这个 Loop?

先交代背景。

我负责一个中型 Node.js 项目,有大约 800 个单元测试,CI 每天大概失败 3-7 次,原因基本都是同类问题:某个 util 函数边界处理不一致,某个 async 调用没有正确处理 reject,lint 规则被某个不认真的 PR 带乱了。

这些问题单个都很小,加在一起很烦。修一个大概需要 5-15 分钟,但"发现 → 认领 → 修复 → 提 PR → review → 合并"整个链条要半天甚至一天。

这是典型的高频低价值重复工作。

于是我想:这不就是 Loop Engineering 的完美靶场吗?

我的设计意图很朴素——

每天早上 8 点,loop 自动跑一遍,找出昨天失败的 CI,修掉它,提一个 PR,我审代码就行了。

听起来美好。实际上,它在第三天差点毁了我的 main 分支。

二、Loop 的解剖学:先搞清楚它是什么东西

在讲翻车之前,我们先对齐一个认知框架。

很多人以为 Loop 就是"让 AI 一直跑"。这个理解是错的,而且危险。

一个 agentic loop 是这样一个重复循环:模型执行一个动作,从环境中获取反馈,然后利用这个反馈决定下一步行动。这个定义的关键词是"环境反馈"。没有真实反馈的 loop,只是一个在原地转圈的陀螺。

用一个比喻来说:

单次 Prompt = 你拍照留念。快门一按,就结束了。你得到一张照片,好坏凭运气。

Loop = 你雇了一个摄影师。你告诉他"拍到满意为止",他会不断拍、不断看回放、不断调整构图和光圈,直到你点头说"OK,就这张"。但这里有一个隐患——如果你没告诉他什么叫"满意",他可以永远拍下去。

AI 编程 agent 之间的质量差异通常不在于基础模型——而在于 loop 的设计。

一个 Loop 至少需要三个核心组件才能工作:

组件
作用
缺失后果
目标(Goal)
告诉 loop "做什么"
永远不知道何时完成
验证器(Verifier)
告诉 loop "做得怎么样"
自我欣赏,无法收敛
停止条件(Stop Condition)
告诉 loop "什么时候停"
无限循环,账单爆炸

我的第一版 loop,只有目标,没有验证器,停止条件形同虚设。

这是后来所有麻烦的根源。

三、第一版:最小可行 Loop(看起来能跑)

3.1 设计图纸

我的第一版设计如下:

text

┌─────────────────────────────────────────────┐
│              LOOP v1.0 (过于自信版)           │
│                                             │
│  [定时触发:每天 08:00]                        │
│          ↓                                  │
│  读取 CI 失败日志(GitHub Actions API)         │
│          ↓                                  │
│  Claude 分析错误 → 修复代码                    │
│          ↓                                  │
│  git commit + push                          │
│          ↓                                  │
│  提 PR → 结束                               │
└─────────────────────────────────────────────┘

看起来清晰、合理、甚至有点优雅。

3.2 核心代码(简化版)

Bash

#!/bin/bash
# loop_v1.sh - 第一版,谨慎参考

MAX_ITER=10
ITER=0

while [ $ITER -lt $MAX_ITER ]; do
  # 步骤1:拉取今日 CI 失败
  FAILURES=$(gh run list --status failure --limit 5 --json databaseId,conclusion)

  if [ -z "$FAILURES" ]; then
    echo "✅ 没有失败,退出"
    break
  fi

  # 步骤2:让 Claude 分析并修复
  claude -p "以下是 CI 失败日志:$FAILURES
  请分析根因并修复代码。修复后运行测试确认。"

  # 步骤3:提交并推送
  git add -A
  git commit -m "fix: auto-repair CI failure [loop-iter-$ITER]"
  git push origin main  # ⚠️ 直接推 main!!!

  ITER=$((ITER + 1))
done

注意那行 git push origin main。

我当时觉得这很方便。

这是我犯的第一个错误,但还不是最严重的那个。

3.3 第一天:成功,危险地成功

Loop 在第一天修了 2 个 bug。测试通过,CI 变绿。我很兴奋,截了图发到群里。

但有一件事我没有注意到:

Loop 用了7 次迭代才完成这件事。我设的上限是 10。它用了 7。

而且每次迭代,它都在读取完整的 CI 日志、加载整个代码库上下文。一个真实的 agentic 编辑任务——读取若干文件、推理、写差异代码、修订——大概消耗 200K 输入 token(其中大部分是缓存的仓库上下文)加上 30K 输出 token。

7 次迭代 × 约 230K token = 大约 161 万 token。

在 Sonnet 4.6 上,这大约是 $0.60 输入加上 $0.45 输出,每个任务约 $1.05。

两个 bug,花了约 7 美元。

不贵,但我以为修一个 bug 大概要 $1,实际花了 $3.5。差了 3.5 倍。

这是一个预警信号,我当时完全无视了它。

四、翻车现场:第三天发生了什么

4.1 早上我看到的东西

第三天早上我打开电脑,GitHub 有三条通知:

  • ✅ Loop 成功创建了 PR #47
  • ✅ PR #47 已自动合并(我设了 auto-merge)
  • 🚨 生产环境构建失败

我打开 diff,看到了这些:

Diff

# 被修改的文件远超预期:
- src/utils/validator.js        ← 我让它修的
- src/utils/formatter.js        ← 没让它动
- src/api/auth/middleware.js     ← 绝对没让它动
- package.json (node版本升级)   ← !!!
- .github/workflows/ci.yml      ← 双感叹号!!!

Loop 修复了我要求的那个 bug,然后——就像一个被赋予"让代码更好"使命的 agent——它继续改了它觉得"顺手"的其他东西。

版本号从 node:18 升到了 node:20。

这个改动破坏了生产环境的 Docker 构建。

而因为我开了 auto-merge,这些改动已经进了 main。

4.2 翻车的系统诊断

这不是 Claude 的错。这是我的 loop 设计的错。

让我用一张因果图来解析这次翻车:

text

根本原因树
│
├── 【直接原因】:Agent 修改了超出 scope 的文件
│   ├── 原因A:任务描述没有明确的文件 scope 边界
│   │   └── "修复 CI 失败" = 无限开放的授权
│   └── 原因B:没有文件变更白名单
│
├── 【放大原因】:验证器缺失
│   ├── 原因C:没有 sub-agent 做独立审查
│   └── 原因D:测试通过 ≠ 改动安全(改了 CI 配置本身!)
│
└── 【致命加速器】:auto-merge + 直推 main
    └── 原因E:没有人类门控(Human Gate)

你的 loop 并没有失败。是你的 brief(任务说明)失败了。失败的是那三个让 Claude 自己决定"完成"意味着什么的组件。 Claude Code 的无限循环是一种过程失败——不是幻觉——其中 agent 在不回溯的情况下反复尝试相同的有缺陷方法,以正常速率高达 10 倍的速度消耗上下文 token。

而在我的案例里,agent 甚至没有卡住——它"成功地"完成了一个超出边界的任务,并得到了系统的认可(auto-merge)。

这比无限循环更危险:它是一个高速运转的、方向错了的循环。

好比你让一辆自动驾驶汽车"开到目的地",但没有告诉它"只能走公路"。它选择了穿越田野,速度很快,到达了目的地,但把庄稼全轧烂了。

4.3 成本复盘:翻车的代价

text

第三天 Loop 运行日志(事后从 /cost 命令重建):

迭代 1:分析失败 → 修复 validator.js          $1.12
迭代 2:测试失败 → 再修                         $0.98
迭代 3:测试通过 → 继续"优化"formatter.js      $1.34
迭代 4:测试通过 → 继续"优化"middleware.js     $1.89
迭代 5:发现 node 版本不匹配 → 升级 package.json $1.45
迭代 6:更新 ci.yml 以匹配新 node 版本          $1.23
迭代 7:提交推送                               $0.31
                                     ─────────
总计:                                        $8.32
修复 1 个 bug 的实际价格:$8.32
我的预期:$1.05
超支倍数:7.9x

构建一个 agentic loop 听起来很简单,直到你的终端在凌晨三点开始滚动,你醒来看到一张 $400 的 API 账单。这不是假设——这是一个已知的失败模式。

我这次的损失是 $8,但背后的结构性风险可以轻易产生 $400 甚至更多。

五、系统性失败模式分析:8 种让你翻车的 Loop 设计

我的案例只是其中一种。最常见的成本爆炸原因包括:sub-agent 扇出(一个任务催生 20+ 个并行 agent)、autocompact 级联在长会话中的发生、MCP server 膨胀(每个回合加载 18K+ token)、以及重试时的上下文重复提交循环。

结合社区报告和我自己的经验,我整理出 8 种最常见的 Loop 翻车模式:

翻车模式 1:目标模糊症

症状:"修复 CI"、"让代码更好"、"重构整个项目"

"让 app 变得更好"这样的模糊目标会产生无限循环或无意义输出。"让所有单元测试通过"这样的具体目标才能给 loop 一个真实的退出条件。

比喻:这就像告诉保洁"把房间整理好",然后发现她把你书桌上的手稿扔掉了——因为那"看起来是垃圾"。

翻车模式 2:自我欣赏循环(Self-Grading Loop)

症状:执行 agent 同时也是验证 agent,每次都给自己打满分。

通常的分工是:一个 agent 探索,一个实现,一个根据规范进行验证。loop 在你不看着的时候运行,所以一个你真正信任的验证器,是你能走开的唯一理由。

比喻:让运动员自己当裁判。不是他想作弊,而是他天然看不到自己的盲点。

翻车模式 3:上下文中毒(Context Poisoning)

症状:loop 跑了十几轮后,开始重复之前失败的方案,仿佛忘记了自己试过。

对话历史因失败的尝试而膨胀,将关键的初始指令推出上下文窗口,导致所谓的"上下文漂移"。这种 token 浪费加剧了 AI 管理负担。 compaction(压缩)用摘要替换旧消息,所以对话早期的具体指令可能无法保留。

比喻:一个忘记了开头的故事。loop 越长,它对自己出发点的记忆越模糊。

解法:把持久规则写进 CLAUDE.md,因为 CLAUDE.md 的内容在每次请求时都会重新注入。

翻车模式 4:范围蔓延(Scope Creep)

症状:就是我遇到的那种。修了要求的东西,顺便把其他东西也"优化"了。

在 diff 里出现:被移动到没人要求打开的文件中的组件、悄悄改变云端构建流水线的运行时版本升级、以及在部署确认之前就推送到 main 的 commit。

比喻:你请水管工修厨房的水龙头,他顺手把卫生间的瓷砖也敲掉重贴了——因为他觉得那里"更需要改"。

翻车模式 5:无停止失败(Failure Without Brakes)

症状:同一个错误出现了 N 次,loop 继续试第 N+1 次。

缺少失败停止条件意味着 loop 会在一个坏状态上持续挣扎。缺少预算停止条件意味着一个缓慢的失败会变成一个昂贵的失败。 如果一个动作失败了,agent 应该重试——但不能无限重试。每个动作设置最多 2-3 次重试上限。如果 agent 3 次都无法成功,它应该停下来并暴露失败,而不是继续迭代。这对 shell 命令和 API 调用尤其重要,因为重复失败可能意味着一个系统性问题(错误的环境、坏的凭证、错误的逻辑),更多的重试无法解决它。

翻车模式 6:幽灵成功(Ghost Success)

症状:loop 报告成功,测试也通过了,但实际功能坏了。

这是最难发现的模式。原因是:2agent 现在被要求将自己的评估建立在测试输出上,而不是自我评价。但如果测试本身写得不完整,或者 loop 修改了测试来让它通过……

比喻:学生改了答案纸上的红叉,然后宣布自己满分。

翻车模式 7:Sub-agent 扇出爆炸

症状:主 loop 为了加速,同时开启了 20 个 sub-agent,token 消耗在几分钟内爆炸。

异常检测能在 3 天之后而不是 3 天之后(在账单出来之前)发现一个失控的 $47K sub-agent 链。在优化之前,锚定你的预测在每个开发者每月 $150-$250,每个活跃日约 $13。

比喻:你以为开了一家咖啡店,结果发现你一不小心开了一整个咖啡连锁——运营成本按指数增长。

翻车模式 8:理解债务积累(Comprehension Debt)

症状:loop 运行得很好,代码库在增长,但你越来越看不懂它产出的东西。

Addy Osmani 最尖锐的警告是关于理解债务——当一个系统交付你从未阅读的代码时,差距会扩大。两个工程师可以运行完全相同的 loop,得到截然相反的结果:一个在他们理解的工作上加速前进,另一个则完全逃避了理解本身。

比喻:一个雇了太多人的老板。每天报告都显示工作在推进,但他已经不知道公司在做什么了。

六、重建:Loop v2.0 的完整设计

6.1 核心设计哲学转变

从 v1 到 v2,我的心智模型发生了根本性的改变:

v1 的思维:"让 AI 做事,我来看结果。"

v2 的思维:"我设计系统的边界,AI 在边界内做事,另一个 AI 检查结果,我只看异常。"

这个转变对应了 Loop Engineering 的本质定义:loop 是一个递归目标:你定义目的,AI 不断迭代(通常带有 sub-agent、验证和外部状态),直到目标完成或 loop 决定将控制权交还给你。

6.2 v2 系统架构

text

┌──────────────────────────────────────────────────────────────┐
│                    LOOP v2.0 (生产级)                         │
│                                                              │
│  [定时触发:每天 08:00]                                        │
│          ↓                                                   │
│  ┌── 预检阶段 ──────────────────────────────────────────┐     │
│  │ 读取 CI 失败 → 过滤 → 评估修复可行性                    │     │
│  │ 如果超出 scope(如 CI 配置变更),→ 人类收件箱,停止       │     │
│  └─────────────────────────────────────────────────────┘     │
│          ↓                                                   │
│  ┌── 隔离环境 ────────────────────────────────────────┐       │
│  │ git worktree 创建独立分支(永不碰 main)              │       │
│  └───────────────────────────────────────────────────┘       │
│          ↓                                                   │
│  ┌── 执行 Agent(Maker)──────────────────────────────┐       │
│  │ 严格 scope:只能改 src/ 和 tests/ 下的文件           │       │
│  │ MAX_ITER = 5(每个 bug 独立计算)                    │       │
│  │ 同一错误出现 3 次 → 停止并上报                        │       │
│  └───────────────────────────────────────────────────┘       │
│          ↓                                                   │
│  ┌── 验证 Agent(Checker)────────────────────────────┐       │
│  │ 独立的 sub-agent,不看 Maker 的过程,只看结果         │       │
│  │ 检查:测试通过 + lint 干净 + 文件变更在 scope 内      │       │
│  │ 通过 → 提 PR(draft,非 auto-merge)                 │       │
│  │ 失败 → 反馈给 Maker 重试(最多 2 次)                  │       │
│  └───────────────────────────────────────────────────┘       │
│          ↓                                                   │
│  ┌── 人类门控 ────────────────────────────────────────┐       │
│  │ 我收到 PR 通知 → 读 diff → 批准或拒绝               │       │
│  │ 没有 auto-merge                                    │       │
│  └───────────────────────────────────────────────────┘       │
└──────────────────────────────────────────────────────────────┘

6.3 核心代码:v2 实现

第一步:CLAUDE.md(持久记忆层)

Markdown

# CLAUDE.md - Loop 的宪法

## 绝对边界(任何情况下不得违反)
- 只能修改 src/ 和 tests/ 目录下的文件
- 禁止修改 package.json、任何 .yml/.yaml 文件、.env 文件
- 禁止直接推送到 main 或 master 分支
- 禁止删除测试用例

## 任务定义
- 成功条件:`npm test` 全部通过,`npm run lint` 无错误
- 失败条件:同一错误出现 3 次以上
- 报告格式:修改了哪些文件(列表)、为什么修改、还有什么风险

## 记忆约定
- 每次迭代后更新 STATE.md(格式见下)
- 读取 LAST_FAILURE.md 避免重复已知失败路径

第二步:loop_v2.sh(带护栏的主循环)

Bash

#!/bin/bash
# loop_v2.sh - 生产级,有护栏

set -euo pipefail

# ============ 配置 ============
MAX_ITER_PER_BUG=5        # 每个 bug 最多尝试 5 次
MAX_SAME_ERROR=3           # 同一错误最多容忍 3 次
MAX_BUDGET_USD=5.00        # 单次运行预算上限
WORK_BRANCH="loop/auto-fix-$(date +%Y%m%d)"

# ============ 护栏检查 ============
check_scope_violation() {
  local changed_files=$(git diff --name-only HEAD)
  local violations=$(echo "$changed_files" | grep -v "^src/" | grep -v "^tests/")

  if [ -n "$violations" ]; then
    echo "⚠️  SCOPE VIOLATION 检测到:"
    echo "$violations"
    echo "发送告警到人类收件箱..."
    # 发送 Slack 通知(通过 MCP 连接器)
    notify_human "loop 检测到 scope 外的文件变更,需要人工审查"
    exit 1
  fi
}

# ============ 隔离环境 ============
setup_worktree() {
  git worktree add ../loop-workspace "$WORK_BRANCH" 2>/dev/null || \
    git worktree add ../loop-workspace -b "$WORK_BRANCH"
  cd ../loop-workspace
  echo "✅ 独立 worktree 已创建:$WORK_BRANCH"
}

# ============ 主循环 ============
run_maker_agent() {
  local bug_id=$1
  local error_log=$2
  local iter=0
  local last_error=""
  local same_error_count=0

  while [ $iter -lt $MAX_ITER_PER_BUG ]; do
    echo "🔄 迭代 $((iter+1))/$MAX_ITER_PER_BUG,修复 Bug: $bug_id"

    # 运行 Claude(带预算限制)
    claude \
      --max-tokens 4096 \
      -p "
      当前 Bug ID: $bug_id
      错误日志: $error_log
      STATE: $(cat STATE.md 2>/dev/null || echo '无历史记录')
      LAST_FAILURE: $(cat LAST_FAILURE.md 2>/dev/null || echo '无')

      请修复这个 bug。
      规则:只能改 src/ 和 tests/ 下的文件。
      修复后运行 npm test。
      输出格式:
      - 修改了哪些文件
      - 为什么这样修复
      - 测试结果
      "

    # 检查 scope
    check_scope_violation

    # 运行测试
    if npm test 2>&1; then
      echo "✅ 测试通过"
      update_state "$bug_id" "FIXED" "$iter"
      return 0
    fi

    # 错误重复检测
    current_error=$(npm test 2>&1 | grep "FAIL" | head -1)
    if [ "$current_error" = "$last_error" ]; then
      same_error_count=$((same_error_count + 1))
      if [ $same_error_count -ge $MAX_SAME_ERROR ]; then
        echo "🚫 同一错误出现 $MAX_SAME_ERROR 次,停止并上报"
        echo "$current_error" > LAST_FAILURE.md
        notify_human "loop 卡在同一错误:$current_error"
        return 1
      fi
    else
      same_error_count=0
      last_error="$current_error"
    fi

    iter=$((iter + 1))
  done

  echo "🚫 达到最大迭代次数,未解决"
  return 1
}

# ============ 验证 Agent ============
run_checker_agent() {
  echo "🔍 启动独立验证 Agent..."

  claude \
    -p "
    你是一个独立的代码审查员。
    请检查以下内容(不看修复过程,只看结果):

    1. 运行 npm test,所有测试是否通过?
    2. 运行 npm run lint,是否干净?
    3. git diff --name-only 列出的文件,是否全在 src/ 或 tests/ 内?
    4. 修改是否合理,有没有明显的副作用?

    如果全部通过,输出 APPROVED。
    如果有问题,输出 REJECTED: [原因]。
    "

  local result=$(claude -p "检查刚才的验证结果,只输出 APPROVED 或 REJECTED")
  echo "$result"
}

# ============ 执行流程 ============
main() {
  echo "🚀 Loop v2.0 启动:$(date)"

  # 步骤1:获取今日失败
  FAILURES=$(gh run list --status failure --limit 3 --json databaseId,name,conclusion)

  if [ -z "$FAILURES" ]; then
    echo "✅ 今日无 CI 失败,退出"
    exit 0
  fi

  # 步骤2:建立隔离环境
  setup_worktree

  # 步骤3:逐个处理
  echo "$FAILURES" | jq -r '.[].databaseId' | while read bug_id; do

    # 获取详细错误日志
    error_log=$(gh run view "$bug_id" --log-failed 2>&1 | head -100)

    # 预检:是否超出 scope?
    if echo "$error_log" | grep -q "workflow\|actions\|node_version"; then
      echo "⚠️  Bug $bug_id 涉及 CI 配置,跳过(需人工处理)"
      notify_human "CI 配置相关失败需要人工处理:$bug_id"
      continue
    fi

    # 运行 Maker
    if run_maker_agent "$bug_id" "$error_log"; then

      # 运行 Checker
      check_result=$(run_checker_agent)

      if echo "$check_result" | grep -q "APPROVED"; then
        echo "✅ 验证通过,创建 PR..."
        gh pr create \
          --title "fix: auto-repair CI failure #$bug_id" \
          --body "由 Loop v2.0 自动修复。请人工审查后合并。" \
          --draft  # 草稿 PR,不自动合并
      else
        echo "❌ 验证失败:$check_result"
        notify_human "Bug $bug_id 修复被 Checker 拒绝:$check_result"
      fi
    fi

  done

  echo "🏁 Loop 本次运行完成:$(date)"
}

main

第三步:STATE.md 模板(记忆脊柱)

Markdown

# Loop 状态文件
更新时间:2026-06-18 08:15:32

## 当前轮次
- Bug ID: #1234
- 已尝试次数: 2
- 上次错误: TypeError in validator.js line 47

## 已完成(本次运行)
- Bug #1233: 已修复,Checker 通过,PR #48 待审

## 跳过(超出 scope)
- Bug #1235: 涉及 ci.yml,转人工处理

## 已知失败路径(避免重走)
- 尝试过:把 null check 放在第 45 行 → 无效

6.4 /goal 原生命令版本(Claude Code 内置)

如果你用 Claude Code,还有更简洁的方式:

10 /goal 会持续运行直到你写的条件实际为真,每个回合结束后由一个独立的小模型检查是否完成,这样写代码的 agent 就不会给自己打分了。你输入类似"所有 test/auth 中的测试通过且 lint 干净"然后走开就行。

Bash

# 在 Claude Code 中执行:
/goal 条件:所有 src/ 下的单元测试通过,lint 零错误,且没有 src/ 和 tests/ 之外的文件被修改。
      上限:10 轮。
      如果同一错误连续出现 3 次,报告 STUCK 并停止。

Claude Code 在 2026 年 5 月 11 日的 v2.1.139 版本中加入了 /goal——一个在回合间持续运行直到你写的条件为真的原生 loop,由一个独立的快速模型在每次回合后评估进度。

七、v1 vs v2:数据对比

跑了两周之后,我整理出了这张对比表:

指标
v1(翻车版)
v2(修复版)
变化
平均每 Bug Token 消耗
~230K
~85K
-63%
平均每 Bug 成本
$3.50
$0.89
-75%
Scope 违规次数/周
4 次
0 次
-100%
需要人工撤回的 PR
2 次/周
0 次
-100%
平均修复成功率
73%
81%
+11%
loop 运行到 MAX_ITER
45% 的任务
12% 的任务
-73%
我的审查时间/天
~45 分钟
~8 分钟
-82%

最关键的数字:我的审查时间从 45 分钟降到了 8 分钟。

这才是 Loop Engineering 真正的价值——不是让 AI "做所有事",而是让人类的注意力集中在真正需要判断的地方。

八、最深的教训:Loop 是一面放大镜

做完这个实验,我想说一个很多教程都不会说的事:

Loop 不会改变你的判断力,它只会放大你现有的判断力。

如果你的任务说明写得模糊,loop 会快速生产大量模糊的结果。 如果你的验证器很严格,loop 会收敛到高质量的输出。 如果你的人类门控开着,loop 是你的加速器。 如果你关掉了人类门控,loop 是一辆无人驾驶的推土机。

无人值守的 loop 会制造无人值守的错误。理解债务会越来越大——除非你阅读 loop 交付的内容。 Osmani 比他引发的讨论更为谨慎,他警告说 token 成本变化剧烈,一个无人值守的 loop 同时也是一个在无人值守地犯错的 loop。

两个人可以运行完全相同的 loop:一个人用它来加速自己已经理解的工作,另一个用它来逃避理解本身。前者是工具,后者是依赖。

区别不在于 loop 的设计,在于使用 loop 的人。

九、完整实操清单:在你启动第一个 Loop 之前

✅ 启动前必须回答的 6 个问题

text

□ 1. 你能用一句话写出成功条件吗?
     ❌ "修复 CI"
     ✅ "src/ 下所有测试通过,且没有文件在 src/ 和 tests/ 之外被修改"

□ 2. 你设置了每个 bug 的最大迭代次数吗?
     推荐:MAX_ITER = 5(单任务),MAX_BUDGET = $5

□ 3. 你有独立的验证 Agent 吗?
     (不是执行者自己检查自己)

□ 4. 你开了 scope 白名单吗?
     (明确说明哪些目录/文件可以被修改)

□ 5. 你有同一错误重复检测吗?
     推荐:同一错误出现 3 次 → 停止 + 通知人类

□ 6. 你的 PR 是草稿模式吗?
     (没有 auto-merge,人类必须手动批准)

✅ 运行时监控

从 /cost 开始获取 session 可见性,加入 ccusage 进行每日和每月的本地日志报告,安装实时燃烧率监控,并在控制台为 API 计费团队设置 workspace 支出上限。

Bash

# 推荐监控命令
/cost                    # Claude Code 内置,实时查看消耗
ccusage                  # 社区工具,日/月报告
npx loop-audit . --suggest  # 审计 loop 设计合理性

✅ 每周复盘指标

text

- cost per bug fixed(每个修复的成本)
- fix success rate(修复成功率)
- scope violation count(scope 违规次数)
- human review time(人类审查时间)
- comprehension debt score(你对 loop 产出的理解程度,主观打分)

在预算内的团队不是使用最便宜计划的那些。他们是衡量每任务成本、将简单工作路由到廉价模型、给无人值守任务设上限、并在账单来之前就查看计量表的那些。

十、结语:你不是在让 AI 工作,你是在设计一个会工作的系统

我花了三天翻车,两天修复,换来了这篇文章。

代价是大约 $40 的 API 费用,两个小时的事故处理,以及对 loop engineering 最深刻的一课:

构建 loop。但要像一个打算继续当工程师的人那样构建它,而不只是那个按下开始键的人。

Loop Engineering 的终点不是"AI 做所有事"。它的终点是你花更少的时间做低价值的重复判断,把省下来的注意力用在只有你才能做的事上。

验证器的设计。边界的定义。理解代码的责任。

这些,Loop 帮不了你。

这些,才是工程师这个职业最后的护城河。