852600df02
消融默认关,关掉时解释阶段一并跳过;选诊断实验用信息价值减成本。 eval/diagnosis/research.json 为第三块配置。vocab 字段说明的出口文字随提示词一起改,见下一次提交的 prompts/ 与同文件改动(本次含在内)。 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
85 lines
5.0 KiB
TypeScript
85 lines
5.0 KiB
TypeScript
import { checkExperiment, checkHunk, checkProtocol, type CodeHunk } from "../jev/index.ts";
|
||
import type { JevJudgment } from "../vocab/index.ts";
|
||
import { programProblems } from "./checks.ts";
|
||
import { protocolBody } from "./protocol.ts";
|
||
import type { Incoming, ProtocolBody, Verdict } from "./types.ts";
|
||
|
||
// 判一份提交收不收(任务书 10 第二部分第 4、5 步):先程序检查,有一项不过就退回、不问 Jev;
|
||
// 全过了再问 Jev,几问全问完再决定,有一问判"是"就退回。收不收只在这一处判(结构.md 第二部分"几条边界")。
|
||
// Jev 调不通、回答读不懂时 jev 报错,这里不接住:那不是模型交得不对,flow 按内部错误停下。
|
||
|
||
/** 判一份提交。回应、统一先拼好冻结协议主体,程序检查、问 Jev、交回都用这同一份。 */
|
||
export async function receive(inc: Incoming): Promise<Verdict> {
|
||
const protocol =
|
||
inc.kind === "response"
|
||
? protocolBody({ kind: "response", content: inc.content, original: inc.known.original })
|
||
: inc.kind === "unification"
|
||
? protocolBody({ kind: "unification", content: inc.content })
|
||
: null;
|
||
const problems = programProblems(inc, protocol);
|
||
if (problems.length > 0) return { accepted: false, reason: ["这份提交没有收下,要改的地方:", ...problems.map((p) => `- ${p}`)].join("\n"), jev: null };
|
||
const asked = await askJev(inc, protocol);
|
||
if (asked === null) return { accepted: true, jev: null, protocol };
|
||
if (asked.flagged.length > 0) {
|
||
return { accepted: false, reason: ["这份提交没有收下,Jev 判出下面几处有问题:", ...asked.flagged].join("\n\n"), jev: asked.judgments };
|
||
}
|
||
return { accepted: true, jev: asked.judgments, protocol };
|
||
}
|
||
|
||
/**
|
||
* 问 Jev(方法.md 4.3 ⑥⑨、诊 4):回应、统一对拼好的协议问冻结条款三问;实现、修复(含诊断程序)每个差异块问代码改动五问,顺序发。
|
||
* 诊断解释与实验(诊 1)对每个实验问冻结条款三问(改动了评测、自相矛盾、太含糊,用诊断的变体问法),顺序发。
|
||
* 没有差异块的改动(二进制、只改可执行位、空文件增删)Jev 看不到内容,不问;一块都没有就等于没问,交回 null。
|
||
* 消融实现不问:冻结协议里没有登记"关掉以后"的随机性和停止条件,五问没有对照(照参考项目)。
|
||
* flagged 是退回原因里每一处的文字:只列判"是"的几问,问题名用 jev 的英文名(用户 2026-10-03 定);判"是"只看 jev 交回的 yes。
|
||
*/
|
||
async function askJev(inc: Incoming, protocol: ProtocolBody | null): Promise<{ judgments: JevJudgment[]; flagged: string[] } | null> {
|
||
if (inc.kind === "response" || inc.kind === "unification") {
|
||
const c = await checkProtocol(inc.jevModel, protocol!);
|
||
return { judgments: c.judgments, flagged: c.flagged ? [`- 冻结协议:${flaggedText(c.judgments)}`] : [] };
|
||
}
|
||
if (inc.kind === "diagnosisProposal") {
|
||
const judgments: JevJudgment[] = [];
|
||
const flagged: string[] = [];
|
||
for (const [i, experiment] of inc.content.experiments.entries()) {
|
||
const c = await checkExperiment(inc.jevModel, experiment);
|
||
judgments.push(...c.judgments);
|
||
if (c.flagged) flagged.push(`- 第 ${i + 1} 个诊断实验(${experiment.name}):${flaggedText(c.judgments)}`);
|
||
}
|
||
return { judgments, flagged };
|
||
}
|
||
if (inc.kind !== "implementation" && inc.kind !== "repair" && inc.kind !== "diagnosisImplementation" && inc.kind !== "diagnosisRepair") {
|
||
return null;
|
||
}
|
||
// 走到这里程序检查已过,代码一定存成了版本。
|
||
const code = inc.known.code as Extract<typeof inc.known.code, { saved: true }>;
|
||
if (code.hunks.length === 0) return null;
|
||
const judgments: JevJudgment[] = [];
|
||
const flagged: string[] = [];
|
||
const nth = new Map<string, number>();
|
||
for (const hunk of code.hunks) {
|
||
nth.set(hunk.path, (nth.get(hunk.path) ?? 0) + 1);
|
||
const c = await checkHunk(inc.jevModel, hunk, code.protocol);
|
||
judgments.push(...c.judgments);
|
||
if (c.flagged) flagged.push(hunkText(hunk, nth.get(hunk.path)!, c.judgments));
|
||
}
|
||
return { judgments, flagged };
|
||
}
|
||
|
||
/** 判"是"的那几问:问题名、概率、阈值。 */
|
||
function flaggedText(judgments: readonly JevJudgment[]): string {
|
||
return judgments
|
||
.filter((j) => j.yes)
|
||
.map((j) => `${j.question} 概率 ${j.probability}(阈值 ${j.threshold})`)
|
||
.join(";");
|
||
}
|
||
|
||
const CHANGE = { added: "新增的文件", deleted: "删掉的文件", modified: "改动的文件" } as const;
|
||
|
||
/** 一个差异块的退回文字:哪个文件的第几块、判"是"的几问,附差异原文。原文里有 ``` 时围栏加长,免得提前收尾。 */
|
||
function hunkText(hunk: CodeHunk, n: number, judgments: readonly JevJudgment[]): string {
|
||
const longest = Math.max(0, ...(hunk.text.match(/`+/g) ?? []).map((s) => s.length));
|
||
const fence = "`".repeat(Math.max(3, longest + 1));
|
||
return [`- ${hunk.path}(${CHANGE[hunk.change]})的第 ${n} 块:${flaggedText(judgments)}`, "", `${fence}diff`, hunk.text, fence].join("\n");
|
||
}
|