#334·edict

[Bug] 已回奏任务未进入 Done,被太子巡检误判停滞并重新派发

Author: SparkHelloCreated Aug 5, 2026Updated Aug 5, 2026

环境

  • Edict commit:14a2075
  • OpenClaw 版本:2026.7.1-2
  • 操作系统:macOS 26.5.2
  • Python 版本:3.12.13
  • 消息渠道:QQ Bot

问题描述

Agent 已经向用户发送最终回奏,任务的 flow_log 也记录了“太子 → 皇上 / ✅ 回奏皇上”,但任务没有同时进入终态 Done,调度器仍保持启用。

达到停滞阈值后,“太子巡检”会把这个事实上已经完成的任务当成停滞任务自动重试并重新派发,导致已经结束的工作重新进入中书/门下/尚书流程。用户随后在 QQ 发送新的正式需求时会创建新的 JJC 任务,于是看板同时出现“旧任务仍运行”和“新任务已创建”。

这不是单纯的前端刷新问题;tasks_source.json 中旧任务本身仍是非终态。

关联跟踪 issue:#191。

复现步骤

  1. 通过 QQ 向太子发送一条正式需求,创建 JJC 任务。
  2. 等待 Agent 完成整条流程并向用户发送最终回复。
  3. 检查旧任务数据:
    • flow_log 已出现 太子 → 皇上,备注为 ✅ 回奏皇上:...
    • todo 已全部完成,或已经具有 ready_to_close: true
    • state 仍为 Zhongshu / Assigned 等非终态
    • _scheduler.enabled 仍为 true
  4. 等待停滞阈值,或者点击“太子巡检”。
  5. 旧任务被自动重试并重新派发。
  6. 再从 QQ 发送一个新的正式需求,会正常创建新任务;此时看板上旧任务和新任务同时处于活跃状态。

实际时间线(已脱敏)

06:33:47  太子 → 皇上:✅ 回奏皇上:任务已完成
           (任务仍未进入 Done)

06:43:52  太子调度 → 皇上: 停滞605秒,触发自动重试第1次
06:43:52  太子调度 → 中书省: 已入队派发(taizi-scan-retry)

重试后,任务又重新流转到门下省和尚书省,即使之前已向用户给出最终回复。

期望行为

  1. “发送最终回奏”和“将任务置为 Done / 关闭 scheduler”应当通过一个原子、幂等的收口操作完成,不能依赖 Agent 连续正确执行两条相互独立的命令。
  2. 收口后至少应设置:
    • state = Done
    • org = 皇上
    • completedAt
    • _scheduler.enabled = false
    • _scheduler.lastDispatchStatus = completed
  3. 调度器应增加防御性检查,避免对明确已收口或已经完成最终回奏的任务执行 retry/escalate/rollback。
  4. 新 QQ 消息创建新任务时,不应使已经回奏的旧任务继续显示为运行中。

实际行为

  • 最终回复已发送,但任务状态没有收口。
  • 调度器继续监控该任务。
  • 达到阈值后旧任务被错误重试。
  • 看板显示旧任务仍在运行,容易让用户误以为 Agent 还在执行。

建议修复

  • 增加统一的 complete / finalize 操作,在同一次原子更新中写入最终流转记录、Done 状态并关闭调度器。
  • 太子最终回复路径只调用这一个收口操作。
  • 调度器扫描时对 Done/Cancelled 之外,再校验明确的 completion marker,防止异常/旧版本 Agent 漏写状态时重新派发。
  • 增加回归测试:已回奏任务经过超过 stall threshold 的扫描后,动作数必须为 0。