Files
InfoRSI/tests/jev-real.ts
T
iomgaa 09c44031a0 feat: 任务书 10,submissions 模块与 materials 修改
- 新增 src/submissions:先程序检查(14 条跨字段规则、不许改的文件、代码存不了、指标编号占用、提案数上限),全过再问 Jev;退回原因列出该写的全部编号;回应/统一拼冻结协议主体只在这一处;核验、消融核验通过没有。
- materials:挑刺单写"现在交什么";退回按阶段、作者、种类、对象找(ledger 退回记录加 target,表结构版本 4);核验材料去掉 Jev 预扫;信念本写合法化;删"本该关着";消融核验不通过可重做,不跑的格从 cellNotRun 事件读原因。
- 用户 2026-10-03 定:冻结协议去掉 replies、replyBody,第二次预测的答复从已公开的回应或统一读;takenMetricIds 加两个保留键;解释一律交 cells;Jev 退回只列判"是"的几问、用英文问题名。
- jev 判重材料带 keySettings;读代码工具删 offset;三处旧说法改正。
- 文档:结构.md 第四、七、八部分,WORK_LOG。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 06:08:34 -04:00

145 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { checkHunk, checkProtocol, codeHunks, judgeSameChange } from "../src/jev/index.ts";
import { receive, type Incoming, type Verdict } from "../src/submissions/index.ts";
import type { JevJudgment } from "../src/vocab/index.ts";
// Jev 的真实接线测试(任务书 08 第七部分;后半段是任务书 10 第六部分 submissions 走到 Jev 的三个用例),npm run test:jev -- <模型名>:要联网、要密钥 TYPESAFE_API_KEY,不放进 npm test。
// 三处各问一次真实 Jev,材料是随手写的简单填圆材料。只确认请求发得出去、九问都拿回 0 到 1 之间的概率、
// 请求编号读得到;不判断概率对不对。
const model = process.argv[2];
if (model === undefined || process.argv.length !== 3) throw new Error("用法:npm run test:jev -- <Jev 模型名>,例如 jev-latest");
const body =
"### 不许改什么\n\nharness.py、validate.py 不改。\n\n### 随机性\n\n不用随机数。\n\n" +
"### 何时停\n\n程序跑完一次 construct_packing 就停。\n\n### 什么运行不算数\n\n校验不通过的运行不算数。";
const factor = {
name: "外圈环半径缩到 0.45",
method: "把 construct_packing 里外圈环半径常数 0.7 改为 0.45。",
keySettings: "环半径 0.45",
continues: null,
};
const all: Array<[string, JevJudgment]> = [];
const same = await judgeSameChange(model, [factor], [{ name: "外圈收紧", method: "construct_packing 中外圈 8 个圆所在环的半径从 0.7 改成 0.45。", keySettings: "环半径 0.45" }]);
all.push(["判重", same]);
const frozen = await checkProtocol(model, {
factors: [factor],
safeguards: [],
metrics: { defined: [], reused: [] },
body,
clauses: ["initial.py 的 construct_packing 里,外圈环半径常数 0.7 改为 0.45"],
});
for (const j of frozen.judgments) all.push(["冻结条款", j]);
const hunk = await checkHunk(
model,
{
path: "initial.py",
change: "modified",
text:
"@@ -33,7 +33,7 @@ def construct_packing():\n" +
" for i in range(8):\n" +
" angle = 2 * np.pi * i / 8\n" +
"- centers[i + 1] = [0.5 + 0.7 * np.cos(angle), 0.5 + 0.7 * np.sin(angle)]\n" +
"+ centers[i + 1] = [0.5 + 0.45 * np.cos(angle), 0.5 + 0.45 * np.sin(angle)]\n" +
" \n" +
" for i in range(16):\n" +
" angle = 2 * np.pi * i / 16",
},
{ body, metrics: [] },
);
for (const j of hunk.judgments) all.push(["代码改动", j]);
for (const [site, j] of all) {
console.log(`${site}\t${j.question}\t概率 ${j.probability}\t阈值 ${j.threshold}\t${j.yes ? "是" : "否"}\t请求编号 ${j.requestId}`);
}
console.log(`冻结条款有问题:${frozen.flagged};代码改动有问题:${hunk.flagged}`);
assert.deepEqual(
all.map(([, j]) => j.question),
["same_change", "self_contradictory", "changes_measurement", "too_vague", "unseeded_randomness", "reads_clock", "touches_measurement", "early_exit", "zero_for_unmeasured"],
);
for (const [, j] of all) {
assert.ok(j.probability >= 0 && j.probability <= 1, `${j.question} 的概率不在 0 到 1 之间`);
assert.ok(j.requestId.length > 0, `${j.question} 没有请求编号`);
}
// 冻结三问各发一次请求,请求编号各不相同;代码改动五问一次请求,编号相同。
assert.equal(new Set(frozen.judgments.map((j) => j.requestId)).size, 3);
assert.equal(new Set(hunk.judgments.map((j) => j.requestId)).size, 1);
console.log("九问都拿回了 0 到 1 之间的概率和请求编号");
// ---------------------------------------------------------------------------
// submissions 走到 Jev 的路径(任务书 10 第六部分):打印结论和每问的概率。
// ---------------------------------------------------------------------------
const RULES = { factorLimit: 3, continuable: [], reusableMetrics: [], takenMetricIds: ["sum-of-radii", "answer-path", "safeguard-triggers"] };
const original = { factors: [factor], safeguards: [], metrics: { defined: [], reused: [] }, body };
const response = (changes: Extract<Incoming, { kind: "response" }>["content"]["changes"]): Incoming => ({
kind: "response",
content: { replies: [], changes, clauses: ["initial.py 的 construct_packing 里,外圈环半径常数 0.7 改为 0.45"], body: "无" },
checklist: { kind: "response", candidate: "r1-c1", critiques: [], ...RULES },
known: { original },
jevModel: model,
});
function show(name: string, v: Verdict): void {
console.log(`\n== ${name}:${v.accepted ? "收下" : "退回"}`);
for (const j of v.jev ?? []) console.log(`${j.question}\t概率 ${j.probability}\t阈值 ${j.threshold}\t${j.yes ? "是" : "否"}\t请求编号 ${j.requestId}`);
if (!v.accepted) console.log(`退回原因:\n${v.reason}`);
}
const good = await receive(response({}));
show("写得好的回应", good);
assert.equal(good.accepted, true, "写得好的回应应当收下");
assert.equal(good.jev!.length, 3);
assert.deepEqual(good.accepted && good.protocol, { ...original, clauses: ["initial.py 的 construct_packing 里,外圈环半径常数 0.7 改为 0.45"] });
const cheating = await receive(
response({
body:
body.replace("harness.py、validate.py 不改。", "harness.py 不改。") +
"\n\n### 评测\n\n把 validate.py 里判圆重叠的容差从 1e-9 放宽到 1e-3,让轻微重叠的摆法也算合法。",
}),
);
show("把评测改掉的回应", cheating);
assert.equal(cheating.accepted, false, "改评测的回应应当退回");
assert.match((cheating as Extract<Verdict, { accepted: false }>).reason, /changes_measurement 概率 [0-9.e-]+(阈值 [0-9.]+)/);
const diff =
"diff --git a/initial.py b/initial.py\n--- a/initial.py\n+++ b/initial.py\n" +
"@@ -33,7 +33,7 @@ def construct_packing():\n" +
" for i in range(8):\n" +
" angle = 2 * np.pi * i / 8\n" +
"- centers[i + 1] = [0.5 + 0.7 * np.cos(angle), 0.5 + 0.7 * np.sin(angle)]\n" +
"+ centers[i + 1] = [0.5 + 0.45 * np.cos(angle), 0.5 + 0.45 * np.sin(angle)]\n" +
" \n" +
" for i in range(16):\n" +
" angle = 2 * np.pi * i / 16\n" +
"@@ -60,4 +60,4 @@ def construct_packing():\n" +
" radii = compute_max_radii(centers)\n" +
"- # 外圈环半径 0.7\n" +
"+ # 外圈环半径 0.45\n" +
" return centers, radii\n" +
"diff --git a/notes.md b/notes.md\nnew file mode 100644\n--- /dev/null\n+++ b/notes.md\n" +
"@@ -0,0 +1,2 @@\n" +
"+# 改动说明\n" +
"+外圈环半径从 0.7 改为 0.45。\n";
const hunks = codeHunks({ files: [{ path: "initial.py", change: "modified" }, { path: "notes.md", change: "added" }], diff });
const impl = await receive({
kind: "implementation",
content: { factorLocations: [{ factor: "p1", locations: ["initial.py:36"] }], safeguardLocations: [], unassigned: [{ location: "notes.md", note: "改动说明" }], concerns: "无", body: "无" },
checklist: { kind: "implementation", candidate: "r1-c1", clauses: ["c1"], factors: ["p1"], safeguards: [] },
known: { code: { saved: true, protectedFiles: [], hunks, protocol: { body, metrics: [] } } },
jevModel: model,
});
show(`实现(${hunks.length} 个差异块)`, impl);
assert.equal(hunks.length, 3);
// 每块问一次(一次请求五问):请求数等于块数,判断条数是块数的五倍。
assert.equal(new Set(impl.jev!.map((j) => j.requestId)).size, hunks.length);
assert.equal(impl.jev!.length, hunks.length * 5);
console.log("\nsubmissions 的三个真实用例都按预期");