Files
Jyotisha/docs/tasks/PROGRESS-report-progress-20260909.md
T
Jesse_ChenandClaude Fable 5 5565b6324e
Independent Staging Quality Gate / validate (push) Successful in 9m50s
Independent Staging Quality Gate / publish (push) Successful in 1m59s
docs(reports): record BUG-601, progress notes and the manual walkthrough
Renumbered from BUG-599: staging took 599 and 600 from other sessions
while this branch was in review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
2026-09-09 03:30:39 +00:00

6.6 KiB
Raw Blame History

PROGRESS · 报告生成分章进度(2026-09-09)

  • 分支:codex/report-progress-20260909,基线 origin/staging = a43a6db8
  • 模式:直接执行模式(用户指定 subagent 执行),无独立任务书;设计口径来自会话内定稿
  • BUG 编号:BUG-601(开工核对当时最大号 598,原写 599;交付前 rebase 发现 staging 已有别的会话占用 599「回访登录自动打开生时校正」与 600「新用户保存账户资料 500」,故顺延到 601)

一、做了什么

/reports/[reportId] 的生成等待屏从「spinner + 秒表」改成分章进度。

后端(本轮唯一的服务端改动)

  1. app/api/reports/[reportId]/route.tslistSections 原先只返回 {status, lastErrorCode},现补上 sectionIdattemptCount。两者都只在服务端消费。
  2. lib/personal-report-route-core.ts
    • 分章行原先只在 row.status === "failed" 时才读reportView 也不含任何分章字段——也就是说生成中根本没有章节数据离开服务端。现改为 failedgenerating 两种状态都读;ready 路径不变,不增加查询。
    • 新增 sectionProgress 推导,随 reportView 第四参数下发,只带 {id, state}

新增共享层

  1. lib/personal-report-progress.ts(新):
    • REPORT_THEME_LABELS / reportThemeLabel:从 personal-report-document-view.tsx 提取,原处改为 import不留第二份副本
    • deriveSectionProgressState(status, attemptCount):行状态 → done / failed / writing / waiting。这是全仓唯一读 attemptCount 的地方,且只在服务端跑。
    • classifyReportProgressStage(phase)preparing / writing / finishing
    • describeReportProgress():纯函数,产出标题句与章节清单。
    • reportProgressSignature():进度指纹,用于停滞判定。
    • REPORT_PROGRESS_STALL_MS = 90_000

前端

  1. components/personal-report/personal-report-progress-panel.tsx(新):按章分格的进度条 + 章节清单。无 percent、无定时器、无 transition。
  2. components/personal-report/personal-report-page.tsx:解析 sections(带白名单校验,形状不对就丢弃而不是渲染成谜之行);用 progressMark 记录进度指纹与时刻,停滞判定复用既有的一秒 tick(waitStartedAt + waitedMs 即"现在"),未新增定时器、未新增 effect;写作阶段隐藏 spinner 换成面板。
  3. app/globals.css:新增等待屏进度样式。
  4. frontend/DESIGN.md §9 新增「报告生成等待态」小节。

二、三条实现事实(做错任一条功能就是错的)

  1. section:<id> 命名的是刚写完的那一章。 emitProgresscomplete()/block() 之后调用(personal-report-generation.ts:3459 / 3485 / 3496)。
  2. "已完成数 + 1"同样会指错。 sectionService.list()section_id 字典序返回(personal-report-section-service-core.ts:113),不是写作顺序。所以顺推出来的"下一章"与真正在写的那一章无关。 → 因此本轮改用行状态判定:start_personal_report_sectionattempt_count + 1 并保持 status='pending'(迁移 20260830020000 第 102111 行),所以"正在写"精确等于 pending && attemptCount > 0,不是推断。测试里专门构造了字典序会指错的用例(正确答案 marriage,顺推会得到 timing)。
  3. blocked 计入完成数,进度条照常前进;收尾走既有 summarizePersonalReportFailure()

三、测试数字

基线(a43a6db8 改后 结论
tsc --noEmit 0 错 0 错 通过
npm run lint 0 error / 108 warning 0 error / 108 warning 通过;warning 数不变,且无一条在本轮改动的文件里
npm test tests 2929 2945 +16
npm test pass 2887 2903 +16
npm test fail 28 28 清单 diff 逐条一致
npm test skipped 14 14 不变
next build / ○ Static ○ Static 通过
globals.css gzip 33,324 B 33,641 B +317 B / +0.95%,在 ±2% 内

28 条失败全部是无 Docker 的数据库/部署/迁移套件,基线即红。失败清单已逐条 diff 比对,完全一致,无新增、无消失

新增测试:frontend/tests/personal-report-progress.test.ts 16 项,覆盖任务要求的六类——off-by-one(含字典序陷阱)、blocked 计入进度、全 ready 与部分 blocked 两种收尾、90 秒停滞文案切换且不出现「第 N 次尝试」、准备/写作/收尾三分支渲染、以及后台字段不出服务端。

未改动任何既有断言,因此无「原值 / 新值 / 原因」三栏。特别说明一条:tests/report-polling-contract.test.ts:105assert.doesNotMatch(pageSource, /章节/),本轮把章节渲染整体放进独立组件 personal-report-progress-panel.tsxpageSource 里确实不出现「章节」,该断言原样通过,未被弱化或删除。

四、偏离与判断

  1. 任务交代「sections[] 目前被剥掉了 sectionId,把它加回去」,实际情况更严重一层。 分章数组根本不在 generating 的响应里——resolveReportRead 只在 failed 时读分章行,reportView 也没有该字段。所以只补 sectionId 不够,必须同时让生成中也读分章行并下发。这是比交代范围略大的服务端改动,但不做则整个功能无数据可用。ready 路径未加查询。
  2. 停滞判定没有用 progressPhase 的持续时长,而是用完整进度指纹phase + percent + 各章状态)。理由:重试时 phase 与 percent 都不动,但若同期别的信号变了,仍不该报"停滞"。指纹变化才重置计时,更严格。
  3. 面板不重复渲染标题句。 标题句(「已完成 N / M 章」)只出现在页面的 <p role="status"> 里,面板只画条与清单。这样读屏软件只播报一次,也不会出现同一句话上下各一遍。
  4. --type-body-xs 这个 token 不存在,写样式时误用后已改掉,改用继承字号。未新增 token。

五、没做的

  • 真实报告生成一次都没跑过(无登录态、无 Chrome、无模型凭据)。写作阶段是否真的出现、章节名是否错位、慢章节文案是否真的切换,全部无运行时证据。已写成 docs/testing/report-progress-20260909.md 八节清单,并记入 BLOCKED.md
  • npm run test:db 未跑(无 Docker,基线同样红)。本轮未动数据库结构、未加迁移。
  • 未 push(按会话纪律,代码分支不自行推送)。