feat: flow 第 1 部分(骨架、研究开始、第零轮)与第零轮检验

按任务书 12 实现 src/flow:从账本现算下一步的纯函数、主循环、恢复入口、派模型任务和跑正式运行两个共用动作、冻结配置、基线、第零轮三个研究者阶段和入口分配,走到第 1 轮时停下。materials 导出 finalEntries、加 researcherId 和 StudyRecord。

审阅采纳两条:研究编号本机已用过时冻结前报错;docker run 没启动时写完结果就停下,不在本进程里无限起新编号。

eval/ 新增第零轮检验:起研究命令行、回放假模型、检验用 Jev 客户端、六问质量评估、16-real-1 回放、杀进程与两份同时跑。tsc 与 depcruise 也检查 eval/,新增 eval 只经 index.ts 用正式代码的规则。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 10:58:52 -04:00
parent 8491191a2b
commit 75d7cffd27
36 changed files with 2456 additions and 14 deletions
+27
View File
@@ -0,0 +1,27 @@
import { parseArgs } from "node:util";
import { loadConfig } from "../../src/config/index.ts";
import { runStudy } from "../../src/flow/index.ts";
// 起研究的命令行入口:像用户一样给配置、指定研究目录、调 runStudy,按 Ctrl-C(SIGINT)时发"停下"信号。
// 新研究:node eval/lib/cli.ts --config <research.json> --dir <研究目录>
// 接着跑:node eval/lib/cli.ts --resume --dir <研究目录>(配置写 null,以账本里冻结的那份为准)
// 结局打印成一行 "RESULT <json>",检验脚本按这一行读。
const { values } = parseArgs({
options: { config: { type: "string" }, resume: { type: "boolean" }, dir: { type: "string" } },
strict: true,
});
if (values.dir === undefined) throw new Error("要写 --dir <研究目录>");
if ((values.config === undefined) === (values.resume !== true)) {
throw new Error("--config <research.json> 和 --resume 二选一,必须写一个");
}
const config = values.config === undefined ? null : loadConfig(values.config);
const stop = new AbortController();
process.on("SIGINT", () => {
console.error("收到 SIGINT,发停下信号");
stop.abort();
});
const outcome = await runStudy({ studyDir: values.dir, config, stop: stop.signal });
console.log(`RESULT ${JSON.stringify(outcome)}`);