fix(home): land on the blank starter home after login and on bare / (BUG-1052)

Product decision 2026-09-27 (D1-D4), overriding the BUG-1038 login-return
stash and the "latest session" default landing:

- A full load of / without ?c= (login, typed address, bookmark, refresh of
  bare /) lands on the current person's blank starter home; an existing
  empty draft of that person is reused, otherwise one is created locally.
- ?c= and ?new=1 are unchanged; a refresh inside a conversation keeps its ?c=.
- The login-return stash is removed: redirectToLogin and sidebar links no
  longer write it, bootstrap no longer reads it and clears a leftover value
  once. replace-selected, the lookup origin/other-subject branch and the warm
  resumeRectification dependency go with it.
- A background answer being recovered no longer takes over the blank home
  (same rule BUG-1015 set for ?new=1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-09-27 00:51:51 +08:00
co-authored by Claude Opus 5.5
parent 76924e3362
commit d2551437c4
32 changed files with 629 additions and 315 deletions
+29
View File
@@ -14127,3 +14127,32 @@
- 相关记录:BUG-305(原记录)、BUG-944(「每个 stream 自己的预算」未落到 compose)、BUG-612(同一 tripwire / 110 秒形状)、BUG-280(回答重试没有独立时间预算,本单一并挂到答案时钟上)。
- 复发自:BUG-305(半截回答被当成功并扣点;原防线只拦「抛出的超时」与 `length`,没拦 Mastra 不抛错的 abort)。
- 修复版本:`1530a0dd`,随 `e8195783` 部署 staging(run 2954)。
## BUG-1052 | 登录后 / 打开裸 `/` 落在上一次对话里(真机:以为在首页提问,其实在旧生时校正会话里)
- 状态:investigating(执行方已修复并本地验证,待 Claude 独立验收与 staging 部署;真机清单 `docs/testing/home-landing-blank-20260927.md` 由产品走)
- 首次发现 / 最近更新:2026-09-27 / 2026-09-27
- 影响面:首页整页加载落点(`frontend/src/lib/chat-session-url.ts` `resolveBootstrapSessionSelection` / `bootstrapSelectionFromLookup`、`frontend/src/lib/home-bootstrap.ts` `resolveStarterHomeLandingSessionId` / `starterHomeLandingNeedsConsultation`、`frontend/src/lib/home-bootstrap-run.ts` `resolveLanding` 与暖返回 `commitWarmLanding` / 恢复段、`frontend/src/lib/home-warm-start.ts` `resolveWarmLanding`、`frontend/src/lib/home-cloud-sync.ts` `redirectToLogin` / `resolveLookupBootstrap`)、侧栏次级页与「去登录」链接(`app-sidebar.tsx` `leaveChat`)、首页内新建对话(`use-session-management.ts` `startNewChat` / `openChatBoundToProfile`)。
- 用户现象:staging `e8195783` 真机:用户登录后在他以为的首页输入「我和父母关系如何」,实际是在上一次的生时校正会话里,Agent 回答说不能用父母这件事去核对高考那一条。
- 触发条件(两条路径,代码逐条核实):
1. 登录返回存根:同一标签页里停在 `/?c=<校正会话>` 时发生任何 401(`redirectToLogin()`),或点侧栏次级页 / 「去登录」链接(`leaveChat()`),都会把当前 `?c=` 写进 `sessionStorage["jyotisha.session-url-return"]`。邮箱验证码登录成功后 `email-otp-login.tsx` 跳 `successPath = "/"`,启动时 `resolveBootstrapSessionSelection` 在没有 `?c=` 时读存根 → `replace-selected` → 写回 `?c=` 并自动打开这条校正会话。真机「落在旧校正里」只能来自这条路径。
2. 默认落点:没有 `?c=` 也没有存根时取会话列表第一条(最近一条),`resolveStarterHomeLandingSessionId` 只在它是生时校正时换成「空咨询或任意一条咨询」,只有一条咨询都没有时才新建空白首页。所以裸 `/`(登录、地址栏、书签、刷新裸 `/`)通常打开最近那条旧咨询,而不是空白首页。
暖返回(BUG-1040 `resolveWarmLanding`)逐条镜像同一套规则(含存根与人物范围),同样会落回旧会话。
- 根因:BUG-1038 为「从次级页回来能回到原会话」保留并强化了登录返回存根(找到即写回 `?c=` 并打开),BUG-599 只规定裸 `/` 不自动打开生时校正、却默认落最近一条普通咨询。两条规则叠加,使「登录后」和「裸 `/`」都被当成「回到上次」,而产品期望的是空白首页。诊断与任务单一致,无更正;补充一点:列表行消息未加载(`messagesHydrated: false`)时 `messages` 也是空数组,旧的「空咨询」判定只看 `messages.length === 0`,理论上会把这类已保存会话当成空草稿,本轮一并收紧。
- 决策记录(产品负责人 2026-09-27,推翻 BUG-1038 的登录返回存根与 BUG-599 / BUG-1038 以来「裸 `/` 默认落最近会话」的落点):
- D1 登录后、以及任何不带 `?c=` 打开 `/`(地址栏、书签、历史、刷新裸 `/`)一律落**空白首页**(空咨询 + 开场问候),不落旧对话;已有同一人物的空草稿就复用,不重复新建(与 `?new=1` / `startNewChat` 同一个去重函数,首问前不落库沿用 BUG-989)。
- D2 `/?c=<id>` 仍打开该对话(分享链接、侧栏链接、站内跳转不变);`?new=1` 不变。
- D3 删除登录返回存根:401 / 重新登录不再回到旧对话;删掉不再使用的写入与读取,只在启动时清一次旧浏览器残留的值;人物档案的范围规则(空白首页绑定当前人物)保持。
- D4 在对话里刷新:地址栏已有 `?c=`(`writeSessionUrl` 写入),刷新留在该对话——核实仍成立。
- 执行方解读(请验收时确认):裸 `/` 启动时若有一条旧咨询的回答仍在后台生成,按 D1「不落旧对话」处理成与 BUG-1015 `?new=1` 相同:恢复照常在后台进行,但不抢空白首页的落点;只有地址栏点名了会话(`?c=` keep / lookup)时恢复才会切过去。
- 修复:
- `resolveBootstrapSessionSelection` 去掉 `storedReturnId` 入参与 `clearStoredReturn` 字段:`?new=1` → new-chat;`?c=` → keep / lookup / replace-clear;其余 → none。`replace-selected` 只服务存根,随之删除;`bootstrapSelectionFromLookup` 去掉来源参数与 `other-subject`。
- 落点:`resolveStarterHomeLandingSessionId` 对 none / replace-clear 只选当前人物的空草稿(新 `isStarterHomeDraft`:consultation、未归档、消息已加载且为空),否则 `starterHomeLandingNeedsConsultation` 返回 true → 本地新建空咨询;冷启动用 `replaceUnsavedEmptyConsultations` 前插(不留重复草稿)。暖返回同一套函数。
- 恢复:新 `landingYieldsToRecovery(urlAction)`,冷、暖两处把「new-chat 不被恢复抢落点」推广到所有非 keep / lookup 落点。
- 存根:删除 `persistLoginSessionReturn` / `readLoginSessionReturn`;`redirectToLogin`、`leaveChat` 不再写;`startNewChat` / `openChatBoundToProfile` 不再清;冷启动 `resolveLanding` 无条件 `clearLoginSessionReturn()` 清旧值;暖返回为存根准备的 `resumeRectification` 依赖一并删除(`page.tsx` 少一行,`Home()` useState / useRef 数不变)。
- 验证:`frontend/tests/new-chat-from-people-lifecycle.test.tsx` 新增 5 条真实 React 生命周期用例(真实 `Home` + `AppSidebar` + `SessionListProvider`,文档加载重置模块状态、保留 storage):裸 `/` 最近是有消息的普通咨询 → 空白首页;最近是生时校正 → 空白首页且不开 Case;`/?c=` 打开并刷新保留;校正会话内刷新保留;校正会话内 401 → 重新登录 `/` → 空白首页。改写 1 条为「旧存根被忽略并清除」。`home-warm-return-lifecycle.test.tsx` 新增冷启动裸 `/` 空白首页、改写暖返回裸 `/` 空白首页(首帧无加载环)。纯函数:`home-bootstrap-reveal`(未加载消息的行不算草稿、恢复让步规则)、`home-warm-snapshot`(暖落点复用本人空草稿、不复用他人草稿)、`new-chat-recovery`(裸 `/` 不被恢复抢、`?c=` 仍被恢复接管)。新增 / 改写的生命周期用例在 `origin/staging` 代码上 12 条失败,修复后全绿。全量、Python、构建、gzip 与本地 Chrome 截图见 `docs/tasks/PROGRESS-home-landing-blank-20260927.md`。
- 防复发:生命周期测试锁「登录 / 裸 `/` → 空白首页」「`?c=` 与刷新保留」;源码合同反向锁 `persistLoginSessionReturn` / `readLoginSessionReturn` / `storedReturnId` / `replace-selected` / `stored-return` 不再出现、`leaveChat` 只关抽屉、`redirectToLogin` 不写存储。BUG-1038 的测试把「回到原会话」当成要守的行为(存根写入、找到即写回 `?c=`),BUG-599 的测试锁「裸 `/` 打开所选普通咨询」,所以没有任何测试会拦「登录后落在旧会话」;这两处断言已按三栏说明改为新行为。
- 未改:站内浏览器「返回」退到一个不带 `?c=` 的历史条目(popstate,`applySessionPopStateRef`)仍按原规则选列表里第一条非校正会话;这不是整页打开 `/`,不在 D1 列举范围内,如需同样落空白首页另开单。
- 相关记录:BUG-1038(登录返回存根与 `bootstrapSelectionFromLookup` 来源参数,本条推翻其存根部分)、BUG-599(裸 `/` 不自动开校正、默认落咨询,本条收紧为空白首页)、BUG-1015(`?new=1` 新建意图与恢复不抢落点,规则被推广)、BUG-1040(暖返回,同规则、首帧无加载环不变)、BUG-989 / BUG-929 / BUG-1001(首问前不落库、空草稿不进列表)、BUG-705(`?c=` lookup 不变)、BUG-936(首屏兜底不变)。
- 复发自:无(产品规则变更 + BUG-1038 / BUG-599 规则叠加的组合路径)。
- 修复版本:`codex/home-landing-blank-20260927`(本地提交,未推送)。
@@ -0,0 +1,92 @@
# 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/部署测试失败,与基线名单逐条一致。
+1
View File
@@ -126,6 +126,7 @@
| 任务书 | 进度 | 主题 | 状态 | 落点 |
| --- | --- | --- | --- | --- |
| — (产品 09-27 拍板 D1–D4,直接执行) | [PROGRESS](PROGRESS-home-landing-blank-20260927.md) | **登录后 / 裸 `/` 落空白首页**:真机登录后在「首页」提问其实问进了上一次生时校正。删登录返回存根(401 / 次级页链接写、登录后写回 `?c=` 打开),裸 `/` 不再落最近会话,一律当前人物的空白首页(复用空草稿);`?c=` / `?new=1` / 对话内刷新不变;推翻 BUG-1038 存根与 BUG-599 默认落点 | 待验收 | `codex/home-landing-blank-20260927`(BUG-1052,本地未推) |
| — (产品 09-26 口头拍板 D1–D3,直接执行) | `PROGRESS-consult-answer-truncation-20260926.md` | **普通咨询回答写到一半被掐断仍扣点(BUG-1051,复发自 BUG-305)**:工具循环与写回答共用 110 秒 signal;Mastra 1.50 超时不抛错(`abort` 块 + `finish(tripwire)` 后正常关流),结算只认抛错与 `length`。D1 写回答自有 70 秒时钟(首用起算,续写 / 回答重试共用,最坏 180 秒,`maxDuration` 240);D2 写回答的最后一个流不是 `stop` 且有正文 → `answer_truncated`、不扣点、记 abort 步、不冲半句,`length` 续写不变;D3 观测加 `composeFinishReason` / `composeAborted` / `answerVisibleChars` | 已验收(真机欠) | `codex/consult-answer-truncation-20260926`(本地,未推送);新回归 15 条用真实 Mastra `Agent`(修复前 11 条红);全量失败名单 0 新增;Python 948/1;`/` ○、gzip 0%;真机清单 `docs/testing/consult-answer-truncation-20260926.md` |
| `TASK-consult-evidence-card-research-20260927.md` | `PROGRESS-consult-evidence-card-research-20260927.md` | **普通对话数据卡调研**:引擎输出逐项分五类计量(现约 4 万 token、父母问题相关约 3.5%);四处领域→技法来源对账并起草各领域数据卡(家庭拆父母/子女);卡体量与逐字一致性;按卡算的提速空间;反馈迭代埋点方案。只调研不改线上 | 待领取 | 分支 `codex/consult-evidence-card-research-20260927`;与 BUG-1053 实现单并行,不碰 consult route / stream-agent-response |
| `TASK-scroll-anchor-hook-fixes-20260926.md` | `PROGRESS-scroll-anchor-hook-fixes-20260926.md` | **滚动锚两处老问题**:直接打开已有会话时监听未挂上(BUG-1043)、校正长回答钉顶后因 96px 阈值被拉到底(BUG-1044)。排在 BUG-1042 合入后。挂载改由容器元素本身驱动(每次提交比对元素 / active / resetKey);钉顶只由用户滚动手势解除 | 已验收(Claude 09-26 直接执行:子代理复现两处根因并修复;Claude 独立复验 tsc/lint 0、全量 3970 条失败名单与基线逐条一致、四路由 ○、gzip 不变;iOS 惯性滚动留真机清单) | `da2613ff`(随 `f1d16405` 部署,health 一致) |
@@ -0,0 +1,62 @@
# 真机清单 · 登录后与打开网址都进空白首页(BUG-1052)· 2026-09-27
部署含 `codex/home-landing-blank-20260927` 的 staging 后照做。先确认 `https://staging.jyotisha.chat/api/health` 的 `deployment.gitCommit` 是这次部署的提交。
## 这次改了什么(给自己看的一句话)
以前登录后、或直接打开网址,会回到上一次的对话(甚至是上一次的生时校正),看起来像首页其实不是。现在:不带对话链接打开网站,永远是空白首页;带对话链接(地址里有 `?c=`)才进那条对话。
准备:用一个已经有至少一条普通对话、一条生时校正记录的账号(本机用 iPhone Safari 或电脑 Chrome 都可以)。
## 1. 退出再登录,落在空白首页
1. 先点开侧栏里那条**生时校正**,确认进到校正界面(地址栏里有 `?c=`)。
2. 左下角账户菜单 →「退出登录」。
3. 用邮箱验证码重新登录。
预期:
- 登录后看到的是**空白首页**:标题「新对话」,中间是「最近还好吗,…?」问候、输入框占位「想聊什么都可以」、下面两个入口按钮。
- 地址栏是 `https://staging.jyotisha.chat/`,**没有** `?c=`。
- 侧栏里那条生时校正仍在,只是没有被选中。
- 在输入框问一句普通问题(例如「我和父母关系如何」),回答是普通对话,**不会**提到高考、生时校正或「不能用这件事核对」。
## 2. 登录过期后重新登录,也不回旧对话(能做就做)
1. 打开那条生时校正(地址栏有 `?c=`),停在这里。
2. 在另一个标签页退出登录(或等登录过期),回到第一个标签页随便点一下,让它跳到登录页。
3. 重新登录。
预期:落在空白首页,地址栏没有 `?c=`,不是刚才那条生时校正。
## 3. 地址栏直接打开网址 / 书签,都是空白首页
1. 在任意一条旧对话里,把地址栏改成 `https://staging.jyotisha.chat/`(去掉后面的 `?c=…`)回车。
2. 从书签或浏览器历史里打开 `https://staging.jyotisha.chat/`。
3. 在空白首页上直接按刷新。
预期:三次都是空白首页「新对话」,不是最近那条对话;刷新后也没有多出空对话(侧栏里不会冒出一排「新对话」)。
## 4. 对话链接照常打开
1. 在侧栏点一条旧的普通对话,地址栏出现 `?c=…`。复制这个地址。
2. 新开一个标签页,粘贴打开。
预期:直接进这条对话,能看到原来的问答,标题是这条对话的标题。
## 5. 在对话里刷新,留在这条对话
1. 在一条普通对话里按刷新:仍在这条对话,问答都在。
2. 在那条生时校正里按刷新:仍在生时校正界面,标题、时间轴都在。
## 6. 从其他页面回首页(不应退步)
1. 点侧栏「星盘」,再点「新建对话」:马上是空白首页,没有加载转圈。
2. 点侧栏「星盘档案」,再点左下角账户头像那一块(回首页):马上是空白首页,没有加载转圈,也不是刚才那条对话。
3. 在「星盘」页点侧栏里的某条历史对话:直接进那条对话。
## 发现问题时请记
- 截图(整屏,带地址栏)。
- 做到第几步、点了什么。
- 地址栏里有没有 `?c=`。
Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB