Running Task 常驻巡检
August 29, 2026 · View on GitHub
目标
持久 Task 为 running 时,插件持续保证其绑定的同一个叶子 Session 仍注册在 DSH ctx.agents 中,且该 Session 的原生 Goal 为 active + armed。外部进程、请求或宿主异常不得让 Task 只在看板上保持运行、实际执行却停住。
Task 只有两类合法等待:向原群任务提出人补充目标信息,或向真人请求处理叶子无法自行解决的外部异常。除此以外,叶子不得结束、暂停 Goal 或把 Task 置为 waiting。
设计
- 以持久 Task 状态作为业务事实,只巡检
runningTask。 - 以 DSH Agent Registry 判断 Session 是否仍存活;
agent.status === idle是正常检查点,不等于 Session 停止。 - Session 已离开 Registry 时,通过
ctx.agents.resume()恢复原childSessionId,不新建 Task、不更换逻辑叶子。 - Goal 为
paused、blocked或active + disarmed时,通过ctx.goals.resume()恢复;Goal 缺失时在原 Session 创建同一 Task 目标。 - Goal 异常发生时若 Agent 仍为
running,等待其进入 DSH 原生 idle 检查点后再恢复,避免在 blocked closing step 中途改 revision 或打断当前 turn。 - Goal 的
roundsStarted >= maxGoalRounds且已进入blocked、paused或active + disarmed时,执行预算已经确定耗尽,不再依赖可能残留的 Agentrunning状态,也不自动重建新 Goal;Runtime 立即把 Task 转为waiting/human-intervention,附带 Goal 轮数、阶段、Session 和 Agent 状态,避免看板假运行并释放并发名额。 - 真人处理阻断问题并明确恢复后,Runtime 若发现原 Goal 轮数已经耗尽,先把
maxGoalRounds增加一组默认预算,再使用编辑后的 Goal revision 执行 resume,确保同一 Task 和 Session 能实际继续运行。 - 恢复后必须重新读取并断言 Session 已注册、Goal 为
active + armed。 - 每次异常及恢复失败写入现有 Supervisor 去重告警;除 Goal 轮数已确定耗尽外,Supervisor 不修改 Task 的业务状态。
waitingTask 表示真实缺信息或缺授权,不参与自动恢复。- 使用定时巡检补充 DSH 生命周期事件;不复制 Session、Goal 或 Goal Round 状态机。
- DSH 启动进程沿用系统
TEMP/TMP;临时目录不能放在 Agent 工作区内部,否则 Codex Connect 的工作区隔离会在命令启动前拒绝执行。
合法阻塞分类与路由
目标信息阻塞
仅当目标、完成条件或任务提出人掌握的必要业务信息不明确时使用:
- 叶子提交结构化
information阻塞,必须包含具体缺失信息和可直接回答的问题,不接受泛化的“请补充上下文”。 - Runtime 将 Task 置为
waiting/information并阻塞原生 Goal。 - resident 主会话收到 Task ID、原群、任务提出人稳定 ID、问题清单和已取得的证据,由主会话在原群与该提出人沟通。
- 群聊答复通过
task-context精确追加到原 Task;Runtime 恢复同一 Session 和 Goal。
真人处置阻塞
仅允许以下叶子已尝试且自身无法解决的外因:操作红线、网络中断、磁盘空间不足、计算或进程资源不足、执行意外事件,以及必须由真人确认处置方案的事项。
- 叶子提交结构化
human-intervention请求,必须包含分类、现场证据、已尝试动作、不能自行解决的原因和希望真人回答的具体问题。 - Runtime 将 Task 置为
waiting/human-intervention,阻塞原生 Goal,并生成稳定阻塞请求 ID。 - 插件向 DWS 登录人的“本人私聊窗口”发送消息,正文携带 Task ID、阻塞请求 ID、目标、原因、证据和所需答复;先持久记录发送任务 ID,再查询并记录真实
conversation_id与message_id。 - 本人发出的消息会被个人 IM 事件流 self-loop 过滤,因此插件按固定间隔增量回读该单聊窗口;只接受引用该
message_id的新消息,以引用消息 ID 去重并精确关联 Task。普通私聊和未引用回复不能恢复 Task。 - Runtime 把真人答复追加到原叶子,恢复同一 Session 和 Goal,并将 Task 改回
running。 - 真人处置等待不设置超时时间;不得因等待数分钟或数小时自动失败、自动完成或创建替代 Task。Runtime 重启后继续使用持久的会话 ID、阻塞消息 ID 和轮询游标等待,直到匹配引用回复或用户明确关闭任务。
- Runtime 对
blockerCategory + 规范化 requestedAction计算稳定范围指纹,并把阻塞及批复写入 Task 历史。同一待批范围重复提交时复用原阻塞请求,不得再次外发;同一范围已经批准时直接恢复同一 Task 并向当前叶子重放批复,不得再次申请。只有范围指纹变化才允许创建新阻塞;物理叶子替换或 Runtime 重启不得丢失已批准范围。
非法阻塞
代码错误、命令失败、可重试的网络波动、可清理的本任务临时资源、普通不确定性、实现困难或仍有安全范围内替代路径时,叶子必须继续诊断、修复或重试。Supervisor 发现 running Task 的 Goal 非法 paused/blocked/disarmed 时,在 Agent idle 后恢复,并把阻塞事实作为纠偏上下文投递给同一叶子。
本人私聊窗口契约
真人就是当前 DWS profile 的登录人。发送目标使用该 profile 的当前 user_id,不得按显示名猜人。发送后必须通过 openTaskId 查询真实 openConversationId/openMessageId,并持久记录发送时间;轮询固定使用该 openConversationId,只完整读取 [阻塞消息发送时间, 本轮时间)。时间窗结果不完整时保持等待并在下轮重查,不得把 partial 当作没有回复。事件订阅不能替代该轮询,因为 DWS 会过滤当前用户自己的消息。
验收
runningTask 的 Goal 被外部暂停后,下一轮巡检恢复为active + armed。runningTask 的 Agent 从 Registry 消失后,下一轮巡检恢复同一 Session ID。waitingTask 的 blocked Goal 保持不变。- 恢复行为产生去重 Supervisor 告警,Task 状态始终不被巡检推进。
- Goal 轮数耗尽时,即使 Agent 状态持续为
running,Task 也必须转为waiting/human-intervention,不得继续显示运行中或自动获得新一组轮数。 - Goal 轮数耗尽产生的阻塞经真人处理并恢复后,Goal 必须增加一组轮数预算并进入
active + armed。 - information 只能经原群提出人答复恢复;human-intervention 只能经真人引用对应私聊阻塞消息恢复。
- 本人私聊发送后取得真实会话和消息 ID;只有引用该消息的新回复能恢复对应 Task,重复轮询不重复投递。