Structure Check Pro (requirement checklist, tool-decided)
把「功能是否实现」从模型的自我报告变成退出码裁决的机械核对。模型声称做完了不可信——本工具按要求清单逐条核对结构证据:要求的东西在不在、导没导出、接没接上、是不是空壳。
Pro 版 = 免费骨架(JS/TS/Python 内置判定)+ 云端结构核对规则包。规则托管在后端服务(verify-rules API,/structure-rules 资源),脱离后端本技能只剩内置骨架——多语言支持与实战空壳签名是付费层的核心价值。
与其他守卫的分工:回归守卫(ai-code-verification-guard)管「改完后行为没变坏」;TDD 守卫(tdd-guard)管「开发顺序合规」;本工具管「结构存在性」。三者互补,可同时启用。
scripts/structure-check.mjs 随本技能分发,<skill-path> 指本技能安装目录。agent 只允许调用脚本并逐字转述 STRUCTURE CHECK 输出块,无权改判结果。
与免费版的差异(为什么值得付费)
| 能力 | 免费版 | Pro |
|---|---|---|
| 退出码裁决(PASS / FAIL / UNVERIFIED) | ✅ | ✅ |
| JS/TS 全量 + Python exists/notStub | ✅ | ✅ |
| 多语言规则:Go / Rust / Java / Kotlin / C# / PHP / Ruby(定义·导出·调用·空壳) | ❌ | ✅ |
实战空壳签名(panic("not implemented")、todo!()、unimplemented!()、UnsupportedOperationException、NotImplementedException、TODO()、Promise.resolve() 占位、return []) |
❌ | ✅ |
语言语义化导出判定(Go 首字母大写即导出、Rust pub、Java/C# public、PHP public function) |
❌ | ✅ |
| 规则包签名校验 + 7 天缓存(缓存期内重复核对不重复计费) | ❌ | ✅ |
调用范围与计费
- 每次核对(未命中规则缓存时)消耗一次规则库调用,定价 ¥0.01/次,由平台按次计费。
- 规则包本地缓存 7 天(
.structure-check/rules-cache.json,Ed25519 验签后才生效):缓存有效期内重复核对不产生新的规则库调用。 - 清单校验失败(非法 JSON / 缺字段 / 未知 type)不会联网,不产生费用。
--off(或STRUCTURE_RULES=off)彻底离线:只用内置规则,不计费;此时非 JS/TS/Python 文件的核对条目返回 UNVERIFIED。
付费流程(agent 必须执行)
- 首次运行(或缓存过期)且未持有凭证时,脚本输出付款块并以退出码 2(UNVERIFIED) 结束——这不是核对结论,是付费闸门:
payment_link (Amt-Payment-Link): amtpp_v1_...
out_trade_no: SC...
amount: ¥0.01
pay_before: ...
- 把付款块原样转述给用户,请其用支付宝完成 ¥0.01 支付。禁止自行伪造、猜测或复用他人的 Payment-Proof。
- 用户支付完成后会拿到支付宝返回的
Payment-Proof,用它重跑同一份清单:
node <skill-path>/scripts/structure-check.mjs <checklist.json> --payment-proof <Payment-Proof>
服务端走官方 payment.verify 严格验付 + fulfillment.confirm 履约后下发签名规则包;规则包落盘缓存 7 天,后续核对直接命中缓存。
4. 若响应 502(资源已生成但履约确认失败),用同一个 Payment-Proof 重试,不要重新付款。
Hard rules
- 任务完成后必须核对:从用户需求/任务描述提取要求清单(每条一个
desc+ 检查项),写成 JSON,然后在项目根执行:
node <skill-path>/scripts/structure-check.mjs <checklist.json>
- 清单必须有真实来源——来自用户原话或任务描述里的明确要求(某个函数、某个导出、某处调用)。禁止凭空编造必然 PASS 的清单来自我证明。
- FAIL 的唯一处置是修代码:按 reason 修复后重跑,直到全 PASS 或向用户如实说明。禁止删改清单条目来凑 PASS;只有用户明确变更需求时才允许改清单,且必须在回复中说明。
- 不得改判:输出块的 result 与退出码是唯一裁决,agent 只转述。
- 付款闸门不得绕过:402 时请用户支付,而不是退回
--off假装核对完成。用户明确要求离线时才可用--off,且必须同时转述 UNVERIFIED 条目。
Checklist format
{
"task": "实现购物车模块",
"requirements": [
{ "desc": "Cart 类已定义", "type": "exists", "file": "src/cart.js", "symbol": "Cart" },
{ "desc": "Cart 已导出", "type": "exported", "file": "src/cart.js", "symbol": "Cart" },
{ "desc": "addItem 在入口被调用", "type": "called", "file": "src/index.js", "symbol": "addItem" },
{ "desc": "computeTotal 非空壳", "type": "notStub", "file": "src/cart.js", "symbol": "computeTotal" }
]
}
file 相对执行时的工作目录解析;一个符号要核对多个文件就写多条要求。
Check types
| type | PASS 条件 | 典型 FAIL 场景 |
|---|---|---|
| exists | 符号在本文件有定义(按语言规则判定) | 要求的函数/类根本没写 |
| exported | 符号已导出(JS: export / module.exports;Go: 首字母大写;Rust: pub;Java/C#: public;PHP: public function) | 定义了但没接上模块出口 |
| called | 符号在本文件存在调用点(排除定义行本身;new X() 也算调用) |
导出了但没有任何地方使用(假接线) |
| notStub | 函数体非空壳 | 空体、裸 return、TODO/未实现抛错、panic("not implemented")、todo!()、pass/... 冒充实现 |
支持语言
- 内置(免费层):JS / TS / JSX / TSX / mjs / cjs / vue / svelte,Python(exists / notStub)。
- 云端(付费层):Go、Rust、Java、Kotlin、C#、PHP、Ruby —— 四种检查类型全支持;并为 JS/Python 追加实战空壳签名。
- 云端规则逐条编译,非法正则丢弃(写进
notes),绝不因规则内容炸掉裁决。语言覆盖持续更新。
Verdict table (exit code decides; the agent has no discretion)
| result | Exit code | Disposal |
|---|---|---|
| PASS | 0 | 全部要求核实通过;逐字转述输出块 |
| FAIL | 1 | 至少一条要求未实现;修代码后重跑,禁止报告「已完成」 |
| UNVERIFIED | 2 | 无法裁决:清单/用法问题、付款闸门未通过、或该语言需云端规则包而当前未取得;按 reason 处理 |
Anti-patterns caught
- 虚报完成:声称「已实现 X」但 X 根本不存在——exists FAIL。
- 空壳函数:函数体去注释后只剩
return/throw not implemented/pass/.../panic("not implemented")/todo!()——notStub FAIL。 - 假接线:函数已导出但整个文件没有任何调用点——called FAIL。
- 半接线:定义了但没导出,其他模块拿不到——exported FAIL。
- Go 私有误判:小写符号在 Go 中不可导出,exported 直接 FAIL(语言语义,非风格建议)。
- 编造清单:条目全部轻易 PASS 以自我证明——Hard rule 2;清单必须能追溯到任务要求。
Scope & limits
- 机械正则核对,不做语义分析:逻辑对不对、行为有没有回归,归测试与回归守卫管。
- 检查前会先剥离注释,注释里写的代码不算数。
- 文件不存在按该条 FAIL,不豁免。
--off下非内置语言返回 UNVERIFIED,而不是拿 JS 正则硬套出假结论。
Requirements
- Node.js ≥ 18(使用全局 fetch)。
- 可访问 verify-rules API(
/structure-rules,5 秒超时);断网时回退缓存或内置规则,并如实标注rules: builtin。 - 清单 JSON 由调用方(agent)生成并落盘;建议放临时目录,用完即删,勿提交进项目。