# PROGRESS · 验收修复单:两条契约测试(2026-09-15) - 执行分支:`codex/chat-reading-load-fix-20260915` - 工作树:`.worktrees/chat-reading-load-fix-20260915` - 基线:`origin/staging` @ `ca5ecafc`(任务书写 `6c748d86`;其后两笔是文档) ## 做了什么 只改 `frontend/tests/` 与文档。未碰 `frontend/src/`。未进 BUG_HISTORY。未改 CHANGELOG。 任务 1 · `chat-bundle-splitting-contract.test.ts` - `message-markdown` 包裹计数 1 → 2,三栏注释写在断言上方。 - `plainParagraphs(spoken) ?? []` 改为断言 `renderProse` 内部的 `(plainParagraphs(text) ?? []).map`。 - **没有只改数字。** 补了「两层必须走同一条渲染路」:口语层与报告层都要出现 `renderProse(spoken|report, renderMarkdown)`,精确计数为 2;禁止 `{renderMarkdown(spoken|report)}` 和 `>{spoken|report}`。一层 markdown、一层裸文本会把计数从 2 打到 1。 任务 2 · `chat-navigation-a11y-contract.test.ts` - `window.location.assign("/login")` 在 `homeSurface` 上 4 → 3,三栏注释写在断言上方。 - 同 test 其余断言未改:`redirectToLogin`、`persistLoginSessionReturn` + `replace("/login")`、`signOut` 的 `assign("/login")`、两条 `doesNotMatch` router.push/replace、billing hook 仍是 4。 ## 测试数字 | | 说明 | | --- | --- | | `test(` 声明 | 未新增 test 函数,Linux 门禁口径仍是 3232 | | `chat-bundle-splitting-contract` | 5 pass / 0 fail(全量 TAP 里 `pre-markdown fallback` 已绿) | | `assign("/login")` 计数 | homeSurface 实测 3(consultation-run / profile-onboarding / home-cloud-sync 各 1);`router.push/replace("/login")` 仍不存在 | | `tsc --noEmit` | 0 错 | | `npm run lint` | **0 error** / 120 warning(既有,未动) | | 本机 Windows 全量 TAP | 3041 tests / 2874 pass / **153 fail** / 14 skip。与本机既有环境缺口同型(CRLF、`SKILL.md` EPERM、Docker/DB、`G:\\G:\\`)。`auth redirects…` 仍红是因为同 test 里未改的 `persistLoginSessionReturn();\n window.location.replace` 碰上工作区 CRLF,不是 4→3 没改对。 | Linux 全量失败必须回到 **27**(基线 `ebd5ba68` 的 Docker / DB / 部署 / rsync 缺口,两条契约漂移去掉后)。本机 153 不能当作 27 的证据;以 Gitea Linux 门禁为准。 ## 既有断言三栏 | 位置 | 原值 | 新值 | 原因 | | --- | --- | --- | --- | | `message-markdown` 包裹数 | 1 | 2 | 口语层 + 完整分析各一个壳;仍精确计数 | | `plainParagraphs(spoken) ?? []` | 口语层字面量 | `renderProse` 内 `(plainParagraphs(text) ?? []).map` | 两层共用 renderProse | | 两层渲染路径 | (原 1 个包裹隐含「markdown 与裸段落同一条路」) | `renderProse(spoken\|report, renderMarkdown)` 恰好 2 次 | 防一层 markdown 一层裸文本 | | `window.location.assign("/login")` | 4 | 3 | 建议问题入口删掉,少一次硬跳转,不是改成 router.push | ## 偏离 无。未走让步 1(两层路径的新断言已落地,不是只改数字)。