# TASK · 修复单:慢网首页 5 条测试未跟上致门禁红 + page.tsx 增长 + 原始附录残留(2026-09-24) ## 基线与现状 - `origin/staging = f125fae0`。staging 线上仍是 `1420471a`:`0e4dd0f4`(慢网首页)之后的**所有代码提交都没部署**,包括 BUG-1020(`fa8fef55`/`133aca49`)与报告操作收敛(`f125fae0`)。 - Claude 09-24 在 Linux / Node 20 独立验收(基线 `edc9c22c` vs `f125fae0`):tsc 0;lint 0 error(warning 119 → 121);`next build` 四路由标记与 gzip 130,932 B 与基线一致;**全量 3807 → 3809 条,失败 56 → 61,新增 5 条红**(下表),其余失败名单与基线逐条相同。门禁会跑同一套前端测试,因此判断门禁红、未发布镜像(Gitea API 匿名 401,run 号请产品在 Gitea 核对)。 - 执行方 PROGRESS 记录了 `npm test` 89 条失败,但**没有与基线逐条比对**,新增的 5 条混在 Windows 环境失败里没被发现;BUG-1021/1022 被提前写成 resolved。 - 分支 `codex/staging-gate-fix-20260924`。 ## 新增 5 条失败(全部是源码合同断言没跟上实现,不是行为回归) | 测试 | 文件 | 原因 | | --- | --- | --- | | auth redirects stay hard document loads so stale session state cannot survive | `tests/chat-navigation-a11y-contract.test.ts` | 断言 `page.tsx` 中 `window.location` 硬跳转共 4 处,实现把「重试」从 `location.reload()` 改成局部重试(任务书 D2),现为 3 处 | | bootstrap failure retries with a hard reload because refresh cannot rerun client bootstrap | 同上 | 正则 `onClick={() => window.location.reload()}>重试`;任务书 D2 **有意推翻**了该断言的前提(局部重试已能重跑 bootstrap) | | new chat keeps its local landing while a reserved older consultation recovers | `tests/new-chat-recovery.test.ts` | 按字符串切 `page.tsx` 源码,结束边界 `if (modelCatalogResult.unavailable)` 已被删除 → `missing source boundary`(我在 BUG-1015 验收时标注过的 P2 脆弱点,这次触发) | | ordinary home landing still activates and announces the reserved consultation | 同上 | 同上 | | tab-local pending ids drive strict bootstrap recovery before the global fallback | `tests/consultation-recovery.test.ts` | 切片起点 `let reservedConsultation: ConsultationStatus | null = null` 已改为 `= await activeStatusPromise` → 切出空串;另断言 `storedPending` 分支先于 `fetchActiveConsultationStatus`,实现改为并行预取 | 同类问题第五次(BUG-933/934/939/992 同型):执行方只跑定向测试,没跑全量并与基线逐条比对。 ## 其它验收问题 1. **P2 红线违反**:`page.tsx` 1849 → 1858 行(+9),任务书红线 4「`page.tsx` 不得净增行」。主要来自「重试」内联的 5 行状态重置。 2. **P2 行为**:`use-billing-panel.ts` 支付轮询成功后改为 `if (typeof payload.credits === "number") notifyBalanceChanged(payload.credits)`;`/api/payment/epay/status` 的 `credits` 是订单点数,**订阅类订单可能为空** → 不发余额事件 → 首页账户不刷新。`page.tsx` 的 `BALANCE_CHANGED_EVENT` 监听只调 `refreshAccount()`、不读传入值,所以应**无条件**通知。 3. **报告操作收敛残留**(`f125fae0` 执行方删除权限被拒):`raw-appendix-download.tsx`、`app/api/reports/[reportId]/raw-appendix/route.ts`、`lib/personal-report-raw-appendix.ts` 已无入口但仍在;执行方也没能写 PROGRESS 与真机清单(工具拒绝写入)。 4. 代码本身(慢网并行、20 秒错误屏、局部重试、不再半揭幕、账单预取与缓存、CRLF 正则)我逐行核对**符合任务书**,不需要改逻辑。 ## 决策记录 - 本单只修测试与收尾,**不改任务书已批准的行为**(D2 局部重试、并行预取、20 秒阈值)。 - 5 条断言按新行为改写,**不得删除测试**;`new-chat-recovery` 与 `consultation-recovery` 的源码切片改为**不依赖会被删改的具体语句**作边界:优先把被测逻辑抽到 `frontend/src/lib/` 纯函数直接调用;做不到时用稳定的注释锚点(如 `// bootstrap:recovery-begin` / `// bootstrap:recovery-end`)并在两处测试共用。 - `chat-navigation-a11y-contract`:硬跳转计数改为 3,并**新增**断言「重试」调用 `reloadSessionList` 且不含 `location.reload`(行为锁,不是弱化)。 - 原始附录三件套连同只测它们的测试一并删除(任务书 D2 已授权);`personal-report-raw-appendix.test.ts` 中仍有价值的投影断言若依赖 `cleanReaderAppendixMarkdown`,保留该 helper 所在模块,只删路由 / 组件 / release 函数。 ## 硬红线 1. 失败清单必须与基线 `edc9c22c` **逐条一致**(56 条),新增 0;进度记录附对比命令与结果。 2. 每条改动的断言写「原值 / 新值 / 原因」三栏;测试总数不低于 3809 − 被删文件的测试数,并列出删了哪些。 3. `page.tsx` 行数 ≤ 1849(`edc9c22c` 基线);`Home()` 不新增 hook。 4. 不改首页 / 账单 / 报告的已验收行为;不改数据库、workflow。 ## 任务分解 - T1 修 5 条断言(抽纯函数或注释锚点)。验收:5 条转绿,`grep -n "modelCatalogResult.unavailable" frontend/tests` = 0。 - T2 `page.tsx` 回到 ≤ 1849 行:重试处理抽到 `frontend/src/lib/` 或现有 hook。 - T3 支付成功无条件 `notifyBalanceChanged`。验收:`billing-panel.test.ts` 新增订阅订单(`credits` 缺失)也触发余额事件。 - T4 删除原始附录三件套与相关测试。验收:`git grep -n "raw-appendix\|RawAppendixDownload\|releaseRawReportAppendix" frontend/src` = 0。 - T5 记录:`BUG_HISTORY` 中 BUG-1021/1022 状态保持 investigating 直到部署 health 核对;补 `docs/tasks/PROGRESS-report-reader-actions-20260924.md` 与 `docs/testing/report-reader-actions-20260924.md`(上一执行方未能写入);本单 PROGRESS。推 staging 后核对门禁绿与 `/api/health` 的 `gitCommit`。 ## 开工前置命令 ```bash git fetch origin --prune git worktree add -b codex/staging-gate-fix-20260924 .worktrees/staging-gate-fix-20260924 origin/staging git worktree add --detach .worktrees/gate-baseline-20260924 edc9c22c # 基线 cd .worktrees/gate-baseline-20260924/frontend && npm test > /tmp/base.log 2>&1 cd ../../staging-gate-fix-20260924/frontend && npm test > /tmp/head.log 2>&1 diff <(grep '^not ok' /tmp/base.log | sed 's/^not ok [0-9]* - //;s/ # .*//' | sort) \ <(grep '^not ok' /tmp/head.log | sed 's/^not ok [0-9]* - //;s/ # .*//' | sort) ``` ## BUG 编号 不新开号;沿用 BUG-1021 / 1022(首页 / 账单)与报告操作收敛的产品变更记录。