09c44031a0
- 新增 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>
206 lines
11 KiB
TypeScript
206 lines
11 KiB
TypeScript
import type { ChecklistOf } from "../vocab/index.ts";
|
||
import { Draft, factorLines, KIND_TEXT, offText, registeredMetrics, taskPoints } from "./blocks.ts";
|
||
import { fenced, json } from "./format.ts";
|
||
import { unassignedChanges } from "./locations.ts";
|
||
import { clauseKey, factorKey, splitCell, type FrozenProtocol, type LocationTable } from "./shapes.ts";
|
||
|
||
// 实验员、核验员的 5 种任务(方法.md 4.3 ⑨ ⑯):只看分给他的那个候选或那一格——冻结协议、起点代码、
|
||
// 要实现或核验的东西。不给信念本(用户 2026-10-03 决定 3)、不给任何运行成绩、不给别的候选。
|
||
// 排法照参考项目 assignedBlocks、ablationBlocks:任务与本轮 → 代码 → 本任务要处理的东西(核验把没有归属的改动放最前)。
|
||
|
||
type Items = { candidate: string; clauses: string[]; factors: string[]; safeguards: string[] };
|
||
|
||
/** 每个函数最先调用:一级分组"分给你的材料",冻结协议进查询,交回协议和对号清单的 FrozenItems。 */
|
||
function frozen(d: Draft, candidate: string): { p: FrozenProtocol; items: Items } {
|
||
d.group("分给你的材料", "下面是分给你的这一个对象的全部材料。");
|
||
const p = d.board.protocol(candidate);
|
||
d.record(candidate, `候选 ${candidate} 的冻结协议`, p);
|
||
return { p, items: { candidate, clauses: p.clauses.map((_, i) => clauseKey(i)), factors: p.factors.map((_, i) => factorKey(i)), safeguards: p.safeguards } };
|
||
}
|
||
|
||
function taskSection(d: Draft, role: string, what: string): void {
|
||
d.section("任务与本轮", [
|
||
`你是${role} ${d.req.actor},现在是第 ${d.round} 轮(阶段编号 ${d.req.stageId})。本次任务:${KIND_TEXT[d.req.kind]},${what}。`,
|
||
"",
|
||
...taskPoints(d),
|
||
]);
|
||
}
|
||
|
||
/** 协议要采集的指标:新登记的全文,引用的取原登记(方法.md 第五部分"引用别人登记过的指标时,沿用原登记的选法")。 */
|
||
function metricSection(d: Draft, p: FrozenProtocol): void {
|
||
const registered = registeredMetrics(d.board);
|
||
const all = [...p.metrics.defined, ...p.metrics.reused.map((id) => registered.find((x) => x.id === id)!)];
|
||
d.section("要实现的指标定义", [
|
||
all.length === 0 ? "(这份协议没有要实现的假设专用指标)" : json(all),
|
||
"",
|
||
"每个指标都由候选代码在正式运行时算出、写进结果文件;测不到的写 null,不写 0。",
|
||
]);
|
||
}
|
||
|
||
function locationTableSection(d: Draft, p: FrozenProtocol): void {
|
||
d.section("要交的因子位置表", [
|
||
"每个因子、每条保障各在哪几行;同一行既属于因子又属于保障时两边都写;不属于任何因子或保障的改动写进 unassigned 并说一句为什么。",
|
||
"",
|
||
...factorLines(p),
|
||
`保障:${p.safeguards.length === 0 ? "没有(保障位置表交空数组)" : p.safeguards.join("、")}`,
|
||
]);
|
||
}
|
||
|
||
function codeLines(d: Draft): string[] {
|
||
return [...d.readableLines(), "读这些目录用 read_source(核验员)或 shell(实验员)。"];
|
||
}
|
||
|
||
/** ⑨ 实现:冻结协议、指标定义、要交的位置表、起点代码(本批基线)。 */
|
||
export function implementation(d: Draft): ChecklistOf<"implementation"> {
|
||
const candidate = d.req.object!;
|
||
const { p, items } = frozen(d, candidate);
|
||
taskSection(d, "实验员", `候选 ${candidate}`);
|
||
d.read(p.baseline, "起点代码(本批基线)");
|
||
d.section("基线代码", [...codeLines(d), "你的工作目录是起点代码的副本,改动都落在工作目录里。"]);
|
||
d.section("本任务要处理的东西", [`### 候选 ${candidate} 的冻结协议`, "", json(p)]);
|
||
metricSection(d, p);
|
||
locationTableSection(d, p);
|
||
return { kind: "implementation", ...items };
|
||
}
|
||
|
||
/** ⑨ 修复:实现的全部材料,加退回意见(最近一次核验里没落实、判越界的几项)、上一次的位置表、上一次提交相对起点的改动。 */
|
||
export function repair(d: Draft): ChecklistOf<"repair"> {
|
||
const candidate = d.req.object!;
|
||
const { p, items } = frozen(d, candidate);
|
||
taskSection(d, "实验员", `候选 ${candidate}`);
|
||
d.read(p.baseline, "起点代码(本批基线)");
|
||
d.read(candidate, "你上一次提交的代码");
|
||
d.section("基线代码", [...codeLines(d), "你的工作目录是上一次提交的代码的副本。"]);
|
||
const v = d.board.published("verification").filter((s) => s.target === candidate).at(-1)!.content;
|
||
d.section("本任务要处理的东西", [
|
||
"### 退回意见",
|
||
"",
|
||
...v.clauses.filter((x) => !x.found).map((x) => `- 条款 ${x.clause} 没落实:${x.where}`),
|
||
...v.factors.filter((x) => !x.found).map((x) => `- 因子 ${x.factor} 没落实:${x.where}`),
|
||
...v.safeguards.filter((x) => !x.found).map((x) => `- 保障 ${x.safeguard} 没落实:${x.where}`),
|
||
...v.unassigned.filter((x) => x.outOfScope).map((x) => `- ${x.location} 判为越界:${x.reason}`),
|
||
"",
|
||
`核验员的说明:${v.body}`,
|
||
"",
|
||
"### 上一次交的位置表",
|
||
"",
|
||
json(d.board.code(candidate).locations),
|
||
"",
|
||
"### 上一次提交相对起点代码的改动",
|
||
"",
|
||
fenced(d.req.changes!.diff, "diff"),
|
||
"",
|
||
`### 候选 ${candidate} 的冻结协议`,
|
||
"",
|
||
json(p),
|
||
]);
|
||
metricSection(d, p);
|
||
locationTableSection(d, p);
|
||
return { kind: "repair", ...items };
|
||
}
|
||
|
||
/**
|
||
* ⑨ 核验:没归到任何因子或保障的改动排第一(程序按位置表现算);冻结协议、位置表、指标定义、改动全文。
|
||
* 因子与保障同一行的地方只作提醒。能走到核验的实现已经过了 Jev,Jev 的判断不给核验员看(Jev 是判别条件,不是提示)。
|
||
*/
|
||
export function verification(d: Draft): ChecklistOf<"verification"> {
|
||
const candidate = d.req.object!;
|
||
const { p, items } = frozen(d, candidate);
|
||
const table = d.board.code(candidate).locations as LocationTable;
|
||
const found = unassignedChanges(d.req.changes!, table);
|
||
d.section("没归到任何因子或保障的改动", [
|
||
"程序按实验员交的位置表,把一行都没落进任何因子或保障的改动列在下面,逐条判断是否越界(location 照这里抄):",
|
||
...(found.unassigned.length === 0 ? ["(没有)"] : found.unassigned.map((u) => `- ${u.location}(${u.note})`)),
|
||
"",
|
||
"实验员自己对不属于任何因子的改动写的说明(只是说明,不算归属):",
|
||
...(table.unassigned.length === 0 ? ["(没有)"] : table.unassigned.map((u) => `- ${u.location}:${u.note}`)),
|
||
"",
|
||
"同一行既属于因子又属于保障的地方(只是提醒,不判越界;在说明里写一句):",
|
||
...(found.overlaps.length === 0 ? ["(没有)"] : found.overlaps.map((o) => `- ${o.location}:因子 ${o.factor}、保障 ${o.safeguard}`)),
|
||
]);
|
||
taskSection(d, "核验员", `候选 ${candidate}`);
|
||
d.read(p.baseline, "起点代码(本批基线)");
|
||
d.read(candidate, "要核验的候选代码");
|
||
d.section("基线代码", codeLines(d));
|
||
const impl = d.board.implementation(candidate)!;
|
||
d.section("本任务要处理的东西", [
|
||
`### 候选 ${candidate} 的冻结协议`,
|
||
"",
|
||
json(p),
|
||
"",
|
||
"### 实验员交的位置表",
|
||
"",
|
||
json(table),
|
||
"",
|
||
"### 实验员的实现说明",
|
||
"",
|
||
impl.content.body,
|
||
"",
|
||
"### 改动全文(候选相对起点代码,每段前后各 3 行上下文)",
|
||
"",
|
||
fenced(d.req.changes!.diff, "diff"),
|
||
]);
|
||
metricSection(d, p);
|
||
return { kind: "verification", unassigned: found.unassigned.map((u) => u.location), ...items };
|
||
}
|
||
|
||
/**
|
||
* 消融两种任务共用(方法.md 4.3 ⑯):任务与本轮、完整代码与本批基线、这一格(关哪个因子、换成什么)。
|
||
* 交回本任务要处理的东西的公共部分:因子清单、完整代码的位置表、冻结协议。
|
||
*/
|
||
function ablation(d: Draft, role: string, codeNote: string[]): { cell: string; key: string; factors: string[]; lines: string[] } {
|
||
const cell = d.req.object!;
|
||
const { candidate, key } = splitCell(cell);
|
||
const { p, items } = frozen(d, candidate);
|
||
taskSection(d, role, `消融格 ${cell}(候选 ${candidate} 关掉 ${key})`);
|
||
d.read(candidate, "完整代码");
|
||
d.read(p.baseline, "本批基线(因子没写关掉时换成什么,就回到它在这件事上的做法)");
|
||
if (d.req.kind === "ablationVerification") d.read(cell, "要核验的这一格的代码");
|
||
d.section("完整代码(消融的起点)", [...codeLines(d), ...codeNote]);
|
||
const f = p.factors[items.factors.indexOf(key)]!;
|
||
d.section("这一格", [
|
||
`格 ${cell}:关掉 ${key} ${f.name}。关掉时换成:${offText(f)}。`,
|
||
`其余因子、配套设定、全部保障(${p.safeguards.length === 0 ? "没有保障" : p.safeguards.join("、")})都照完整代码保留。`,
|
||
]);
|
||
const lines = ["### 因子清单", "", ...factorLines(p), "", "### 完整代码那次实现交的位置表", "", json(d.board.code(candidate).locations), "", "### 冻结协议", "", json(p)];
|
||
return { cell, key, factors: items.factors, lines };
|
||
}
|
||
|
||
/**
|
||
* ⑯ 消融实现:从完整代码出发只关指定的因子。核验不通过重做时(这一格已有公开的消融核验)另放退回意见:
|
||
* 最近一次核验里关错了的因子和核验员写的依据,写法同修复的退回意见。
|
||
*/
|
||
export function ablationImplementation(d: Draft): ChecklistOf<"ablationImplementation"> {
|
||
const a = ablation(d, "实验员", ["你的工作目录是完整代码的副本,改动都落在工作目录里。"]);
|
||
const verified = d.board.published("ablationVerification").filter((s) => s.target === a.cell).at(-1);
|
||
const opinion: string[] = [];
|
||
if (verified !== undefined) {
|
||
const off = new Set([a.key, ...lastAblation(d, a.cell).alsoOff]);
|
||
const wrong = verified.content.factors.filter((x) => x.off !== off.has(x.factor));
|
||
const text = (x: (typeof wrong)[number]) => `- 因子 ${x.factor} 应当${off.has(x.factor) ? "关着" : "照留"},核验员看到的是${x.off ? "关着" : "照留"}:${x.where}`;
|
||
opinion.push("### 退回意见", "", "上一次交的这一格没通过消融核验,下面是关错了的因子:", ...wrong.map(text), "");
|
||
}
|
||
d.section("本任务要处理的东西", [...opinion, ...a.lines]);
|
||
return { kind: "ablationImplementation", cell: a.cell, off: a.key, factors: a.factors };
|
||
}
|
||
|
||
/** 这一格最近一次公开的消融实现提交。 */
|
||
const lastAblation = (d: Draft, cell: string) => d.board.published("ablationImplementation").filter((s) => s.target === cell).at(-1)!.content;
|
||
|
||
/** ⑯ 消融核验:只查是不是只关了指定的因子(加实验员报的一起关的因子)。不算没有归属的改动。 */
|
||
export function ablationVerification(d: Draft): ChecklistOf<"ablationVerification"> {
|
||
const a = ablation(d, "核验员", []);
|
||
const also = lastAblation(d, a.cell).alsoOff;
|
||
d.section("这一格实际要关的因子", [
|
||
[a.key, ...also].join("、") + (also.length === 0 ? "(只关指定的因子)" : "(指定的因子加实验员报的一起关的因子)"),
|
||
]);
|
||
d.section("本任务要处理的东西", [
|
||
...a.lines,
|
||
"",
|
||
"### 改动全文(这一格的代码相对完整代码,每段前后各 3 行上下文)",
|
||
"",
|
||
fenced(d.req.changes!.diff, "diff"),
|
||
]);
|
||
return { kind: "ablationVerification", cell: a.cell, factors: a.factors };
|
||
}
|