# 消息回执与时间线合并

基线：`official/dev` 的 `f8b81f0e167977c154591fd35207a51a0b87272f`。整合 #842 / #843 后沿用社交手机号缓存任务分支，保留已有按钮、绑定弹窗与后台刷新策略。

## 缺陷与修复

后台读和实时推送会用新的服务端窗口替换消息列表，而原逻辑只保留已确认的发送。发送中的占位消息会先消失；此时回执找不到原消息又直接返回，直到自己的实时消息到达才重新出现。真实组件的两条受控并发用例在修改前均能复现。

`ArkmeConversationMessageMergeOwner` 统一合并本地发送、回执、实时事件和后台读。尚未确认的发送不被旧快照清掉，回执可原地补全；新版本正文、媒体与动作引用不会被旧回执或旧快照回退。通过 relation/event identity 区分同一快记的不同消息出现位置。

渲染身份与服务端导航身份分离。消息片段和虚拟列表分块沿用首次显示的 key；表态容器提前保持结构，确认前禁用订阅与按钮，确认后启用。回执不再通过更换父节点重新挂载气泡。导航、滚动锚点仍使用正式事件标识。

失败或结果未确认时保留消息与状态，继续用已有草稿恢复/重试流程；同一发送身份重试清除旧失败状态。实时成功优先于迟到的网络错误。明确删除及完整覆盖窗口里的确认缺失能淘汰本地保留项；旧页、旧尾部和分页缺失不等同于删除。

## Owner 与边界

| 消费面 | 结果 |
| --- | --- |
| UI | 插件 Browser UI 持有唯一消息合并入口及稳定渲染身份；私聊、群聊和消息延展接入 |
| Host | 沿用既有发送、实时与统一时间线接口、权限和幂等身份；无新增接口或服务端写入语义 |
| Tools / SDK | N/A：本次是 UI 状态协调，不新增业务能力；已有公开合同不变 |
| Client / Harness | 源码不变；通过官方 DSH CLI 安装不可变插件包到现有独立测试 Profile |

本地提交最多保留 64 条，不淘汰未完成请求；容量已满且全部在发送时，在消费新草稿前拒绝。完成的回执保留 60 秒；失败项可由后续已完成项淘汰。既有外部创建回执缓存仍最多 64 条/60 秒。全部状态按账号 owner 与会话隔离，不增加网络请求、订阅 owner 或定时器。正式时间线仍沿用既有窗口、分页和 DOM 上限；没有创建第二份完整历史缓存。

## 验证

- 合并用例覆盖 ACK、实时推送、后台读的六种顺序，返回 ID 映射、旧版本覆盖、同记录多次出现、删除早于回执、失败/不确定结果后重试、账号/会话隔离、容量和过期。
- 私聊和群聊真实组件覆盖发送中后台读、上一条消息实时到达；逐阶段断言消息始终只有一条，确认前后保持同一气泡实例。
- jsdom 覆盖虚拟分块首条消息正式 ID 改变并启用表态；断言 DOM 节点、焦点不变，未确认时不启动表态请求。
- 最终 `pnpm typecheck` 通过。全量命令：`NODE_OPTIONS=--no-experimental-webstorage pnpm test --maxWorkers=2 --testTimeout=30000 --hookTimeout=30000`，耗时 377.93 秒；1001 文件通过、4 文件失败、15 文件跳过；11,761 项通过、79 项失败、20 项跳过。新增并发与节点身份用例全部通过。
- 79 项失败已在同一依赖树、未修改的 `f8b81f0e` 源码快照中逐一复现，失败名称完全一致：会话发送目录 70 项、社交导航 7 项、Host 操作静态合同 1 项、World 导航 1 项。没有新增失败，但全量门禁未全绿。
- 构建与官方 DSH 包安装由同一最终源码执行，运行结果和包摘要记录在任务交付回执。
- 已证明的是并发语义和节点身份；未将自动化组件测试等同于真实账号端到端验收，也不据此声称跨平台性能提升。实际慢网及连续发送体验由测试页面继续验证。
