日志:input-processor jyotish-skill-bound abort ×2,modelStepCount 0、 0 token、整轮 69ms,模型从未被调用。windowJyotishInstructions 从不含 BOUND_METHOD_MARKER,而 getWindowJyotishAgent 照样 attach 绑定,自 9958e00a(08-21)起申报时段每轮必败。abort 与「模型没调工具」同码, 是它藏四周的原因。初版任务书的「模型没调工具」立论已证伪并改写。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
7.5 KiB
TASK · 申报时段咨询修复(2026-09-18 第四轮)
基线:
origin/staging@9cdcf96b(已部署,健康检查一致)。 事故记录:docs/BUG_HISTORY.mdBUG-954(根因已由服务端日志确认)。 BUG 编号起点:开工时最大号为 BUG-954,本单占 BUG-954 ~ BUG-958。修订说明(2026-09-18 晚):本单初版按「模型没调工具」立论,服务端日志已证伪。根因是窗口 Agent 的系统提示里没有 skill 方法块,模型从未被调用。原 §3「服务端预跑」降级为 P2 结构性改进(BUG-957),不再是本单的 P0。
0. 事故实证(服务端日志)
staging 真实一轮(consultationMode=declared_birth_window、theme=general、问题「未来半年我事业如何?」、history=[]),docker logs jyotisha-staging-web-1:
[WORKFLOW] Error executing step ...input-processor.step.processor:jyotish-skill-bound:
Error: Jyotish skill method is not bound into the system prompt for jyotish-vedic-astrology ← 出现两次(两次 attempt)
[agent-observability] toolCalls: [] modelStepCount: 0 inputTokens: 0 outputTokens: 0
run.total durationMs: 69 retryCount: 1 errorCode: runtime_contract_incomplete
整轮 69 毫秒,模型一次都没被调用,0 token。 公开事件里的 skill.started/completed 是绑定步骤自己报的,不代表方法块真的进了提示。
1. 根因
| 位置 | 事实 |
|---|---|
skill-binding.ts:143-153 |
jyotishSkillBoundProcessor 在输入处理阶段断言系统提示含 BOUND_METHOD_MARKER = <jyotish-skill name="jyotish-vedic-astrology">,缺失即 abort() |
index.ts:21 |
${jyotishSkillMethodBlock} 只插值进 jyotishInstructions(本命) |
index.ts:176-190 |
windowJyotishInstructions 从来没有这个块 |
index.ts:198 |
getWindowJyotishAgent 照样 ...jyotishSkillBinding() |
时间线:处理器 d04fc30b(08-18)引入 → 窗口 Agent 9958e00a(08-21)新建时就带绑定、不带方法块 → 申报时段路线自 2026-08-21 起每轮必败,已持续约四周。
为什么四周没人发现:abort() 被翻成与「模型没调工具」同一个公开码 runtime_contract_incomplete。BUG-922/923/937 处理的正是同名现象,本命线被救活后现象消失一半,窗口线这条根因从未被触及。
2. BUG-954(P0)窗口 Agent 必须绑定方法块
windowJyotishInstructions注入带 marker 的方法块。不能直接照抄jyotishSkillMethodBlock:它带本命 Level 2 报告骨架与「六步宫位 / Yoga 表 / 技法审计表」的输出要求,与窗口口径(无精确应期、只报稳定层、变动层列可能性)冲突。做法二选一,在进度记录里写明选了哪条:- (a) 抽出
jyotishSkillMethodBlock的「方法主体 + marker」部分,报告骨架段落作为可选后缀,本命加、窗口不加; - (b) 窗口保留完整方法块,紧随其后用窗口口径逐条覆盖(明确写「以下窗口约束优先于上面方法块里的报告骨架与应期表述」)。
- (a) 抽出
- 验收标准:
- 新增源码合同测试——凡 attach
jyotishSkillBinding()的 Agent,其instructions必须包含BOUND_METHOD_MARKER(遍历index.ts里的 Agent 工厂,不是逐个手写断言); - 新增运行测试——构造窗口 Agent 的输入处理,
jyotishSkillBoundProcessor不 abort; - 部署后在 staging 真发一轮申报时段提问,
/api/healthSHA 对得上,回执里有run-jyotish-window-consultation的 completed 步。
- 新增源码合同测试——凡 attach
3. BUG-955(P1)处理器 abort 不得与「合同未完成」同码
abort() 目前落到与「模型没调工具」相同的公开码,是这条 bug 藏四周的直接原因。
- 输入处理器 abort 走独立内部码(例如
skill_binding_failed),回执追加validation skill-binding-abort failed,服务端打[consult-binding-error]日志(requestId + 内部码,不含提示词原文)。 - 公开层可以继续用现有枚举,但回执必须能一眼区分「装配失败」与「模型没调工具」。
- 参照 BUG-938 对供应商 error 块的同类处置。
- 验收:假流两条——装配失败 / 模型没调工具,回执步骤名不同;
agent-observability两个码都能落日志。
4. BUG-956(P1)合同未绿时不得静默丢弃模型正文
stream-agent-response.ts 现在在合同未绿时丢弃全部正文,用户只看到「未完成」。即便 BUG-954 落地,这条兜底仍要有:
- 两次 attempt 后合同仍未绿、但模型产出过非空正文时,不再整轮失败;改为交付该正文并在回执追加
validation contract-degraded failed,同时在正文末尾附一句服务端确定性说明(文案对照frontend/docs/VOICE.md,不得由模型生成)。 - 模型既没调工具也没写字时,维持现有
runtime_contract_incomplete(不扣点)。 - 验收标准:假流「无工具 + 有正文」→ 用户拿到正文 + 降级说明;假流「无工具 + 无正文」→ 仍是
runtime_contract_incomplete。
5. BUG-957(P2)结构性改进:计算不该由模型触发
本单初版的主修法,现在降级为独立改进项,与 BUG-954 无因果关系,但值得单独做:run-jyotish-window-consultation 的 inputSchema 只有 question(consultation-tools.ts:765-767),出生数据完全服务端绑定——由模型决定调不调,对计算结果没有信息增益,只多一条失败路径(BUG-205/214/922/923/937 都在这条链上)。建议服务端在模型循环前预跑计算并记账,工具仍留在 Agent 上命中同请求缓存。不要与 BUG-954 同轮做:先让窗口路线活过来并在真实环境验证,再动运行时结构。
6. BUG-958(P3)窗口指令里「必须调工具」与「不得给应期」的冲突要写清
src/mastra/index.ts:178-190 补一句显式口径:应期类问题仍然要先调工具,再用稳定层给方向性回答,并说明哪部分需要出生分钟;不得因为「精确应期不可用」而跳过计算或拒答整题。验收:consultation-workflow-contract.test.ts 加一条源码断言。
7. 硬红线
tsc --noEmit0 错、npm run lint0 error、npm test失败数不超过基线9cdcf96b实测的 31 条且清单逐条一致;测试总数不低于 3495。- 不得放宽
contractReady()的「每请求一次真实计算」语义。BUG-954 是把方法块补进提示,不是绕过绑定校验;不得用「删掉jyotishSkillBinding()」的方式让窗口路线通过。 - 不得再写
toolChoice: "required"/ named toolChoice。 - 改既有断言写「原值 / 新值 / 原因」三栏。
8. 开工前置
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
让步顺序:BUG-954 单独一轮先上(四周不可用,越快越好,改动面是一段提示词 + 两条测试),955 同轮或紧随;956 次之;957 必须等 954 在真实环境验证通过后另开一轮;958 顺手。
收工:docs/tasks/PROGRESS-window-consult-contract-20260918.md + docs/BUG_HISTORY.md(954 按证据转 resolved,955~958 新增)+ CHANGELOG.md(申报时段咨询四周不可用属用户可感知),与代码同一批推 staging。