probe-kit
Verified@xwtxxxx/probe-kit · v0.2.0 · MIT
DSH 探针工具包:卡面合法性、卡契约校验、审计档生成 —— 四个零依赖 CLI + 一个最小宿主插件壳。
Install
dsh plugin add @xwtxxxx/probe-kit Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
AI 说「done」,凭什么信?
27 种「AI 假完成」+ 一套可复现的探针卡
一、这是什么
我们只做一件事:AI 说 "done" 是主张,不是事实 —— 把它变成能被证明的东西。
手上是三样东西:27 条「AI 假完成」病例(每条来自一次真实事故,已写成成文);一套探针卡(语言无关的检查卡:注入什么坏情况 ⇒ 该报警还是该漏);以及它们的机器判据工具(查卡是否合格、查卡面能否被解析、把插件包的静态命中写成审计档、把卡逐条真跑对账(probe-runner))。
一张卡 = 一个实验:把某种真实世界的坏情况注进去 → 看被测装置会不会报警。不报警 ⇒ 这个装置在这条上就是 fail-open —— "没查到"被当成了"查过了没问题"。
一句话卖点:我们不比谁"扫得广",我们比谁证得实。
二、凭什么信
- 27 条全部来自真实事故。 每条卡的
evidence就是那次事故的物证,带真实数字(例:一份 85 行的 UTF-8 文件被读成 38 行,且不报错)。 - 每条都能复现。 每张卡写死四件事:
inject(怎么造出坏情况,并在末尾自证注入生效)、run(怎么把坏数据喂给被测装置)、expect(什么算报警、什么算漏,且锚在独立真值上 —— 不许拿被测装置自己打印的数字当判据)、verify(两个标本的实测记录:一个真实工具 + 一个故意犯同种错的中立装置)。 - 我们自己也在用。 首批 2 份审计档已进一个真门禁,用门禁自己的匹配逻辑验证 PASS。
- 卡本身也被机器守着。
card-yaml-lint(卡面能不能被当成 YAML 读出来)+card-contract-lint(按契约逐条机器核对卡是否合格)。工具只证明"这几项机器查过了、结果如下",不代替人工审卡。 - 成文与契约随包附带。 27 条病例的完整成文见
docs/27-ways-ai-fakes-done.md;探针卡的格式契约(唯一格式权威)见docs/JUDGE.md。
三、怎么用(四种接法)
四种接法只需要 node,零第三方依赖。以下命令均在仓库根执行。
① 当 checklist 走一遍
把 27 条的「怎么抓」当检查项,逐条对着你的交付走。先机器核对这套卡本身合格:
node bin/card-contract-lint.mjs --cards probes
- 解决什么问题:确认"你要照走的这份 checklist 逐条符合契约",不是靠感觉。
- 看什么:逐项可观测计数。命中
0且退出码0才算可信;有命中 ⇒ 退出码1,逐张逐条列出。报告里单列「未检查项」:状态skipped表示该项没跑,绝不静默当通过。
② 接进你的门禁
把"卡面合法性"做成入口门槛 —— 卡面读不出来,照卡执行都是空谈:
node bin/card-yaml-lint.mjs --dir probes || exit 1
- 解决什么问题:非
0即卡面不合法,卡在入口。 - 退出码:
0全部合法 |1有违规 |2用法或环境错误。 - 可选严格档(默认行为一字不变):
node bin/card-yaml-lint.mjs --dir probes --strict-escapes,在默认判据之上额外报出双引号标量内「合法但会静默变形」的转义。
③ 接给你的 AI 代理
让它每次宣称完成前先自证这几条,并产出一份门禁认得的审计档:
node bin/audit-kit.mjs --plugin <插件包目录>
解决什么问题:吃一个插件包目录,产出符合门禁格式的审计档;
--out <目录>真写出、--json机器可读、--stamp <yyyyMMdd-HHmmss>固定时间戳。退出码:
0已产出有效审计档且结论不是 reject|1自检失败(拦下不产出)|2用法或参数错|3审计结论为 reject(机判 critical 或--recommendation reject;审计档已产出,供门禁|| exit 1拦住)。门禁怎么接(可整行复制):退出码
0= 结论不是 reject、3= 结论是 reject(两者都表示工具正常运行),1= 自检失败、2= 用法或参数错。结论以recommendation为准 ——node bin/audit-kit.mjs --plugin X || exit 1能拦住 reject,但它分不出「结论 reject(3)」与「自检失败(1)/用法错(2)」;要只对 reject 拦,用下面这行:node bin/audit-kit.mjs --plugin <插件包目录> --json | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{try{process.exit(JSON.parse(s).recommendation==='reject'?1:0)}catch{process.exit(1)}})" || exit 1
④ 一条命令把 27 张卡跑一遍
把 27 张卡逐条注入坏情况、喂给对应的中立标本装置,看它到底会不会报警:
node bin/probe-runner.mjs --cards probes --toys toys
toys/ 是每张卡对应的中立标本装置:它故意犯卡所描述的那一种错,用来验证「检查装置会不会报警」—— 该漏的漏、该报的报,对账只认退出码(该漏 ⇒ 期望退出码 0;该报 ⇒ 期望非 0)。输出是逐条可观测计数(一致/不一致/skipped):skipped 表示该项没跑,成因有三:① 卡 verify 里的本体工具未随包提供(<repo>/… 引用,×21);② 该卡无对应本体、本身不适用(×6);③ 玩具依赖 inject 预置的 git 仓库(×1)——绝不静默当通过。runner 在含非 ASCII 字符的路径下会打印告警,且部分卡会因此多计 skipped(实测中文路径:卡 27|verify 54|一致 21|不一致 3|skipped 30)。⇒ 上表基线的成立条件有两条,缺一不可:① 纯 ASCII 路径;② 运行位置不在任何 git 仓库内部。 ② 的理由:p6 的夹具需要 git init,而本运行器按红线不执行 git ⇒ 仓外它如实记为 skipped;若把本包放在某个 git 仓库内部运行(例如 node_modules 装进一个 git 项目、或直接 clone 后在仓库里跑),p6 的玩具会向上借用外层仓库的 .git ⇒ 不再 skipped,跑出假绿(实测:仓内位置 卡 27|verify 54|一致 24|不一致 3|skipped 27,比对基线多 1 一致、少 1 skipped)。⇒ 复跑基线时请把本包复制到 git 仓库之外再运行。退出码 1 表示存在不一致。实测基线(2026-10-04,仓库根跑④):卡 27|verify 54|一致 23|不一致 3|skipped 28|run_error 0 —— 3 处不一致是已知保留缺陷(p13/p19/p15 三张卡的 verdict 如实记录了对应装置的真实缺陷,按"暴露优于掩盖"保留,不造假绿)。
四、我们的做法与局限
- 探针卡是我们手工写的,覆盖面有限。 27 张卡全部来自我们自己 27 次真实事故的复盘,覆盖面 = 我们踩过的坑,不是"AI 假完成"的全集;没踩过的骗法这里没有。每张卡的
limits写明"什么情况下不适用",照卡执行前先读它。 - 被审对象本身就是扫描器时会「自命中」。 判据工具的代码里必然含被检的那些模式(
regex、process.exit、子进程调用、编码处理……)。别把源码里出现某模式当成命中 —— "代码里出现"与"在这个模式上 fail-open"是两回事;唯一的分辨办法是按卡注入坏情况看行为,不是扫它的源码下结论。 - 我们给的是证据,不是保证。 每张卡只有两个标本、一次本机实测。换装置、换环境、换版本之后,"报警/漏"的结论不自动成立 —— 以你自己的复跑为准。每张卡
inject末尾的注入自证不过,实验即作废(这道闸正是防止"照卡执行却测了个空操作")。 - 平台差异会让注入变形。 部分卡依赖系统代码页、
PowerShell5.1 的标量语义、git行为 —— 同一张卡换平台可能注入不生效或现象不同。照卡执行时先看deps与limits,注入自证不过就停,别硬跑。
五、安装与许可
包名:@xwtxxxx/probe-kit。
dsh plugin --profile <profile> add @xwtxxxx/probe-kit
环境要求:
| 要求 | 说明 |
|---|---|
| Node.js ≥ 20 | 与 package.json 的 engines 一致(≥ 20) |
宿主带 dsh plugin 命令 |
安装/卸载都经它 |
| pnpm 在 DSH 进程的 PATH 上 | 安装依赖它,必须在 DSH 进程可见的 PATH 上 |
当前壳不注册任何钩子,安装不改变宿主行为,价值在 bin/ 的 CLI。
许可:MIT。