触发与范围
桌面聊天同一 thread 的旧 REST 快照在新 SSE snapshot 后返回时,原 mergeConversationView 保留较新消息正文,却直接接纳旧快照的 state、queue、watermark 等控制字段;同一 turn 的旧记录也覆盖最新状态。界面可同时显示完成的正文和回退的 running/待审批状态。
按 P2 主会话状态一致性追踪。2026-09-30 的原 hook/merge 隔离 fixture 已确认逻辑;没有真实 REST/SSE、桌面 profile、审批、工具或权限操作,没有消息/引用丢失或生产事故证据。范围仅为 desktop-owned 主聊天的快照 admission 与合并,共享 Web 文件用于定位,不要求本轮修改 Web 或后端。
原模块验证与保护对照
fixture 原样转译并运行 useConversation、mergeConversationView、stream reducer 与加载辅助逻辑,使用 React test renderer。apiFetch、EventSource、timer 和分页响应全为内存合成对象,无真实网络、存储、账号或 Provider;未使用的 receipt/命令依赖一旦调用就抛错。
- 同 generation 的新完成快照先进入 hook;挂载时仍 pending 的旧 REST 随后完成。watermark 回退、running_turn_id 与旧 pending/queue 恢复,turn 的 completed 状态变回 running。
- 同 message ID 的最新正文 stream_seq 较高,原 mergeMessageLists 正确保留完整新正文。这不是消息内容被旧响应覆盖。
- 原纯 merge 另验证低 generation 的 next:current_generation 回退,但已知 retry/supersession 仍过滤旧分支正文、保留当前分支。
- 顺序新 snapshot 正常推进;切换到另一 thread 后,旧 REST 和旧 EventSource snapshot 都被原归属 guard 拒绝。
完整输入、合并对象、原请求与源码哈希只保存在本地 ignored artifact;控制状态回退不能写成真实批准、重新执行或删除数据。
根因与影响边界
合并逻辑判断 nextGen > prevGen 时清理旧分支,没有拒绝 nextGen 更低或同 generation 低水位的快照。最终 ...next 覆盖控制字段,mergeTurnLists 对同 turn ID 也直接采用 incoming。消息 seq 保护解决正文新旧,却没有让整体快照状态保持一致。
这会使主聊天呈现过时的运行、待审批和队列信息;UI 用户决定可能基于旧状态。真实命令结果和授权仍需服务独立判断,本轮没有提交任何决定,不能把状态错误升级为权限或执行事故。现有跨 thread/旧流、正文和 supersession 保护均应保留。
桌面优化与验收
- 主聊天快照用明确 thread、generation 与 watermark/等价版本判定是否可成为当前控制状态;低版本快照不能接管 state/queue/turn 状态。
- 历史分页可补充正文和引用,控制状态与当前有效分支按独立的已确认版本合并,避免用旧页整体替换。
- 重跑原 hook 的乱序序列:已完成状态、当前 generation、已解决的待审项与队列不回退,较新正文仍保留。顺序推进、跨 thread、旧流、重复增量和 supersession 对照继续通过。
- 在可弃置桌面数据环境补真实延迟响应验收,仅用合成内容与 recorder;未完成前不宣称端到端事故或已修复。
去重与源码
#80 是侧栏整列表 refresh;本条是主 view 的控制状态/turn/generation 合并,使用不同模块路径和验收对象。#38 的停止结果解释、#67 的审批决定投递也不替代此快照保护。关联 Epic #31。
固定公开代码供导航,当前源文件哈希为本次证据:useConversation / mergeConversationView、stream reducer。
触发与范围
桌面聊天同一 thread 的旧 REST 快照在新 SSE snapshot 后返回时,原
mergeConversationView保留较新消息正文,却直接接纳旧快照的 state、queue、watermark 等控制字段;同一 turn 的旧记录也覆盖最新状态。界面可同时显示完成的正文和回退的 running/待审批状态。按 P2 主会话状态一致性追踪。2026-09-30 的原 hook/merge 隔离 fixture 已确认逻辑;没有真实 REST/SSE、桌面 profile、审批、工具或权限操作,没有消息/引用丢失或生产事故证据。范围仅为 desktop-owned 主聊天的快照 admission 与合并,共享 Web 文件用于定位,不要求本轮修改 Web 或后端。
原模块验证与保护对照
fixture 原样转译并运行
useConversation、mergeConversationView、stream reducer 与加载辅助逻辑,使用 React test renderer。apiFetch、EventSource、timer 和分页响应全为内存合成对象,无真实网络、存储、账号或 Provider;未使用的 receipt/命令依赖一旦调用就抛错。完整输入、合并对象、原请求与源码哈希只保存在本地 ignored artifact;控制状态回退不能写成真实批准、重新执行或删除数据。
根因与影响边界
合并逻辑判断 nextGen > prevGen 时清理旧分支,没有拒绝 nextGen 更低或同 generation 低水位的快照。最终
...next覆盖控制字段,mergeTurnLists 对同 turn ID 也直接采用 incoming。消息 seq 保护解决正文新旧,却没有让整体快照状态保持一致。这会使主聊天呈现过时的运行、待审批和队列信息;UI 用户决定可能基于旧状态。真实命令结果和授权仍需服务独立判断,本轮没有提交任何决定,不能把状态错误升级为权限或执行事故。现有跨 thread/旧流、正文和 supersession 保护均应保留。
桌面优化与验收
去重与源码
#80 是侧栏整列表 refresh;本条是主 view 的控制状态/turn/generation 合并,使用不同模块路径和验收对象。#38 的停止结果解释、#67 的审批决定投递也不替代此快照保护。关联 Epic #31。
固定公开代码供导航,当前源文件哈希为本次证据:useConversation / mergeConversationView、stream reducer。