Files
nana-story/docs/status/2026-07-29-m2-wave7-context-checkpoints.md
2026-07-29 10:14:21 +08:00

114 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M2 第七波:当前分支上下文检查点
日期:2026-07-29
## 本轮结果
本轮完成了长分支上下文主链:运行时按实际 LAPP 模型预算编排 prompt schema v3
超出预算时使用当前选中的同一个模型生成玩家安全的滚动摘要;摘要与来源指纹组成
非权威检查点,并在最终回合成功时与新故事节点原子提交。历史不会为了适配窗口而被
静默截断。
这套机制适用于普通继续与重生成。它不引入导演 Agent、独立摘要模型、向量记忆库或
跨分支记忆。
## SQLite schema v3
- 新增 `context_checkpoints` 缓存表,以不可变的故事节点作为 host,保存覆盖范围、
prompt / checkpoint schema 版本、稳定前缀哈希、摘要和叙事来源哈希。
- schema v1 与 v2 数据库都能迁移至 v3;迁移不会修改故事节点、线路头、物化状态或
活动线路。
- Memory 与 SQLite Store 使用同一检查点语义:只沿目标节点的 `parent_id` 祖先链
查找最近的可达检查点,兄弟分支和其他故事不可见。
- 缓存行的类型、版本、大小、规范 SHA-256、host 和覆盖范围都会被校验。损坏或未知
版本的行被当作可重建的 cache miss,并继续查找更早的有效祖先;权威祖先链损坏仍是
硬错误。
- 删除全部检查点不会改变节点、线路、状态哈希或 `PlayerView`
- 内存和 SQLite 后端均覆盖 500 节点祖先链读取与检查点查找,长线路不再受界面层
200 节点展示限制。
## 缓存友好的 prompt schema v3
模型输入固定分成三段:
```text
stable_prefix
branch_context
checkpoint?
raw_tail[]
dynamic_tail
```
- `stable_prefix` 只包含角色、Persona、剧情模块、绑定世界书的版本来源及稳定安全
规则;资源未变化时保持字节一致,便于供应商前缀缓存命中。
- `branch_context` 使用一个已验证的祖先检查点加最近原文;至少保留最新的已提交节点,
节拍文本不会被截断。
- `dynamic_tail` 保留本轮输入、实际触发的世界书条目、剧情事件、可见状态与重生成的
固定定性结果,不允许被摘要替代。
- 输入预算来自当前 LAPP 模型的 `context_window``max_output_tokens`;缺失元数据
使用显式标记的保守回退。输出、system、工具 schema、消息 framing、一次隐藏检定
续调用与安全余量都会先从窗口中扣除。
- 完整请求在发给 provider 前再次预检。动态尾部、固定部分或单个历史节点本身无法
容纳时会失败关闭,而不是删字、截断或越过模型窗口。
- V1 每次玩家行动最多进行一次隐藏检定;这使为工具调用及其续写保留的预算存在明确
上界。初始请求会明确提示该限制,检定结果返回后以及重生成回合只向模型暴露
`submit_turn_plan`,不会再提供第二次检定工具。
- 可继续的候选节点会在 `begin_commit` 前,以提交后的状态、同一资源编译器和同一
模型预算验证一次最小“下一轮继续”上下文。即使回复满足静态字段上限,只要它作为
强制保留的最新原文会让下一轮无法编排,本轮就整体失败且不移动线路头。
## 同模型滚动摘要
- 压缩复用当前 TurnPlan provider 的同一 LAPP executor、模型、调用闸门和
`TurnControl`,不会暗中切换模型或绕过供应商配置。
- 每次摘要请求都是新的单用途会话,只开放一个严格的 `submit_context_summary`
工具;正常文本、额外工具调用、未知字段、空白或超大摘要都会被拒绝。
- 首次加载超长分支时按有界块滚动摘要;后续压缩把上一个自包含摘要与新增的连续节点
一起压成新的自包含摘要,不在 prompt 中嵌套摘要链。
- 摘要来源仅包含当前根到覆盖节点路径上的实际玩家输入、公开场景、角色视觉状态和
已提交演出节拍。
- 精确关系值、骰点和难度、状态 delta、NPC 私物和私密知识、未触发世界书、未选择
建议、兄弟分支、凭据、原始供应商响应与推理过程都不进入摘要请求。
- 摘要分类由运行时固定为 `non_authoritative_narrative`;模型只能提供文本,摘要不能
作为规则触发、状态恢复或判定事实来源。
## 原子提交与中断边界
- 压缩发生在模型生成正式 TurnPlan 之前。生成的检查点先停留在内存中,不会立即写库。
- 普通回合使用 `append_node_with_checkpoint`,重生成使用
`append_regenerated_node_with_checkpoint`;节点、物化状态、线路头与待提交检查点
在同一 Store 原子操作中落库。
- 检查点必须 host 在提交前的历史头上,并与该祖先链的覆盖范围一致。陈旧线路、
错误故事、无效范围或状态不一致都会使整次写入失败,节点与检查点均不落库。
- 取消或超时可发生在摘要、正式模型调用或最终提交边界之前。只要中断先于
`begin_commit`,待提交检查点与故事节点都会被丢弃,线路头保持不变。
- 一旦 `begin_commit` 成功,取消不再与写入竞争;调用方接收该原子提交的确定结果。
- 重生成继续复用原玩家行动、权威 delta、隐藏检定与终局状态;检查点只覆盖待替换
节点的父路径,旧节点及旧分支保持不可变。
## 验证
- Rust workspace**215** 项测试通过。
- Contracts1。
- Domain5。
- Engine21。
- Runtime106。
- Store65。
- Tauri 后端:17。
- `cargo clippy --workspace --all-targets -- -D warnings`:通过。
- Web5 个测试文件 / **29** 项测试、TypeScript 严格检查与生产构建通过。
- 契约:**25** 份 JSON Schema 与 TypeScript DTO 无漂移。
测试覆盖包括预算边界、prompt schema v3 编排、同模型严格摘要工具、滚动与增量摘要、
检查点哈希和失效、兄弟分支隔离、schema v1 / v2 迁移、缓存删除、500 节点祖先链、
节点与检查点原子提交、压缩后取消不移动线路头、隐藏检定工具单次暴露,以及合法但
会阻断后续上下文的超长回复在提交前被拒绝。
## 尚未关闭
- 尚未使用用户实际 LAPP profile、Vault 凭据和在线模型完成端到端调用;本报告不宣称
在线 LAPP 冒烟通过。
- 本轮没有完成窗口截图或人工视觉检查;本报告不宣称视觉验收通过。
- Gitea SSH 推送在当前执行环境中仍未验证;本轮成果当前只能视为本地工作树状态,
不能宣称已经同步到远端。