Claude Code Harness 08:Verify:从感觉到证据

Plan 锁方向,TDD 锁行为。但局部行为被锁住,不代表整个系统可以交付。

Claude Code 在实现阶段最典型的停点问题不是"不会做",而是停得太早。局部测试过了、代码读起来没问题、能给出一个自洽解释——然后形成"任务大概收敛了"的判断。工程世界不接受"大概收敛了",只接受"已经验证过了"。

这一章要做的事情很具体:把 Verify 从"最后想起来再跑一下"变成系统的默认闭环。


一、Plan 和 TDD 之后还缺什么

修了一个接口层 bug,问题复现明确、写了失败测试、最小修复、局部测试通过。看起来很完整。

但此时直接收工依然可能漏掉:typecheck 没过、某个 lint 规则新报了、别的测试因为这个改动开始失败、这个接口对应的前端调用链也被影响了。

三者各管一段:

Plan = 定地图
TDD = 锁局部行为
Verify = 看系统是否真的到站

没有 Verify,Claude Code 很容易停在"局部逻辑看起来没问题,所以任务差不多完成了"这个位置。这个"差不多",恰恰是工程事故最喜欢藏身的地方。


二、Claude Code 为什么特别容易缺 Verify

三个结构性原因。

偏向完成叙事。 强推理模型天然擅长把当前已有信息组织成看起来完整的结论。一旦 bug 看起来修了、测试至少过了一部分、代码读起来也没大问题,它就会快速形成"任务大概收敛了"的内部判断。这不是低级错误,是生成系统的结构特征。

偏向推理而非检查。 它更擅长分析、解释、生成,而不是枯燥地跑一串命令再一个个看结果。所以 Verify 必须做成系统层,靠一条"记得验证"的提示几乎没效果。

没有固定顺序时验证退化成随机抽检。 先跑了 test 觉得没问题就没再跑 typecheck;build 过了就没回头看 lint。问题不在不会验证,而在没有固定顺序时,验证最终退化成"跑了哪个算哪个"。


三、Verify 的固定顺序

很多团队说"有验证",但做的只是"想起来就跑一下,看到哪里顺手跑哪里"。要让 Verify 稳定,它需要固定顺序:

Targeted behavior locked (TDD 阶段完成)
   ↓
Build
   ↓
Typecheck
   ↓
Lint
   ↓
Tests
   ↓
Review / Security Review (按需)
   ↓
Ready or Not Ready

顺序的意义在于:让"完成"从感觉变成流程结果。

一个更深层的设计原则是"做"和"判"分离。生成者天然对自己的结果偏乐观,Claude 很擅长把当前实现解释得很合理、把局部成功组织成"任务完成了"的叙事。更稳的方式是让生成和评估在明确的阶段分开。


四、任务清晰度 × 验证清晰度

一张判断 Claude Code 适不适合深入推进的四象限:

                验证清晰
             低            高
任务清晰  +----------------------+
低        | 高效跑偏     | 可探索    |
高        | 卡在人工验收 | 最适合Agent|
          +----------------------+

任务清晰 + 验证清晰时,Claude Code 最能发挥。任务清晰但验证不清晰时,吞吐量通常卡在人工验收。验证清晰但任务不清晰时,系统可能高效跑偏。两者都不清晰时,不应该扩大 agent 自主度。


五、Verify 在完整工作流中的位置

Task → Plan → Confirm → TDD / Minimal Implementation → Targeted test passes
   ↓
Verify
   ├── Build
   ├── Typecheck
   ├── Lint
   ├── Tests
   ├── Review
   └── Security Review (when needed)
   ↓
Ready / Not Ready

Verify 不是收尾动作,而是"完成状态"的裁判。没有它,Claude Code 的"完成"只是一种语言输出。


六、一个真实例子

上一章锁住的结算逻辑测试通过了。如果这时没有 Verify,Claude 很可能说"问题已经修复"。但开发者还关心:这次改动有没有影响 payout ledger 的别的路径?type 定义有没有被连带破坏?通知逻辑是否正常?有没有引入新的 lint 错误?

TDD 证明的是"这个行为现在对了"。Verify 证明的是"这个改动放回系统里还能站住"。局部胜利是最容易被误判成"整体完成"的。


七、/verify 命令模板

直接落在 .claude/commands/verify.md

# /verify

Run verification in this order:

1. Build
2. Typecheck
3. Lint
4. Tests
5. Review / Security checks when relevant

Output format:

## Verification Report

- Build:
- Typecheck:
- Lint:
- Tests:
- Review:
- Security:

## Result

- Ready for delivery / Not ready

## Remaining Issues

- ...

Rules:
- Do not say the task is complete before verification is done.
- If any step fails, stop and report clearly.
- Do not treat partial success as final completion.

这个模板固定了三件事:顺序、输出结构、失败时的行为。Claude Code 一旦没有这三样约束,就特别容易先跑最容易过的、只汇报好的部分、失败时继续往后硬跑。


八、Verify 分层:基础版和扩展版

不是每个任务都需要重型审查。

基础 Verify 适合小功能、局部 bugfix、低风险重构,包含 build / typecheck / lint / tests。

扩展 Verify 适合鉴权、权限、支付、数据删除、涉及 secret 或 PII 的变更,额外包含 review 和 security review。

同样,局部验证和全局验证也应该分层。开发过程中先做局部收敛(targeted test、受影响模块的 typecheck、相关路径的 lint),在交付节点做全局确认(全量 build、全量 test、完整 review)。先局部收敛、再全局闭环,既不会一上来太重,也不会让交付边界越来越虚。


九、怎么让 Verify 真正成为默认路径

只在 CLAUDE.md 里写一句"完成前请先验证"远远不够。三层配合:

Rules 里立底线。 未验证前不要宣称完成;不要用解释替代验证证据。

Commands 里立入口。 /verify 作为固定触发点。

Hooks 里做拦截。 Stop 时提醒当前会话还没 verify;高风险变更前强提醒。

这一套组合起来,Verify 才会从"好习惯"变成系统行为。


十、本章交付

Verify 清单:

  • 当前任务的 targeted behavior 是否已经被锁住?
  • Build 是否通过?
  • Typecheck 是否通过?
  • Lint 是否通过?
  • Relevant tests 是否通过?
  • 这次改动是否需要 code review?
  • 这次改动是否需要 security review?
  • 是否还有未解释的失败或跳过项?
  • 是否可以明确判断为 Ready / Not Ready?

社区参考方案: everything-claude-code 仓库提供了三个相关命令——/verify(基础四项)、/quality-gate(把验证提升成门禁)、/eval(承接 Generator/Evaluator 分离)。先问清楚自己的项目缺的是基础 Verify 还是更成熟的评估闭环,再决定怎么借鉴。

最小落地动作:.claude/commands/verify.md,先写死基础四项,把 review / security review 作为第二层补进去。


十一、小结

Plan 锁方向、TDD 锁行为、Verify 锁交付。到这里工作系统开始有了"知道什么时候才算做完"的能力。

但一套系统只要还在靠人记得执行,就一定会退化。下一章进入 Hooks:把高频、机械、容易忘的动作自动化。