muse-agent-example/docs/2026-07-21-升格级联重跑设计.md
zizi b9ff4d0b40 修复: 阻断历史单窗重跑破坏成长链
以正文证据校验实体出场章,补齐失败恢复和参数边界;历史窗口重跑在写入前失败关闭,仅保留末窗安全重试。记录 work8 全书前滚重建的 P0/P1 边界。
2026-07-21 16:08:15 +08:00

15 KiB
Raw Blame History

升格级联重跑设计

日期:2026-07-21 状态:已完成独立评审,P0/P1 边界已冻结 适用范围:parse-book 作品面升格管线 执行状态:P0 历史 redo 安全门已完成并验证;一次性备份、恢复演练、reset 和 1..116 重建尚未执行,执行前仍需用户绑定确认

一、评审结论

当前 --redo-window K 只撤销并重写第 K 窗。在串行生长的升格管线中,后窗已经消费了旧的卡、别名、出场记录、水位和向量;只重写历史单窗会制造前后代际不一致。因此,本次修复分成两个互不阻塞的阶段:

阶段 目标 本阶段必须交付 明确不做
P0 立即止损并恢复 work 8 封死历史 redo;停止 work 8 评测读取;建立一次性可校验备份;经用户确认后执行 reset_upgrade_work;全书 1..116 正序重建;完成验收 不建设通用持久任务、恢复点、围栏接管和真正级联
P1 建立可长期使用的历史重跑能力 持久任务、恢复点、写入围栏、强杀恢复、真正的 K..F 级联重跑 不作为 P0 的前置条件,不借 P0 成功宣称 P1 完成

P0 是本次 work 8 恢复的唯一方案。 不再根据审计是否充分选择 84..F 撤销,也不在本次恢复中实现或调用真正级联。

二、事实与边界

2.1 已确认事实

  • work 8 当前设计基线末窗为 F=116。
  • 已知失活触发点是 window 101;101 不是末窗,也不是 P0 的重建终点。
  • 升格按窗口串行生长,后窗依赖前窗形成的卡、别名、出场记录、水位、审计和向量。
  • 当前 --redo-window 只处理指定单窗,不能重建该窗之后已经形成的派生判断。
  • 现有 reset_upgrade_work.py 会软删本书活跃升格卡,将全部窗口重置为 pending,并清理本书别名、出场留档、卡水位和升格审计;旧向量行保留,但随所属旧卡软删而退出召回。
  • 正常 parse_upgrade.py run 会按章节顺序处理未完成窗口,可用于全书正序前滚重建。

2.2 执行前必须重新核验

F=116 是本设计的确认基线,不是允许执行时静默变化的动态参数。任何破坏性动作前必须只读核验:

  1. work 8 恰有 116 个有效窗口,窗号和章节范围连续,正文可读。
  2. 当前没有 work 8 升格写入进程,也没有评测任务正在读取 work 8。
  3. 正文版本、窗口边界、字段合同和必要模型配置已生成不可变摘要。
  4. reset_upgrade_work --work-id 8 的预览影响范围与备份清单一致。

任一项不满足,立即停止。特别是实际末窗不等于 116 时,不得自动扩大或缩小范围,必须重新生成设计基线并取得新的用户确认。

2.3 本文不授予执行权限

全书 reset 会软删和硬删现有派生数据,是破坏性动作。本文评审通过不等于授权执行。 只有一次性备份完成并校验通过后,向用户展示本次执行摘要并取得针对该摘要的明确确认,才能执行数据库写入或模型调用。

三、P0:立即止损与 work 8 全书重建

3.1 P0 总流程

