Skip to content

[Desktop/Chat][P2] 较早的历史定位请求不得替换较新的目标窗口 #84

Description

@jiayuqi7813

触发与范围

桌面聊天主流的同 thread 历史定位 helper 同时处理两个不同 target:先请求 A,再请求 B;B 先完成并安装窗口后,迟到的 A 仍会安装其旧窗口。两次原 ensureMessageVisible 均返回 ok,最终 around_message_id 和 messages 窗口却回到较早的 A。

按 P2 历史定位状态归属追踪。2026-09-30 仅由原 hook 的内存分页 fixture 确认;没有实际桌面点击、SSE、滚动或私有聊天,没有永久消息/引用丢失、工具或权限事故。范围仅为 desktop-owned 聊天历史定位的请求 generation/窗口提交,共享 Web 文件作定位,不要求本轮修改 Web 或后端。

原 hook 证据与已有保护

fixture 原样转译并执行 useConversation,使用 React test renderer。REST/page、EventSource 与 timer 全为内存边界;当前同 thread 有可用 tip,两目标都不在当前窗口。依次调用原 ensureMessageVisible,再控制 B page 先返回、A page 后返回。

  • B 返回后,原 helper 返回 ok,view.messages 与 around_message_id 指向 B。
  • A 迟到后也返回 ok,原 setter 将窗口替换为 A,较新的 B 不再属于当前窗口。
  • 若 A pending 期间调用原 jumpToLatestMessages,epoch 递增;tip 更新后 A 被返回 cancelled,无法再替换窗口。
  • 若切换 thread,A 返回 missing,当前另一聊天窗口保持不变。

完整分页内容、helper 返回值、view、假请求/timer 和源码哈希只存本地 ignored artifact。此证据是 hook 的数据窗口,不是原生 viewport 已滚到 A 的实测。

根因与影响边界

ensureMessageVisible 捕获 aroundEpochRef,但新的 around 请求自身不推进该 epoch。两同 thread 请求因此具有相同有效标识,晚完成的旧请求仍通过 isLive 和 setView 检查。jump-to-latest 的 epoch 保护工作,不能据此推断两次 around 之间也按最新用户目标取消旧结果。

Timeline 的 anchorRequestRef 与 Shell 深链 cancelled guard 仍可阻止旧任务继续执行高亮/滚动;它们没有作为取消身份传入 hook,无法阻止 helper 内的窗口提交。本轮静态核对这些 caller,未执行真实 Timeline/滚动,不能声称其最终视觉必然错误。

确定的缺口是:较早的页面请求可改变较新定位已使用的数据窗口。分页原文仍在服务中,后续可重新读取;这里不是记录被删除,也未测试引用发送或真实命令。

桌面优化与验收

  • 为每次明确 around 目标分配新的请求身份,或传入调用方取消范围;提交窗口、pending-around、返回状态都绑定到最新有效目标。
  • 失效请求返回 cancelled,不替换较新窗口。保留 jump-to-latest、thread switch 与 supersession 的已有保护。
  • 重跑原 hook 两目标乱序:B 完成后 A 不能替换 B,旧任务返回 cancelled;顺序请求、返回最新、线程切换与失效分支目标继续正确。
  • 在可弃置桌面环境补连续历史/深链定位及真实滚动验收,仅用合成消息;未完成前不宣称实际视口事故或完整恢复保证。

去重与源码

本条为两个同 thread around 任务之间的身份,已有 jump-to-latest epoch 对照通过,不把它另报为失效。不同 thread 的旧响应和 supersession 保护也保持成立。#80 是侧栏旧列表,#81 是 inbox 服务重建游标;均非此定位窗口根因。关联 Epic #31。

固定公开代码仅用于导航,隔离证据保存当前源码哈希:useConversation / ensureMessageVisible、Timeline caller、Shell 深链 caller。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions