🐸 青蛙编程网
首页 / AI / 脚手架 Harness / 6. 综合练习

7. 综合练习

这是什么:迷你 Harness = 一个项目最小可用的六层底座——目录、约束、状态、工具、验证、恢复,各有一个能跑的例子。

为什么用:六层听着吓人,但每层都能单独加。一次全上容易卡在半路,不如从最缺的那一层开始补。

如何用:本章按六步走,每步都有验收标准和「什么时候可以停」的判断,做完你就有了自己的 Level 1~2 Harness。

7.1 目标与验收清单

目标:给一个真实项目(用本文的博客仓库当例子)配出一套 Level 1 → Level 2 的 Harness。

层 本次要落的东西
L1 信息边界 一个目录式 AGENTS.md,指向 docs/ 下的分册
L6 约束 一个能机械执行的检查(不是提示词)
L4 状态 一个进度文件模板 + 一个任务交接文档模板
L2/L3 工具与编排 一份工具清单 + 一份权限清单
L5 验证 一个「跑完能给出修复建议」的检查命令

验收清单:

  • 第 1 步:写出现在处于 Level 0~4 的哪一级,缺哪两层
  • 第 2 步:AGENTS.md 不超过 100 行,每条规则都能指向一个文件
  • 第 3 步:检查脚本的报错信息里带修复方法
  • 第 4 步:进度文件和交接文档各有一份模板,且已提交进仓库
  • 第 5 步:权限清单里 git push、rm、curl 都有明确档位
  • 第 6 步:有一条命令能一键验证,且失败时能指出改哪儿

贯穿全程的例子:这个博客仓库本身就适合当练手对象——它已经有 doc/architecture.md、doc/authoring.md 这样的分册文档,也有 tools/ 下的校验脚本,正好对应 L1 和 L6。

7.2 第 1 步:先定位,别急着搭

对照第 1.6 节的分级表,给自己的项目诚实地打个分:

检查项 有 / 没有
有 AGENTS.md(或等价的项目说明)
有能自动跑的检查(lint / 测试 / 结构检查)
有任务状态文件
CI 里跑着 Agent 相关的检查
有独立的验收环节(不是自己写自己验)
  • 全没有 → Level 0
  • 只有第 1 项 → Level 1
  • 前三项都有 → Level 2
  • 再加多 Agent 分工与持久化记忆 → Level 3

这一步的产出是一句话,写进 PR 描述或 issue:

当前 Level 1,缺 L6(机械化约束)和 L5(独立验证)。本次先补 L6。

有了这句话,后面每加一件东西都知道自己在第几层,不会无限膨胀。

7.3 第 2 步:L1 —— 目录式 AGENTS.md

不要新建一堆规则,直接把已有的文档重新组织成索引。

以本仓库为例,doc/ 下已经有四份文档,天然就是分层结构:

# AGENTS.md(约 60 行,只做索引)

## 这个仓库是什么
个人博客的静态站点,用 `v2/` 下的 Python 脚本构建(无 VitePress / Node)。目录说明见 `README.md`。

## 改内容前必读
- 写作规范(章节模板、链接规范、风格要求):`doc/authoring.md`
- 架构与变更流程(先文档后代码):`doc/architecture.md`
- AI 操作边界(允许区 / 禁区):`doc/ai-ops.md`
- 内容规划(新增技术栈的批次与章节):`doc/roadmap.md`

## 常用命令
- 构建并监听:`python v2/build.py --all --watch`
- 本地预览:`python -m http.server 8931 --directory v2/dist`
- 构建验证:`python v2/build.py --all` + `python v2/tools/check_site.py`
- 校验章节开头格式:`node tools/check-three-step.mjs`
- 校验改动范围:`node tools/check-region-only.mjs`

## 硬约束
- 涉及站点结构的改动,**先改 `doc/` 再改代码**,同一次提交
- `server/**` 与 `v2/dist/` 构建产物是禁区,改动需用户确认
- 构建不通过不算完成

## 提交约定
- 中文 commit message 用文件 + `git commit -F <file>`
- `git commit` / `git push` 须经用户确认

注意三点:

  1. 每条都指向文件,没有一条是「你要注意 X」这种空话
  2. 硬约束单独一节,且都是可执行的(改流程、禁区、构建)
  3. 行数可控,正文可以再长,但索引这一层保持在百行内

7.4 第 3 步:L6 —— 一个能机械执行的检查

挑一条最容易违反、也最值得自动化的规则。博客仓库里有个现成例子:每个教程章节开头必须符合「三步思维」三段式。这条规则完全可以脚本化。

# tools/check-three-step.mjs(简化示意)
const LABELS = ['**这是什么**:', '**为什么用**:', '**如何用**:']

for (const rel of changedFiles) {
  const lines = readFileSync(rel, 'utf8').split(/\r?\n/)
  const region = regionBetweenH1AndFirstH2(lines)

  const found = LABELS.map(l => region.findIndex(x => x.startsWith(l)))
  if (found.some(i => i < 0)) {
    report(rel, '缺少三步思维三段之一')
  }
  // 段间空行、字数区间、H2 数量不变……依次检查
}

跑起来:

node tools/check-three-step.mjs

你会看到(示意):

通过 12 / 12

有问题的文件则长这样:

docs/ai/harness/practice.md
  - 标签数=2(应为 3)
  - **如何用**:前缺空行

重点是报错信息:它说清了「哪个文件、缺什么、怎么改」。这就是第 5 章说的「报错要能指导下一步」。

同类可做的检查还有:

检查 抓什么
死链检查(v2/tools/check_site.py) 链接到不存在的页面、锚点缺失
章节模板检查 开头格式、结尾「下一章」链接
目录一致性检查 v2/nav.json 的章节和实际 md 文件对不上
章节数一致性检查 README 写的章数和实际文件数不符