flowchart TD
    A[封死历史 redo] --> B[停止 work 8 升格写入与全部评测读取]
    B --> C[只读预检并冻结 F=116 与输入摘要]
    C --> D[生成一次性备份]
    D --> E{读回与恢复校验通过?}
    E -- 否 --> X[失败关闭,不改业务数据]
    E -- 是 --> F[展示 work 8 / 1..116 / 备份 ID / 破坏影响]
    F --> G{用户明确确认本次 reset?}
    G -- 否 --> X
    G -- 是 --> H[执行 reset_upgrade_work]
    H --> I{reset 后空态验收通过?}
    I -- 否 --> Y[停止并保持评测关闭,人工决定是否恢复备份]
    I -- 是 --> J[按 1 到 116 严格正序前滚重建]
    J --> K{P0 全链验收通过?}
    K -- 否 --> Y
    K -- 是 --> L[用户确认解除 work 8 评测读取禁令]

3.2 封死历史 redo

P0 第一项是让历史单窗重跑失败关闭,避免 P1 完成前再次制造代际错位:

  • --redo-window K 指向已完成历史窗时,必须在任何业务写入前拒绝。
  • 不提供 --force、配置开关或“已知风险继续”等绕过路径。
  • 正常运行中对当前失败窗的撤销后同窗重试不属于历史 redo,可以保留;它不能越过失败窗,也不能回写更早的已完成窗。
  • 只有 P1 真正级联通过全部验收后,历史 redo 才能以新的 K..F 语义重新开放。

3.3 停止 work 8 评测读取

冻结区间从生成备份前开始,到 1..116 重建和 P0 验收全部通过、用户明确同意开放为止。在此期间:

  • 停止 work 8 的在线评测、离线回放、批处理评测、评测快照装配、评测导出和缓存预热。
  • 停止普通升格写入、历史 redo 和其他会修改 work 8 升格派生状态的任务。
  • 只允许本次预检、备份、重建和验收使用受控入口;验收查询不产生评测结果。
  • 任一失败或中断都保持关闭,不能因为进程退出、窗口暂停或备份恢复成功而自动开放。

P0 必须留下冻结开始、命中拒绝、验收结束和解除冻结的记录。最终验收要求冻结区间内 work 8 的成功评测读取数为 0。

3.4 一次性可校验备份

P0 备份是本次 work 8 reset 前的唯一恢复基线,不是 P1 的通用恢复点系统。备份必须在同一个一致性读视图中覆盖:

状态域 备份范围
drafts work 8 全部 upgrade_book 卡,包含活跃、软删、版本和归属字段
windows work 8 全部 116 个窗口及状态、错误、边界和软删字段
aliases work 8 全部别名行
presence work 8 全部出场留档
card_state work 8 全部卡水位
audits 所有指向 work 8 升格卡的审计行
embeddings 所有指向 work 8 升格卡的向量行、内容哈希、模型和软删状态

备份工件必须满足:

  1. 生成唯一 backup_id,记录数据库标识、生成时间、代码版本、F=116 和输入摘要。
  2. 每个状态域记录行数、主键集合摘要和按稳定顺序计算的内容校验值;备份文件另记 SHA-256。
  3. 备份存放在不会被 reset_upgrade_work 影响的位置,只允许授权操作者读取或恢复,不得被后续尝试覆盖。
  4. 生成后重新读回,核对文件校验值、七域行数和内容摘要。
  5. 在隔离库或隔离 schema 做一次恢复演练;恢复后的七域摘要必须与源数据一致。

任一校验或恢复演练失败,P0 停止,不得执行 reset。

3.5 用户确认硬门

备份校验通过后必须停止,并向用户展示以下固定摘要:

  • 作品:work_id=8,范围:1..116。
  • backup_id、备份 SHA-256、七域行数与校验结果。
  • 将执行的破坏性入口:reset_upgrade_work --work-id 8 --execute。
  • reset 的影响:软删活跃升格卡、全部窗口置为 pending、硬删别名/出场留档/水位/审计;随后会调用模型从窗 1 重建到窗 116。
  • 失败边界:P0 没有 P1 的强杀自动恢复;失败后 work 8 保持关闭,由用户决定续跑还是恢复唯一备份。

确认必须绑定本次 work_id、范围、输入摘要和 backup_id。旧确认、默认值、通用 --yes 或范围变化后的确认均无效。没有本次明确确认,流程只能停在这里。

3.6 reset 与正序前滚

