eval: 准备正向采纳的真实运行恢复与质量评估
新增单份串行启动入口、首个正向运行杀进程恢复证据、逐候选审阅导出与账目统计;参考只读副本分数对照。456项免费测试通过,尚未启动三份真实验收。同步结构说明与当前工作状态。
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
import {
|
||||
Board,
|
||||
protocolMetrics,
|
||||
type TaskMaterial,
|
||||
} from "../../src/materials/index.ts";
|
||||
import { checkoutVersion, compareVersions } from "../../src/workspace/index.ts";
|
||||
import { candidateHistory, jsonFile } from "../lib/forward.ts";
|
||||
import { ofKind, readLedger } from "../lib/ledger.ts";
|
||||
|
||||
// 任务书16五项质量评估的候选审阅材料;不判路线、不代替全新上下文逐条阅读。
|
||||
// node eval/forward/export.ts <研究目录> <全新绝对输出目录>
|
||||
const [study, output, ...extra] = process.argv.slice(2);
|
||||
if (!study || !output || extra.length || output !== resolve(output))
|
||||
throw new Error(
|
||||
"用法:node eval/forward/export.ts <研究目录> <全新绝对输出目录>",
|
||||
);
|
||||
mkdirSync(output); // 不覆盖以前的审阅材料。
|
||||
const records = readLedger(study);
|
||||
const board = new Board(records);
|
||||
const repo = join(study, "repo.git");
|
||||
const batch = board.decision("batch", 1)!;
|
||||
const baseline = board.code(board.baselineOf(1));
|
||||
const plans = ofKind(records, "runPlanned").filter(
|
||||
(p) => p.content.round === 1 && p.content.purpose === "forward",
|
||||
);
|
||||
const index = [];
|
||||
for (const candidate of batch.output.chosen) {
|
||||
const dir = join(output, candidate);
|
||||
mkdirSync(dir);
|
||||
const history = candidateHistory(records, candidate);
|
||||
const candidatePlans = plans.filter((p) => p.content.object === candidate);
|
||||
const started = candidatePlans.filter((p) =>
|
||||
ofKind(records, "runStarted").some((s) => s.content.run === p.content.run),
|
||||
);
|
||||
const protocol = ofKind(records, "protocol")
|
||||
.filter((p) => p.content.candidate === candidate)
|
||||
.at(-1)!;
|
||||
jsonFile(join(dir, "protocol.json"), {
|
||||
record: protocol,
|
||||
resolvedMetrics: protocolMetrics(board, board.protocol(candidate)),
|
||||
});
|
||||
mkdirSync(join(dir, "baseline"));
|
||||
checkoutVersion(repo, baseline.version, join(dir, "baseline"));
|
||||
for (const attempt of history.attempts) {
|
||||
const path = join(dir, `code-${attempt.code.seq}`);
|
||||
mkdirSync(path);
|
||||
checkoutVersion(repo, attempt.code.content.version, path);
|
||||
jsonFile(
|
||||
join(dir, `changes-${attempt.code.seq}.json`),
|
||||
compareVersions(repo, baseline.version, attempt.code.content.version),
|
||||
);
|
||||
}
|
||||
// 首轮里每个候选只正式跑一个已通过版本;无启动的候选仍导出历史,但不冒称有最终通过代码。
|
||||
const firstRun = started[0];
|
||||
const finalCode =
|
||||
firstRun === undefined
|
||||
? null
|
||||
: ofKind(records, "code")
|
||||
.filter((c) => c.content.object === candidate && c.seq < firstRun.seq)
|
||||
.at(-1)!;
|
||||
if (finalCode !== null) {
|
||||
mkdirSync(join(dir, "final"));
|
||||
checkoutVersion(repo, finalCode.content.version, join(dir, "final"));
|
||||
}
|
||||
const finalAttempt =
|
||||
finalCode === null
|
||||
? null
|
||||
: history.attempts.find((a) => a.code.seq === finalCode.seq)!;
|
||||
jsonFile(join(dir, "final-implementation.json"), finalAttempt);
|
||||
jsonFile(join(dir, "attempts.json"), history.attempts);
|
||||
jsonFile(join(dir, "verifications.json"), history.verifications);
|
||||
const calls = ofKind(records, "callStarted").filter((c) => {
|
||||
const material = c.content.materials as TaskMaterial;
|
||||
return (
|
||||
material.object === candidate &&
|
||||
["implementation", "repair", "verification"].includes(material.kind)
|
||||
);
|
||||
});
|
||||
jsonFile(
|
||||
join(dir, "calls.json"),
|
||||
calls.map((c) => ({
|
||||
record: c,
|
||||
sessions: join(study, "calls", c.content.call, "sessions"),
|
||||
})),
|
||||
);
|
||||
jsonFile(
|
||||
join(dir, "rejections.json"),
|
||||
ofKind(records, "rejection").filter(
|
||||
(r) =>
|
||||
r.content.target === candidate &&
|
||||
["implementation", "repair", "verification"].includes(r.content.kind),
|
||||
),
|
||||
);
|
||||
const manifest = {
|
||||
study,
|
||||
candidate,
|
||||
protocolSeq: protocol.seq,
|
||||
baselineVersion: baseline.version,
|
||||
finalCode,
|
||||
ran: started.length > 0,
|
||||
runs: candidatePlans.map((p) => ({
|
||||
plan: p,
|
||||
result:
|
||||
ofKind(records, "runResult").find(
|
||||
(r) => r.content.run === p.content.run,
|
||||
) ?? null,
|
||||
artifacts: join(study, "runs", p.content.run),
|
||||
})),
|
||||
};
|
||||
jsonFile(join(dir, "manifest.json"), manifest);
|
||||
writeFileSync(
|
||||
join(dir, "review.txt"),
|
||||
`任务书16第3.2节:只读本候选,分两步评估,中文直接回复,不写文件。\n` +
|
||||
`第一步只读 protocol.json(冻结协议全文及引用指标原定义)、baseline/、final/、final-implementation.json(正文、位置表、concerns)。\n` +
|
||||
`逐条实现条款、因子、保障检查漏做、协议之外的改进、位置表是否准确,每条附代码文件和行号。先形成独立结论,再打开核验历史。\n` +
|
||||
`第二步读 verifications.json、attempts.json、code-<序号>/、changes-<序号>.json;每次核验对照其中code指向的那一版,不拿最终修好版本倒判历史。判断该拒却通过、不该拒却拒绝;修复是否只改指出处。\n` +
|
||||
`需要时读 calls.json 和 rejections.json;模型材料和原始会话都可追溯。不把提交格式退回当成核验失败。\n` +
|
||||
`答案路径只核对每个可能交出最终答案分支的标签,不预测实际走哪个分支。报告先写实现忠实度,再写逐次核验误判和修复范围。\n` +
|
||||
`按任务书15附录一路线代号归类冻结协议,另标是否完整高上限路线(起点、连续改进全部圆、多起点或扰动、合法收尾),附协议原文位置。\n` +
|
||||
`本候选${manifest.ran ? "已启动正式运行" : "未启动正式运行;没有final/,只评历史,不列成跑过的候选"}。\n`,
|
||||
);
|
||||
index.push({
|
||||
candidate,
|
||||
ran: manifest.ran,
|
||||
directory: dir,
|
||||
finalVersion: finalCode?.content.version ?? null,
|
||||
});
|
||||
}
|
||||
jsonFile(join(output, "index.json"), index);
|
||||
console.log(`候选审阅包:${output}`);
|
||||
Reference in New Issue
Block a user