Agent 工程体系:规程与质量闸门
检查没跑,就别说通过 · 约 4 分钟读完
让 AI 帮忙写代码久了,我发现最怕的不是它写错,而是检查根本没跑,结果却显示「通过」。于是攒了这么一套东西:开工前怎么对齐需求,平时跑什么检查,交付前过什么闸门,以及怎么确认检查器本身靠得住。代码在 [GitHub](https://github.com/tianwena/ai-eng-system) 上。
大概怎么用
分三段:开工前用三张图加一份契约把需求说清楚;平时跑轻量检查;要交出去了再跑一遍加固闸门。改这套体系本身的时候,跑完整自测。
它没有重新发明 CI、静态扫描和 linter,而是在外面一层约定:什么条件下跑、结果怎么说、问题归谁。写这篇的时候里面有 36 个技能和 19 个脚本。
没跑完,就不能说通过
一项检查的结果有四种:
| 结果 | 意思 |
|---|---|
| 通过 | 跑了,没问题 |
| 失败 | 跑了,有问题 |
| 跳过 | 这次没跑,并且写明为什么、少查了什么 |
| 没跑成 | 环境或工具不够,跑不起来 |
整体退出码 0 是通过,1 是失败,3 是有东西没验证完。跳过的就是跳过,不能算进「验证过了」。
这么较真是因为真出过事:一个不是 Git 仓库的目录,密钥检查压根没执行,工具却报了「通过」。
踩过的五种坑
- 出错没人知道:量化系统的 A/B 战绩因为异常被吞掉,停写了九天,一点动静都没有。
- 没跑算成跑了:没执行的检查被总结果当成了通过。
- 文档数字对不上:检查项、技能数、脚本清单,前后四次和实际内容不一致。
- 检查器自己有 bug:有永远成立的判断条件,有 10 行只匹配上 2 行的,还有把说明文字当成接口定义的。
- 检查把现场弄脏了:跑完留下一堆缓存和日志,没有版本控制的目录很难恢复。
所以检查器自己也得被检查。
怎么测检查器
故意埋错。 把仓库复制到临时目录,塞进一个已知的错误,看检查器能不能报出来、位置对不对;再留一份没动过的干净副本,确认它不会见什么都报错。现在有 61 个这样的用例。每次埋错前后都比一下文件指纹,如果替换根本没发生,用例自己就判失败,免得「其实没埋进去,还以为检查器很灵」。
期望清单单独放。 闸门应该跑哪些检查,单独维护一份清单,再拿去和运行报告对。要是从被检查的代码里自动生成清单,删掉一项检查时两边一起变少,就发现不了了。
文档数字自动对账。 文档里每个数字都登记它在哪个文件、哪一行、按什么规则数,跑的时候现数一遍再对。新写的数字要记得登记,不然它管不到。
改检查器要找人复审。 之前检查器出的三次 bug,两次是换了个干净的上下文去真实代码库上跑才发现的,一次是靠负向测试。所以动检查器、闸门和钩子,一律换一个独立上下文再审一遍;改改文档措辞就不用这么麻烦。
检查别乱写文件
测试和 linter 就算只是「检查」,也会偷偷写缓存。现在字节码之类的都重定向到临时目录,测试框架和 linter 的本地缓存也关了。有一次跑完数了一下,留下 42 个残留文件,修完就干净了。「只读」得靠跑前跑后比文件来确认,不能看命令名字就信。
拿去真实代码库上跑
在四个真实代码库上跑过,包括狼人杀,还有数据、桌面程序和小工具,一共揪出二十多个实际问题,大多数是代码库自己的毛病,也有这套体系自己的误报,都记下来了。
做完这个我对「检查」的看法变了:好的检查工具不是一直亮绿灯,而是能老实告诉你哪些查过了、哪些还没查。
