852600df02
消融默认关,关掉时解释阶段一并跳过;选诊断实验用信息价值减成本。 eval/diagnosis/research.json 为第三块配置。vocab 字段说明的出口文字随提示词一起改,见下一次提交的 prompts/ 与同文件改动(本次含在内)。 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
776 lines
29 KiB
TypeScript
776 lines
29 KiB
TypeScript
import { Type, type Static, type TSchema } from "typebox";
|
||
import { Id } from "./basics.ts";
|
||
import type { SubmissionKind } from "./roster.ts";
|
||
import { HypothesisMetric } from "./runs.ts";
|
||
|
||
/**
|
||
* 每种提交的字段定义(方法.md 第五部分)。同一份定义同时是类型、收件时的格式检查、
|
||
* 发给模型的提交工具参数,所以字段说明写给模型看,每个字段都写明出口。
|
||
* 这里只管单个字段长什么样;跨字段的规则(q₁ < q₅ < q₉ 严格递增、因子数上限、覆盖是否齐全等)
|
||
* 在 submissions 模块。
|
||
* 程序分配的编号(候选、挑刺、入口编号)不让模型填;因子、实现条款的编号就是它在清单里的位置。
|
||
*/
|
||
|
||
/** 文字字段:不能为空,也不能只有空白。 */
|
||
const TEXT = { pattern: "\\S" };
|
||
/** 不认识的字段一律不收。 */
|
||
const CLOSED = { additionalProperties: false } as const;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 共用字段
|
||
// ---------------------------------------------------------------------------
|
||
|
||
/** 三个数:一个分数的事前判断(方法.md 第二部分"范围")。 */
|
||
export const Range = Type.Object(
|
||
{
|
||
q1: Type.Number({ description: "有一成可能低于这个数" }),
|
||
q5: Type.Number({ description: "有一半可能低于这个数" }),
|
||
q9: Type.Number({ description: "有九成可能低于这个数" }),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description:
|
||
"三个数,按分数原值写,不管越大越好还是越小越好。必须严格递增 q1 < q5 < q9,认为几乎不变就写一个很窄的范围。" +
|
||
"没有\"不知道\"这个选项:拿不准就把 q1 和 q9 拉开",
|
||
},
|
||
);
|
||
export type Range = Static<typeof Range>;
|
||
|
||
const FactorKey = Type.String({
|
||
pattern: "^p[1-9][0-9]*$",
|
||
description: "因子编号:它在冻结协议因子清单里的位置,第 1 个是 p1",
|
||
});
|
||
|
||
const SafeguardName = Type.String({
|
||
pattern: "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$",
|
||
description:
|
||
"保障短名:字母、数字和 ._-。不能叫 main,也不能写成 p1、p2 这种因子编号的样子," +
|
||
"因为答案路径里 main、因子编号和保障短名放在一起;位置表也按它对号",
|
||
});
|
||
|
||
const ClauseKey = Type.String({
|
||
pattern: "^c[1-9][0-9]*$",
|
||
description: "实现条款编号:它在冻结协议实现条款里的位置,第 1 条是 c1",
|
||
});
|
||
|
||
const CodeLocation = Type.String({
|
||
pattern: "^[^:\\s]+(:[1-9][0-9]*(-[1-9][0-9]*)?)?$",
|
||
description: "代码位置:\"文件\"、\"文件:行号\"或\"文件:起-止\",行号以本次提交代码为准。一个值只写一个连续范围,不带括号标签;多处位置拆开写",
|
||
});
|
||
|
||
const CONCERNS = Type.String({
|
||
...TEXT,
|
||
description:
|
||
"照冻结原文实现、但你认为会出问题的地方,尤其是某条保障会挡掉或改变什么。" +
|
||
"它会转给研究者,不阻止运行,也不改动协议。没有就写\"无\"",
|
||
});
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 第零轮:入口、讨论、志愿(方法.md 4.2)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const Entry = Type.Object(
|
||
{
|
||
name: Type.String({
|
||
...TEXT,
|
||
description: "名称:离开这份清单单独看也读得懂",
|
||
}),
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"Markdown:从哪里开始看(先读哪段代码、先问哪个问题、先质疑哪个设定)、为什么值得有人去走。" +
|
||
"只写起点,不写\"应该改成什么、能到多少分\"",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
const ENTRIES = Type.Array(Entry, {
|
||
minItems: 2,
|
||
maxItems: 3,
|
||
description: "2–3 个入口,彼此尽量不重叠;想不出第三个就交两个。编号由程序按顺序分配",
|
||
});
|
||
|
||
export const EntrySubmission = Type.Object(
|
||
{
|
||
entries: ENTRIES,
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const DiscussionSubmission = Type.Object(
|
||
{
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"讨论正文,Markdown。目标是分工,不是达成共识:哪些入口其实是同一条路," +
|
||
"哪条路没人站但值得走,你自己想走哪条",
|
||
}),
|
||
entries: Type.Optional({
|
||
...ENTRIES,
|
||
description: "可选:整份替换你自己的入口清单(2–3 个)。不换就不交这个字段",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const ClaimSubmission = Type.Object(
|
||
{
|
||
choices: Type.Array(Id, {
|
||
minItems: 1,
|
||
description:
|
||
"志愿:按你想走的先后排入口编号,照材料里列的写,可以排别人的入口;至少排材料里写明的个数",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 提案(方法.md 4.3 ②、第五部分"提案")
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const Factor = Type.Object(
|
||
{
|
||
name: Type.String({
|
||
...TEXT,
|
||
description: "名称:离开这份提案也读得懂",
|
||
}),
|
||
method: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"做法:改什么、怎么改。配套设定(离开这个因子就没有意义的设定值)写在这里,跟着它一起开、一起关",
|
||
}),
|
||
keySettings: Type.String({
|
||
...TEXT,
|
||
description: "关键设定:决定这个因子效果的设定值,例如\"统计窗口 1000 次查找、每次最多删四分之一\";没有写\"无\"",
|
||
}),
|
||
offBehavior: Type.Optional(
|
||
Type.String({
|
||
...TEXT,
|
||
description: "关掉这个因子时换成什么。省略就回到基线在这件事上的做法",
|
||
}),
|
||
),
|
||
continues: Type.Union([Id, Type.Null()], {
|
||
description:
|
||
"延续信念本里的哪个因子:写它的因子编号。只用于同一个想法的新版本(换了设定、换了基线);" +
|
||
"受它启发想出来的新想法不算延续。新因子写 null",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
const FACTORS = Type.Array(Factor, {
|
||
minItems: 1,
|
||
description:
|
||
"因子清单:每个因子是单独放到基线上也说得通的改动,编号就是位置(第 1 个是 p1)。" +
|
||
"只有一个因子就写一个;拿不准一处改动算因子还是保障,就算因子。" +
|
||
"超过因子数上限时把多出来的留到下一轮,不要几个捆成一个",
|
||
});
|
||
|
||
const SAFEGUARDS = Type.Array(SafeguardName, {
|
||
description:
|
||
"保障清单,每条一个短名。保障在任何一格里都不改变评测打出来的分数,只在评测本来不收的情形下动手," +
|
||
"动手时只修到刚好合法、退回基线做法或直接报错;做不到的、拿不准的都是因子。没有保障交空数组",
|
||
});
|
||
|
||
const METRICS = Type.Object(
|
||
{
|
||
defined: Type.Array(HypothesisMetric, {
|
||
description: "新登记的假设专用指标,编号只写短名;没有就交空数组",
|
||
}),
|
||
reused: Type.Array(Id, {
|
||
description:
|
||
"引用已登记的假设专用指标,照材料里已登记指标清单的全名(\"候选编号.短名\")写;没有就交空数组。" +
|
||
"要测的量清单里已经有,就引用它,不换个名字重新登记:两个名字测同一个东西,会被当成两份独立的证据",
|
||
}),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description:
|
||
"指标登记:这个候选要采集哪些假设专用指标。最终指标和常规辅助指标程序每次都会采集,不用在这里写。" +
|
||
"假设专用指标由候选代码在运行当中算出,候选代码拿不到基线的成绩,\"比基线好多少\"这类量测不到。" +
|
||
"协议在某种情形下会让某个指标写 null(例如某条分支没走到、某个因子被关掉),就别给它选 invalidateRun,否则那次正式运行白跑",
|
||
},
|
||
);
|
||
|
||
const PROPOSAL_BODY = Type.String({
|
||
...TEXT,
|
||
description:
|
||
"提案正文,Markdown,带小标题:每个因子为什么可能有效;" +
|
||
"每条保障做什么、属于拦 / 补 / 改哪一种、自检时怎么想的;" +
|
||
"协议(不许改什么、随机性怎么处理、何时停、什么样的运行不算数);因子之间的关系。" +
|
||
"某方面不适用写\"不适用:原因\"。协议里不要求实验员按正式规模运行程序来核对什么,正式规模只由程序跑。" +
|
||
"不写自己估的分数或提升量;引用已测到的分数要写明出自哪次运行;" +
|
||
"文献和别人报告的数值只当起点,说明与本任务的区别;从第 2 轮起说明哪些新的观测影响了这条提案",
|
||
});
|
||
|
||
export const ProposalSubmission = Type.Object(
|
||
{
|
||
factors: FACTORS,
|
||
safeguards: SAFEGUARDS,
|
||
metrics: METRICS,
|
||
authorEstimate: Range,
|
||
body: PROPOSAL_BODY,
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description:
|
||
"一条提案。authorEstimate 是你自己估的这个改法跑出来的最终指标,交上来就封存," +
|
||
"到本轮结束前不给任何人看。交不出合格提案时不要凑,在回复里写清卡在哪里",
|
||
},
|
||
);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 两次预测、挑刺(方法.md 4.3 ④⑤⑦)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
/** 第一次、第二次预测用同一个定义:对一个候选的最终指标给三个数。 */
|
||
export const PredictionSubmission = Type.Object(
|
||
{
|
||
range: Range,
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"理由,Markdown:参照了什么,这一个和参照差在哪、所以往哪边挪;" +
|
||
"同一阶段你给别的候选的数和这一个相同或不同,差别出在机制的哪里",
|
||
}),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description: "对这个候选跑出来的最终指标给三个数",
|
||
},
|
||
);
|
||
|
||
export const CritiqueSubmission = Type.Object(
|
||
{
|
||
target: Type.String({
|
||
pattern: "^(whole|p[1-9][0-9]*)$",
|
||
description: "针对谁:整条提案写 whole,针对某个因子写它的编号(p1、p2……)",
|
||
}),
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"挑刺内容,Markdown。每条意见写清是什么、在哪(能对照代码的写出位置)、不处理会怎样," +
|
||
"以及作者给出什么就能解决(不替作者选取值)。" +
|
||
"确实没找到问题,写查了什么、为什么认为没有",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 回应与统一(方法.md 4.3 ⑥)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const REPLIES = Type.Array(
|
||
Type.Object(
|
||
{
|
||
critique: Type.String({
|
||
...Id,
|
||
description: "挑刺编号,照材料里列的写",
|
||
}),
|
||
reply: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"先用一句复述这份挑刺说的是什么(照原意,不答弱化的版本),再给采纳、部分采纳或不采纳。" +
|
||
"采纳的说出改在改动的哪一项、哪一条条款,只在答复里表态等于没改;不采纳的先摆证据(代码位置、运行编号、协议原文)再讲理由;" +
|
||
"部分采纳的说清另一部分为什么不改、还剩什么局限。一份挑刺里有几条意见,在这一条里逐条答",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "材料\"本任务要答复的挑刺\"里列出的每一份挑刺各答复一条;没有挑刺交空数组",
|
||
},
|
||
);
|
||
|
||
const CLAUSES = Type.Array(
|
||
Type.String({
|
||
...TEXT,
|
||
description:
|
||
"一条实现条款:实验员要做的一件事,写到不用猜就能实现。开头写位置:\"文件\"、\"文件:行号\"或\"文件:函数名\"," +
|
||
"只写一个行号或一个函数名、不写范围,文件和函数要在基线代码里真实存在",
|
||
}),
|
||
{
|
||
minItems: 1,
|
||
description:
|
||
"实现条款,编号就是位置(第 1 条是 c1)。实验员照它实现,核验员逐条对号。" +
|
||
"条款之间不矛盾;不改任务自带的评分和校验程序,不改最终指标的算法;不让实验员按正式规模运行程序来核对什么",
|
||
},
|
||
);
|
||
|
||
export const ResponseSubmission = Type.Object(
|
||
{
|
||
replies: REPLIES,
|
||
changes: Type.Object(
|
||
{
|
||
factors: Type.Optional(FACTORS),
|
||
safeguards: Type.Optional(SAFEGUARDS),
|
||
metrics: Type.Optional(METRICS),
|
||
body: Type.Optional(PROPOSAL_BODY),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description:
|
||
"改动了的部分:写上的一项整项替换原提案的对应部分,没写的沿用原提案。" +
|
||
"什么都没改就交空对象。作者自评不能改",
|
||
},
|
||
),
|
||
clauses: CLAUSES,
|
||
body: Type.String({
|
||
...TEXT,
|
||
description: "答复正文,Markdown:逐条答复之外要补充的话。没有挑刺、也没有要补充的,写\"无\"",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const UnificationSubmission = Type.Object(
|
||
{
|
||
factors: FACTORS,
|
||
safeguards: SAFEGUARDS,
|
||
metrics: METRICS,
|
||
body: PROPOSAL_BODY,
|
||
replies: REPLIES,
|
||
clauses: CLAUSES,
|
||
sources: Type.Array(
|
||
Type.Object(
|
||
{
|
||
proposal: Type.String({
|
||
...Id,
|
||
description: "被合并的原提案编号,照材料里列的写",
|
||
}),
|
||
coverage: Type.String({
|
||
...TEXT,
|
||
description: "这份原提案在统一后的协议里哪里体现;没采纳的部分写明为什么",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
minItems: 1,
|
||
description: "逐条写明每份原提案在哪里体现",
|
||
},
|
||
),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description:
|
||
"几条提案合成的候选,由你写成一份完整的冻结协议。只能用原提案和挑刺里有的改动,不能另加新改动",
|
||
},
|
||
);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 实现、修复、核验(方法.md 4.3 ⑨)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const LOCATIONS = Type.Array(CodeLocation, { minItems: 1 });
|
||
|
||
/** 实现和修复用同一个定义。代码本身由程序从实验员的工作目录冻结,不作为字段交。 */
|
||
export const ImplementationSubmission = Type.Object(
|
||
{
|
||
factorLocations: Type.Array(
|
||
Type.Object(
|
||
{
|
||
factor: FactorKey,
|
||
locations: LOCATIONS,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description:
|
||
"因子位置表:冻结协议里每个因子一项,列出本次代码中它实际所在的全部位置,不只列这次修复的部分。一处代码服务两个因子,两边都写",
|
||
},
|
||
),
|
||
safeguardLocations: Type.Array(
|
||
Type.Object(
|
||
{
|
||
safeguard: SafeguardName,
|
||
locations: LOCATIONS,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description:
|
||
"保障位置表:每条保障一项,短名照冻结清单写,位置以本次代码为准。同一行既属于因子又属于保障时,两边都写。冻结协议没有保障就交空数组",
|
||
},
|
||
),
|
||
unassigned: Type.Array(
|
||
Type.Object(
|
||
{
|
||
location: CodeLocation,
|
||
note: Type.String({
|
||
...TEXT,
|
||
description: "为什么不属于任何因子或保障,一句说明",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "不属于任何因子或保障的改动,按本次代码相对本批基线的完整差异列出,并说明服务哪项要求;没有就交空数组",
|
||
},
|
||
),
|
||
concerns: CONCERNS,
|
||
body: Type.String({
|
||
...TEXT,
|
||
description: "实现说明,Markdown:位置表之外需要说明的事。修复时逐条回应退回意见:改在哪里,或以协议原文和代码位置说明为什么不改。协议要求自行求解核数而未执行的,说明数值留给正式实验核对,不声称已经验证。没有要补充的就写\"无\"",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
const FOUND = Type.Boolean({
|
||
description: "找到代码且实际行为符合该项要求写 true;找不到、找到但不一致或材料不足以核清,写 false(记为没落实)",
|
||
});
|
||
|
||
const WHERE = Type.String({
|
||
...TEXT,
|
||
description: "代码位置和足以复核的依据,对应冻结要求。没落实时区分具体偏差与核不了:写明看过哪里、哪里不符或还缺什么,不把猜测写成事实",
|
||
});
|
||
|
||
export const VerificationSubmission = Type.Object(
|
||
{
|
||
clauses: Type.Array(
|
||
Type.Object(
|
||
{
|
||
clause: ClauseKey,
|
||
found: FOUND,
|
||
where: WHERE,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "每条实现条款一项",
|
||
},
|
||
),
|
||
factors: Type.Array(
|
||
Type.Object(
|
||
{
|
||
factor: FactorKey,
|
||
found: FOUND,
|
||
where: WHERE,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "每个因子一项",
|
||
},
|
||
),
|
||
safeguards: Type.Array(
|
||
Type.Object(
|
||
{
|
||
safeguard: SafeguardName,
|
||
found: FOUND,
|
||
where: WHERE,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "每条保障一项;冻结协议没有保障就交空数组",
|
||
},
|
||
),
|
||
unassigned: Type.Array(
|
||
Type.Object(
|
||
{
|
||
location: Type.String({
|
||
...CodeLocation,
|
||
description: "材料列出的改动块位置,逐字照抄位置本身,不带展示用的括号标签,不合并不同改动块",
|
||
}),
|
||
outOfScope: Type.Boolean({
|
||
description: "超出冻结协议、改了最终指标的测量或校验、未按登记定义采集或用占位数掩盖缺测,写 true;落实冻结要求所需的辅助代码写 false",
|
||
}),
|
||
reason: Type.String({
|
||
...TEXT,
|
||
description: "指出该块代码及对应的冻结要求,说明它为什么必要或哪里超出要求",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "材料里列出的没有归属的改动,逐条判断是否越界;材料说没有就交空数组",
|
||
},
|
||
),
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"说明,Markdown:逐项结果之外需要说明的事。材料里列出的同一行既属于因子又属于保障的地方,在这里各写一句提醒(只是提醒,不判越界)。" +
|
||
"没有要补充的就写\"无\"",
|
||
}),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description: "只交逐项结果,通过与否由程序推出:任何一项没落实或判为越界,就退回实验员修复",
|
||
},
|
||
);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 诊断:解释与实验、预测、实现、核验(方法.md 4.3 诊 1–诊 4、第五部分"诊断"三行)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const DiagnosisExplanation = Type.Object(
|
||
{
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"Markdown:为什么卡在这里,剩下的空间在哪,什么样的实测会推翻它(写不出推翻它的实测,说明这条解释还不能被检验,先改具体再交)。" +
|
||
"诊断问的是剩下的空间在哪,不是上一步的功劳怎么分。没有具体判断就直说,写明查了什么、为什么拿不准",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
const DiagnosisExperiment = Type.Object(
|
||
{
|
||
name: Type.String({
|
||
...TEXT,
|
||
description: "名称:离开这份清单单独看也读得懂",
|
||
}),
|
||
spot: Type.String({
|
||
...TEXT,
|
||
description: "动哪一处:在当前基线的哪一处代码或哪一步上动手,只写一处(文件、函数或步骤名),其余照基线保留;想测两处就拆成两个实验",
|
||
}),
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"Markdown:在这一处怎么动(换成明显更强的版本、换成另一种做法、拿掉,或放宽某个限制)、" +
|
||
"做完交出什么能判分的答案、几种可能的结果各排除哪几条解释(有分不开的也写明)。不写自己估的分数,分数在下一步交",
|
||
}),
|
||
metrics: Type.Array(HypothesisMetric, {
|
||
description:
|
||
"登记假设专用指标:这个实验的代码要额外记录的量,编号只写短名;没有就交空数组。" +
|
||
"诊断实验里的指标只能选 recordMissing(缺了只记缺失),选 invalidateRun 会被退回",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const DiagnosisProposalSubmission = Type.Object(
|
||
{
|
||
explanations: Type.Array(DiagnosisExplanation, {
|
||
minItems: 1,
|
||
description: "诊断解释清单,编号由程序分配;条数上限见材料。真有第二个看法再写第二条,各条之间要真的不同;没有具体判断,就写一条直说没有的",
|
||
}),
|
||
experiments: Type.Array(DiagnosisExperiment, {
|
||
minItems: 1,
|
||
description:
|
||
"诊断实验清单,个数上限见材料。好的实验是不同解释对它的预测差得远:大家都预测涨不了多少的实验,测了也不改变下一步。" +
|
||
"每个实验只动一处,用时要放得进分到的那份时间;想不出能把解释分开的实验,就交最能暴露你的解释错在哪的那个",
|
||
}),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description: "对当前基线的诊断:几条解释,和能把它们分开的几个实验。实验正文里不写自己估的分数",
|
||
},
|
||
);
|
||
|
||
export const DiagnosisPredictionSubmission = Type.Object(
|
||
{
|
||
predictions: Type.Array(
|
||
Type.Object(
|
||
{
|
||
explanation: Type.String({ ...Id, description: "你自己的诊断解释编号,照材料里列的写" }),
|
||
experiment: Type.String({ ...Id, description: "合并后的诊断实验编号,照材料里列的写,别人提的也要给" }),
|
||
range: Range,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description:
|
||
"你自己的每条诊断解释对每个合并后的实验各给三个数:按这条解释,做了这个实验,分数有一成、一半、九成可能低于多少。" +
|
||
"不多不少,每一对只写一次;按这条解释本身写,不往折中的范围靠;解释和这个实验没关系就按基线附近写并放宽;拿不准就把 q1 和 q9 拉开",
|
||
},
|
||
),
|
||
body: Type.String({
|
||
...TEXT,
|
||
description: "理由,Markdown:这些数是怎么来的,不同解释给的数差在哪里;几条解释给的数差不多,写明它们在这些实验上分不开",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
/** 诊断实现和修复用同一个定义。代码本身由程序从实验员的工作目录冻结,不作为字段交。 */
|
||
export const DiagnosisImplementationSubmission = Type.Object(
|
||
{
|
||
locations: Type.Array(
|
||
Type.Object(
|
||
{
|
||
experiment: Type.String({ ...Id, description: "诊断实验编号,照材料里列的写" }),
|
||
locations: LOCATIONS,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "位置表:选中的每个实验一项,列出本次代码中这个实验实际所在的全部位置,行号以本次提交代码为准",
|
||
},
|
||
),
|
||
concerns: CONCERNS,
|
||
body: Type.String({
|
||
...TEXT,
|
||
description: "实现说明,Markdown:位置表之外需要说明的事;实验原文没规定规模时,写你选了什么、为什么放得进分到的时间。修复时逐条回应核验意见:改在哪里,或以实验原文和代码位置说明为什么不改。没有要补充的就写\"无\"",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const DiagnosisVerificationSubmission = Type.Object(
|
||
{
|
||
experiments: Type.Array(
|
||
Type.Object(
|
||
{
|
||
experiment: Type.String({ ...Id, description: "诊断实验编号,照材料里列的写" }),
|
||
followed: Type.Boolean({
|
||
description: "照实验写的做法实现了写 true;没找到、做得不一样或材料不足以核清,写 false",
|
||
}),
|
||
nothingElse: Type.Boolean({
|
||
description: "没有动实验写的那一处以外的地方写 true;顺手改了别处(含顺手改进)写 false",
|
||
}),
|
||
where: WHERE,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "选中的每个实验一项,逐个判断,一个实验不通过不影响别的实验",
|
||
},
|
||
),
|
||
body: Type.String({
|
||
...TEXT,
|
||
description: "说明,Markdown:逐项结果之外需要说明的事。没有要补充的就写\"无\"",
|
||
}),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description: "只交逐个实验的结果,通过与否由程序推出:任何一项写 false 的实验退回实验员修复,用完修复次数仍不通过的实验从这次诊断里拿掉",
|
||
},
|
||
);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 解释、消融、收尾(方法.md 4.3 ⑭⑯⑱)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const Explanation = Type.Object(
|
||
{
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"Markdown:机制是什么、哪个因子在出力、什么情况下不成立、因子之间在效果上怎么互相依赖" +
|
||
"(例如\"没有 p2,p3 就没用\",当作预测交给消融检验)、结论覆盖哪些设定、没覆盖哪些。" +
|
||
"没有具体的机制判断就直说",
|
||
}),
|
||
cells: Type.Optional(
|
||
Type.Array(
|
||
Type.Object(
|
||
{
|
||
factor: FactorKey,
|
||
range: Range,
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description:
|
||
"每一格三个数:假如这条解释是对的,关掉这个因子后最终指标的范围。" +
|
||
"材料说要给每格的数时(开着消融),材料里列出的每一格都要有;" +
|
||
"没有具体的机制判断时,照实把范围写宽。材料说不给每格的数时(关掉了消融),不交这个字段",
|
||
},
|
||
),
|
||
),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const ExplanationSubmission = Type.Object(
|
||
{
|
||
explanations: Type.Array(Explanation, {
|
||
minItems: 1,
|
||
description: "一般交一条就够,真有第二个机制判断时再交第二条——比如你的主判断若错了最可能是哪种错法,答得出来就写成第二条,写明哪一格能把两条分开;条数上限见材料",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
export const AblationImplementationSubmission = Type.Object(
|
||
{
|
||
alsoOff: Type.Array(FactorKey, {
|
||
description:
|
||
"需要一起关的因子:只有关掉指定因子后代码真的跑不起来、必须连带关掉别的因子时才写。" +
|
||
"只关指定因子就交空数组",
|
||
}),
|
||
cannotRun: Type.Union([Type.Null(), Type.String(TEXT)], {
|
||
description:
|
||
"这一格跑不起来、也给不出一起关的方案时写原因,这一格不启动、不扣次数。跑得起来写 null",
|
||
}),
|
||
concerns: CONCERNS,
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description: "从完整代码出发,把指定的因子换回关掉时的做法,其余因子和全部保障照留",
|
||
},
|
||
);
|
||
|
||
export const AblationVerificationSubmission = Type.Object(
|
||
{
|
||
factors: Type.Array(
|
||
Type.Object(
|
||
{
|
||
factor: FactorKey,
|
||
off: Type.Boolean({
|
||
description: "这份代码里这个因子是关着的写 true,照完整版本保留写 false",
|
||
}),
|
||
where: Type.String({
|
||
...TEXT,
|
||
description: "依据:在哪几行看到的。不属于任何单个因子的总体核对说明(怎么核的、行号怎么对上的),写进被关掉因子那一项的依据里",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
),
|
||
{
|
||
description: "冻结协议里每个因子一项",
|
||
},
|
||
),
|
||
},
|
||
{
|
||
...CLOSED,
|
||
description: "只查一件事:是不是只关了指定的因子",
|
||
},
|
||
);
|
||
|
||
export const WrapUpSubmission = Type.Object(
|
||
{
|
||
body: Type.String({
|
||
...TEXT,
|
||
description:
|
||
"收尾,Markdown:什么被支持了、什么被挑战了、下一步想往哪走:沿某个因子继续,或换一条更可能拿最高分的路线。" +
|
||
"推广结论时写清它覆盖哪些设定。某方面没有写\"没有:为什么\"。" +
|
||
"原样放进下一轮的提案材料,所有人都读得到",
|
||
}),
|
||
},
|
||
CLOSED,
|
||
);
|
||
|
||
/** 每种提交用哪个字段定义,键与 roster.ts 的 SUBMISSION_KINDS 相同。 */
|
||
export const SUBMISSION_SCHEMAS = {
|
||
entry: EntrySubmission,
|
||
discussion: DiscussionSubmission,
|
||
claim: ClaimSubmission,
|
||
diagnosisProposal: DiagnosisProposalSubmission,
|
||
diagnosisPrediction: DiagnosisPredictionSubmission,
|
||
diagnosisImplementation: DiagnosisImplementationSubmission,
|
||
diagnosisRepair: DiagnosisImplementationSubmission,
|
||
diagnosisVerification: DiagnosisVerificationSubmission,
|
||
proposal: ProposalSubmission,
|
||
firstPrediction: PredictionSubmission,
|
||
critique: CritiqueSubmission,
|
||
response: ResponseSubmission,
|
||
unification: UnificationSubmission,
|
||
secondPrediction: PredictionSubmission,
|
||
implementation: ImplementationSubmission,
|
||
repair: ImplementationSubmission,
|
||
verification: VerificationSubmission,
|
||
explanation: ExplanationSubmission,
|
||
ablationImplementation: AblationImplementationSubmission,
|
||
ablationVerification: AblationVerificationSubmission,
|
||
wrapUp: WrapUpSubmission,
|
||
} as const satisfies Record<SubmissionKind, TSchema>;
|
||
|
||
/** 某种提交的内容类型,例如 Submission<"proposal">。 */
|
||
export type Submission<K extends SubmissionKind> = Static<(typeof SUBMISSION_SCHEMAS)[K]>;
|