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>
This commit is contained in:
+70
-11
@@ -2,10 +2,10 @@ import assert from "node:assert/strict";
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { test } from "node:test";
|
||||
import { beliefBook, callId, queryMaterial, readPrompts, type TaskMaterial } from "../src/materials/index.ts";
|
||||
import { beliefBook, queryMaterial, readPrompts, type TaskMaterial } from "../src/materials/index.ts";
|
||||
import { SUBMISSION_KINDS, type SubmissionKind } from "../src/vocab/index.ts";
|
||||
import { tempDir } from "./ledger-helpers.ts";
|
||||
import { CHANGES_C1, CRITIQUE_ID, everything, material, NONE, study, studyUpTo } from "./materials-helpers.ts";
|
||||
import { CHANGES_C1, CRITIQUE_ID, everything, material, NONE, study, studyUpTo, TABLE_C1 } from "./materials-helpers.ts";
|
||||
|
||||
// 每种任务至少一个测试:在真实账本里写到某一步,生成材料,查该有的有、不该有的没有、对号清单对。
|
||||
// 预期值按方法.md 条文手写(研究进程见 materials-helpers.ts 的注释),不从实现推。
|
||||
@@ -63,7 +63,7 @@ test("第 1 轮提案:你认领的入口放在最前;没有上一轮;对
|
||||
factorLimit: 3,
|
||||
continuable: [],
|
||||
reusableMetrics: [],
|
||||
takenMetricIds: ["sum-of-radii", "wall-seconds"],
|
||||
takenMetricIds: ["sum-of-radii", "wall-seconds", "answer-path", "safeguard-triggers"],
|
||||
});
|
||||
const h = headings(m);
|
||||
assert.ok(h.indexOf("你自己的") < h.indexOf("公共材料") && h.indexOf("公共材料") < h.indexOf("信念本"), "先你自己的、后公共材料");
|
||||
@@ -82,7 +82,7 @@ test("第 2 轮提案:上一轮全部收尾、上一轮实验员的提醒、
|
||||
factorLimit: 3,
|
||||
continuable: ["r1-c1-p1", "r1-c1-p2", "r1-c2-p1"],
|
||||
reusableMetrics: ["restart-count"],
|
||||
takenMetricIds: ["sum-of-radii", "wall-seconds", "restart-count"],
|
||||
takenMetricIds: ["sum-of-radii", "wall-seconds", "answer-path", "safeguard-triggers", "restart-count"],
|
||||
});
|
||||
for (const x of ["上一轮的收尾", "上一轮实验员实现时的提醒", '可以写进"延续"的因子', "已登记指标清单", "研究记录", "信念本"]) {
|
||||
assert.ok(headings(m).includes(x), `应有一节"${x}"`);
|
||||
@@ -109,6 +109,13 @@ test("挑刺:按原提案挑,对号清单是那条提案和它的因子", (t
|
||||
lacks(m, "6.661");
|
||||
});
|
||||
|
||||
test("挑刺的现在交什么:可以交一份或几份,每份调用一次;不写调用一次就完成", (t) => {
|
||||
const m = material(studyUpTo(t, "critiqueOpen"), "critique", "a2", "s1-crit", "r1-a1-1", NONE);
|
||||
const end = m.firstMessage.slice(m.firstMessage.lastIndexOf("# 现在交什么"));
|
||||
assert.ok(end.includes("每调用一次 research_submit 交一份挑刺;可以交一份或几份"), end);
|
||||
assert.ok(!end.includes("交上就完成了"), end);
|
||||
});
|
||||
|
||||
test("回应:本人原提案和针对它的全部挑刺", (t) => {
|
||||
const l = studyUpTo(t, "responseOpen");
|
||||
const m = material(l, "response", "a1", "s1-resp", "r1-c1", NONE);
|
||||
@@ -120,7 +127,7 @@ test("回应:本人原提案和针对它的全部挑刺", (t) => {
|
||||
factorLimit: 3,
|
||||
continuable: [],
|
||||
reusableMetrics: [],
|
||||
takenMetricIds: ["sum-of-radii", "wall-seconds"],
|
||||
takenMetricIds: ["sum-of-radii", "wall-seconds", "answer-path", "safeguard-triggers"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -139,11 +146,17 @@ test("第二次预测:冻结协议、挑刺与答复配对、本人第一次
|
||||
has(m, "6.661 / 6.662 / 6.663");
|
||||
has(m, "乙的挑刺:扰动可能混杂(推测)");
|
||||
has(m, "作者的答复:甲答复:保留扰动");
|
||||
has(m, "### 答复正文");
|
||||
lacks(m, "5.551");
|
||||
lacks(m, "甲第一次理由");
|
||||
lacks(m, "7.772");
|
||||
});
|
||||
|
||||
test("新登记指标不能用的编号里有答案路径、保障动手次数两个保留键(用户 2026-10-03 定)", (t) => {
|
||||
const c = material(studyUpTo(t, "proposalOpen"), "proposal", "a1", "s1-prop", null, NONE).checklist as Extract<TaskMaterial["checklist"], { kind: "proposal" }>;
|
||||
assert.ok(c.takenMetricIds.includes("answer-path") && c.takenMetricIds.includes("safeguard-triggers"), JSON.stringify(c.takenMetricIds));
|
||||
});
|
||||
|
||||
test("解释:本轮运行、提醒、要给三个数的格、产物只进查询;看不到别人的第一次预测", (t) => {
|
||||
const l = studyUpTo(t, "explOpen1");
|
||||
const m = material(l, "explanation", "a2", "s1-expl", null, { changes: null, artifacts: { "run-1": { "stdout.log": "日志正文" } } });
|
||||
@@ -229,6 +242,35 @@ test("核验:没有归属的改动排第一;因子与保障同行只作提
|
||||
assert.ok(!headings(m).includes("信念本"));
|
||||
});
|
||||
|
||||
test("核验材料里没有 Jev 的概率和阈值:收下实现时用过 Jev,也不给核验员看", (t) => {
|
||||
const l = studyUpTo(t, "implOpen");
|
||||
const jev = [{ question: "early_exit", questionHash: "ab".repeat(32), threshold: 0.6312, probability: 0.4321, yes: false, requestId: "req-1" }];
|
||||
l.append("submission", { stageId: "s1-impl-c1", author: "x1", kind: "implementation", target: "r1-c1", item: null, version: 1, jev, content: { ...TABLE_C1, concerns: "无", body: "实现说明" } });
|
||||
l.append("stageClose", { stageId: "s1-impl-c1" });
|
||||
l.append("code", { object: "r1-c1", version: "v-c1", locations: TABLE_C1 });
|
||||
l.append("stageOpen", { stageId: "s1-ver-c1", stage: "verification", round: 1, roster: ["v1"] });
|
||||
const m = material(l, "verification", "v1", "s1-ver-c1", "r1-c1", { changes: CHANGES_C1, artifacts: null });
|
||||
has(m, "实现说明");
|
||||
for (const x of ["0.4321", "0.6312", "early_exit", "预扫"]) lacks(m, x);
|
||||
});
|
||||
|
||||
test("消融实现重做:材料放上一次消融核验关错的因子和依据;第一次做时没有退回意见", (t) => {
|
||||
assert.ok(!everything(material(studyUpTo(t, "ablationImplOpen"), "ablationImplementation", "x1", "s1-ai", "r1-c1-p1", NONE)).includes("### 退回意见"));
|
||||
const l = studyUpTo(t, "ablationImpl");
|
||||
// 这一格要关 p1、照留 p2;核验员看到 p1 还开着、p2 照留:只有 p1 关错了。
|
||||
l.append("submission", {
|
||||
stageId: "s1-av", author: "v1", kind: "ablationVerification", target: "r1-c1-p1", item: null, version: 1, jev: null,
|
||||
content: { factors: [{ factor: "p1", off: false, where: "solve.py:12 仍在跑多起点循环" }, { factor: "p2", off: false, where: "solve.py:30 照留" }] },
|
||||
});
|
||||
l.append("stageClose", { stageId: "s1-av" });
|
||||
l.append("stageOpen", { stageId: "s1-ai2", stage: "ablationImplementation", round: 1, roster: ["x1"] });
|
||||
const m = material(l, "ablationImplementation", "x1", "s1-ai2", "r1-c1-p1", NONE);
|
||||
has(m, "### 退回意见");
|
||||
has(m, "- 因子 p1 应当关着,核验员看到的是照留:solve.py:12 仍在跑多起点循环");
|
||||
lacks(m, "solve.py:30 照留");
|
||||
assert.deepEqual(m.checklist, { kind: "ablationImplementation", cell: "r1-c1-p1", off: "p1", factors: ["p1", "p2"] });
|
||||
});
|
||||
|
||||
test("消融实现:这一格、因子清单、完整代码的位置表;看不到运行成绩", (t) => {
|
||||
const l = studyUpTo(t, "ablationImplOpen");
|
||||
const m = material(l, "ablationImplementation", "x1", "s1-ai", "r1-c1-p1", NONE);
|
||||
@@ -305,15 +347,32 @@ test("可见性 5:第零轮闭门写入口时看不到别人的入口", (t) =>
|
||||
|
||||
test("可见性 6:别人的退回不放进材料;本人重新发起时放上一次被退回的原因", (t) => {
|
||||
const l = studyUpTo(t, "secondOpen");
|
||||
const call = callId("s1-sp", "a1", "secondPrediction", "r1-c1", 1);
|
||||
l.append("callStarted", { call, actor: "a1", stageId: "s1-sp", model: "glm-5.3", materials: null });
|
||||
l.append("rejection", { stageId: "s1-sp", author: "a1", kind: "secondPrediction", submitted: { range: { q1: 3, q5: 2, q9: 1 } }, reason: "甲被退回:三个数不递增", jev: null });
|
||||
l.append("callEnded", { call, wallSeconds: { status: "measured", value: 3 }, status: "notSubmitted", reason: "没交成" });
|
||||
const reject = (author: string, target: string, reason: string) =>
|
||||
l.append("rejection", { stageId: "s1-sp", author, kind: "secondPrediction", target, submitted: { range: { q1: 3, q5: 2, q9: 1 } }, reason, jev: null });
|
||||
reject("a1", "r1-c1", "甲被退回:三个数不递增");
|
||||
reject("a2", "r1-c1", "乙被退回");
|
||||
const retry = material(l, "secondPrediction", "a1", "s1-sp", "r1-c1", NONE);
|
||||
assert.ok(retry.firstMessage.includes("# 上一次为什么没交成"));
|
||||
has(retry, "甲被退回:三个数不递增");
|
||||
lacks(material(l, "secondPrediction", "a1", "s1-sp", "r1-c2", NONE), "甲被退回");
|
||||
lacks(material(l, "secondPrediction", "a2", "s1-sp", "r1-c1", NONE), "甲被退回");
|
||||
lacks(retry, "乙被退回");
|
||||
lacks(material(l, "secondPrediction", "a2", "s1-sp", "r1-c2", NONE), "甲被退回");
|
||||
});
|
||||
|
||||
test("退回按对象找:本人同一阶段对两个候选各被退回一次,重新发起时只放这个对象的那一条", (t) => {
|
||||
// 两个候选的第二次预测并行,退回交错写入;不靠模型调用的记录定位。
|
||||
const l = studyUpTo(t, "secondOpen");
|
||||
const reject = (target: string, reason: string) =>
|
||||
l.append("rejection", { stageId: "s1-sp", author: "a1", kind: "secondPrediction", target, submitted: {}, reason, jev: null });
|
||||
reject("r1-c1", "c1 第一次被退回");
|
||||
reject("r1-c2", "c2 被退回");
|
||||
reject("r1-c1", "c1 第二次被退回");
|
||||
const c1 = material(l, "secondPrediction", "a1", "s1-sp", "r1-c1", NONE);
|
||||
has(c1, "c1 第二次被退回");
|
||||
lacks(c1, "c1 第一次被退回");
|
||||
lacks(c1, "c2 被退回");
|
||||
const c2 = material(l, "secondPrediction", "a1", "s1-sp", "r1-c2", NONE);
|
||||
has(c2, "c2 被退回");
|
||||
lacks(c2, "c1 第");
|
||||
});
|
||||
|
||||
test("可见性 7:信念本只写已公开的记录:正向运行在采纳决定写入后才出现", (t) => {
|
||||
|
||||
Reference in New Issue
Block a user