Files
Jyotisha/docs/tasks/TASK-session-list-single-source-fix-20260917.md
T

98 lines
9.4 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.
# 验收修复单 · 会话列表单一数据源:四条源码合同没跟着外壳搬家,门禁卡住(2026-09-17)
## 0. 基线
- 验收对象:`e4e73f56`(会话列表单)与 `6d81062b`(校正输入框守卫单),当前都在 `origin/staging`head `cc1a8980`
- 分支:`codex/session-list-single-source-fix-20260917`,从 `origin/staging` 起。
- 范围:`frontend/tests/` 四个合同测试;`tests/test_daily_and_rectification_entrypoints.py``frontend/src/app/(app)/page.tsx`F3,只允许减行或持平);`docs/`。不动 provider、不动排序、不动路由组。
- BUG 段:**BUG-933 起**(基线最大号 BUG-932)。
- **本单是 staging 能否部署的唯一拦路石**:`/api/health` 仍是 `dc2f2a16`,今天四个代码提交一个都没上线。
## 1. 验收结论
### 校正输入框守卫单 `6d81062b`**通过**
| 任务 | 结果 |
| --- | --- |
| T1 `send()` 会话类型守卫 | 通过。`consultSendBlockedByRectificationSession` 在扣点与撤回窗口之前拦下,保留草稿,转 `openRectificationSession`;刷新恢复重放同样受守卫,pending 存储里指向校正会话的记录直接丢弃 |
| T2 普通输入框只有禁用态 | 通过。`inputDisabled` / `submitBlocked` 都加了 `activeRectificationSession`,占位文案「正在打开生时校正…」,打开失败出「重新打开生时校正」按钮并先清 `rectificationError` |
| T3 三条回退路径 | 通过,且多修了归档一条。`fallbackSessionId` 优先非校正会话,落到校正会话时走 `selectSession` 的延迟切换 |
| T4 服务端错误码 | 通过。类型不对回 `409 session_not_consultation`(在扣点预留之前,不扣点),真查不到仍 404;客户端 `payloadCode` 把 code 带到 `ConsultationResponseError`,命中后回滚乐观消息、不显示报错、直接开校正面 |
| T5 记录 | 通过。BUG-924 / 925、CHANGELOG、DESIGN、VOICE、真机清单齐 |
| `page.tsx` 行数 | 1830 → 1830 |
残留一条 P3,见 F3。
### 会话列表单 `e4e73f56`**未通过(P1**
实现本身按任务书落地:多键排序(`ordering` 改数组 + `formatOrderClause`)、`(app)` 路由组 + `(app)/layout.tsx` 常驻外壳 + `SessionListProvider``app/``SidebarProvider` 恰好一次、`use-sidebar-data.ts``sidebar-data-cache.ts` 已删、服务端排除 `messages = []` 并单独回一条 `draft` 供启动复用、标题改「类别 · M月D日」并删 `uniquify``toSidebarSessionRow` 两处侧栏共用。两条让步(元数据操作未上移、延迟落库未做)任务书都允许。
**但 `npm test` 多出 4 条红,且这 4 条会让 staging 门禁必红。**
`.gitea/workflows/backend-quality-gate.yml``Validate backend, package, frontend, and database contracts` 步骤在 `set -euo pipefail` 下依次跑 `npm test --prefix frontend``npm run lint --prefix frontend`。这 4 条是纯源码正则合同,不依赖 Docker、不依赖环境,在门禁机上照样红:
| 测试文件 | 断言找不到的东西 | 它现在在哪 |
| --- | --- | --- |
| `chat-navigation-a11y-contract.test.ts` | `<main className="chat-app">` 紧跟 `replyAnnouncement` 的 sr-only 播报 | `<main>``(app)/layout.tsx`,播报仍在 `page.tsx`,只是不再相邻 |
| `rectification-history-open-20260909.test.ts` | `page.tsx``openErrorSessionId={rectificationErrorSessionId}` | `(app)/layout.tsx``registration.openErrorSessionId` 传给 `AppSidebar` |
| `rectification-surface-contract.test.ts` | `page.tsx``openingSessionId={rectificationOpeningSessionId}` | 同上,经 `registration.openingSessionId` |
| `chat-session-url.test.ts` | `page.tsx``const [nextAccount, modelCatalogResult, sessionsPayload]` | 启动改成 `await sessionListReady` + `sessionListBoot()`,这个解构没了 |
四条被保护的性质**都还成立**`/``○ Static`,侧栏行仍拿得到 opening / openError,播报仍在),所以是合同陈旧、不是行为回归。但它们被留在红里,等于把门禁堵死。
根因是流程:执行方只跑了定向测试(进度记录写「定向 26 + 先前 114/115」),没跑全量 `npm test`,也因此没发现同批次带进的两处 TS 错(`session-sidebar-row.ts(30,41)``chart-library-session.test.ts(89,42)`,进度记录写着「tsc 0 错」,实测 2 错,后来由滚动单的 `cc1a8980` 顺手修掉)。
## 2. 任务分解
### F1 四条源码合同跟着外壳搬家(BUG-933)
四条都按「原值 / 新值 / 原因」三栏改写,**不得删除测试、不得弱化成只判存在**:
- `chat-navigation-a11y-contract.test.ts`:改为分别断言 `(app)/layout.tsx` 里有且只有一处 `<main className="chat-app">`,且 `page.tsx``replyAnnouncement` 的 sr-only 播报仍带 `role="status" aria-live="polite" aria-atomic="true"`,并且它是 `SidebarInset` 内容的第一个子节点。
- `rectification-history-open-20260909.test.ts``rectification-surface-contract.test.ts`:改为断言 `(app)/layout.tsx``openErrorSessionId` / `openingSessionId` / `openErrorMessage` 传给 `AppSidebar`,且 `page.tsx``registerShellControls` 载荷里带这三个字段(两端都断,缺一端就等于断链)。
- `chat-session-url.test.ts`:把「首页自己并发拉账户/目录/列表」的断言改成「首页 `await sessionListReady` 后读 `sessionListBoot()`,并且 `page.tsx` 里不再出现 `fetchSessions(`」,保留它原本要守的「`/` 是静态路由上的客户端读」这一性质。
- 验收:`npm test --prefix frontend` 的失败清单与 `cc1a8980` 比**少这 4 条、不多任何一条**;`npm run lint` 0 error。
### F2 两条陈旧的 Python 入口合同(BUG-934
`tests/test_daily_and_rectification_entrypoints.py` 断言首页出现 `daily-starlanguage-card` / `birth-rectification-card`,这两个类名在 `62903b7a`(空状态改成「问候 + 输入框 + 两枚入口 pill」)就已删除,全仓已无。**这是既有欠账,不是本批引入**,也不在 `CORE_PYTEST_TARGETS` 里,所以不挡门禁,但任何一次 Python 定向跑都会红。
- 改为断言当前真实的入口形态(`StarterEntries` 的两枚 pill 与 `startDailyStarlanguageConsultation` / 校正入口),或在确认无对应实现后连同该断言一并删除并在测试里写明原因。选哪种由执行方判断后写进进度记录。
- 验收:`.venv/bin/python -m pytest tests/test_daily_and_rectification_entrypoints.py` 全绿。
### F3 校正守卫的残留死角:一个会话都不活跃时输入框静默吞发送(BUG-935)
`page.tsx``activeSession` 现在是 `sessions.find(id === activeSessionId) ?? sessions.find(非校正)`。当**列表里只剩校正会话**时它是 `undefined`(旧代码 `?? sessions[0]` 不会)。此时:`activeRectificationSession` 为假 → 普通输入框**可用**;按发送 `send()``!currentSession` 直接 `return false`,没有任何提示;因为 `activeRectificationSession` 为假,「重新打开生时校正」按钮也不出现。
触发路径:账号里只有校正会话,或删除当前普通会话后剩下全是校正会话,且此时校正面正在打开或打开失败。窄,但正是本单要消灭的那类死角。
- 修法:`activeSession` 为空且列表里存在校正会话时,按「校正会话占位」处理——输入框禁用、占位文案「正在打开生时校正…」、打开失败出重开按钮;派生值放进现有 hook 或 `rectification-session-composer-guard.ts``page.tsx` 不增行。
- 验收:`rectification-session-composer-guard.test.ts` 加一条纯函数断言(输入「列表全是校正会话、activeSession 为空」→ 锁定态为真);`send()` 在无活跃会话时不得静默返回而不给任何反馈。
### F4 记录
- `docs/BUG_HISTORY.md` 新增 BUG-933 / 934 / 935933 关联 BUG-927 与 BUG-745935 关联 BUG-924)。
- BUG-927 的「防复发」补一条:**外壳搬家必须同步搬走针对 `page.tsx` 的源码合同,且交付前必须跑全量 `npm test``tsc --noEmit`,不得只跑定向。**
- `docs/tasks/PROGRESS-session-list-single-source-fix-20260917.md`;状态板三行改状态。
- T2 的「元数据操作未上移到 provider」目前只写在进度记录里,补进 `BLOCKED.md`,与延迟落库那条并列。
## 3. 硬红线
1. 不得靠删测试或放宽断言过门;四条合同必须仍然守住原来的性质。
2. 不动排序、provider、路由组的既有行为。
3. `page.tsx` 不增行。
4. 交付前必须跑**全量** `npm test --prefix frontend``tsc --noEmit``next build --webpack`,并把失败清单与 `cc1a8980` 逐条比对后写进进度记录。
## 4. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/session-list-single-source-fix-20260917 .worktrees/session-list-single-source-fix-20260917 origin/staging
cd .worktrees/session-list-single-source-fix-20260917/frontend
./node_modules/.bin/tsc --noEmit && npm run lint && npm test 2>&1 | tail -20
```
## 5. 验收口径
`tsc --noEmit` 0 错;`npm run lint` 0 error`npm test` 相对 `cc1a8980` 少 4 条红、不新增;`next build --webpack` 通过且 `/``○ Static`、首屏 gzip ±2%`pytest tests/test_daily_and_rectification_entrypoints.py` 全绿。合入后必须核对 `/api/health``deployment.gitCommit` 等于最近一次含门禁路径的 staging 提交——今天四个代码提交至今一个都没上线。