58081a2d51
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
4.6 KiB
4.6 KiB
任务书 · MD-only 首跑失败取证与修复(2026-09-07)
基线:origin/staging @ 7cf7705a(开工 git fetch 后以 HEAD 为准)。
事故实证
- 2026-09-07 05:14 UTC 用户创建 personal_full(5 主题),MD-only 路径第一次真实运行:
failed / calculation_unavailable,progressPercent=30 / progressPhase=failed(引擎调用阶段)。报告 idde2c2efb-9f1e-4cc6-8dc3-72bdfdb3b977,requestIdd17c27ef-2ceb-4dd8-af4d-12107b4de7e4。当时部署72dd5e9d(含 BUG-574 修复与 MD-only worker)。 - 委托方本地复现排除了代码路径:最新 staging 代码起本地引擎,按
buildLongformBirthPayload同形 payload(虚构盘 + provisional + candidate_range + packs:["full"] + markdown)POST/api/professional_report_reference→ HTTP 200、3.3 秒、315KB。代码与合同没问题,失败是 staging 环境特有。 - detail API 未透出附录错误码(观测缺口,本轮补)。
两个可判别嫌疑(任务 0 一条查询定案)
generatePersonalReportLongform 失败时把错误类别写进 personal_report_longform_appendices.last_error_code:
| last_error_code | 含义 | 指向 |
|---|---|---|
upstream_unavailable / upstream_busy |
引擎 HTTP 非 200 | 嫌疑 A:staging api 容器版本滞后(web 随 deploy 更新,api 容器若未随部署重建,端点行为/参数支持与 web 不配套)或引擎在该输入上 500 |
generation_failed |
非 LongformGenerateError(180s AbortSignal.timeout 的 TimeoutError 落这里) |
嫌疑 B:staging 上全量 pack 超 180 秒(外部 VedAstro 网关串行拉满;本地 3.3s 是因外部层快速 blocked) |
empty_markdown |
200 但空文 | 引擎版本/参数不配套的另一种表现(同嫌疑 A) |
任务 0(P0,门控)· staging 取证定案
- 查 requestId
d17c27ef…的 appendix 行:status / attempt_count / last_error_code。 - web 容器日志该时段
[personal-report]行;api 容器访问日志有无对应POST /api/professional_report_reference及其耗时/状态码。 - api 容器运行版本:镜像构建时间 / 容器内代码是否含
professional_report_reference最新实现(gaps2 的e4d16b75级别);对照 deploy 管线是否会重建 api 容器。 - 从 web 容器内对
api:5200手工 POST 同形 payload(虚构盘)计时与状态码。
PROGRESS 写明定案(A / B / 其他),再进任务 1。
任务 1(P0)· 按定案修复
- 定案 A(api 容器滞后):把 api 容器纳入部署链(或把"api 容器更新步骤"固化进 deploy 流程与 runbook),更新后复测;防复发:health 增加引擎版本/构建指纹字段,web 与 api 版本不配套时可见。
- 定案 B(超时):不许一上来就调大 180s——先量真实耗时构成(外部网关占比);优先让报告路径的引擎调用带
defer_optional_external_evidence(或等价参数)跳过/并行可选外部证据(引擎已有该机制,consultation 前台路径在用),把确定性本地全量控制在可预算时间内;外部层缺席按诚实标签落 blocked 行(gaps2 静默跳过禁令继续适用)。超时值若仍需调整,用实测数据定,写 PROGRESS。 - 任何情况下:
calculation_unavailable保持 retryable 语义,但确认 job 三次尝试真实发生且每次都调用了引擎(时间戳对齐)。
任务 2(P1)· 观测补口
- detail API(失败报告)透出 appendix 的
last_error_code(错误码级,不含内容),报告页失败态显示可读原因——本轮取证难就难在这个码埋在表里。 - worker 引擎调用记录耗时与 HTTP 状态(数值日志)。
任务 3(P0 收尾)· 收官 smoke 重跑
修复部署后按 docs/operations/personal-report-staging.md smoke:列表/详情/创建,创建走到 ready——这是报告线的最终收官项:~30s(或实测预算内)ready、详情页 TOC/宽表、导出 .md、0 用量计费结算、新卡片 card_summary 显示。
硬红线
既有全部延续(迁移规范、诚实标签、静默跳过禁令、不改 .gitea/workflows/**、不提升 main、./node_modules/.bin/tsc、真实用户资料不入库、日志无内容)。取证要快——容器 recreate 丢日志的教训已发生过一次。
收尾
docs/tasks/PROGRESS-report-longform-e2e-fail-20260907.md;docs/BUG_HISTORY.md 条目(编号对远端);不提升 main。
交付物清单
- 任务 0 四项取证与定案
- 按定案的修复 diff + 防复发项(api 版本可见性 或 外部证据 defer + 实测耗时表)
- 观测补口 + 测试
- 收官 smoke 全项记录