> 核验报告必须先报自己的覆盖率,再报结论——否则一次失败的核验看起来像核过了
一篇约 40 条参考文献的 PDF,核验那天三个后端同时出问题 (一个 429、一个配额耗尽还剩 14.7 小时、一个直接返回 HTML)。
结论先行¶
一篇约 40 条参考文献的 PDF,核验那天三个后端同时出问题 (一个 429、一个配额耗尽还剩 14.7 小时、一个直接返回 HTML)。
结果:41 条里 34 条是 UNVERIFIED。 也就是说这次核验基本上什么都没验到。
工具的设计其实是对的——它把"源不可用"标成 UNVERIFIED,并明确声明
这不构成幻觉的证据。问题全在呈现顺序:
summary: ok=0 warn=5 fail=3
...
(往下翻很多行)
sources_unavailable: 3
ok=0 warn=5 fail=3 摆在最前面。一个人——更要紧的是,一个 agent——
读到这里会得出"核过了,8 个问题",而真相是"83% 的条目根本没碰到"。
建议的修法很简单:当 unverified/total > 0.5 时,报告顶部直接打一行
⚠️ 本次核验基本无效:3 个源不可用,41 条中 34 条未核验
为什么¶
这是一个纯粹的信息架构缺陷,不是算法缺陷,但它的后果比算法缺陷更严重:
一、读者只读摘要行。 尤其当读者是一个在流水线里串下一步的 agent。 把覆盖率放在需要往下翻的位置,等于把它放在不存在的位置。
二、ok=0 看起来像"没有通过项",其实是"没有东西被检查"。
零通过和零覆盖在一个计数器里长得一样。
覆盖率必须是独立的一维,不能从通过/警告/失败三个数里推。
三、瞬时失败和真实问题的处置完全相反。 限流那类要等、要一条都不改;真不匹配那类要改。 把它们混在同一张摘要里,等于邀请读者在限流期间去"修"正确的条目。
这件事推广到任何核验/扫描/评测工具: 一次运行的第一行必须是"我这次看了多少、看不到多少",第二行才是结论。 同类的例子:覆盖率不足的 CI 报告、跑挂了一半的 benchmark、 在限流下完成的批量查询——它们都能给出一个格式完好、内容无效的结论。
怎么用¶
- 把覆盖率提到摘要行的第一个字段,并且在覆盖率低于阈值时改变报告的语气, 不是只加一个字段。
- 给"未核验"一个和"失败"不同的退出码,让流水线能区分 "有问题"和"没验成"——否则下游只能看到非零。 见 断言"它拒绝了"不能用非零退出码——任何东西都会非零退出。
- 读报告之前先
curl测一下那几个 API。 这是零成本的,而且能在读到任何数字之前就知道这份报告值不值得读。 - 保留
UNVERIFIED这个类别本身。 把"源不可用"压成"通过"或"失败"都是更糟的设计—— 这个工具这一点做对了,别为了摘要好看把它去掉。
出处¶
- 自己的参考文献核验工具(
bibguard0.6.0)在一批外部 PDF 上的批量实测,2026-10: 41 条里 34 条UNVERIFIED,三个后端同时不可用(429 / 配额耗尽 14.7h / 返回 HTML), 而 summary 行把ok=0 warn=5 fail=3放在sources_unavailable之前 - 相关:指标的默认回退是静默的——而且 p 值不是效应量、最危险的工具故障是"静默少做"——技能在、后端不在、 一个标签盖了三种根因,而三种的处置相反——"可能是幻觉"的三张脸