Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
10 KiB
PROGRESS · 登录后 / 裸 / 落空白首页,删除登录返回存根(BUG-1052)· 2026-09-27
- 执行方式:直接执行(产品负责人授权子代理执行;Claude 事后独立验收)
- 基线:
origin/staging5f2e007f开工;提交前变基到76924e33(只多一份任务书文档,代码与测试结果不变) - 分支:
codex/home-landing-blank-20260927(本地提交,未推送) - BUG 编号:1052(开工时最大号 1051)
- 决策:产品 2026-09-27 D1–D4,推翻 BUG-1038 登录返回存根与「裸
/默认落最近会话」,写在docs/BUG_HISTORY.mdBUG-1052 决策记录
结论
| 项 | 结果 |
|---|---|
| 根因 | 与任务单诊断一致:① 登录返回存根(401 / 侧栏次级页与「去登录」链接写入,登录后 replace-selected 写回 ?c= 并打开)——真机「落在旧校正里」只能来自这条;② 默认落点取最近一条,只从生时校正换到「空咨询或任意咨询」,所以裸 / 通常开最近一条旧咨询。暖返回逐条镜像。补充:旧空咨询判定只看 messages.length,未加载消息的列表行也会被当草稿,已收紧 |
D1 裸 / → 空白首页 |
完成。none / replace-clear 只复用当前人物的空草稿(isStarterHomeDraft),否则本地新建;冷启动用 replaceUnsavedEmptyConsultations 前插不留重复;暖返回同一套函数 |
D2 ?c= / ?new=1 |
不变,有生命周期用例锁住 |
| D3 删除存根 | 完成。删 persistLoginSessionReturn / readLoginSessionReturn、storedReturnId、clearStoredReturn、replace-selected、lookup 来源参数与 other-subject、暖返回 resumeRectification 依赖;redirectToLogin / leaveChat 不写、startNewChat / openChatBoundToProfile 不清;冷启动无条件 clearLoginSessionReturn() 清旧值。人物范围:空白首页绑定当前人物、只复用本人草稿 |
| D4 对话内刷新 | 核实成立(URL 带 ?c= → keep),生命周期用例 + Chrome 截图 |
| 执行方解读(待验收确认) | 裸 / 时若有旧回答在后台生成:恢复继续,但不抢空白首页(landingYieldsToRecovery:只有 keep / lookup 让步),与 BUG-1015 ?new=1 同规则 |
| 未改 | 站内浏览器「返回」退到不带 ?c= 的历史条目(popstate)仍选列表第一条非校正会话;不是整页打开 /,不在 D1 列举内 |
改动文件
| 文件 | 改动 |
|---|---|
frontend/src/lib/chat-session-url.ts |
选择函数去存根;lookup 结果只剩 found / missing / unavailable;删写 / 读存根,保留清理 |
frontend/src/lib/home-bootstrap.ts |
isStarterHomeDraft、新落点规则、landingYieldsToRecovery;LandingSession 加可选 messagesHydrated / archivedAt |
frontend/src/lib/home-bootstrap-run.ts |
冷落点按当前人物范围、去重前插、无条件清旧存根、恢复让步规则;暖提交删存根分支与 resumeRectification |
frontend/src/lib/home-warm-start.ts |
去 storedReturnId 与存根分支 |
frontend/src/lib/home-cloud-sync.ts |
redirectToLogin 不写存根;resolveLookupBootstrap 去存根来源 |
frontend/src/components/app-sidebar.tsx |
leaveChat 只关抽屉 |
frontend/src/hooks/use-session-management.ts |
新建对话不再清存根 |
frontend/src/app/(app)/page.tsx |
删暖刷新的 resumeRectification 一行(1370 → 1369 行;Home() useState 33 / useRef 37 不变) |
改动的既有断言(原值 / 新值 / 原因均已写在测试行内注释)
| 文件 | 用例(原标题 → 新标题) | 摘要 |
|---|---|---|
chat-session-url.test.ts |
new chat intent overrides … plus login return → … invalid c | 去 storedReturnId / clearStoredReturn |
| 同上 | new chat bootstrap consumes the URL … | clearStoredReturn 条件清 → 无条件清;直接前插 → replaceUnsavedEmptyConsultations |
| 同上 | bootstrap reads a listed ?c= session and ignores login storage → bootstrap reads a listed ?c= session | 去存根字段 |
| 同上 | bootstrap restores a stored login return only when the URL has no c → bare / after login never returns to a stored conversation (BUG-1052) | replace-selected → none,源码反向锁 |
| 同上 | bootstrap clears an illegal or unknown session query | 去存根字段(2 处) |
| 同上 | default bootstrap selection does not write a session URL | 去存根字段;replace-selected 正向 → 反向 |
| 同上 | 401 login redirect stashes the current session id … → 401 login redirect stashes nothing … | 正向 persistLoginSessionReturn → 反向 |
| 同上 | login return storage only accepts a UUID session id → a leftover login-return stash from an older build is only ever cleared | 写 / 读 → 只清、隐私模式不抛 |
chat-navigation-a11y-contract.test.ts |
auth redirects stay hard document loads … | persistLoginSessionReturn();\n replace → clearHomeWarmSnapshot();\n replace + 反向 |
sidebar-contract.test.ts |
reaches chart, ephemeris and reports with links … | leaveChat 先存根 → 只关抽屉 + 反向 |
home-bootstrap-reveal.test.ts |
default landing replaces a latest rectification session … | replace-selected → lookup;none 选普通咨询 → 选空草稿 |
| 同上 | bare home still opens the selected ordinary chat without creating another → bare home with a latest ordinary chat lands on a new blank starter home (BUG-1052) | NeedsConsultation false → true |
session-lookup-unlisted.test.ts |
lookup results … | 去 clearStoredReturn |
| 同上 | a looked-up stashed return writes its URL back … → only a ?c= is ever looked up … (BUG-1052) | 来源参数删除,源码反向锁 |
home-warm-snapshot.test.ts |
warm landing follows the cold rules: ?c= keeps, stash writes back, … → … bare / is the blank starter home, ?new=1 is a new chat | bare CONS → 新建空对话;新增复用本人草稿 / 不复用他人草稿 |
new-chat-recovery.test.ts |
ordinary home landing still activates and announces … → bare / keeps the blank starter home while … recovers (BUG-1052) | active 旧会话 → 空白首页、notice 清空、storedCleared true;另加 ?c= 仍被接管 |
new-chat-from-people-lifecycle.test.tsx |
侧栏新建对话 ×5、他人存根不落锁死页 | 离开时存根 RECT → null(落点断言不变) |
| 同上 | a stashed session of the same person found beyond the first page opens … → a leftover stash … is ignored and cleared … (BUG-1052) | 打开校正并写回 ?c= → 空白首页、不 lookup、清旧值 |
| 同上 | an in-page new chat drops the stashed return … → an in-page new chat leaves no return trail … | 不预置存根,断言新建不写 |
home-warm-return-lifecycle.test.tsx |
a stashed return to a rectification session reopens it … → a warm return to bare / after a rectification session lands on the blank starter home … | 写回 ?c= 打开校正 → 空白首页、首帧无加载环 |
| fixtures(非断言) | home-bootstrap-run / session-list-lifecycle / consultation-recovery / new-chat-recovery / home-warm-snapshot |
去掉 selection 里的 clearStoredReturn 字段 |
新增:生命周期 5 条(裸 / 最近普通咨询 / 最近生时校正、?c= + 刷新、校正内刷新、校正内 401 → 重登)、暖返回冷启动裸 / 1 条、纯函数 2 条(未加载消息的行不算草稿、恢复让步规则)、?c= 恢复接管 1 条。改写与新增的生命周期用例放到 origin/staging 代码上跑:12 条失败(?c= 与刷新两条本就应通过,作 D2 / D4 护栏);修复后全绿。
验证
| 项 | 结果 |
|---|---|
tsc --noEmit |
0 错 |
npm run lint |
0 error(128 warning,改动文件无新增与本单标识符相关的 warning) |
全量 npm test(Node 22.14) |
4078 / 24 fail / 28 skip;基线 4069 / 24 / 28。失败名单与基线逐条一致(全部 Docker/DB);消失的 12 个用例名全部是改名,三栏说明在行内,新增 21 个名 |
| Python 门禁集合 | 948 passed / 1 skipped(与基线一致) |
npm run build -- --webpack |
/、/chart、/ephemeris、/people 均 ○ Static;已删构建产生的 frontend/frontend/ |
首屏 gzip(rootMainFiles 4 个文件 zlib 默认级别求和) |
131,253 B;基线 130,933 B,+0.24%,在 ±2% 内 |
| 定向 13 个文件 | 167 / 0 fail |
本地 Chrome(headless,CDP 拦截 /api/* 返回虚构数据)
next start(本单构建)+ Chrome --headless=new,截图在 docs/testing/home-landing-blank-20260927/:
| 截图 | 场景 | 结果 |
|---|---|---|
1-bare-latest-rectification.png |
列表 = [生时校正(最近), 普通咨询],打开 / |
空白首页「新对话」、地址 /、无转录、未开校正 |
2-bare-latest-consultation.png |
列表 = [普通咨询(最近,有消息), 生时校正],打开 / |
空白首页 |
3-bare-leftover-stash.png |
sessionStorage 预置旧存根 = 校正会话,打开 / |
空白首页,存根被清 |
4-c-link-consultation.png |
打开 /?c=<咨询> |
进该对话、有问答 |
5-c-link-rectification.png |
打开 /?c=<校正> |
进校正界面 |
6-refresh-in-rectification.png |
在 5 上刷新 | 仍在校正界面、地址不变 |
POST /api/rectification/cases/open 共 2 次,只出现在 5 / 6。右下角「合盘历史暂时无法读取」提示是本 harness 未 mock /api/synastry-reports(404)所致,与本单无关。
环境缺口
- 无受控登录账号:真实邮箱验证码登录、真实 401 过期后重登、iPhone Safari 走查留给
docs/testing/home-landing-blank-20260927.md。 - 无 Docker:24 条 DB/部署测试失败,与基线名单逐条一致。
验收(Claude,2026-09-27)
独立复跑(Node 22.14,基于 76924e33):tsc 0;lint 0 error;npm test 4078 / 24 fail / 28 skip,失败名单与基线 ct-test.log(4069 / 24)逐条一致;12 个测试改名均有三栏说明;Python 门禁集退出 0;/、/chart、/ephemeris、/people ○ Static;rootMainFiles gzip(level 9)130933 B,±0%。提交无删除、未碰 .gitea/、vendor/、deploy/。截图核对:最近一条是生时校正时,裸 / 落在空白首页,侧栏历史仍在。认可两处执行方判断:裸 / 时后台恢复中的旧回答不再抢占首页(与 BUG-1015 ?new=1 同规则);站内浏览器后退到无 ?c= 的历史项不在本单范围。真实 OTP 登录、401 过期重登、iPhone 走查按清单待产品走。