docs(tasks): daily deep-dive empty answer + thinking word-salad fix brief (BUG-609/610)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
This commit is contained in:
Jesse_Chen
2026-09-09 08:55:13 +00:00
co-authored by Claude Fable 5.1
parent ee6173e887
commit 48d2ff8038
2 changed files with 57 additions and 0 deletions
+1
View File
@@ -86,6 +86,7 @@
| `TASK-rectification-timeline-20260909.md` | — | 常驻吸顶时间轴:轴锁**当前**搜索窗口并随放宽缩放、时段/分钟两套标记、候选点二元编码不分置信度(BUG-560 blocked)、无 hoverBUG-575)、只读不可采用。实现用第三个 grid 行而非 `position: sticky``useConversationScrollAnchor` 一行不改;条高固定是正确性要求;吸顶条只留区间与宽度两个元素 | 已验收通过;宽度口径与空心点两处未通过→修复单 | `ce91a0d2` |
| `TASK-rectification-timeline-fix-20260909.md` | `PROGRESS-rectification-timeline-fix-20260909.md` | 时间轴修复单:宽度读数改含两端分钟数(与 BUG-593 报告/卡片一致);标记改读推断层候选全集,被淘汰分钟留在原地变空心(客户端投影只含 active,DESIGN §10 描述在真实数据下画不出) | 已验收通过 | `92e3d5e7`BUG-602603 |
| `TASK-rectification-conversation-economy-20260909.md` | `PROGRESS-rectification-conversation-economy-20260909.md` | 对照竞品后产品拍板三条:开场三句讲做法 + 一次收多件(推翻 opening brief「不要一次说完/不举例」与 SKILL L52);采集题「没有 / 记不清」按钮(不做示例骨架条);每轮只留一句(方法句进活动记录、点选旁白去领先落后、证据轮正文一句复述 + 服务端裁剪);Skill 10.0.19 | 已验收通过(2 条 P3 备注) | `aa7ccb30` + `1453fb16`BUG-604606Skill 10.0.19 |
| `TASK-consultation-daily-empty-answer-20260909.md` | `PROGRESS-consultation-daily-empty-answer-20260909.md` | 首页「深入看今日」计算完成却 `empty_answer`:入口定的 `timing` 被模型改成 `general``canonicalDomainPlan` 以模型为准),分段写作标题与今日格式错位,分段 `maxSteps=1` 且工具仍可调 → 模型在分段里再调工具、零正文;思考流按 chunk 过滤漏出缺词英文 | 待执行 | `codex/consultation-daily-empty-answer-20260909`BUG-609610 |
### 聊天主链路与首页
@@ -0,0 +1,56 @@
# TASK · 「深入看今日」计算完成却没有回答(empty_answer),且思考流漏出缺词英文(2026-09-09)
- 基线:`origin/staging` @ `ee6173e8`(staging 部署以健康接口为准)
- 分支:`codex/consultation-daily-empty-answer-20260909`,基于 `origin/staging`
- 执行方:coding agent;验收:Claude
- 涉及文件:`frontend/src/mastra/consultation-tools.ts``canonicalDomainPlan` L291、`AGENT_SLICE_MAX_STEPS` L56、`consultationSliceGenerationSettings` L73)、`frontend/src/app/api/consult/route.ts``composeSection` L1151、`retryForAnswer` L1128)、`frontend/src/lib/stream-agent-response.ts``composeByHeadings` L420、`consumeAttempt` L336)、`frontend/src/lib/consultation-thinking-plan.ts``natalConsultationThinkingPlan`)、`frontend/src/lib/consultation-entrypoint.ts``daily_starlanguage` 扩展 L7280)、`frontend/src/lib/public-thinking.ts`
- BUG 编号起点:**BUG-609**`docs/BUG_HISTORY.md` 当前最大 BUG-608
- 优先级:**P1**(首页入口"深入看今日"整条失败;不扣点是对的,但用户拿不到回答)
## 1. 事故实证(2026-09-09 staging,用户转录;只写结构)
活动区依次:读取分析方法 → 计算本命盘 → 先整理本盘的统一参数 → **接下来分析你的综合** → 用审计表收口后再落到生活("已完成 5 步")。随后思考区出现一段缺词英文(`The a for 2026-09-09 (, per). The is a - an, not a. … The be "" or "timing" - is a/trend. … Let me use: [""]. … "timing"? … Let me run-jyotish-.`),最后正文只有 `计算已完成,但这次没有生成回答,本次不会扣点。请再发送一次。``empty_answer`)。
## 2. 根因
### 2.1 BUG-609P1):入口定的是"时运",模型自己改成"综合";写作阶段想改回来时已经没有步数
1. 首页"深入看今日"发的是 `theme: "timing"` + `entrypoint: "daily_starlanguage"``page.tsx` L14661470),问题被扩展成"深入解读 ${日期} 的今日主题:今日趋势、适合推进、需要避开、一个行动建议"(`consultation-entrypoint.ts` L7280)。
2. `run-jyotish-consultation``canonicalDomainPlan``consultation-tools.ts` L291):模型**显式传了 `domains`** 就以模型为准,只有省略时才用路由选的 `theme`。活动区"接下来分析你的综合"证明本次执行的是 `general`,即模型把服务端定的 `timing` 改成了 `general`
3. 计算完成后进入按标题分段写作(`composeByHeadings`):标题来自 `natalConsultationThinkingPlan({domains: 已执行领域})` = 统一参数与原始结构 / **综合** / 技法审计表 / 现代生活。这套标题与"今日趋势 / 适合推进 / 避开 / 行动"完全对不上。思考流里模型正是在纠结这件事("is a daily/trend … 'timing'? … Let me use: [timing] … Let me run-jyotish-consultation")。
4. 每个分段调用 `maxSteps = AGENT_SLICE_MAX_STEPS = 1` 且**工具仍然可用**`streamOptions` 没有 `toolChoice: "none"`,分段提示只是文字上说"不要再调用排盘工具")。模型在分段里发起了第二次工具调用(想换 `timing`),一步用完,没有任何正文。四个分段全空 → `retryForAnswer` 再跑一次完整循环 → 仍空 → `empty_answer`。这是 BUG-280"计算成功、模型没写"的又一条来路,BUG-280 的重试救不了它,因为重试后模型面对的还是同一套错位标题。
### 2.2 BUG-610P2):思考流按 chunk 过滤,英文被削成词渣
`sanitizePublicThinkingText``public-thinking.ts`)对每个 `reasoning-delta` chunk 判断"含 ≥4 字母英文且无中文就丢"。流式 chunk 常常是一两个词:长词所在的 chunk 被丢、短词(The / a / for / is / to / Let me)和带中文的 chunk 被放行,拼出来就是用户看到的那段。工具名只剥了后缀(`run-jyotish-` 残留)。
## 3. 决策记录
1. **入口驱动的请求由服务端钉死领域。** `entrypoint` 存在(`daily_starlanguage` / `birth_time_rectification`)时,`canonicalDomainPlan` 忽略模型传的 `domains`,只执行路由 `theme`(本例 `timing`);模型传了不同值记 `plan_override_ignored` 到 receipt,不报错不扣步。普通问题维持现状(模型可选多领域)。
2. **"深入看今日"用自己的写作标题。** 新增 `dailyConsultationThinkingPlan()`:一节"今日趋势"、一节"适合推进 / 需要避开"、一节"一个行动 + 边界句"(边界句沿用扩展里的"探索性日提示,不是确定预测"),技法审计表折进最后一节。`natalConsultationThinkingPlan` 只用于非入口问题。
3. **分段写作禁用工具。** `composeSection``agent.stream``toolChoice: "none"`(计算已缓存,分段本来就不该调工具);某一段返回空正文时,同一段再试一次(仍 `toolChoice: "none"`,提示追加"上一段没有输出正文,请直接写这一节"),再空才进入既有 `retryForAnswer`
4. **思考流按句过滤。** `sanitizePublicThinkingText` 改成有状态的缓冲:按 `。!?\n` 或英文句号切句后再判定;纯英文句整句丢,工具名整个删(连前缀);未闭合的尾巴等下一个 chunk。对外仍只发 `thinking.delta`
5. 不动计费(空回答仍不扣点)、不动 `AGENT_MAX_STEPS = 8` / `AGENT_TIMEOUT_MS = 110s`、不动 Skill。
## 4. 任务分解
- 4.1 决策 1`consultation-tools.ts` + `route.ts``entrypoint``ConsultationAgentContext`;测试——`entrypoint=daily_starlanguage, theme=timing`,模型传 `domains:["general"]` → 执行 `timing`receipt 含 `plan_override_ignored`;无 entrypoint 时行为不变。
- 4.2 决策 2`consultation-thinking-plan.ts` 新增 daily 计划;`route.ts``daily_starlanguage` 分支用它;测试——标题序列为三节,正文以 `## 今日趋势` 开头;`applyThinkingSectionProgress` 能按新标题标 done。
- 4.3 决策 3`composeSection``toolChoice: "none"`,分段空正文重试一次;测试(`consultation-agentic-runtime.test.ts` 扩)——mock 某段模型只发 tool-call 无文本 → 该段重试后写出正文,`fullOutput` 非空、不触发 `retryForAnswer`;两次都空才 `answer-retry`。三栏:原值"分段可调工具"→ 新值"分段禁用"→ 决策 3。
- 4.4 决策 4`public-thinking.ts` 改缓冲实现;测试——把事故那段按 3–6 字符切成 chunk 喂入,输出不含任何 4 字母以上英文词、不含 `run-jyotish`,中文句完整;纯中文思考原样通过。
- 4.5 记录:`docs/BUG_HISTORY.md` BUG-609(复发关联 BUG-280:同一"计算成功、模型没写"现象,新来路是入口领域被改写 + 分段可调工具)、BUG-610;`CHANGELOG.md``PROGRESS-…``docs/testing/` 加"首页点『深入看今日』必须得到三节回答,思考区不得出现英文词渣"。触发链若执行方能从 staging `[agent-observability]` 日志取到该 run 的 `tool.input.domains``modelFinishReason`,写进 BUG-609 的验证段;取不到写 `investigating`,但决策 1–4 都是确定性缺陷,照做。
## 5. 让步顺序
4.3 与 4.1 先做(最小改动即可止血);4.2 必做;4.4 必做;4.5 不可省。
## 6. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/consultation-daily-empty-answer-20260909 .worktrees/consultation-daily-empty-answer-20260909 origin/staging
cd .worktrees/consultation-daily-empty-answer-20260909
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
cd frontend && ./node_modules/.bin/tsc --noEmit; npm run lint 2>&1 | tail -1
ls tests/consultation-*.test.ts tests/public-thinking*.test.ts tests/agent-*.test.ts 2>/dev/null | xargs npx tsx --test 2>&1 | grep -E "^# (tests|pass|fail)"
```