Benchmark Validator 工具箱
四步:验契约 → 逐维度找证据给分 → 交执行器算 → 写判决。
🚨 发 JSON 的铁律:任何带 JSON 的内容,一律用文件写入工具直接写文件, 绝不在 bash 命令里内联 JSON 字符串(多重双引号会让工具调用崩溃并陷入死循环)。 JSON 里不许有真实换行符,
remediation_note的换行写成\n。
以下命令里:
R=data/companies/<公司ID>/runs/<rootRunId> # root run 目录
D=$R/nodes/<你的 nodeRunId> # 你自己的目录(提示词里给了绝对路径)
n=<本轮 attempt 号>
1. 验契约(决定你这一轮有没有活干)
node server/services/goal-contract.js validate --run-dir $R
看它打印的 sections: 一行有没有 benchmark。退出码:0 合法 / 1 契约非法 / 2 没契约或参数错。
1 和 2 都按 input_underspecified 判,把打印的 [rule] detail 原样抄进判决。
2. 读标准与被测产物(只读)
cat $R/artifacts/goal-benchmark.json # 维度 / 权重 / 及格线 / rubric / evidence_hint
ls $R/artifacts/ # 别的段写了没有
cat $R/artifacts/acceptance.json # 三段合成的契约入口
# 被测产物:路径由引擎在提示词里给(上游节点的 output_ref),按 evidence_hint 去里面找证据
ls <提示词给的被测产物目录>
❌ 不要读提示词没给到的节点目录(§四.A.5 隔离规则)。
❌ 不要写 $R/artifacts/ 下的任何文件——共享产物区对你只读,
判决由 run 自动落到 artifacts/verdicts/,不用你动手。
3. 写分数文件 + 交执行器
用文件写入工具写 $D/attempt-$n.scores.json,形如 {"scores": {"<维度名>": 87, …}}。
文件名后缀 .scores.json 是有讲究的:引擎认判词只认严格的 attempt-<n>.json,
而 goal-contract.js 能从这个文件名推出 nodeRunId 与 attempt,两边都不出错。
node server/services/goal-contract.js run --run-dir $R \
--target $D/attempt-$n.scores.json --run-id <本次 runId> --json
退出码:0 判决 pass / 1 判决 fail / 2 跑不出判决。
只读 sections.benchmark 那一格,顶层 ok 含别的 section,不是你的结论。
查历史判决(判断"是不是同一个问题反复出现"时用得上):
node server/services/goal-contract.js list --run-dir $R --only-failed --limit 10
node server/services/goal-contract.js show --run-dir $R --verdict-id <vd-…>
4. 写判决回执
用文件写入工具写 $D/attempt-$n.json(形状见 agent.md「产出格式」,schema: "work-validator/v1")。
这份文件不写 = 引擎判「无法判定」= 直接按失败走兜底边
(你的节点名以 -validator 结尾,graph-engine.js 的 requiresAttributionProduct 强制要求它存在)。
不要覆盖上一次 attempt 的文件——判决过程要可审计。
写完只回一句话总结:过没过 + 哪一维拖后腿 + 一句理由。不要把整份 JSON 复述一遍。
你不该用的工具
| 别用 | 为什么 |
|---|---|
goal-contract.js put … |
那是出题,是 goal-benchmark 的活。改标准要打回去,不是顺手改 |
| 任何写代码 / 改文档的工具 | 你判卷,不修卷 |
任何写 $R/artifacts/ 的动作 |
共享产物区对你只读;判决由 run 自动落盘 |
node bin/lemon.js task dispatch(尤其发给 innovator) |
判了 skill_defect 也只挂起等人工,L4 是 P3 非目标 |
| 训练 / 进化 / retrain 相关的一切 | 同上 |
直接写 data/ 下的 sqlite |
fail_reason / remediation_note 由引擎从你的 JSON 里读走并落库 |
| 读提示词没给到的节点目录 | 隔离规则 |
| 给出「该怪哪个 org node」的最终归因 | 那是 validator-triager 的活;你只给本段的 fail_reason |