feat: 任务书 10,submissions 模块与 materials 修改

- 新增 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>
This commit is contained in:
2026-10-03 06:08:34 -04:00
parent a0ee4ef7a2
commit 09c44031a0
34 changed files with 1221 additions and 169 deletions
+36
View File
@@ -0,0 +1,36 @@
import type { Submission } from "../vocab/index.ts";
// 一份已经收下的核验、消融核验的结论(任务书 10 第三部分第 2、3 条):判的是"收下之后通过没有",不是"收不收"。
/**
* 核验通过没有(方法.md 4.3 ⑨):任何一项没落实,或者任何一条没有归属的改动判为越界,就不通过。
* 没落实的条款、因子、保障和越界的改动分开列:保障短名可能和别的编号同形。
*/
export function verificationOutcome(v: Submission<"verification">): {
passed: boolean;
clauses: string[];
factors: string[];
safeguards: string[];
outOfScope: string[];
} {
const clauses = v.clauses.filter((x) => !x.found).map((x) => x.clause);
const factors = v.factors.filter((x) => !x.found).map((x) => x.factor);
const safeguards = v.safeguards.filter((x) => !x.found).map((x) => x.safeguard);
const outOfScope = v.unassigned.filter((x) => x.outOfScope).map((x) => x.location);
return { passed: clauses.length + factors.length + safeguards.length + outOfScope.length === 0, clauses, factors, safeguards, outOfScope };
}
/**
* 消融核验通过没有(方法.md 4.3 ⑯):这一格要关的因子(off)和实验员报的一起关的因子(alsoOff)都写了"关着",
* 其余因子都写了"照留",才算通过。leftOn 是该关却照留的,wronglyOff 是该留却关了的。
*/
export function ablationOutcome(
v: Submission<"ablationVerification">,
off: string,
alsoOff: readonly string[],
): { passed: boolean; leftOn: string[]; wronglyOff: string[] } {
const shouldBeOff = new Set([off, ...alsoOff]);
const leftOn = v.factors.filter((f) => shouldBeOff.has(f.factor) && !f.off).map((f) => f.factor);
const wronglyOff = v.factors.filter((f) => !shouldBeOff.has(f.factor) && f.off).map((f) => f.factor);
return { passed: leftOn.length + wronglyOff.length === 0, leftOn, wronglyOff };
}