这类检查一旦写出来就一劳永逸——每次提交自动跑,不用人记。

7.5 第 4 步:L4 —— 状态文件与交接文档

建两个模板,进仓库:

.agent/progress.md(当前任务进度):

# 当前任务
<一句话>

## 状态
进行中

## 已完成
- <input type='checkbox' disabled> ...

## 当前卡在哪
<卡点 + 已排除的可能>

## 关键决策
- <决策>:<理由>

## 验证命令
```bash
<一条能验证的命令>
```

.agent/handoff.md(交接文档,四件套):

# 任务交接:<任务名>

## 目标
<目标 + 验收标准>

## 已完成
- ✅ <改动>(文件:<路径>)

## 未完成
- ⬜ <下一步>(卡在:<原因>)

## 改过的文件
- `<路径>`(新增 / 修改 / 删除)

## 失败原因(别重蹈)
- 试过 <方案>,失败于 <原因>。正确做法是 <方案>。

## 下一步验证命令
```bash
<命令>
```

交接文档里最值钱的是「失败原因」那一节——它把「试错」从一次会话的易失记忆变成仓库里的长期资产。

配套约定写进 AGENTS.md:

## Agent 协作约定
- 开工前先读 `.agent/progress.md`;每完成一块就更新它
- 上下文快满或需要换会话时,按 `.agent/handoff.md` 的格式交接
- 交接文档只记决策和卡点,不记流水账

7.6 第 5 步:L2/L3 —— 工具清单与权限清单

写一份角色 → 工具的表,再给每个工具定权限档位:

角色 允许的工具 禁止
规划 Agent 读文件、搜索、列目录 写文件、跑命令
实现 Agent 读文件、写文件、跑测试 推送、部署
验收 Agent 跑应用、跑测试、截图 改代码

规划与实现分成两个角色(哪怕是同一个 Agent 分两轮跑),规划阶段不给写工具,能挡住「边想边改」。

权限清单:

{
  "permission": {
    "bash": {
      "git status": "allow",
      "git diff": "allow",
      "git log *": "allow",
      "npm test": "allow",
      "python v2/build.py *": "allow",
      "python v2/tools/check_site.py": "allow",
      "git commit *": "ask",
      "git push *": "ask",
      "rm *": "deny",
      "curl *": "deny",
      "wget *": "deny"
    }
  }
}

三条挑法:

  • 只读操作直接 allow,别浪费确认机会
  • 有副作用但可逆的 ask(commit、push)
  • 不可逆或外发的 deny(rm、curl、wget)

7.7 第 6 步:L5 —— 一条能验证的命令

验证闭环的入口是一条一键命令:

node tools/check-three-step.mjs \
  && node tools/check-region-only.mjs \
  && python v2/build.py --all \
  && python v2/tools/check_site.py

把它写进一个脚本或 Makefile,就能做到「一条命令验证全部」。

这条命令要满足三个条件:

  1. 能自动跑——不依赖人记得执行
  2. 失败时指出改哪儿——不是「校验失败」,是「哪个文件、哪一行、怎么改」
  3. 和提交挂钩——放进 pre-commit 钩子或 CI,让不合格的改动进不了主干

再加一个独立验收环节。哪怕只有一个问题,也值得让「实现」和「验收」分属两轮:

实现 Agent 写完 → 验收 Agent 只做三件事:
  1. 跑应用,看功能能不能用
  2. 对照需求清单逐条核对
  3. 只提「能不能用 / 不能用」,不提「代码写得丑」

刻意不让验收 Agent 提代码风格意见——风格由 Linter 管,验收只管功能。两件事混在一起,验收就会变成代码审查,注意力被稀释。

7.8 常见翻车现场

症状 原因 改法
AGENTS.md 越写越长 把它当手册用 只留索引,细节进 docs/
检查脚本没人跑 没挂钩子 挂 pre-commit 或 CI
报错只说「不合法」 缺修复建议 报错里写清改哪个文件、怎么改
Agent 反复试同一个错 工具返回不可行动 改返回格式,补下一步建议
状态永远没更新 没约定 写进 AGENTS.md,开工前先读
交接后接着走错方向 交接文档漏了失败原因 交接模板强制带「失败原因」
权限弹窗太烦 全设成 ask 只读 allow,不可逆 deny
一上来就搭全自动 目标过大 先做 Level 1:AGENTS.md + 一个检查

动手改

  1. 给你的项目写一句定位:「当前 Level X,缺 Y、Z,本次先补 Y」,贴进 issue 或 AGENTS.md
  2. 把项目里现有的文档重组成索引 + 分册,建一个不超过 100 行的 AGENTS.md
  3. 挑一条「你希望 Agent 永远别犯」的错,写成一个校验脚本,让它的报错带上修复建议
  4. 建 .agent/progress.md 和 .agent/handoff.md 两个模板,约定开工先读、做完更新
  5. 写一份权限清单,把 git push、rm、curl 三个先定了档

小结

  • 先定位再动手:诚实地给自己打 Level 0~4 的分,缺哪层补哪层
  • L1:AGENTS.md 只做索引,指向分册文档,硬约束单独一节
  • L6:把最容易违反的规则写成校验脚本,报错必须带修复建议,并挂进 pre-commit / CI
  • L4:progress.md 记进度和决策,handoff.md 记四件套 + 失败原因
  • L2/L3:角色分工(规划只读、实现能写、验收只验功能)+ 三档权限
  • L5:一条一键验证命令 + 一轮独立验收
  • 一次只补一层,Level 1 已经能覆盖大部分高频错误

下一站:技能 Skills,把「怎么做事」也封装成可复用的资产 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。