Files
cc-web/.trellis/tasks/10-10-snapshot-history-pagination/research/persistence-result.md
shiyue 69b6db0f5b 修复完整会话历史与长气泡交互并更新 CentOS 7 发布包
提交当前工作区全部源码、回归脚本、任务记录及重新构建的 Bun baseline 发布包。发布单文件 MCP 初始化及前端资源一致性验证通过。
2026-10-10 23:40:16 +08:00

53 lines
4.7 KiB
Markdown
Raw 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.

# 完整历史持久化实现记录
日期:2026-10-10。负责范围:服务端完整归档、保存入口与生命周期、专项回归。
## 失败回归证据
先新增 `scripts/session-history-store-unit.js`,使用生产保存、裁剪、读取、resolver 函数及临时文件系统。原生日志测试通过真实 JSONL 文件和生产 `createCodexRolloutStore` 解析,未使用消息数组 mock 替代读取。
旧实现运行 `timeout 60s node scripts/session-history-store-unit.js` 退出码 1,9 项失败、2 项通过,约 1.2 秒:
- 650 条保存后重开只读回最后 180 条及提示;快照上限调为 500 仍损失 150 条。
- 长正文、125 条工具调用、工具参数/结果、长数组和深层元数据未完整保存。
- 受限短预览再次保存被接受,旧修订也可覆盖后来已提交的追加。
- 完整档案不存在,原子归档失败保护和缓存失败提交语义不成立。
- 真实 rollout 确认前缀后 resolver 仅在内存合并,没有建立自身档案。
完整原始输出在临时日志 `/tmp/ccweb-persistence-before.txt`;本文件记录可审计结论,未写入任何真实会话或配置。
## 已确定设计
- 新增 `lib/session-history-store.js`,`sessions/_history/<id>.json` 为完整会话的原子提交点。
- 归档保存完整 JSON 数据,排除既有运行态句柄,不进入消息/正文/工具/数组预览裁剪。
- 可信加载来源与归档修订使用内存身份信息,root 快照或任意短预览不能伪造完整加载。
- 可信当前修订精确替换消息数组;可信旧修订基于加载基线合并本次变更,保留后来已提交的追加和元数据,冲突字段保留已提交值。未经可信加载的短预览拒绝覆盖档案。
- 完整归档成功、快照失败视作已提交;`loadSession` 无 root JSON 仍优先读归档,列表接入归档孤儿缓存修复。
- 旧截断状态继续保留。只有现有边界规则确认原生前缀后,才把补齐结果提交档案。
## 实现与验证
核心模块与 `saveSession` / `loadSession` 接入已完成;统一生命周期已覆盖:
- `resolveSessionHistory` 使用既有边界规则确认后先提交归档,提交失败只返回原快照。
- `loadSession` 即使 root JSON 缺失仍读取归档;列表枚举孤立档案,按归档修订修复有界缓存,缓存继续失败时使用内存有界预览展示。
- 导入统一先读取可信档案;已有会话只有可靠边界确认后才补前缀,保留 cc-web 专有气泡和顺序。
- `/clear` 建立新的清空修订,旧运行对象不能复活原线程历史或返回输出;删除会话同步删除自身档案。
- 迁移保留原始快照备份,使用统一完整归档入口,不再直接写无界 root JSON。
当前专项检查:
- `timeout 60s node scripts/session-history-store-unit.js`:完整持久化回归 **21 项通过**。
- `timeout 60s node scripts/session-history-unit.js`:原服务端历史回归 **12 项通过**。
- `timeout 60s node scripts/history-frontend-unit.js`:前端历史分页、目录索引、认证隔离和重试通过。
- `timeout 60s node scripts/history-runtime-unit.js`:生产 runtime 完整采集 **13/13 通过**,覆盖长正文、纯文本/结构块混合、纯工具、Claude tool_result、Codex App 工具数组及有界传输。
- `timeout 60s node scripts/history-runtime-completion-unit.js`:完成、恢复及保存失败生产路径 **13/13 通过**,已接入全量回归。包含真实保存失败注入、保留唯一运行输出、存储恢复后恰好提交一次、跨会话与 child 冲刷重试,以及任务看板 650 条历史保持完整;详情见 `completion-regression-result.md`。
- `npm run regression`:**Regression checks passed**。
- 隔离 Firefox 归档重启验收:`historySource=archive`、148 条消息、6 个分页块、下标连续且无重复;原始日志夹具移开后仍可读。
生产路径补充保护:普通纯文本 CLI 回合保留字符串内容形状;结构化或混合回合才使用内容块数组;初次用户消息、steer、跨会话回传均在保存成功后才继续;CLI/Codex App 恢复在会话读取或归档保存失败时保留运行目录和完整运行态,避免清理唯一可恢复记录;CLI 使用 runKey 防止清理失败后的重复入库。
旧版本对照:`timeout 60s node scripts/history-runtime-unit.js --baseline-head` 复现预期的 9 项历史缺陷,证明专项断言确实覆盖原问题。核心文件 Node 语法检查与 `git diff --check` 通过。
边界:以上均为隔离临时目录、夹具或本地回归;未读取或修改用户在另一客户端看到的真实会话,未重启生产服务,不能据此声称那 45 条旧消息已经找回。