第 07 章 · Ratchet 法则:让错误只发生一次

本篇目标:把「这次修好了」变成「这类错误永久消失」。 这是 L1 → L2 的分水岭,也是整个 Harness 工程最有复利的一章。


7.1 原始定义

社区 Mitchell Hashimoto(HashiCorp 联合创始人、Terraform 作者)在 My AI Adoption Journey(2026-02-05)Step 5「Engineer the Harness」中命名了这个实践:

"Anytime you find an agent makes a mistake, you take the time to engineer a solution such that the agent never makes that mistake again."

紧接着他给出最克制的操作定义:

"It comes in two forms: better implicit prompting (AGENTS.md) and actual, programmed tools."

只有两种形式:改规则文件,或写一个能被 Agent 调用的工具。后面所有框架——LangChain 的公式、Böckeler 的 Guides/Sensors、七层生产架构——都是这两条的展开。

官方 Ryan Lopopolo, Harness engineering: leveraging Codex in an agent-first world(2026-02-11)把信条浓缩成一句:"Humans steer. Agents execute." 并给出两条与本章完全同构的判断:

早期进展慢「not because Codex was incapable, but because the environment was underspecified」——修复从来不是「try harder」,而是问「what capability is missing, and how do we make it both legible and enforceable for the agent?」

「building software still demands discipline, but the discipline shows up more in the scaffolding rather than the code.」

「legible + enforceable」正是本章的两步:先让信息可见(规则/文档),再让它强制生效(测试/hook)。


7.2 Ratchet 循环

   ① 观察        ② 定责              ③ 固化              ④ 验证
 真实失败  →  极简对照 / 读日志  →  规则 or 工具 or 闸门  →  同一题面重跑
    ↑                                                        │
    └────────────── ⑤ 写进 git,月度复审 ←────────────────────┘

每一步的验收点:

步 必须留下什么 常见偷懒
① exact symptom、涉及的文件/工具、正确行为 只写「Agent 又错了」
② 一次极简模式对照 + 日志片段 直接归咎模型
③ 一条带原因的规则,或一个新工具 改一句提示词就收工
④ 重跑结果(含失败样本) 「感觉变好了」
⑤ 进 git、可 diff、可 review 规则散落在个人聊天记录里

判据 9:一条没有对应失败记录的规则,删掉。一条没有验证过的修复,不算修复。


7.3 从 5 个真实错误开始

社区 Heym 的建议:写下最近 5 次 Agent 犯的错,从 review、failed run、trace 里收集,保留精确症状、涉及文件/工具、正确行为。「Five real mistakes are a better starting point than a generic template.」

不要从网上抄一份通用 AGENTS.md 模板。模板里的规则没有对应你的失败,只会占系统提示词的预算。

模板:

## F-003 · 把迁移文件写进了 src/db/
- 症状:2026-11-02 一次任务中,Agent 新建 `src/db/20261102_add_col.sql`
- 日志:`tool/call c-14` → write_file,路径 `src/db/...`;`request/context` 中无迁移约定
- 正确行为:迁移一律放 `prisma/migrations/`,且不得修改已有迁移
- 定责:极简模式同样写错 → 信息不对等,非模型能力问题
- 固化:规则 R-003 + coverage test `test_migration_location.py`
- 验证:同一题面重跑 3 次,3/3 通过

7.4 规则怎么写:命名文件与测试

社区 三条被广泛引用的写法约束:

原则 出处 含义
每行可追溯到一次真实失败 Addy Osmani, 2026-04-19 零 aspirational rules
控制在 300 行以内、优先指针而非拷贝 Philipp Schmid, 2026-02-24 AGENTS.md 是索引,不是文档库
好文件靠迭代长出来,不靠一次性规划 GitHub Blog 对 2500+ 仓库的分析 允许它随时间变长

规则章节的标准形状(社区 Heym 仓库实践:一条规则 = 一个三级标题):

### R-003 · 数据库迁移的存放位置
所有 schema 变更都必须新建迁移文件到 `prisma/migrations/`,
不得修改已存在的迁移,不得把 .sql 写进 `src/db/`。

原因:迁移顺序由文件名决定,手写会破坏可重放性(见 F-003)。
所有者:`prisma/migrations/`
执行者:`backend/tests/test_migration_location.py` —— 发现违规即让构建失败。

三个不可省字段:为什么 / 哪个文件负责 / 哪个测试兜底。


7.5 「A rule without a test is a wish」

社区 这是 Harness 工程里最值钱的一句话。规则写在 Markdown 里,模型大约会遵循;写成构建检查,则 100% 生效。

coverage test 的模式固定:读注册表 / 列表 → 对遗漏失败 → 失败消息写成给 Agent 看的提示。

# test_migration_location.py —— 不测任何业务行为,只测覆盖
import unittest
from pathlib import Path
from app.registry import list_sql_writers

ALLOWED_ROOT = Path("prisma/migrations")

