# PROGRESS · 申报时段计算改为服务端预跑(2026-09-18) 工作树:`.worktrees/contract-degraded-pass4-20260918` 分支:`codex/contract-degraded-pass4-20260918` 基线:`origin/staging` @ `1061514f` 前序:`TASK-window-consult-contract-20260918.md` §5、BUG-954 已在 staging 验证通过 任务:BUG-957 ## 结论 申报时段的窗口计算不再等模型决定调不调。服务端在模型开口前先跑同一套工具体,进度写进同一条 NDJSON 流;算出的 packet 以服务端确定性消息注入本轮上下文。工具仍挂在窗口 Agent 上,再调用会命中同请求缓存,成功次数仍是 1。本命线没动。没有 `toolChoice: "required"`。 ## 做法 | 点 | 落地 | | --- | --- | | 缓存位置 | `WindowConsultationAgentContext.calculationCache`,不是工厂局部 `let`。重建 tools 仍共享 | | 预跑 | `precomputeWindowConsultation(ctx, { question, writer })` 走同一 `execute` 体,记账 `consultationToolCompleted` / `successCount === 1` / 回执 `run-jyotish-window-consultation` | | 时机 | `streamAgentResponse` 的 `warmup`:`run.started` 与 skill 事件之后、`consumeAttempt` 之前 | | 注入 | 预跑成功后往 `baseMessages` 追加 `windowPrecomputedPacketMessage`。上下文溢出缩历史时把同一条消息再贴回去,避免丢掉已算好的包 | | 失败 | warmup 吞掉错误,合同保持红;模型仍可调工具;既有 retry + 降级仍在 | | 本命 | 不预跑 | ## 测试 | 项 | 结果 | | --- | --- | | 预跑成功 + 模型不调工具 | 合同绿,回执有窗口工具 completed 步,正文送达,无降级说明 | | 预跑成功 + 模型再调工具 | 缓存命中,`consultationToolSuccessCount === 1` | | 预跑失败 + 模型只写字 | 仍降级,不是静默成功 | | 源码合同 | 窗口 Agent 仍 attach 工具;本命工厂仍是局部 `let calculation`;窗口分支有 warmup;本命分支没有 | | `tsc --noEmit` | 0 错 | | `npm run lint` | 0 error(120 warning,与基线同量级,未顺手修) | | 定向 6 个测试文件 | 132 tests / 130 pass / 2 fail。两条失败都是本机 Windows `EPERM` 无法为 live skill 建 symlink,与基线缺口同类 | 未跑全量 `npm test`(基线 3501 / 31 fail)。Linux 门禁才是验收数字。本机无登录态、无 Chrome。