获得确认后,P0 只允许以下路径:

  1. 执行现有 reset_upgrade_work.py --work-id 8 --execute,不得另写临时 SQL 替代,不得改走 --redo-window。
  2. reset 后立即验证:活跃升格卡为 0;116 个有效窗口全部为 pending;别名、出场留档、卡水位和指向旧升格卡的审计均为空;旧向量只挂在软删旧卡上,不参与召回。
  3. 使用正常升格入口从窗 1 开始,严格按 1,2,...,116 正序前滚;不得跳窗、并行同书窗口或从 84/101 起跑。
  4. 每个窗口只有在完整提交并通过窗后不变量后才能进入下一窗。全局 $24/6000 治理或局部上限可以让运行在窗边界暂停,但 work 8 仍保持关闭。
  5. 普通失败按现有“当前失败窗撤销后重试/续跑”处理。发生强杀、状态不可解释或输入摘要漂移时立即停止,保持评测关闭;P0 不声称能自动接管恢复。

3.7 window 101 回归基线

window 101 是已知失活触发点,必须作为状态转移回归检查,不得只看窗 116 的最终活跃卡数:

  • reset 前记录目标逻辑实体在 window 100 结束、window 101 处理后以及 102..116 的卡身份、活跃状态、归并关系、水位和审计来源。
  • 重建时记录同一逻辑实体在 window 100/101/116 的对应状态。
  • 验收必须证明 window 101 按当前业务证据产生了正确状态转移,且 102..116 消费的是重建后的新前态。
  • 不能用“最终存在一张同名活跃卡”代替验证;新建重复卡、错误归并后复活或旧新代际叠加均不通过。

四、P0 验收与完成口径

P0 只有同时通过以下门槛才算完成:

验收门 必须证据
历史 redo 已封死 历史 --redo-window 在写入前被机械拒绝;当前失败窗重试仍正常
冻结有效 从备份前到开放前,work 8 成功评测读取数为 0,且无第二升格写入者
备份可恢复 唯一 backup_id、SHA-256、七域摘要和隔离恢复演练全部通过
确认有效 确认记录绑定 work 8、1..116、输入摘要和 backup_id,且发生在 reset 前
reset 正确 执行入口和影响行数可追踪;reset 后空态不变量全部通过
顺序完整 窗口完成事件严格为 1..116,无跳窗、倒序、并行或旧状态复用
window 101 回归 100→101 的状态转移符合业务证据;102..116 持续消费新前态;无重复逻辑实体或代际混合
七域一致 卡、窗口、别名、presence、水位、审计和向量互相一致;活跃向量哈希匹配活跃卡正文
开放受控 116 窗全部完成且全链验收通过后,仍需用户明确同意才解除评测读取禁令

以下情况只能报告局部进度,不能说 P0 完成:备份只生成未恢复演练;reset 成功但未跑满 116;window 101 最终态看似正常但过程未核验;任务暂停或回滚;只验证一张卡;评测读取未证明全程为 0。

五、P1:持久任务与真正级联

P1 在 P0 独立完成后实施。它把历史重跑从一次性运维动作升级为可恢复、可并发约束、可审计的产品能力。

5.1 持久任务与恢复点

每次历史重跑创建持久任务,至少记录:task_id、work_id、起点 K、冻结末窗 F、输入版本、当前阶段、逆序/正序游标、最近完成窗口、恢复点、围栏令牌、暂停原因、错误和终态。

  • 任务创建时冻结 K..F 和输入版本;范围或输入漂移时失败关闭。
  • 任何撤销前创建可恢复到任务开始前的全书恢复点,并机械验证完整性。
  • 每个窗口边界形成持久检查点。模型计算期间不持有数据库长事务。
  • 暂停必须续接同一任务;不得另起普通升格任务越过未完成级联。

5.2 写入围栏与读取关闭

