# Project 07. 搭建你的第一个自动循环

> 相关讲义：[L13. 从手动驱动到自动循环](./../../lectures/lecture-13-loop-engineering/index.md)

## 你要做什么

这是从 "Harness" 到 "Loop" 的跃迁项目。你已经知道怎么给 agent 配好一套环境、一套指令、一套反馈——现在你要把这套东西变成一个能自己跑的循环。

你会做三个递进的实验：先把一个任务从手动跑变成 `/goal` 自动跑，再把一个巡检任务变成 `/loop` 定时跑，最后做一个带 maker-checker 分离的完整循环，体验「人退到循环外面」是什么感觉。

## 使用仓库里的项目

仓库路径：[`projects/project-07/`](https://github.com/walkinglabs/learn-harness-engineering/tree/main/projects/project-07)

| 目录 | 里面有什么 | 做什么 |
|------|----------|--------|
| [`starter/`](https://github.com/walkinglabs/learn-harness-engineering/tree/main/projects/project-07/starter) | 一个带有完整 harness 的小型知识库项目（P06 完成态），包含 AGENTS.md、feature_list.json、init.sh、session-handoff.md、clean-state-checklist.md。 | 把这套 harness 改造成能自动循环的版本。 |
| [`solution/`](https://github.com/walkinglabs/learn-harness-engineering/tree/main/projects/project-07/solution) | 三个循环的完整实现：goal loop、loop timer loop、maker-checker loop，加上 loop 状态文件和验证脚本。 | 参考 loop 的设计方式和状态管理模式。 |

## 用什么工具

- Claude Code 或 Codex
- Git
- 你在 P06 搭建好的完整 harness
- 一个你常用的终端复用工具（tmux 或 screen，用于观察长时间运行的 loop）
- 可选：GitHub Actions 或 cron（用于事件驱动/定时驱动的进阶实验）

## 具体步骤

### 准备工作

1. 基于 P06 完成后的代码，从同一个 commit 出发。
2. 创建三个分支：`p07-goal-loop`、`p07-timer-loop`、`p07-maker-checker`。
3. 确认你的 harness 是工作的：跑一次 init.sh，确认状态文件、feature list、交接文档都在。
4. 选一个你要让 loop 反复做的**目标任务**。建议选一个中等大小、有明确完成标准的任务，比如："给所有模块补充单元测试，覆盖率达到 80%" 或 "把所有 API 端点加上输入验证"。

### 实验一：Goal Loop —— 从手动跑到自动跑

切到 `p07-goal-loop` 分支。

1. **写目标描述**：把你选的任务写成一份 `goal.md`，包含：
   - 明确的目标（"完成什么算做完"）
   - 验证方式（"怎么确认做完了"——跑测试？跑 lint？检查覆盖率？）
   - 停止条件（"什么时候应该停下"——最大回合数？时间上限？预算上限？）
   - 约束（"不能碰什么"——生产配置、数据库 schema 等）

2. **第一次手动跑**：你自己手动给 agent 发指令，完成一次这个任务。记录用了多少回合、你介入了多少次、结果质量如何。这是你的基线。

3. **用 `/goal` 跑**：用同一份 `goal.md` 作为输入，用 `/goal` 模式跑一次。agent 自己循环直到达成目标或触发停止条件。

4. **对比结果**：
   - 回合数差异
   - 你介入的次数差异
   - 结果质量差异（用同样的验证标准）
   - 你花的时间差异

5. **迭代 goal.md**：如果结果不好，改 goal 描述，再跑一次。直到你对结果满意，或者确认 goal loop 在这个任务上的极限在哪里。

### 实验二：Timer Loop —— 把巡检变成心跳

切到 `p07-timer-loop` 分支。

1. **选一个巡检任务**：找一个你平时手动做的、重复性的检查工作。比如：
   - 每小时跑一次测试，有失败就修
   - 每天早上检查依赖有没有安全更新
   - 每次提交后检查代码有没有违反编码规范
   - 定期扫描 TODO 注释，看哪些已经过期了

2. **写巡检脚本/prompt**：把巡检的步骤写清楚——检查什么、发现问题了怎么办、什么时候需要叫人。

3. **用 `/loop`（或 Codex 的对话线程自动化）跑**：
   - 设置合理的间隔（建议 10-30 分钟，太短你会被打扰，太长看不出效果）
   - 让它跑至少 2 小时（或者你去干别的事，过一会儿回来看）

4. **记录结果**：
   - 它发现了多少问题？
   - 它自己修了多少？
   - 有多少是误报？
   - 有多少是它修坏了的？
   - 你花了多少时间跟进它的结果？

5. **思考**：这个巡检任务值得自动化吗？节省的时间和你跟进它花的时间比，哪个多？如果不划算，是任务选错了还是 loop 设计得不好？

### 实验三：Maker-Checker Loop —— 把你从循环里拿出来

切到 `p07-maker-checker` 分支。

这是三个实验里最重要的一个。你要做一个**完整的、你不需要在场的循环**：

1. **设计循环结构**：
   - **Maker agent**：负责实现，写代码，改文件
   - **Checker agent**：负责验证，跑测试，做代码审查，打通过/不通过
   - **状态文件**（`loop-state.md`）：记录当前轮次、做了什么、验证结果、下一轮要做什么
   - **停止条件**：连续 N 轮通过，或者达到最大轮次

2. **写三份 prompt**：
   - Maker 的指令（做什么、怎么做、什么不能碰）
   - Checker 的指令（验证什么、怎么验证、什么算通过、发现问题了怎么反馈）
   - 循环控制逻辑（谁先跑、跑完了怎么交接、下一轮怎么启动）

3. **跑至少 5 轮循环**：
   - 第一轮：Maker 实现 → Checker 验证 → 不通过 → 反馈给 Maker
   - 第二轮：Maker 根据反馈修改 → Checker 再验证 → ...
   - ...
   - 直到连续通过，或者你叫停

4. **记录每一轮的状态**：
   - 轮次
   - Maker 做了什么
   - Checker 发现了什么问题
   - 通过/不通过
   - 你有没有介入（如果介入了，为什么）

5. **最后复盘**：
   - 你一共介入了几次？为什么介入？
   - 如果没有介入，结果会怎么样？
   - Checker 有没有漏过问题？
   - Maker 有没有在同一个问题上反复犯错？
   - 这个循环的质量天花板在哪里？是 Maker 的能力还是 Checker 的能力？

## 怎么衡量结果

| 指标 | 实验一（Goal） | 实验二（Timer） | 实验三（Maker-Checker） |
|------|--------------|---------------|----------------------|
| 任务完成率 | 目标达成了吗？ | 巡检了多少次？ | 多少轮后通过？ |
| 人类介入次数 | 你插手了几次？ | 你跟进花了多久？ | 你介入了几次？ |
| 结果质量 | 和手动比怎么样？ | 误报率多少？漏检率多少？ | Checker 发现了多少你没发现的问题？ |
| 时间节省 | 你省了多少时间？ | 值得自动化吗？ | 你花在设计循环上的时间 vs 你省下来的时间 |
| 可靠性 | 停止条件靠谱吗？ | 有没有跑飞了？ | 循环会不会卡死在同一个地方？ |

## 要交什么

- `goal.md`（实验一的目标描述，至少迭代了两个版本）
- 实验一的对比记录：手动 vs goal loop
- 实验二的巡检 prompt 和 2 小时运行日志
- 实验三的三份 prompt（Maker / Checker / 循环控制）
- 实验三的 `loop-state.md`（至少 5 轮记录）
- 最终复盘：三个实验的收获、你对 loop engineering 的理解变化、哪些事情适合 loop 化、哪些不适合

## 对应讲义

- [Lecture 13 — 从手动驱动到自动循环](../../lectures/lecture-13-loop-engineering/index.md)
- [Lecture 12 — 为什么每次会话都必须留下干净状态](../../lectures/lecture-12-why-every-session-must-leave-a-clean-state/index.md)（loop 的每一轮都需要 clean state）
- [Lecture 11 — 为什么可观测性属于 harness 的一部分](../../lectures/lecture-11-why-observability-belongs-inside-the-harness/index.md)（你需要看到 loop 内部在发生什么）
- [Lecture 05 — 为什么状态文件是跨会话连续性的核心](../../lectures/lecture-05-why-long-running-tasks-lose-continuity/index.md)（loop 状态文件是 state file 的延伸）
