mcpField
V
verify-with-controls

verify-with-controls

github.com/vivswan测试与质量161 次安装1 天前更新
代码仓库

关于 verify-with-controls

verify-with-controls 是面向 Agent 和工程师的审查技能,帮助在报告测试结果、缺失、成功或静止状态前确认依据可靠。它强调验证探测工具和检查器,而不是直接相信看似合理的读数或日志。

主要功能

  1. 01零结果须附证据或明确报错
  2. 02用正向控制验证缺失结果
  3. 03独立复核异常读数
  4. 04核对后置条件而非只看日志
  5. 05报告前重新测量
  6. 06用负向控制验证检查器

适用场景

  1. 01确认搜索无结果是否可信
  2. 02验证部署或改动是否真正落地
  3. 03发送告警前重新核查
  4. 04测试 CI 门禁能否失败

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vivswan/skills --skill verify-with-controls

安装后在 Claude Code 中输入/verify-with-controls确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.md
README.md
.codex-plugin/
plugin.json
agents/
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. 读数为零或缺失:探针是否具备证据或报错机制(1),且正向控制是否通过同一仪器(2)?
  2. 读数令人警觉:是否用第二种独立方法重新推导(3)?
  3. “操作成功”:是否检查了后置条件,还是只看了作为近似的日志(4)?
  4. 判断一段时间内状态持续不变或缺失:是否观察了两次,并在发送之前立即重新测量(5)?
  5. 检查器显示绿色:它是否曾经显示过红色(6)?

审查标准

安装此技能后,运行代码审查的技能(例如 /rubber-duck-review)会将本节扩展到审查者提示词中。要求审查者标记以下问题:

  • 可能对“缺失”和“未能查到”返回相同值的探测或检查:被吞掉的错误、未经验证的路径、结果为零却被直接信任的 grep 或筛选器
  • 缺少负向对照的检查器和门禁:没有任何依据能证明它们可以通过与绿色运行相同的断言路径失败
  • 在后置条件本身可检查的情况下,仅根据日志行或退出代码得出成功结论

使用上文“在得出结论时”中的检查流程对发现的问题进行分类。

评论

支持 Markdown