同一本书同一时刻只允许一个升格写入任务。数据库可信边界为每次任务发放递增围栏令牌;所有升格写事务都必须验证令牌。

  • 租约或心跳过期只表示任务可被接管,不表示普通写入者可以进入。
  • 接管者取得新令牌后,旧进程即使复活也无法提交。
  • 任务从撤销开始到验收发布前,业务消费和评测读取只能看到“重跑中/待恢复”,不能读取半成品。

5.3 真正级联语义

P1 重新开放后的 --redo-window K 固定表示:冻结当前末窗 F,先按 F..K 逆序撤销,再按 K..F 正序重放。撤销和重放都不得跳窗;后窗只能读取前窗已经重放完成的新状态。

flowchart LR
    A[创建持久级联任务 K..F] --> B[取得新围栏令牌]
    B --> C[冻结输入并校验全书恢复点]
    C --> D[关闭本书消费与评测读取]
    D --> E[逆序撤销 F..K]
    E --> F[校验已回到 K-1]
    F --> G[正序重放 K..F]
    G --> H{全链验收通过?}
    H -- 是 --> I[发布新代际并开放读取]
    H -- 否 --> J[恢复任务前恢复点并保持关闭]

5.4 强杀与恢复

强杀后不得猜测进度。下一执行者读取持久任务、恢复点、最近完成检查点和当前围栏令牌:

  • 未开始当前窗口写入时,从该窗口继续。
  • 当前窗口事务未提交时,从该窗口重新计算。
  • 阶段或数据无法由检查点证明时,恢复任务前恢复点并将任务置为失败关闭。
  • 恢复、接管或回滚完成前,旧任务令牌、普通写入和所有消费读取均不得重新开放。
stateDiagram-v2
    [*] --> preflight
    preflight --> snapshotting: 预检通过
    snapshotting --> undoing: 恢复点校验通过
    undoing --> replaying: 已回到 K-1
    replaying --> paused: 达到治理或局部上限
    paused --> replaying: 同一任务续接
    undoing --> recovery_required: 强杀或状态不明
    replaying --> recovery_required: 强杀或状态不明
    recovery_required --> restoring: 新围栏持有者接管
    restoring --> failed_closed: 已恢复任务前状态
    replaying --> validating: 已重放到 F
    validating --> restoring: 验收失败
    validating --> succeeded: 验收通过并发布

5.5 P1 验收

P1 完成至少要求:

  1. 给定任意 K..F,事件顺序严格为撤销 F..K、重放 K..F。
  2. 在恢复点生成、逆序撤销、正序重放、暂停等待和最终验收阶段分别强杀,重启后都能由持久证据决定续接或恢复。
  3. 两个同书进程并发时只有新围栏持有者能写;旧进程复活提交被拒绝;不同作品可并行。
  4. 任一中间态的业务消费和评测读取均被拒绝,只有完整新代际发布后开放。
  5. 恢复点往返后七域逐行一致;窗口检查点不会留下半窗卡、孤儿别名、超前水位或旧向量。
  6. P0 的历史 redo 禁令只有在上述自动化、数据库集成和强杀演练全部通过后才能解除。

六、实施顺序

  1. P0 代码止损(已完成):历史 redo 安全门仅允许末窗重跑;历史窗、不存在窗、不连续窗口、正文为空和负数参数均在业务写入前拒绝。验证证据:parse upgrade 128 项、parse LLM 9 项、outline 11 项全部通过,独立复审 PASS,真实 work 8 的 redo 101 已在写入前拒绝。
  2. P0 执行准备(未执行):只读预检、一次性备份与隔离恢复演练尚未执行。
  3. 人工确认门(待执行):备份与恢复演练通过后,仍须提交绑定 work_id=8、1..116、输入摘要和 backup_id 的破坏性执行摘要,取得用户明确确认。
  4. P0 数据恢复(未执行):尚未执行 reset,也未开始 1..116 正序重建和验收;只有取得第 3 步绑定确认后才能执行。
  5. P1 长期能力(未执行):持久任务、恢复点、围栏、强杀恢复和真正级联仍属后续范围。

当前已完成第 1 步。第 2 至第 5 步均未执行;全书破坏性 reset 仍无执行授权。