docs(bugs): 补 BUG-939/940/941(脏思维链删词、正文夹带方法学记账、110s 闸门致空回答)
三条均为已定位未修复,修复决策统一收在 TASK-consult-three-channels-20260918。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PD5E87p38yFHcjZ6rnvXcz
This commit is contained in:
@@ -12285,3 +12285,51 @@
|
||||
- 相关记录:BUG-214、BUG-268、BUG-282、BUG-937
|
||||
- 复发自:无
|
||||
- 修复版本:`8b11ae7d`
|
||||
|
||||
## BUG-939 | 思维链过滤器在句内删词:≥4 字母英文词被挖掉,连词与孤儿标点留给用户
|
||||
|
||||
- 状态:open(已定位,未修复;设计见 `docs/tasks/TASK-consult-three-channels-20260918.md`)
|
||||
- 首次发现:2026-09-18
|
||||
- 最近更新:2026-09-18
|
||||
- 影响面:`frontend/src/lib/public-thinking.ts`、`stream-agent-response.ts` 的 `reasoning-delta → thinking.delta` 两处映射、`consultation-run-timeline.ts` 的 think 行。所有展示思考的咨询运行。
|
||||
- 用户现象:staging run `1b81e263` 的思考区是词沙拉:`"这周哪些事最好先放一放" — are put .`、`"深入看今日" and the a .`、`统一参数 for 's - I can .`。产品负责人的原话是「思维链里的内容也很脏,导致用户在看正文时很迷惑」。
|
||||
- 触发条件:模型的推理句是中英混排(引用了用户的中文问题 + 英文推理),即绝大多数句子。
|
||||
- 根因:`sanitizeCompletedSentence()` 在句子通过 CJK 门之后,仍执行 `.replace(/[A-Za-z]{4,}/g, "")`——删掉所有 ≥4 字母的英文词,而 `are`/`put`/`the`/`for`/`I can` 这些三字母以内的连词全部留下;`releaseCompleted()` 又按 `buffer.search(CJK_RE)` 从第一个汉字处截断,留下句首的孤儿引号与破折号。BUG-612/613 的按句缓冲只解决了「在哪切」,没解决「切完还删词」。更上游的问题是:展示给用户的「思考」是从 provider 的 reasoning token 抓取再过滤得到的,而 provider CoT 本来就不是产品文案,任何过滤器都只能在「英文流水账」和「中文碎片」之间二选一。
|
||||
- 修复:决策已锁(TASK 文档 P1/P2/P3)——provider reasoning 永不外发,只进服务端日志;展示用的思考改为模型有意写给用户的结构化条目(Pass 1 计划 + Pass 2 证据解读),一次发一条完整条目而非 chunk;`public-thinking.ts` 整个删除,`thinking.delta` 退出事件协议。条目过 zod,校验不过**整条丢弃**,不得改写其中的字。
|
||||
- 验证:待实现。回归口径:思考面板每条必须成句、含 CJK、无孤儿标点;断言事件流里不存在任何 `reasoning-delta` 转发。
|
||||
- 防复发:正则只能当门(接受/拒绝/重来),不能当刀(就地删改)。展示给用户的文本不得由「抓取模型内部输出 + 过滤」得到。
|
||||
- 相关记录:BUG-612/613(按句缓冲,本条的上一轮修复)、BUG-277(同类:用缓冲实现「不该展示」)、BUG-940、BUG-941
|
||||
- 复发自:BUG-612/613
|
||||
- 修复版本:待实现
|
||||
|
||||
## BUG-940 | 本命正文首节是参数罗列、尾节是技法审计表:方法学记账被当成用户读物
|
||||
|
||||
- 状态:open(已定位,未修复;设计见 `docs/tasks/TASK-consult-three-channels-20260918.md`)
|
||||
- 首次发现:2026-09-18
|
||||
- 最近更新:2026-09-18
|
||||
- 影响面:`frontend/src/lib/consultation-thinking-plan.ts` 的 `REPORT_HEADING` 与 `consultationComposeHeadingGroups`、分段写作产出的正文。所有本命路线咨询。
|
||||
- 用户现象:正文读起来像模型的思考过程。第一节标题「统一参数与原始结构」(岁差、上升、宫位罗列),倒数第二节「技法审计表」,用户反馈「感觉正文里也有思考的内容」。
|
||||
- 触发条件:任何本命路线咨询。日签路线不受影响。
|
||||
- 根因:`REPORT_HEADING = { foundation: "统一参数与原始结构", audit: "技法审计表", wrap: "现代生活" }` 把方法学记账直接排成用户可读章节;同文件的 `DAILY_HEADING`(今日趋势 / 适合推进 · 需要避开 / 一个行动)已经是干净口径,本命路线没跟上。审计与参数本来就是结构化数据(`workflowReceipt`、`techniqueAuditTable`),让模型把它们复述成散文既占正文篇幅又降低可读性。
|
||||
- 修复:本命写作计划改成面向问题的章节;`统一参数与原始结构` 与 `技法审计表` 退出正文,改由折叠的证据面板直接渲染结构化回执。正文出现方法学记账一律由合规校验 pass 判不通过。
|
||||
- 验证:待实现。回归口径:正文中方法学记账段落数 = 0;证据面板能从回执渲染出同等信息。
|
||||
- 防复发:结构化数据不得让模型复述成散文;正文只承载结论。
|
||||
- 相关记录:BUG-939、BUG-941
|
||||
- 复发自:无
|
||||
- 修复版本:待实现
|
||||
|
||||
## BUG-941 | 一个 110s 闸门被计算吃光,分段写作全部静默 abort,回执分不清「没写」与「被掐」
|
||||
|
||||
- 状态:open(已定位,未修复;设计见 `docs/tasks/TASK-consult-three-channels-20260918.md`)
|
||||
- 首次发现:2026-09-18
|
||||
- 最近更新:2026-09-18
|
||||
- 影响面:`frontend/src/app/api/consult/route.ts` 的 `agentAbortSignal` 与 `composeSection`、`stream-agent-response.ts` 的 `composeByHeadings` / `section-empty-retry`、`consultation-tools.ts` 的领域时长与写回答预留常数。所有多领域本命咨询。
|
||||
- 用户现象:staging run `1b81e263`:计算成功(`tool.completed`,61710ms),随后 5 节写作全部空转,回执里 5 条 `section-empty-retry` + 1 条 `answer-retry`,最终 `run.failed / empty_answer`「计算已完成,但这次没有生成回答」。用户等满约 110 秒、不扣点、什么也没拿到,并反馈「生成速度还是很慢」。
|
||||
- 触发条件:计算阶段耗时接近领域预算上限(本轮 2 领域 ≈31s/个),之后还要走 5 节分段写作。
|
||||
- 根因:整轮只有一个 `AbortSignal.timeout(AGENT_TIMEOUT_MS = 110_000)`(`route.ts:898`),被首轮、工具、每一节写作、续写、重试共用;预算常数按 21s/领域算(`consultation-tools.ts:93`),实测 ≈31s,`domainFitsRunBudget` 的外推(31+31=62 ≤ 65)刚好放行第二个领域,计算结束时只剩约 40s,而分段写作还需要 ≥5 次完整模型往返。被 abort 的流不抛错、不产生 `error` 块(`stream-agent-response.ts:408` 若有 error 会记 `model-stream-error`,本轮回执一条都没有),因此每节表现为「模型什么都没写」,触发 `section-empty-retry` 与 `answer-retry`,最后归成 `empty_answer`。`CONSULTATION_ANSWER_RESERVE_MS = 45_000` 是给「一次成文」设计的,分段写作落地后没有重算。
|
||||
- 修复:正文回到一次成文(取消 `composeSection` / `composeByHeadings` / `section-empty-retry`,进度粒度由思考通道提供);引入运行预算账本,每阶段开工前申请时间,不足即降级而非硬跑;每个 stream 用 `min(阶段预算, 剩余总预算)` 的独立 AbortSignal,**任何 abort 追加 `kind:"abort"` 运行步**;领域时长常数按实测重算。建议同批把 run 搬出 HTTP 请求(后台 job + 事件日志 + 断线重放),并把 evidence packet 随 job 落库供追问复用。
|
||||
- 验证:待实现。回归口径:构造「计算占满预算」的假运行,断言降级路径产出正文且回执含 abort 步;断言任何已产出正文片段的运行不得以 `empty_answer` 结束。
|
||||
- 防复发:一个 deadline 不得同时约束多个阶段;静默失败必须留痕——回执要能区分「模型没写」与「流被掐」。预算常数必须与它约束的流程同时更新。
|
||||
- 相关记录:BUG-280、BUG-268(同为超时与空回答)、BUG-939、BUG-940
|
||||
- 复发自:无
|
||||
- 修复版本:待实现
|
||||
|
||||
Reference in New Issue
Block a user