Files
InfoRSI/src/submissions/receive.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

85 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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");
}