class MigrationLocationCoverage(unittest.TestCase):
    """No default. 新增写 .sql 的位置而未登记,就在这里让构建失败。"""

    def test_every_sql_writer_is_in_allowlist(self):
        bad = [w for w in list_sql_writers()
               if not Path(w.path).is_relative_to(ALLOWED_ROOT)]
        self.assertEqual(
            bad, [],
            "以下位置写了迁移但不在 prisma/migrations/:" + repr(bad)
            + "。请把路径改到 prisma/migrations/,"
              "并阅读 AGENTS.md 的 R-003 后再决定。",   # ← 失败消息就是 prompt
        )

社区 Heym 仓库公开数据:5 个「只检查 coverage」的测试,覆盖 63/63 node placement、125 expression cases、15 modules、16 UI files;一个 shell 脚本在本地与 CI 同时拒绝任何超过 10,000 行的源文件。这类测试便宜、不依赖时序与网络、且只在真正破坏规则的 PR 上失败。

社区 该仓库 AGENTS.md 六个月的实测增长,可作为「ratchet 长什么样」的参照:

日期 行数 词数 规则章节
2026-04-27(首次提交) 134 1,038 12
2026-06-15 143 1,188 13
2026-08-15 186 2,280 18
2026-09-15 267 3,596 23
2026-10-14 294 4,170 26

首次提交后 20 次变更中,16 次在同一个 commit 里同时改了测试。这个比例比文件长度更能说明 ratchet 是否真的在转。


7.6 关键反模式:Harness 应该随模型变强而变轻

社区 一条常被忽略的维护纪律:把规则分成两类,每次模型升级后花 30 分钟复审:

类型 例子 处置
永久性约束 「提交前必须跑测试」「禁止改 generated 目录」「人工审批后才可对外发送」 保留,升级为 hook
补偿模型弱点的临时规则 「文件限制 500 行,因为模型读长文件吃力」「一次只改一个文件,因为模型会混淆多文件编辑」 删除

判断句:「这条规则是在约束行为,还是在补偿一个当前版本的能力缺陷?」后者的生命周期由模型厂商决定,写死在 Harness 里会变成技术债。

配套动作:每月复审一次,删掉「删了也不会再出错」的规则。一个只涨不跌的 AGENTS.md 本身就是 Harness 退化的信号——它会在上下文预算里挤掉真正重要的东西(第 09 章)。


7.7 在 DSH 里的四个落点

落点 适合固化什么 强度
AGENTS.md / 项目文档 团队约定、目录所有权、命令清单 建议级(模型可能忽略)
自定义斜杠命令(ctx.commands) 每周重复的流程,如 /repo 确定性派发,不走模型回合
Skills 大份参考文档、API 规格,按需加载 建议级 + 省上下文
Hook / 审批策略 / 沙箱 必须 100% 生效的禁区 强制级(第 08 章)

原文 一句话可以直接作为本章收尾:自定义斜杠命令 = 把一段你每周都要重复描述的流程,写成一条命令。

把它推广:Harness 工程 = 把每一次你不得不重复解释、重复纠正、重复救火的东西,写进环境里。


7.8 本章产出与验收

核心产出:AGENTS.md(5 条规则,每条带 F-xxx 失败编号、原因、所有者文件)+ 至少 1 个 coverage test + 一次重跑验证记录。

验收点:

  • 每条规则都能指向一次具体失败;指不出的删掉
  • 至少一条关键规则有让构建失败的测试,且失败消息写明「改哪个文件、读哪条规则」
  • 能区分永久约束与临时补偿,并列出至少 1 条计划删除的规则
  • 规则文件进 git,可 diff、可 review
  • 同一题面重跑 3 次,结果一致

延伸阅读

来源 URL 等级
Hashimoto, My AI Adoption Journey https://mitchellh.com/writing/my-ai-adoption-journey 社区
OpenAI, Harness engineering: leveraging Codex in an agent-first world https://openai.com/index/harness-engineering/ 社区
Böckeler, Harness engineering for coding agent users https://martinfowler.com/articles/harness-engineering.html 社区
Addy Osmani, Agent Harness Engineering https://addyosmani.com/blog/agent-harness-engineering/ 社区
Schmid, Writing good agent files https://www.philschmid.de/writing-good-agents 社区
GitHub Blog, How to write a great agents.md(2500+ 仓库) https://github.blog/ai-and-ml/github-copilot/how-to-write-a-great-agents-md-lessons-from-over-2500-repositories 社区
Heym 公开 AGENTS.md 与 coverage tests https://github.com/heymrun/heym/blob/main/AGENTS.md 社区
DSH 仓库自带 AGENTS.md https://github.com/deepseek-ai/deepseek-harness/blob/master/AGENTS.md 官方
本系列为本站原创教程,基线为微信公众号《DeepSeek Harness 最新高阶指南》(2026-11-05),并汇总 DeepSeek 官方仓库与文档站、Cordis / arXiv:2608.25512、以及 OpenAI / Anthropic / LangChain / Martin Fowler 等一手资料。每条引用均标证据等级,完整清单见 附录 B;未定位到一手来源的线索单列,未编造补位。DeepSeek Harness 为 developer preview,官方 SAFETY.md 明确「未经过安全审计、不得视为生产就绪」,命令与配置键可能随版本失效。资料截止 2026-11-06。姊妹篇:《FDE 入门到精通》。