Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2.4 KiB
2.4 KiB
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 的全部行为与测试不得弱化。
硬红线
- 真实 React 生命周期测试:以"加载屏 → 揭幕"的方式挂载已有消息的会话,断言监听已挂上、短回答不显示「跳到最新」;校正面长回答钉顶后不被拉到底,用户手动滚到底后恢复跟随。
- 真实浏览器(CDP 假数据)复测两个场景并截图。
- 全量测试与基线逐条一致、新增 0;改动断言三栏;更新 DESIGN 对应说明。
任务分解
- T1 BUG-1043(D1)+ 测试。
- T2 BUG-1044(D2)+ 测试。
- T3 记录:更新 BUG-1043 / 1044(BUG-1042 单已建号,状态 investigating → 修复后按部署结果改);PROGRESS;
docs/testing/清单。