853a0147f2
plan.submit_gdd 此前要求提交的 decisions[] 前缀与 session.decisionsSummary 六个字段逐项相等,prototypeValidationItems 整体相等。那六个字段没有一个由策划子 Agent 生产:id、topic、state、answerSource、round、answerSummary 全部是 Runtime 在用户答题时从问题与答案投影出来的。子 Agent 只能从 Supervisor 转述的委派 task 里 回抄,而权威台账从不注入它的上下文,拒绝 observation 也只有一句"未逐项匹配"、不含 差异。于是这个零信息量的回抄成了唯一的提交前提:用户只要自由填写过一次,逐字复现 就依赖一条没有机制保证的 LLM 转述链,抄歪即在 5 次盲重试后 run failed。 同一条相等约束还顺带禁掉了纠错。答非所问的自由填写被投影成 confirmed 之后 (planning_coordinator.rs 的 else 分支对任何非选项答案一律断言 confirmed), 子 Agent 即便看出绑定错了也不能改——改一个字就过不了相等校验。 现在只守真正要守的那一条:不能声称用户确认过他没确认的东西。 - submit_decisions_respect_session_authority 取代逐项相等,只校验三点: 不得凭空造出没有 session 支撑的 confirmed;不得丢弃用户已作出的决定; 用户亲选的 prototype_pending 不得被改判。 - apply_plan_session_authority_to_submit_input 把 answerSummary、answerSource、 round 直接覆盖进 input,覆盖发生在 durable action identity 重放比对之前, 且只读跨 submit successor 原样保留的 decisionsSummary/prototypeValidationItems, 所以同一 actionId 重放结果稳定。 - topic 与 state 归子 Agent:可按答案真实内容重命名决定,可把 confirmed 降级为 default_pending。这是纠正错误绑定的唯一出口,方向单向。 顺带修掉开场需求长度的三方不一致:入口不设限,AGENT_RUNTIME_TASK_MAX_CHARS 截断到 4000(超长再补一个省略号),而 plan session 的 initial request 硬拒 400。 401~4001 字的需求会让根 run、Goal Contract 与首跳委派全部正常建立,直到策划子 Agent 的 task-start 才炸在 planning-session-projection-failed,且 session 从未 创建、同一根 task 重试必然复现。PLAN_INITIAL_REQUEST_MAX_CHARS 直接绑定上游常量。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>