验证主张完整性
当代理说"测试通过了"、“覆盖率 87%"、“这段代码不再用了,可以删除"时,如何相信这些话?验证主张完整性 (Verification-Claim Integrity)正是处理这个问题。它的规则是:不主张未经观察的成功,不主张未经验证的缺陷。
代理在说"完成了"方面存在学习偏差。用户想听什么,它就倾向于以积极的方式总结结果。如果系统不补偿这种偏差,“通过了"的说法将变得不可信。
还有一个更危险的方向。当代理声称"这个 SPEC 缺少关闭”、“这个包的覆盖率低”、“这个功能还在使用,不应该删除"时,这些主张可能是错误的。仅从文本模式推断缺陷,或者因为引用存在就认为功能仍然活着,就会修复不存在的问题,或试图恢复已删除的代码而造成浪费。
注意没有证据不是成功的证据,也不是失败的证据。 没有运行检查本身并不意味着可以声称"通过了"或"失败了"。两者都是未经观察的主张。
核心规则只有一句话。
代理不得主张未经直接验证的完成、缺陷、债务、漂移或建议的前提。
这条规则双向绑定。
- 成功方向 — “测试通过了”、“覆盖率 87%"、“lint 干净"等主张,只有实际运行了命令并观察到其输出时才成立。未运行的命令、跳过的步骤是空白,不是通过。
- 缺陷方向 — “这个 SPEC 缺少关闭”、“这个包的覆盖率低”、“这段代码是漂移"等主张,也只有通过域的专用工具验证时才成立。仅从前置文本或 grep 结果推断缺陷就是未经观察的缺陷主张。
缺陷方向更危险。错误的"删除"主张会在下次构建或测试中立即被反驳,但错误的"保留"主张会让死代码存活,没有任何信号。
规则不只绑定一个表面。它绑定四个可能渗入未经观察的主张的地方。
| 表面 | 绑定对象 | 示例 |
|---|---|---|
| 编排器自我报告 | 完成报告和验证矩阵中的所有 PASS 行 | “所有验证都通过了"横幅的每一行 |
| 代理完成报告 | 代理的自我验证矩阵(测试·构建·覆盖率·lint) | “测试 PASS,覆盖率 87%” 报告 |
| 缺陷·债务·漂移主张 | 缺陷或技术债务"存在"的所有主张 | “SPEC X 是关闭债务”、“包 Y 的覆盖率低” |
| 建议的前提主张 | 成为"保留/删除"建议理由的前提 | “这个功能还活着”、“其他消费者依赖它” |
第四个表面是验证建议理由的规则。要建议"不应该删除”,必须直接确认该功能的生产者是否仍然存在,消费者是否仍然可达。可达性不是正当理由。 引用存在并不是引用还活着的证据。
这条规则的实际执行机制是五段落报告格式。当代理报告完成或验证时,如果分成五个段落来写,就会分离观察到的和未经观察的,未经观察的部分会以空白形式显现。
用一句话断言要声明的内容。验证矩阵的一行,或散文报告的一句话,就是一个主张单位。
写实际运行的命令和其输出的原样。不是摘要。如果主张是"测试通过了”,这一段就要有 go test ./... 命令和该命令吐出的输出块。“所有测试都通过了"的摘要不是证据。输出本身是承载负担的 artifact。
说明针对哪个基准测量了这个主张。是在这次运行中,针对这棵树直接运行的命令和观察到的输出。不应借用从其他 SPEC、其他包、其他时间点记住的数值。如果说"覆盖率 87%",就意味着刚才在这棵树上运行 go test -cover ./internal/<pkg>/... 并观察到了 coverage: 87.0% of statements。
列出明确未验证的内容。这一段是整个格式的核心。它防止未经观察的主张作为空白通过。未验证段落为空意味着"没有未经验证的内容"的强主张,本身必须为真。不确定时不要留白,要写名字。
观察到的证据之后仍然存在的不确定性。与未验证(未经观察)不同。残余风险是即使观察到了仍然可能错误的东西。不稳定的测试、环境依赖行为、推迟的验收标准、验证时间和使用时间之间的窗口等属于这里。
一个状态报告统计了 29 个 status: implemented 且缺少 era: 字段的 SPEC,仅从前置文本推断"这 29 个是缺少 V3R6 关闭的 SPEC”,然后建议批量关闭。
这是未经观察的缺陷主张。报告者没有运行域的专用工具。最终运行 moai spec audit --json 时,发现这 29 个全部归类为现有祖父 (grandfather) era (V3R2-R4 28 个 + V2.x 1 个)。era_final: true,受保护对象,不是 V3R6 3-阶段关闭的目标。整个目录的 MUST-FIX 漂移是 0。推断的"关闭债务"不存在,如果进行批量关闭,就会无理由地触及 29 个受保护对象。
信息教训: 缺陷主张在域工具确认之前只是假设。缺少era:且为implemented的文本模式与两种解释(祖父遗留 vs 现代关闭债务)都兼容。只有工具能分支。当存在域工具(moai spec audit、go test -cover、golangci-lint)时,不应仅从文本主张缺陷。
用户指示删除某个目录。编排器删除 artifact 时只保留了一个项目。删除的前提是"会从所有分散用户那里移除活着的功能”,并建议单独的退休 SPEC。
这个前提从未被验证。编排器只确认了该扫描可达,以及 SPEC 仍然读作 status: implemented,并将两者都视为功能还活着的证据。两者都不是。直接枚举生产者,发现已经全部消失。命令、工作流、代理、CLI、脚手架、4-locale 文档页面全都不存在。已完成的退休 SPEC 已经将该功能从所有分散用户那里永久移除,后续清理提交清理了剩余孤儿。扫描只是扛过了两次清理而已。
信息教训: 可达性不是正当理由,SPEC 仍然读作status: implemented也不是功能还活着的证据。后续 SPEC 可能已经退休了。要发出与用户指令相悖的保留建议,必须枚举要保留之物的生产者,并确认是否有已完成的退休 SPEC。未经验证前提的异议是未经观察的主张。
这条规则是阅读代理报告时"依据是什么?“这一习惯的系统性表达。MoAI-ADK 强制代理用五个段落报告,而不是以"通过了"结束,并且只接受通过域工具直接验证的结果作为证据。结果:
- 可以信任完成报告 — “测试通过"意味着实际命令和输出。
- 减少因虚假缺陷而触及代码 — 缺陷主张经过工具确认。
- 防止死代码复活 — 保留建议必须确认生产者存在。
TRUST 5 质量的"可追踪”(Trackable)原则在这里成为现实。所有主张都归因于观察到的证据时,报告才真正可审计。
- TRUST 5 质量 — 五个质量原则,可追踪原则的上层框架
- 基于 SPEC 的开发 — 用证据判定验收标准的 3-阶段生命周期
- Harness 工程 — 设计代理环境的范式