# 升格级联重跑设计 > 日期: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 总流程 ```mermaid 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` 正序重放。撤销和重放都不得跳窗;后窗只能读取前窗已经重放完成的新状态。 ```mermaid 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 强杀与恢复 强杀后不得猜测进度。下一执行者读取持久任务、恢复点、最近完成检查点和当前围栏令牌: - 未开始当前窗口写入时,从该窗口继续。 - 当前窗口事务未提交时,从该窗口重新计算。 - 阶段或数据无法由检查点证明时,恢复任务前恢复点并将任务置为失败关闭。 - 恢复、接管或回滚完成前,旧任务令牌、普通写入和所有消费读取均不得重新开放。 ```mermaid 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 仍无执行授权。