Files
Jyotisha/docs/tasks/PROGRESS-home-landing-blank-20260927.md
T
Jesse_ChenandClaude Opus 5.5 03c7c0a97e
Independent Staging Quality Gate / validate (push) Successful in 11m42s
Independent Staging Quality Gate / publish (push) Canceled after 23s
docs(tasks): home-landing-blank acceptance
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-09-27 01:00:38 +08:00

97 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROGRESS · 登录后 / 裸 `/` 落空白首页,删除登录返回存根(BUG-1052)· 2026-09-27
- 执行方式:直接执行(产品负责人授权子代理执行;Claude 事后独立验收)
- 基线:`origin/staging` `5f2e007f` 开工;提交前变基到 `76924e33`(只多一份任务书文档,代码与测试结果不变)
- 分支:`codex/home-landing-blank-20260927`(本地提交,未推送)
- BUG 编号:1052(开工时最大号 1051)
- 决策:产品 2026-09-27 D1–D4,推翻 BUG-1038 登录返回存根与「裸 `/` 默认落最近会话」,写在 `docs/BUG_HISTORY.md` BUG-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 走查按清单待产品走。