点选题把分类器两次异常说成用户没说清(BUG-722);引擎 429 被压成坏了且重算静默失败(BUG-723);两次 attempt 总预算大于路由 maxDuration(BUG-724)。本单只改归因:classifier_unavailable 请用户重发、busy 分档并可见「这次没有重新比较」、整轮 225s 预算不够则 host fallback。不改计费、分类模型、并发闸门。
5.5 KiB
5.5 KiB
PROGRESS · 三处把系统故障说成别的东西(2026-09-15 / 2026-09-16)
工作树:.worktrees/rectification-failure-attribution-20260915
分支:codex/rectification-failure-attribution-20260915
任务书基线:6b3248bf(已被后续合入);代码基线 origin/staging @ a8d29d1b
本机 Windows。
Skill 未 bump。未改 frontend/src/app/page.tsx、计费口径、分类所用模型、并发闸门、docs/tasks/README.md 状态列。未 push HEAD:staging。
开工基线
| 项 | 数字 |
|---|---|
frontend/src/app/page.tsx |
1951 行(未改) |
| 最大 BUG 号 | BUG-720(本单占用 722 / 723 / 724;721 留给 engine-memoization) |
tsc --noEmit |
收尾 0 错 |
npm run lint |
0 error(全仓既有 warning 119;本单未新增 error) |
frontend/node_modules 已存在,未新建 junction。
任务状态
| 任务 | 状态 | 说明 |
|---|---|---|
| 6.1 分类器 unavailable vs unclear | 完成 | outcome 三档;点选题与 discriminator 不再合并 null / unclear;采集题 unclassified 未改 |
| 6.3 整轮超时预算 | 完成 | RECTIFICATION_RUN_BUDGET_MS=225s < maxDuration 240s;不足最小重试时长走 host fallback |
| 6.2 引擎分档 + 可见「这次没有重算」 | 完成 | busy/http_error/timeout/bad_payload;429 有限退避;失败正文含「这次没有重新比较」 |
| 6.4 Bug 历史 | 完成 | BUG-722 / 723 / 724 |
实现要点
classifyTurnIntentWithRetry返回outcome。classifier_unavailable专指两次都没拿到结构化分类(抛异常或解析空)。点选题回「这边没接上,把刚才那句再发一次就行。」焦点保持 active,不写证据、不扣点。readEngineJson对齐星盘页的四档失败。score / block_scan 对 429 按Retry-After退避,上限 2 次、总退避 6s(具名常量)。autoRescoreAfterEvidenceChange失败打rectification_rescore_failed,projection 带error_kind。主持人用withRescoreSkippedNotice补「这次没有重新比较」,并剥掉「收窄 / 范围从」进度句。- 整轮 deadline 225s。第二次尝试只在剩余 ≥ 20s 时启动。
210_000只定义在rectification-run-budget.ts,activity-labels与agent-run从那里 import。 agent-run不再顶层 import@/mastra/agentic-rectification(该模块会在加载时创建 skill symlink)。步进预算抽到step-budget.ts,避免 Windows 无 symlink 权限时 stream 测试整文件无法加载。agentic-rectification.ts再导出,既有 import 路径不变。
既有断言改动
| 文件 | 原值 | 新值 | 原因 |
|---|---|---|---|
rectification-answer-choice.test.ts 超时合同 |
agent-run 内 = 210_000,只断言 210s < 240s |
210_000 只在 rectification-run-budget.ts;整轮 225s < 两条路由读出的 maxDuration |
BUG-724 总预算必须小于路由墙 |
rectification-window-cluster-cap-20260909.test.ts 分类调用 |
await classifyRectificationTurnIntent |
await classifyTurnIntentWithRetry |
BUG-722 discriminator 与点选题同一入口 |
rectification-collect-stall.test.ts 点选题切片 |
classified.intent === |
classified?.intent === |
BUG-722 classified 在 unavailable 时为 null |
rectification-v9-status-security.test.ts stale policy 重算失败形状 |
原始 Error 文案 stale policy must rescore |
RectificationEngineError / http_error,且确实打了 /score |
BUG-723 抛错不得把上游原文泄漏给工具层 |
未弱化其它既有断言。timeout after a stamped open_question fails closed 保持现状(不把题干贴进超时回复)。
测试
| 命令 | 结果 |
|---|---|
tsc --noEmit |
0 错 |
npm run lint |
0 error / 119 warning(与既有全仓 warning 同量级) |
任务书所列 tsx 测试(除 rectification-v9-agent.test.ts) |
定向套件绿:classifier / stream(50) / answer-choice / spoken-collect / unwritten-evidence / chart-view-engine / engine-contract / voice-copy / window-cluster / eight-method |
rectification-v9-agent.test.ts |
环境缺口:模块加载 agentic-rectification 时 symlinkSync(..., "dir") EPERM。本机 Node 只能建 junction。该失败在改本单之前就存在,不是本单回归。 |
page.tsx |
仍 1951 行,未改 |
全量 npm test |
# tests 3189 / # pass 3104 / # fail 71 / # skipped 14(修 collect-stall / status-security 两处源码合同后,这两条已绿)。失败集中在无 Docker 的 database-*、部署/Caddy/shell、Windows symlink EPERM(rectification-v9-agent.test.ts、api-service-unavailable 动态 import 路由、skill-binding)。不含本单定向套件。 |
npx next build --webpack |
compile + TypeScript 过;Collecting page data 死在既有 SkillPackageRegistryError EPERM symlink(/api/daily-starlanguage),与本单无关。Turbopack 因 frontend/node_modules junction 指向主仓而直接 panic。未能本机核对 / 是否 ○ Static。 |
环境缺口
- 无 Docker:数据库套件红,不伪装成通过。
- 无登录态、无 Chrome:浏览器级验收不在本单。
- Windows 无 symlink 权限:
symlinkSync(..., "dir")EPERM。凡顶层加载getRectificationV9Agent/RECTIFICATION_V9_SKILL_PATH的测试或next build收集路由都会红。本机 Node 只能建 junction。stream / unwritten-evidence 因 runner 不再顶层加载该模块而可跑。 next build:webpack 编译过、tsc 过;收集页面数据时 skill runtime symlink EPERM。不伪装成/○ Static 已核过。