关于 verify-with-controls
verify-with-controls 是面向 Agent 和工程师的审查技能,帮助在报告测试结果、缺失、成功或静止状态前确认依据可靠。它强调验证探测工具和检查器,而不是直接相信看似合理的读数或日志。
主要功能
- 01零结果须附证据或明确报错
- 02用正向控制验证缺失结果
- 03独立复核异常读数
- 04核对后置条件而非只看日志
- 05报告前重新测量
- 06用负向控制验证检查器
适用场景
- 01确认搜索无结果是否可信
- 02验证部署或改动是否真正落地
- 03发送告警前重新核查
- 04测试 CI 门禁能否失败
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vivswan/ skills --skill verify-with-controls安装后在 Claude Code 中输入/verify-with-controls确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSE.mdREADME.md.codex-plugin/plugin.jsonagents/openai.yaml详细介绍
使用对照验证
一次读数不等于一项发现。在“没有匹配项”(零)、“一半的检查消失了”(警报)、“工作已落地”(成功声明)或“没有任何东西在运行”(静止)成为结论之前,读数必须通过对照验证。这意味着附上证据、每个零值背后都有阳性对照、怀疑测量工具、检查后置条件、发送时重新测量,以及确认过确实会失败的检查器。
六条规则,每一条都源自一个差点在生产环境中发布的错误结论:
| # | 规则 | 它能避免的故障 |
|---|---|---|
| 1 | 提供证据或报错,绝不只给一个零 | 用一个 0 同时表示“没有”和“我没能查到” |
| 2 | 相信零值之前先做阳性对照 | 失灵的工具如实回答了错误的问题 |
| 3 | 先怀疑测量工具 | 看似合理的数字测量的却是错误对象 |
| 4 | 后置条件才是真相 | 成功日志对应的状态实际上从未改变 |
| 5 | 观察两次再判断,发送前重新测量 | 报告与其描述的状态发生竞争 |
| 6 | 对检查器做阴性对照 | 无法变红的关卡 |
1. 提供证据或报错,绝不只给一个零
如果一个探测器对“没有”和“我没能查到”都返回 0,那么它从设计上就有问题。再仔细解读输出也无济于事。这两种含义呈现为同一个字节。
$ git diff --numstat origin/main...HEAD -- src/fetaure/
$ # empty, exit 0: reads as "this branch touched nothing there"
只要有一个字母换了位置,路径规格就会匹配不到任何曾经存在的内容。“该路径下没有更改”和“我探测了错误的位置”会呈现为同一个空的成功读数。形如这样的连续零值,险些把真实且已落地的工作报告为缺失。
可靠的探测器会先证明问题可被回答,然后才相信零值;对于无法取得的读数,它会报错。根据测量所读取的相同端点验证路径规格。这里藏着三个陷阱:
- 三点差异比较的是 MERGE BASE 与 HEAD,而不是两个指定的分支顶端
- 验证失败却以 0 退出,只是另一个只有零值的结果
- 管道只返回最后一条命令的状态,因此
pipefail能防止失败的ls-tree被另一端点的匹配结果掩盖
$ set -o pipefail
$ base=$(git merge-base origin/main HEAD) &&
{ git ls-tree -r --name-only "$base" -- src/fetaure/ &&
git ls-tree -r --name-only HEAD -- src/fetaure/; } | grep . ||
{ echo "ERROR: no trustworthy reading (instrument error above, or pathspec at neither endpoint)" >&2; exit 1; }
ERROR: no trustworthy reading (instrument error above, or pathspec at neither endpoint) # and exit 1
这个错误的零值现在会变成明确的非零错误。对于任一端点上存在的路径规格(包括整个分支都删除了的路径),同一探测器会打印匹配路径并以 0 退出,因此通过时也有证据,只有这样空差异才算读数。非零读数也会以相同方式报告匹配行,绝不只报告数量。
推论:对可用探测器的任何缩小范围变体,都是一个新探测器。在相信其空结果之前,先证明缩小后的形式在一个必定匹配的案例中返回非空结果。示例:探测 stash 中某路径下的工作时,将一个刚刚成功运行的命令缩小了范围:
$ git stash show --numstat 'stash@{0}' # works: prints the stash's files
$ files=$(git stash show --numstat 'stash@{0}' -- docs/ 2>/dev/null)
$ echo "${files:-nothing under docs/}"
nothing under docs/
stash 中确实有 docs/ 下的工作。git stash show 不接受路径规格,因此这个缩小范围后的命令什么也没测到。它的报错被丢弃到了 stderr,而捕获到的 stdout 无论如何都是空的。
能揭露这个问题的对照:对一个 stash 必须包含的路径运行缩小范围后的形式,并观察它在那里也读出空结果;在此之前,它的空结果没有任何意义。
2. 阳性对照:一次必须为非零的读数
相信任何零值或缺失读数之前,都要用同一个工具取得一次必须为非零的读数。空无一物的世界和失灵的工具会产生相同的零值。只有对照才能将两者区分开来。
一个硬编码了错误仓库根目录的落地检查器,把两个已落地文件报告为已丢失。它取得的每个读数在内部都一致,只是如实回答了错误的问题:它探测的树中不可能包含这些文件。
$ landed-check docs/new-guide.md # 0 - alarming reading, do not report yet
$ landed-check README.md # control: known present, must read non-zero
0 # it reads zero -> the instrument is blind
多加一条命令,就能在警报发出之前,把“文件不见了”变成“我的检查器看不到”。
3. 会不会是我的仪器出了问题?
报告令人警觉的读数之前,请用第二种方法重新推导。仪器故障会产生一个看似可信、却错误的数字,而可信的数字看起来不会有任何问题。
$ gh pr checks 123 | tr -s ' ' '\t' | awk -F'\t' '{print $2}' | grep -c pass
10 # of 14 known checks - four "missing"?
包含空格的名称会被拆成多个字段,因此并非每一行的第二个字段都是状态列:14 个中有 10 个,是个看似可信、却衡量错了对象的数字。第二次推导跳过了解析,结果并不一致:
$ gh pr checks 123 --json state --jq 'map(.state) | group_by(.) | map({(.[0]): length})'
[{"SUCCESS":14}]
两种推导结果不一致时,先怀疑仪器,再怀疑现实;在结果一致之前,不要把读数写进任何报告。
4. 日志只是近似;后置条件才是真相
退出码能捕捉硬失败。输出判定能捕捉软中止,即工具输出自己的失败信息,却以 0 退出。二者都不能代替对所需状态的验证。
两种生产环境中的情况:
$ sync-tool push
ERROR: Push failed (remote rejected)
Sync finished successfully.
$ echo $?
0 # the tool's verdict line and its exit code both read success
$ merge-queue add 456
queued OK # success means ENQUEUED; the commits are not on the mainline yet
这两条消息说的都是真话,但说的不是你关心的事情。你需要的是关于现实的断言,所以要检查现实:
$ git fetch origin main && git merge-base --is-ancestor "$sha" FETCH_HEAD && echo landed
该引用确实位于必须的位置吗?这就是后置条件。日志永远只是对它的近似。
检查 FETCH_HEAD,也就是刚才 fetch 写入的引用。origin/main 本身是否更新,取决于远程服务配置的获取映射;过时的远程跟踪引用和日志一样,只是近似。
只有当落地过程保留提交 ID 时,祖先关系检查才有定论。压缩、变基和摘取落地都会重写 $sha,因此在这些情况下,祖先关系检查失败本身不能证明任何事情。
对于这些情况,后置条件是 FETCH_HEAD 中的内容本身:更改文件的确切内容存在于获取到的最新提交中。主题匹配最多只用于定位落地提交,绝不能作为检查依据,因为压缩也可能重写主题。
5. 标记之前观察两次,发送之前重新测量
状态变化可能与报告发生竞态。有两种用途不同的判断标准:
- 通过一段时间内的两次观察来决定是否要 LOOK:单次读数仍然,不代表状态持续不变。
- 在发送之前立即重新测量,以决定是否要 SEND。支持这条规则的事故中,每一次险些误报都在最后一次重新测量时消除了,而不是第一次读数时。
reading 1 no change -> keep watching, not a flag yet
reading 2 still no change -> the flag is earned on this evidence
re-measure before sending changed 37 seconds ago -> withhold; the claim went stale
基于真实证据达到标准的标记,在发送时仍可能已经失效。结论只在测量时刻成立,而发送它就等于断言它现在成立,所以现在就测量。
撤回标记也一样:撤回同样是关于当前状态的断言。
6. 负向控制:证明检查器确实会失败
一个永远不会变红的门禁什么也验证不了;一个从未出现过失败的检查器,即使通过了,也不能证明任何事情。让一个必须失败的哨兵通过与真实检查相同的断言路径。单独的测试测试路径会控制错误的仪器。
// The real checks and the control share assertContains, so the control
// certifies the exact code path every green check ran through.
test("negative control: the shared assertion fails on an impossible token", () => {
expect(() => assertContains(doc, "zzImpossibleToken414")).toThrow();
});
对于验证落地或部署的检查器,要用一个必须失败的状态来运行它(落地前的引用、缺少文件的树),并观察它在那里变红,然后再相信它显示绿色。
得出结论时
这些规则可以归纳为一道检查,在结论发出之前立即执行:
- 读数为零或缺失:探针是否具备证据或报错机制(1),且正向控制是否通过同一仪器(2)?
- 读数令人警觉:是否用第二种独立方法重新推导(3)?
- “操作成功”:是否检查了后置条件,还是只看了作为近似的日志(4)?
- 判断一段时间内状态持续不变或缺失:是否观察了两次,并在发送之前立即重新测量(5)?
- 检查器显示绿色:它是否曾经显示过红色(6)?
审查标准
安装此技能后,运行代码审查的技能(例如 /rubber-duck-review)会将本节扩展到审查者提示词中。要求审查者标记以下问题:
- 可能对“缺失”和“未能查到”返回相同值的探测或检查:被吞掉的错误、未经验证的路径、结果为零却被直接信任的 grep 或筛选器
- 缺少负向对照的检查器和门禁:没有任何依据能证明它们可以通过与绿色运行相同的断言路径失败
- 在后置条件本身可检查的情况下,仅根据日志行或退出代码得出成功结论
使用上文“在得出结论时”中的检查流程对发现的问题进行分类。