Files
Jyotisha/docs/tasks/TASK-scroll-anchor-hook-fixes-20260926.md
T

2.4 KiB
Raw Blame History

TASK · 滚动锚两处老问题:直接打开会话时监听未挂上 + 校正长回答被拉到底(2026-09-26)

基线

  • BUG-1042 修复单(080ea5ca,按钮间距)合入后的 origin/staging。分支 codex/scroll-anchor-hook-fixes-20260926。
  • 只改 frontend/src/hooks/use-conversation-scroll-anchor.ts 与其调用处;与 TASK-rectification-dup-question-20260926 不交叉,可并行。

事故实证(BUG-1042 执行方用 CDP 实测发现)

  • BUG-1043(普通咨询):页面直接打开一个已有消息的会话(刷新、?c= 深链、启动落到最近会话)时,hook 的 scroll 监听与 ResizeObserver 从未挂上(插桩计数 0)。表现:短回答也显示「跳到最新」,滚动不更新它,点了也不跟随。先开 /?new=1 再点进同一会话则正常。疑似原因:加载屏期间容器为 null,effect 提前返回;揭幕后 active / resetKey 未变,effect 不重跑。
  • BUG-1044(生时校正长回答):钉顶后视口距底部 94 px,落在 hook 的 96 px「已回到底部」阈值内,measure() 把它当作读者回到底部 → 释放 holdUnpin、anchored = true → 长回答被拉到底。普通咨询停在约 198 px,不受影响。改前改后行为一致(非 BUG-1042 引入)。

决策记录

  • D1 BUG-1043:监听挂载必须在滚动容器真正出现后发生(容器 ref 变化时重新挂载,或以 callback ref 驱动),不依赖 active / resetKey 变化。
  • D2 BUG-1044:钉顶后在用户主动滚动之前,不得因"距底部小于阈值"自动恢复贴底;判断"回到底部"必须来自用户滚动事件,而不是钉顶 / 留白造成的几何位置。
  • D3 BUG-930 / 931 / 932 / 1042 的全部行为与测试不得弱化。

硬红线

  1. 真实 React 生命周期测试:以"加载屏 → 揭幕"的方式挂载已有消息的会话,断言监听已挂上、短回答不显示「跳到最新」;校正面长回答钉顶后不被拉到底,用户手动滚到底后恢复跟随。
  2. 真实浏览器(CDP 假数据)复测两个场景并截图。
  3. 全量测试与基线逐条一致、新增 0;改动断言三栏;更新 DESIGN 对应说明。

任务分解

  • T1 BUG-1043(D1)+ 测试。
  • T2 BUG-1044(D2)+ 测试。
  • T3 记录:更新 BUG-1043 / 1044(BUG-1042 单已建号,状态 investigating → 修复后按部署结果改);PROGRESS;docs/testing/ 清单。