docs: 申报时段整轮失败定位 BUG-954,出服务端预跑任务书

回执零 tool 步 + 有合同 retry + 公开码 runtime_contract_incomplete,
按 BUG-938 的分流规则排除供应商 error 块,两次 attempt 都是模型没调
工具。根因链 922→923→937:required 被拒后改回 auto,洞回归。窗口工具
入参只有 question,计算不需要模型触发,改服务端预跑。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
This commit is contained in:
Jesse_Chen
2026-09-18 07:18:35 +00:00
co-authored by Claude Opus 5
parent 9cdcf96b18
commit d0317f7f4e
3 changed files with 103 additions and 0 deletions
+1
View File
@@ -138,6 +138,7 @@
| `TASK-consult-three-channels-20260918.md` | `PROGRESS-consult-three-channels-20260918.md` | 咨询运行时三通道:进度 / 思考 / 正文生成时分离。设计分支误用 BUG-939/940/941,落地改号 942944 | 验收未通过(见修复单) | `94c1e81f` |
| `TASK-consult-three-channels-fix-20260918.md` | `PROGRESS-consult-three-channels-fix-20260918.md` | 验收修复单:领域上限解耦(945)、31s 预算断言(946)、校正思考分片门(947)、Pass 4 按模式分流(948)、容量算术(949) | 已验收通过(Claudetsc 0 / lint 0 error / npm test 3491 条 31 红且与基线 `742ffbc6` 同一组、原 12 条红全绿 / `/` 仍 Static / 首屏 js gzip 468,388 B 较基线 +0.02%);review 另出 BUG-950~953 见下一行 | `e32ce624` |
| `TASK-consult-pass4-streaming-20260918.md` | `PROGRESS-consult-pass4-streaming-20260918.md` | 验收 review 三轮:Pass 4 一 hold 正文就整段蹦出、逐字流式消失(BUG-950 产品拍板按句放行);无出生分钟模式整段被一句拒绝顶掉、一般知识句一起丢(951 改按句丢弃);该模式下日期不留痕(952);校正流 token 级 thinking 是死链,按 P2 删除并把测试翻转成否定合同(953)。基线 `1e553976` | 待验收 | `cd4775ae` |
| `TASK-window-consult-contract-20260918.md` | — | **P0 线上**:申报时段问「未来半年我事业如何」整轮 `runtime_contract_incomplete`,回执零 tool 步(BUG-954)。根因链 922→923→937`required` 被供应商拒收后改回 `auto`,「模型可以不调工具」的洞回归;而窗口工具入参只有 question,计算本就不需要模型触发 → 改服务端预跑。另含合同未绿不得静默丢正文(955)、窗口指令应期冲突(956)。基线 `9cdcf96b` | 待领取 | — |
| `TASK-first-paint-dead-screen-fallback-20260917.md` | — | 真机:首页永远停在「正在载入账户」,兜底全在没跑起来的 bundle 里(BUG-936 investigating)。根 layout 加与 bundle 无关的内联兜底 + 去掉本仓正则后行断言 | 待领取 | — |
| `TASK-consultation-answer-start-anchor-20260917.md` | `PROGRESS-consultation-answer-start-anchor-20260917.md` | 主会话回答落在结尾:`useConversationScrollAnchor` 是贴底跟随,流式期间视口钉在最后一个字,回答开头滚出视口;改为发送后问题钉顶、回答向下长、长出视口显示「跳到最新」、末尾动态留白;产品追加拍板:校正面同一语义(推翻 BUG-041/048 贴底),本轮开头 = 用户行或新助手行。BUG 段 930 起 | 已验收(经修复单) | `worktree/green-harbor-5be3` |
| `TASK-consultation-answer-start-anchor-fix-20260917.md` | `PROGRESS-consultation-answer-start-anchor-fix-20260917.md` | 验收修复单:F1 头就是留白行时留白按整视口算(BUG-931);F2 留白只在钉住期间存在(BUG-932);前置:先修 e4e73f56 的两处 TS 错否则门禁不过 | 已验收 | `cc1a8980`Claude 验收:tsc 0 / lint 0 error / npm test 3457 条 39 红与 11c0028d 逐条一致、新增 2 条绿 / `next build --webpack` 通过、`/` Static、首屏 gzip 591,242(较 09-16 基线 582,800 +1.45%,含会话列表单)/ Chrome 真实布局 S1–S6 全部通过,S6 新助手行距顶 16px 且增高不动,S5 不再写留白);真机六条欠 |
@@ -0,0 +1,82 @@
# TASK · 申报时段咨询不再靠模型触发计算(2026-09-18 第四轮)
> 基线:`origin/staging` @ `9cdcf96b`(已部署,健康检查一致)。
> 事故记录:`docs/BUG_HISTORY.md` BUG-954investigating)。
> BUG 编号起点:开工时最大号为 **BUG-954**,本单占 **BUG-954(转 resolved~ BUG-956**。
## 0. 事故实证
staging 真实一轮(`consultationMode=declared_birth_window``theme=general`、问题「未来半年我事业如何?」、`history=[]`):
```
run.started → skill.started/completed → activity(loading-method) → run.failed
code = runtime_contract_incomplete
receipt.steps = [skill, runtime-contract-retry] ← 没有任何 tool 步
receipt.stepBudget = {planned: 11, used: 2}
receipt.workflow = {route: declared-birth-window, status: blocked, missingLayers: [birth-minute]}
receipt.skill = {loaded: true, referenceReads: 0, methodologySections: 0}
```
排除项:这不是供应商 error 块那条路。BUG-938 的修复规定 error 块会写 `validation model-stream-error failed`、**不**触发合同 retry、公开码为 `calculation_failed`。本次三项全不符,所以两次 attempt 都是**模型没有调用 `run-jyotish-window-consultation`**。
## 1. 根因链(为什么「修过了还犯」)
| 轮次 | 做了什么 | 留下什么 |
| --- | --- | --- |
| BUG-922 | 提示词改成「每一轮都必须先调工具」 | 提示词是软约束 |
| BUG-923 | 第 0 步 `toolChoice: "required"` | 记录里写明「`auto` 不能保证第 0 步调用」 |
| BUG-937 | 某些 thinking 供应商拒收 `required`,改回 `activeTools` + `auto` | **把 BUG-923 的洞原样放回来**,没有补第三条路 |
| 本轮 | —— | 模型不调工具 → 合同未绿 → 正文被丢弃 → 整轮失败 |
叠加因素:`windowJyotishInstructions``src/mastra/index.ts:176-190`)同时写着「每轮必须先调工具」和「`can_answer_precise_timing` 恒为 false,不得给出月份 / 日期 / 大运边界」。本次问题(未来半年事业)正是应期语义,模型在两条指令冲突下选择「我答不了、不调工具」是最可能的路径;它若写了解释文字,也会因为 `contractReady()` 未绿被整段丢弃(`stream-agent-response.ts:336-339`)。
**结构缺口一句话**`run-jyotish-window-consultation``inputSchema` 只有 `question``consultation-tools.ts:765-767`),出生数据完全服务端绑定——**让模型决定调不调,对计算结果没有任何信息增益,只增加一条失败路径。** 本命路线同理。
## 2. 决策记录(待产品确认,实现前必须回填「已授权」)
产品诉求(2026-09-18):只知道出生范围的用户必须能正常使用产品。本单把「模型触发计算」改成「服务端预跑计算」,模型只负责写作。这**推翻**了 BUG-922/923/937 那条「靠提示词 + toolChoice 让模型调工具」的路线,但不推翻它们的目的(每轮必须有本请求内的真实计算)。
## 3. BUG-954(P0)服务端预跑,模型不再负责触发计算
1. 申报时段路线在进入模型循环**之前**,服务端直接执行窗口计算(现有 `createWindowConsultationTools``execute` 主体抽成可独立调用的函数),把 evidence packet 作为服务端消息注入上下文。
2. `consultationToolSuccessCount` 由这次服务端执行记账,`contractReady()` 因此在模型开口前就已绿;工具仍然留在 Agent 上(模型想再调一次,命中同一请求内缓存,不重复计算)。
3. 合同 retry 那条路保留,但它现在只可能因为「服务端计算失败」触发,不再因为「模型没调」触发。
4. 验收标准:
- 新增合同测试——申报时段路线在模型**一次工具都不调**的假流下,仍然产出回答、`run.failed` 不出现、回执里有 `run-jyotish-window-consultation` 的 completed 步;
- 现有 `consultationWindowPrepareStep` 的两条断言按新口径改写(三栏说明);
- 不得再出现 `toolChoice: "required"` 或 named toolChoiceBUG-937 防复发条款仍然有效)。
## 4. BUG-955(P1)合同未绿时不得静默丢弃模型正文
`stream-agent-response.ts` 现在在合同未绿时丢弃全部正文,用户只看到「未完成」。即便 BUG-954 落地,这条兜底仍要有:
1. 两次 attempt 后合同仍未绿、但模型产出过非空正文时,不再整轮失败;改为交付该正文并在回执追加 `validation contract-degraded failed`,同时在正文末尾附一句服务端确定性说明(文案对照 `frontend/docs/VOICE.md`,不得由模型生成)。
2. 模型既没调工具也没写字时,维持现有 `runtime_contract_incomplete`(不扣点)。
3. 验收标准:假流「无工具 + 有正文」→ 用户拿到正文 + 降级说明;假流「无工具 + 无正文」→ 仍是 `runtime_contract_incomplete`
## 5. BUG-956(P2)窗口指令里「必须调工具」与「不得给应期」的冲突要写清
`src/mastra/index.ts:178-190` 补一句显式口径:应期类问题**仍然要先调工具**,再用稳定层给方向性回答,并说明哪部分需要出生分钟;不得因为「精确应期不可用」而跳过计算或拒答整题。验收:`consultation-workflow-contract.test.ts` 加一条源码断言。
## 6. 待取证据(不阻塞开工)
staging 该 `requestId=95de38fd-…` 的服务端日志:`modelFinishReason`、有无 `[consult-provider-error]`、模型是否产出过被丢弃的正文、本次模型 id 的供应商。拿到后回填 BUG-954 的根因段并转 `resolved`;拿不到就保持 `investigating`,但 §3 的结构修法与日志结论无关,可以先做。
## 7. 硬红线
1. `tsc --noEmit` 0 错、`npm run lint` 0 error、`npm test` 失败数不超过基线 `9cdcf96b` 实测的 31 条且清单逐条一致;测试总数不低于 3495。
2. 不得放宽 `contractReady()` 的「每请求一次真实计算」语义——本单是把计算**提前到服务端**,不是取消它。
3. 不得再写 `toolChoice: "required"` / named toolChoice。
4. 改既有断言写「原值 / 新值 / 原因」三栏。
## 8. 开工前置
```bash
git fetch origin --prune
git worktree add -b codex/window-consult-contract-20260918 \
.worktrees/window-consult-contract-20260918 origin/staging
cd .worktrees/window-consult-contract-20260918/frontend
npm test 2>&1 | grep -E "^# (tests|pass|fail)" # 开工基线:tests 3495 / pass 3449 / fail 31
```
收工:`docs/tasks/PROGRESS-window-consult-contract-20260918.md` + `docs/BUG_HISTORY.md`954 转 resolved 或保持 investigating955/956 新增)+ `CHANGELOG.md`,与代码同一批推 `staging`