flow: 消融到收尾、轮末解封、一轮接一轮与研究结束(任务书 17 第二块)

- ⑬–⑱:listCells 从采纳决定和冻结协议现算(不写记录);explanation 有消融才开
  阶段;selectCells 照 CellRuleInput 拼输入(余额当时现算、decisionSeed 版本 2),
  写种类 cells 的决定,没选中的格不另写事件;消融实现/核验按第几次编号
  (r<轮>-ablationImplementation-1、verification-1、-2……从账本数),重做从上一次
  这一格代码接着改,次数用完写 cellNotRunEvent 不跑不扣次;cannotRun 传 null 不核验
  不运行不扣次;alsoOff 用 sharedSettings 沿用同设置的第一格;消融运行一个接一个跑,
  用途 ablation,登记/扣次/恢复与正向同一入口,恢复时指标缺失策略覆盖为只记缺失
  (方法.md 第五部分);settle 拼 SettleInput 调 settleAblation,结算与 chooseBet 的
  bet 决定写在同一事务;wrapUp 阶段关闭后,本轮选中的每个候选在同一个事务里解封
  作者自评(取最后一版提案的封存)。
- 一轮接一轮:每轮开头用 runBalance 现算余额,余额为 0 不开新轮;走到 export 停下,
  原因"导出还没写"。去掉 roundsNext 里 step.id !== "listCells" 的临时写法。
- 消融中发现由 materials 的 Board.baselineOf 从结算输出读出,flow 不另写采纳记录
  (已核实 materials 已实现)。
- 测试 +14:下一步分支 8 条(含收尾关闭后才解封、余额 0 走到导出停、关掉消融时
  解释照方法停下)、消融步骤 6 条(选格输入逐字段手拼对账、结算四种结局、同设置
  沿用、解封取最后一版封存);npm run check 通过,npm test 472 条通过。
- 全新上下文审阅一轮(只看消融重做循环、登记扣次恢复、选格/结算/押的因子输入、
  解封时机、下一轮与结束条件):没有会污染账本的问题;采纳一条小修(删掉未用的
  导入),其余笔记照列不改。

flow 1302 → 1662 行(上限 3500),materials 未动(1930 行)。
This commit is contained in:
2026-10-04 14:04:55 -04:00
parent d7885008fe
commit 144b88480b
9 changed files with 779 additions and 32 deletions
+4
View File
@@ -14,6 +14,7 @@ import type { Study } from "../study.ts";
* 两次抽取不会用同一串随机数。选格由 flow 第 4 部分接上。
*/
const SEED_VERSIONS = { batch: 1, cells: 2 } as const;
export { SEED_VERSIONS };
/** 一对提案(或提案与留池候选)的 Jev 判断,原样存进判重合并决定的输入。 */
export type SamePair = { a: string; b: string; judgment: JevJudgment };
@@ -38,6 +39,7 @@ export async function dedupe(s: Study, round: number): Promise<void> {
const pairs: SamePair[] = [];
for (const [a, b] of asks) pairs.push({ a, b, judgment: await judgeSameChange(model, factorsOf.get(a)!, factorsOf.get(b)!) });
const output = groupSameChange(round, proposals.map((p) => p.item!), carried, pairs);
// SAFETY: JevJudgment 和 DedupOutput 都是纯 Json 值;账本在写入时校验 Json。
s.ledger.append("decision", {
decision: "dedup",
round,
@@ -97,6 +99,7 @@ export function freezeProtocols(s: Study, round: number): void {
answer.kind === "response"
? protocolBody({ kind: "response", content: answer.content, original: board.proposal(proposals[0]!).content })
: protocolBody({ kind: "unification", content: answer.content });
// SAFETY: FrozenProtocol 是纯 Json 值;账本在写入时校验 Json。
s.ledger.append("protocol", { candidate, protocol: freezeProtocol(body, candidate, round, baseline, proposals) as unknown as Json });
}
});
@@ -125,6 +128,7 @@ export function selectBatch(s: Study, round: number): void {
};
const rule = steps.round.find((x) => x.id === "selectBatch")!.rule!.name as BatchRuleName;
const { rule: used, ...output } = runBatchRule(rule, input);
// SAFETY: rules 是纯计算,输入输出都是纯 Json 值;账本在写入时校验 Json。
s.ledger.append("decision", {
decision: "batch",
round,