
Loop Engineering 从入门到进阶手册 · 第 5 篇 前面几篇讲了 Loop 的积木、模式和三角色架构。 这一篇只做一件事:搭一个最小可跑的 CI 自动修复 Loop。
这篇不教你搭一个“全自动程序员”。
我们只搭一个很窄、很实用的小 Loop:
每天检查一次项目里的失败测试或明确 bug,挑一个可验证的小问题,生成修复建议,跑测试,写出结果报告;能修就留下可 review 的 diff 和 PR 摘要,修不了就停下来交给人。
它不会自动合并代码。
它不会绕过人工 review。
它也不会处理“重构整个系统”“让项目更优雅”这种大而空的目标。
你读完应该能拿走三样东西:
TODO.md state file 模板这篇只讲 Codex CLI + 外部调度器 这一条路径。
原因很简单:命令可见、状态可存、失败可查,新手也更容易复盘。
搭 Loop 前,项目至少要满足五个条件。
不需要 100% 覆盖率,但至少要有一条能判断成败的命令:
npm test
或者:
pytest
Loop 的成败标准,大多数时候就是测试。没有测试的 Loop,很容易变成 Agent 自说自话。
先确认项目在 Git 里:
git status
后面无论是开独立分支、开 worktree,还是生成 PR,都需要 Git 做隔离和回滚。
更准确地说,项目最好已经有一个干净的基线提交。
如果是刚建的小项目,先提交一次当前状态:
git add .
git commit -m "baseline"
否则 Checker 审 diff 时,会把所有文件都看成本轮改动,验收结果会很脏。
建议准备一份 AGENTS.md。
最少写清楚四件事:
可以让 Agent 先起草一版:
阅读这个项目,生成一份 AGENTS.md。
需要包含:安装步骤、测试命令、代码约定、禁止修改的文件、需要人工确认的风险操作。
不要第一步就上定时任务。
先手动执行一轮,确认它不会误删文件、不会乱改无关模块、不会把失败测试解释成成功。
自动化之前,先证明这条链路能跑通。
再做一次 Codex CLI 环境烟测:
codex exec --sandbox read-only "只读取 AGENTS.md 和 TODO.md,不要修改文件"
如果这里直接报错,先处理本机 Codex 登录、权限或运行目录问题。
例如遇到 attempt to write a readonly database、failed to initialize in-process app-server client 这类错误,说明 Codex CLI 自己的运行环境还没准备好。这个问题不属于 Loop 逻辑,但会让第一步直接失败。
坏目标长这样:
让项目更稳定
修一下 auth 模块
优化 CI
这种目标会让 Agent 发散,因为它不知道做到哪一步算完成。
好目标要能验收:
修复 test/auth 里的失败测试,并确保 npm test 通过。
修复 CI 中 eslint 报错,只允许改动相关文件,不做无关重构。
根据最近一次失败日志定位问题,给出最小修复方案;如果无法修复,输出阻塞原因。
一个合格目标至少满足三个条件:
标准 | 说明 | 检查方式 |
|---|---|---|
具体 | 能判断完成没完成 | 能不能用通过/失败回答 |
可测试 | 有命令或证据验证 | 能不能跑测试、lint、type check |
有边界 | 不会无限扩大范围 | 有没有明确禁止无关重构 |
一句话检验:
如果一个目标不能写成 checklist,就先不要放进 Loop。
Loop 不能只靠聊天上下文。
上下文会丢,任务会中断,Agent 会忘记上一轮为什么这么判断。
所以先放一个状态文件,例如 TODO.md:
# TODO.md - CI 修复 Loop 状态
## Goal
- [ ] 修复一个有明确失败信号的 CI 问题
- [ ] 相关测试通过
- [ ] 不做无关重构
- [ ] 如果失败,记录尝试过程和阻塞原因
## Candidate Issues
| 优先级 | 来源 | 失败信号 | 处理状态 |
|---|---|---|---|
| P1 | CI log | test/auth/login.test.ts failed | 待处理 |
## Current Attempt
- Issue:
- Branch:
- Last command:
- Last result:
- Next action:
## Log
| 时间 | 动作 | 结果 | 下一步 |
|---|---|---|---|
| | | | |
这个文件给 Loop 提供外部记忆,避免每一轮都只靠聊天上下文。
每一轮都要读它、更新它。哪怕 Agent 中途断掉,人也能接手。
第一轮不要让 Agent 改代码。
先让它只读仓库,找出一个适合自动修复的小问题。
codex exec --sandbox read-only \
"阅读 AGENTS.md、TODO.md 和最近的测试输出。
找出一个最适合自动修复的问题。
只允许输出分析,不要修改文件。
输出内容包括:
1. 失败信号
2. 相关文件
3. 推荐修复范围
4. 验收命令
5. 是否适合进入自动修复 Loop"
这一步的目标是筛选。
适合进入 Loop 的问题,一般有这些特征:
不适合进入 Loop 的问题,要直接丢回人工处理。
通过侦察后,再进入 Maker。
Maker 的任务只有一个:最小修复。
codex exec --sandbox workspace-write \
"你是 Maker。
读取 AGENTS.md 和 TODO.md。
只处理 TODO.md 中优先级最高、且有明确失败信号的问题。
要求:
1. 先说明你准备修改哪些文件
2. 只做最小修复,不做无关重构
3. 修改后运行 TODO.md 中的验收命令
4. 把运行结果写回 TODO.md
5. 如果连续 2 次同一测试失败,停止并记录阻塞原因
6. 不要 push,不要 merge,不要修改生产配置"
如果你担心它改动太大,可以先让 Maker 只生成 patch 建议,再由你确认后执行。
对新手来说,我更建议先这样做。
Maker 写完后,不要让它自己宣布成功。
换一个 Checker 来验收。
codex exec --sandbox read-only \
"你是 Checker。
请审核当前 diff 和 TODO.md。
只做验证,不要修改代码。
检查项:
1. 是否只修改了相关文件
2. 是否存在无关重构
3. 是否运行了约定测试
4. 测试结果是否真的通过
5. 是否引入安全风险、硬编码密钥或危险权限
6. 如果不通过,请列出具体失败原因和下一步建议
7. 如果通过,请生成 PR 摘要"
Checker 要尽量“难说话”。
它的职责是保护你的代码库,专门检查 Maker 有没有跑偏。
假设 CI 失败日志里有这样一条:
FAIL test/auth/login.test.ts
Expected status 401, received 500
TODO.md 可以这样写:
## Candidate Issues
| 优先级 | 来源 | 失败信号 | 处理状态 |
|---|---|---|---|
| P1 | CI | login.test.ts: Expected 401, received 500 | 待处理 |
## Current Attempt
- Issue: 登录失败时错误码不符合预期
- Branch: loop/fix-auth-login-status
- Last command: npm test -- test/auth/login.test.ts
- Last result: 待运行
- Next action: 检查 auth handler 的错误处理分支
Maker 的目标就很窄:
只修复 login.test.ts 中 Expected 401, received 500 的问题。
不修改测试预期。
不改动无关 auth 文件。
修复后运行:npm test -- test/auth/login.test.ts
Checker 的验收也很窄:
检查 diff 是否只围绕登录错误处理。
确认没有把测试改成适配错误实现。
确认 npm test -- test/auth/login.test.ts 通过。
如果通过,生成 PR 摘要;如果失败,说明失败原因。
PR 摘要模板:
## Summary
- 修复登录失败时返回 500 的问题
- 将认证失败分支调整为返回 401
## Verification
- npm test -- test/auth/login.test.ts
## Risk
- 只影响 auth login 错误处理
- 不涉及权限模型和数据库结构
这就是一个最小闭环。
问题小,验收清楚,失败能停。
手动跑通以后,再考虑自动调度。
最朴素的方式,是让 cron 或 GitHub Actions 定时执行 codex exec。
示例 cron:
0 9 * * 1-5 cd /path/to/repo && codex exec --sandbox read-only "检查 TODO.md、测试输出和最近 CI 失败,生成今日 Loop 候选项"
这条路径的优点是透明:什么时候跑、跑了什么、输出在哪里,都能查。
建议先让定时任务只做“侦察”,不要直接改代码。
等你确认候选项质量稳定,再开放 Maker。
CI 修复 Loop 至少要有四个断路器。
断路器 | 推荐值 | 作用 |
|---|---|---|
连续失败上限 | 2 次 | 防止同一错误反复烧 token |
单次运行时长 | 30 分钟 | 防止长时间卡住 |
改动范围 | 只允许相关文件 | 防止顺手重构 |
人工确认 | merge 前必须 review | 防止自动化越权 |
可以直接写进提示词:
安全限制:
1. 同一个测试连续失败 2 次后停止。
2. 单次运行超过 30 分钟后停止。
3. 只允许修改和失败测试直接相关的文件。
4. 不要 push 到 main。
5. 不要 merge。
6. 遇到支付、权限、数据删除、生产配置,必须停止并交给人工确认。
记住:自动化越强,停止规则越要明确。
Loop 烧 token 的速度,通常比想象中快。
尤其是 Maker 写一轮,Checker 验一轮,失败后再重复,很容易把一次“小修复”跑成一串调用。
在我的本地 Codex Desktop 环境里,一次 4 个文件的烟测,只读侦察、Maker、Checker 三步都出现过数万 tokens 的消耗。
所以第一个 Loop 不要放在大仓库里试,也不要让提示词一次要求它“全面分析整个项目”。
几个简单原则:
第一周每天一次就够了。
别一开始就每小时跑。
定时任务先只做侦察和排序。
等候选项足够稳定,再让它进入修复。
Checker 的任务是判断和列问题,不一定要用最强模型。
如果工具支持模型分工,可以让 Checker 用更轻的模型。
提示词里写清楚:
如果没有失败测试、没有阻塞 PR、没有明确 bug,不要生成长报告。
只在 TODO.md 中记录“无可处理项”。
“修复所有 CI 问题”听起来很爽,但对第一个 Loop 来说太大。
先从一个失败测试开始。
Agent 有时会为了通过测试,直接修改测试预期。
所以 Maker prompt 里要写清楚:除非人工批准,不要修改测试预期。
小问题被改成大重构,是自动修复里最常见的失控方式。
Checker 必须审 diff 范围,发现无关重构就打回。
第一个 Loop 不要自动 merge。
先让它开 PR,人工 review 后再合并。
修不了也要有产出。
最低要求是写清楚三件事:
如果你今天就想试,按这个顺序来:
AGENTS.mdTODO.mdcodex exec --sandbox read-only 做侦察第一次只跑一轮。
跑通一轮,比收藏十篇方法论更有用。
这篇文章里的主路径基于本地可执行命令和外部调度器:codex exec、git、TODO.md、测试命令。
工具边界按以下原则处理:
codex-cli 0.139.0 可用的核心命令是 codex exec。/loop、scheduled tasks、/goal 不在本文展开,避免把不同工具的能力混在一篇实操里。参考来源:
到这里,《Loop Engineering 从入门到进阶手册》的第一阶段先告一段落。
前面 5 篇文章,已经把一条基础路线跑完了:
接下来我会继续整理、补充和实测,把这个系列做成一版更完整的《Loop Engineering 从入门到进阶手册》。
如果你想看后续版本,可以在评论区告诉我:
如果留言里 Claude Code 版呼声高,我会单独写一篇:用 Claude Code 搭 CI 修复 Loop。