Files
InfoRSI/tests/config-steps.test.ts
T
iomgaa 852600df02 feat: 诊断(任务书 18 第一块):诊断数学、四种提交、一次运行跑多个实验、账本与材料、flow 诊断各步
消融默认关,关掉时解释阶段一并跳过;选诊断实验用信息价值减成本。
eval/diagnosis/research.json 为第三块配置。vocab 字段说明的出口文字随提示词一起改,见下一次提交的 prompts/ 与同文件改动(本次含在内)。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 10:36:20 -04:00

329 lines
12 KiB
TypeScript

import assert from "node:assert/strict";
import { test } from "node:test";
import { checkConfig, stepList, type ResearchConfig, type StepList } from "../src/config/index.ts";
import { fullConfig, naiveConfig } from "./config-helpers.ts";
// 每份预期都对照 docs/结构.md 第三部分"步骤清单"和 docs/方法.md 第十一部分逐条手写,不从实现里推。
// 记法:[步骤, 执行 / 跳过, 规则];规则写名字和版本,版本取 rules 登记表里写的 1。
type Row = [string, "execute" | "skip", { name: string; version: number } | null];
const E = "execute" as const;
const S = "skip" as const;
function rows(steps: StepList["study"] | StepList["round"]): Row[] {
return steps.map((s) => [s.id, s.status, s.rule]);
}
function listOf(change: (flow: Extract<ResearchConfig["flow"], { preset: "full" }>) => void): StepList {
const config = fullConfig();
change(config.flow as Extract<ResearchConfig["flow"], { preset: "full" }>);
return stepList(checkConfig(config));
}
/** 跳过的步骤都写了原因。 */
function assertReasons(list: StepList): void {
for (const s of [...list.study, ...list.round]) {
if (s.status === "skip") assert.ok(s.reason.length > 0, `${s.id} 跳过却没写原因`);
}
}
test("步骤清单:完整流程全开", () => {
const list = listOf((f) => (f.diagnosis = { enabled: true, perResearcher: 2, maxExperiments: 4 }));
assert.equal(list.preset, "full");
assert.deepEqual(rows(list.study), [
["freezeConfig", E, null],
["baselineRun", E, null],
["entryDraft", E, null],
["discussion1", E, null],
["discussion2", E, null],
["claim", E, null],
["assignEntries", E, null],
["rounds", E, null],
["export", E, null],
]);
assert.deepEqual(rows(list.round), [
["openRound", E, null],
["carryOverPool", E, null],
["diagnosisProposal", E, null],
["diagnosisDedupe", E, null],
["diagnosisPrediction", E, null],
["selectDiagnosis", E, { name: "valueMinusCost", version: 1 }],
["diagnosisImplementation", E, null],
["diagnosisRun", E, null],
["diagnosisSettle", E, null],
["proposal", E, null],
["dedupe", E, null],
["firstPrediction", E, null],
["critique", E, null],
["response", E, null],
["freezeProtocol", E, null],
["secondPrediction", E, null],
["selectBatch", E, { name: "bestExpected", version: 1 }],
["implementation", E, null],
["verification", E, null],
["repair", E, null],
["forwardRun", E, null],
["publish", E, null],
["informationAccount", E, null],
["adopt", E, null],
["listCells", E, null],
["explanation", E, null],
["selectCells", E, { name: "valueMinusCost", version: 1 }],
["ablationImplementation", E, null],
["ablationVerification", E, null],
["ablationRun", E, null],
["settle", E, null],
["wrapUp", E, null],
]);
});
test("步骤清单:只关第零轮", () => {
const list = listOf((f) => (f.roundZero = { enabled: false }));
assertReasons(list);
assert.equal(list.preset, "full");
assert.deepEqual(rows(list.study), [
["freezeConfig", E, null],
["baselineRun", E, null],
["entryDraft", S, null],
["discussion1", S, null],
["discussion2", S, null],
["claim", S, null],
["assignEntries", S, null],
["rounds", E, null],
["export", E, null],
]);
assert.deepEqual(rows(list.round), rows(stepList(fullConfig()).round));
});
test("步骤清单:只关第一次预测", () => {
const list = listOf((f) => (f.firstPrediction = false));
assertReasons(list);
assert.deepEqual(rows(list.study), rows(stepList(fullConfig()).study));
assert.deepEqual(rows(list.round), [
["openRound", E, null],
["carryOverPool", E, null],
["diagnosisProposal", S, null],
["diagnosisDedupe", S, null],
["diagnosisPrediction", S, null],
["selectDiagnosis", S, null],
["diagnosisImplementation", S, null],
["diagnosisRun", S, null],
["diagnosisSettle", S, null],
["proposal", E, null],
["dedupe", E, null],
["firstPrediction", S, null],
["critique", E, null],
["response", E, null],
["freezeProtocol", E, null],
["secondPrediction", E, null],
["selectBatch", E, { name: "bestExpected", version: 1 }],
["implementation", E, null],
["verification", E, null],
["repair", E, null],
["forwardRun", E, null],
["publish", E, null],
["informationAccount", E, null],
["adopt", E, null],
["listCells", E, null],
["explanation", E, null],
["selectCells", E, { name: "valueMinusCost", version: 1 }],
["ablationImplementation", E, null],
["ablationVerification", E, null],
["ablationRun", E, null],
["settle", E, null],
["wrapUp", E, null],
]);
});
test("步骤清单:只关挑刺与回应,协议照样冻结", () => {
const list = listOf((f) => (f.critique = false));
assertReasons(list);
assert.deepEqual(rows(list.study), rows(stepList(fullConfig()).study));
assert.deepEqual(rows(list.round), [
["openRound", E, null],
["carryOverPool", E, null],
["diagnosisProposal", S, null],
["diagnosisDedupe", S, null],
["diagnosisPrediction", S, null],
["selectDiagnosis", S, null],
["diagnosisImplementation", S, null],
["diagnosisRun", S, null],
["diagnosisSettle", S, null],
["proposal", E, null],
["dedupe", E, null],
["firstPrediction", E, null],
["critique", S, null],
["response", S, null],
["freezeProtocol", E, null],
["secondPrediction", E, null],
["selectBatch", E, { name: "bestExpected", version: 1 }],
["implementation", E, null],
["verification", E, null],
["repair", E, null],
["forwardRun", E, null],
["publish", E, null],
["informationAccount", E, null],
["adopt", E, null],
["listCells", E, null],
["explanation", E, null],
["selectCells", E, { name: "valueMinusCost", version: 1 }],
["ablationImplementation", E, null],
["ablationVerification", E, null],
["ablationRun", E, null],
["settle", E, null],
["wrapUp", E, null],
]);
});
test("步骤清单:只关消融,解释也跳过,选格没有规则", () => {
const list = listOf((f) => (f.ablation = { enabled: false }));
assertReasons(list);
assert.deepEqual(rows(list.study), rows(stepList(fullConfig()).study));
assert.deepEqual(rows(list.round), [
["openRound", E, null],
["carryOverPool", E, null],
["diagnosisProposal", S, null],
["diagnosisDedupe", S, null],
["diagnosisPrediction", S, null],
["selectDiagnosis", S, null],
["diagnosisImplementation", S, null],
["diagnosisRun", S, null],
["diagnosisSettle", S, null],
["proposal", E, null],
["dedupe", E, null],
["firstPrediction", E, null],
["critique", E, null],
["response", E, null],
["freezeProtocol", E, null],
["secondPrediction", E, null],
["selectBatch", E, { name: "bestExpected", version: 1 }],
["implementation", E, null],
["verification", E, null],
["repair", E, null],
["forwardRun", E, null],
["publish", E, null],
["informationAccount", E, null],
["adopt", E, null],
["listCells", S, null],
["explanation", S, null],
["selectCells", S, null],
["ablationImplementation", S, null],
["ablationVerification", S, null],
["ablationRun", S, null],
["settle", S, null],
["wrapUp", E, null],
]);
});
test("步骤清单:朴素循环", () => {
const list = stepList(naiveConfig());
assertReasons(list);
assert.equal(list.preset, "naive");
assert.deepEqual(rows(list.study), [
["freezeConfig", E, null],
["baselineRun", E, null],
["entryDraft", S, null],
["discussion1", S, null],
["discussion2", S, null],
["claim", S, null],
["assignEntries", S, null],
["rounds", E, null],
["export", E, null],
]);
assert.deepEqual(rows(list.round), [
["openRound", E, null],
["carryOverPool", S, null], // 候选不留池
["diagnosisProposal", S, null], // 不诊断
["diagnosisDedupe", S, null], // 不诊断
["diagnosisPrediction", S, null], // 不诊断
["selectDiagnosis", S, null], // 不诊断
["diagnosisImplementation", S, null], // 不诊断
["diagnosisRun", S, null], // 不诊断
["diagnosisSettle", S, null], // 不诊断
["proposal", E, null],
["dedupe", E, null], // 判重照常
["firstPrediction", S, null], // 不预测
["critique", S, null], // 不挑刺
["response", S, null], // 不回应
["freezeProtocol", E, null], // 提案直接冻结
["secondPrediction", S, null], // 不预测
["selectBatch", E, { name: "uniformRandom", version: 1 }], // 均匀随机选批
["implementation", E, null],
["verification", E, null],
["repair", E, null],
["forwardRun", E, null],
["publish", E, null],
["informationAccount", S, null], // 没有预测,记不了信息账
["adopt", E, null], // 采纳规则和完整流程相同
["listCells", S, null], // 不消融
["explanation", S, null],
["selectCells", S, null],
["ablationImplementation", S, null],
["ablationVerification", S, null],
["ablationRun", S, null],
["settle", S, null],
["wrapUp", S, null], // 没有收尾
]);
});
test("步骤清单:第零轮讨论 1 次时跳过第 2 次;只有一位研究者时不讨论", () => {
const once = listOf((f) => (f.roundZero = { enabled: true, discussions: 1 }));
assertReasons(once);
assert.deepEqual(rows(once.study).slice(2, 7), [
["entryDraft", E, null],
["discussion1", E, null],
["discussion2", S, null],
["claim", E, null],
["assignEntries", E, null],
]);
const config = fullConfig();
config.models.researchers = [config.models.researchers[0]!];
const single = stepList(checkConfig(config));
assertReasons(single);
assert.deepEqual(rows(single.study).slice(2, 7), [
["entryDraft", E, null],
["discussion1", S, null],
["discussion2", S, null],
["claim", E, null],
["assignEntries", E, null],
]);
});
test("步骤清单:换规则后清单里的规则跟着换", () => {
const list = listOf((f) => {
f.batchRule = "uniformRandom";
f.ablation = { enabled: true, cellRule: "randomSameCount" };
});
const rule = (id: string) => list.round.find((s) => s.id === id)!.rule;
assert.deepEqual(rule("selectBatch"), { name: "uniformRandom", version: 1 });
assert.deepEqual(rule("selectCells"), { name: "randomSameCount", version: 1 });
});
test("步骤清单:诊断开、消融关(现行配置):诊断七步执行,消融七步(含解释)跳过", () => {
const list = listOf((f) => {
f.diagnosis = { enabled: true, perResearcher: 2, maxExperiments: 4 };
f.ablation = { enabled: false };
});
assertReasons(list);
const status = (id: string) => list.round.find((s) => s.id === id)!.status;
for (const id of [
"diagnosisProposal", "diagnosisDedupe", "diagnosisPrediction", "selectDiagnosis",
"diagnosisImplementation", "diagnosisRun", "diagnosisSettle",
]) {
assert.equal(status(id), "execute", id);
}
for (const id of [
"listCells", "explanation", "selectCells", "ablationImplementation", "ablationVerification", "ablationRun", "settle",
]) {
assert.equal(status(id), "skip", id);
}
// 诊断七步排在留池之后、提案之前(方法.md 4.3"诊断"一段)。
const ids = list.round.map((s) => s.id);
assert.deepEqual(ids.slice(ids.indexOf("carryOverPool"), ids.indexOf("proposal") + 1), [
"carryOverPool", "diagnosisProposal", "diagnosisDedupe", "diagnosisPrediction", "selectDiagnosis",
"diagnosisImplementation", "diagnosisRun", "diagnosisSettle", "proposal",
]);
assert.deepEqual(list.round.find((s) => s.id === "selectDiagnosis")!.rule, { name: "valueMinusCost", version: 1 });
});