Files
cc-web/.planning/codex-rollout-history-merge/task_plan.md

4.6 KiB
Raw Blame History

Codex rollout 历史合并修复计划

目标

让 cc-web 持久化消息成为当前会话的权威顺序;Codex native rollout 仅补充更早历史,按 turn 聚合助手输出,并通过稳定消息标识完成历史合并与前端去重。

合并契约

  • 持久化快照中去掉 ccwebPersistenceNotice 后的消息保持原有顺序,是当前会话的权威尾部;native 只能补充快照之前的消息。
  • 快照压缩时保存 historySnapshotBaseIndex(native 逻辑消息索引)与 historySnapshotCount,旧快照缺字段时按稳定 ID/最长公共后缀推断,无法确认边界时保留快照。
  • 合并顺序固定为:native 更早消息 → cc-web 持久化消息 → 当前运行中的消息;相同稳定 ID 只保留 cc-web 消息,ID 冲突且内容不一致时以持久化消息为准并记录告警。
  • native 缺失、解析异常、边界无法确认或合并结果不能证明快照尾部完整时,返回 cc-web 快照,不把未经确认的 native 消息插入当前视图。
  • session_info、resume_session_result、session_history_chunk 均调用同一解析结果;分页只对该结果切片。

稳定标识契约

  • 用户消息:优先 clientMessageId,兼容旧字段 id;缺失时生成并持久化 client:<uuid>。
  • Codex App 助手消息:使用 codexAppTurnKey,其输入为 session/thread/turn 的稳定字段;旧消息缺失时从对应运行状态或时间戳生成一次并保存。
  • native rollout 助手消息:使用 nativeTurnKey,由 threadId + turnId/turn_context 组成;同一 turn 跨刷新保持一致。
  • 跨对话回传:保留 replyToRequestId(兼容 crossConversation.replyRequestId),同时生成 reply:<requestId> 作为稳定消息 ID;来源元数据始终保留。
  • 其他历史消息按 message:<role>:<timestamp>:<sha256(content)> 降级,避免数组下标去重;ID 冲突时以权威来源和较完整内容决胜。

Turn 聚合契约

  • 以 turn_id、turn_context.turn_id、turn_context.id 或 session/thread 上下文组成 turn key;缺失时使用相邻事件窗口的稳定 fallback key。
  • 同一 turn 内按 rollout 文件顺序合并文本片段、工具调用与工具结果;只有遇到下一条用户消息、turn 完成/失败事件或文件结束才 flush。
  • tool call/result 绑定同一调用 ID;空 turn 不产出气泡;跨对话内部 user 回传不作为普通 user 消息插入。

前端契约

  • 服务端先输出规范化消息序列;前端渲染层按 message.id/messageId/nativeTurnKey/codexAppTurnKey/replyToRequestId 形成稳定键。
  • renderMessages、分页 prepend、reconcileRenderedSessionMessages 均按稳定键去重,索引仅用于定位/排序兼容;同键内容更新应替换原 DOM,不追加新气泡。
  • 实时消息与历史消息竞态时,以服务端规范化消息为准,保留当前用户消息与对应助手回复邻接关系;跨对话回传显示来源标识,角色保持 assistant。

可验收测试矩阵

  • 历史合并:无 native、无快照、完全重叠、native 仅更早、快照尾部用户消息、native 异常/边界不明回退快照;断言顺序、长度、稳定 ID。
  • rollout 聚合:同一 turn 多个 message/tool/result 仅一条 assistant;下一用户消息 flush;turn 完成/失败 flush;内部回传不生成 user 气泡。
  • 稳定 ID:重复加载/刷新/分页 ID 不变;clientMessageId、codexAppTurnKey、replyToRequestId 去重;冲突以持久化消息为准。
  • 前端回归:session_info/resume/history chunk 重复到达不追加;实时流与历史同时到达不拆泡;来源标识和当前生成消息同时可见。
  • 浏览器实测:重载运行会话时用户原问题、架构回复、子对话来源标识、当前生成消息均按逻辑顺序可见。

步骤

  • [complete] 盘点服务端、rollout、持久化与前端消息链路
  • [complete] 设计并实现稳定消息标识与 native 历史合并
  • [complete] 聚合 Codex rollout 的同一轮助手输出
  • [complete] 调整前端规范化历史渲染与稳定 ID 去重
  • [complete] 增加历史合并和 rollout 聚合回归测试
  • [complete] 运行静态检查、单测和浏览器/集成验证并收尾

约束与决策

  • 保留工作区已有未提交改动,不覆盖 lib/ccweb-mcp-server.js 与 scripts/ccweb-message-reply-unit.js。
  • 不把未确认的 native 消息插入当前 cc-web 快照;合并失败时返回快照。
  • 回传消息保留来源标识,不能伪装成普通用户气泡。
  • 所有可观测失败记录简短告警,不阻断当前会话展示。

错误记录

错误 尝试 处理