OpenProgram · Harness 设计

整个会话运行时的重启恢复与 Goal 设计

设计问题:App 或 worker 重启后,如何自动继续原本在执行的会话与 Goal,恢复子任务、审批、上下文和用量,同时不重复未知写入、不恢复用户主动停止的工作。

面向框架开发与产品验收。本文定义目标方案;实现状态集中在文末。范围覆盖 Web、TUI、ACP、后台 Job 和已获授权的子任务;Goal 使用同一聊天执行层。保留 Python Workflow API,不复制另一套执行引擎,不增加通用调度框架,不承诺任意外部操作恰好执行一次。

已核实的现状 · 自动恢复合同 · 全状态恢复矩阵 · 故障验收矩阵

核心合同:恢复会话不等于重试工具。旧轮次可以结束为 interrupted,旧操作仍保持 outcome_unknown;新轮次先检查现实状态。Goal、Todo、聊天记录和已发生用量均保留。
  1. 1. 保存目标原目标、完成条件、权限范围和显式预算。
  2. 2. 普通聊天工作agent 维护 Todo,使用现有工具及审批。
  3. 3. 轮次结束检查结算用量,判断继续、等待、暂停或验收。
  4. 4. 验收完成逐项证据成立后提交 achieved;否则继续工作。

默认没有轮数上限。轮数只是诊断信息,不能替代进度或停止条件。短状态工具 create_goal/get_goal/update_goal 保留;它们只读写目标,不在一次函数调用中执行整个任务。

五个 harness:采用什么,不复制什么

参照及证据核实的行为OpenProgram 的选择
Codex:历史修复 · 空闲续轮缺失工具输出补 aborted;Goal 通过普通线程空闲准入继续。采用普通聊天续轮、配对修复和当前状态验证;不把 aborted 解释为外部效果已撤销。
Claude Code:恢复 · Goal 评估崩溃中的工具不自动重跑;独立小模型按对话证据评估 Goal。仅核实官方合同,非内部源码。采用恢复后不盲目重跑与独立完成审查;不每个工作轮次都额外评估,避免无必要的延迟和费用。
OpenCode:历史转换 · 步骤用量pending/running 调用转换成中断错误;模型步骤结束记录 tokens 与 cost。采用可继续的中断历史和逐请求用量;Todo 是工作计划,不独立决定完成。
OpenClaw:配对修复匹配已有结果,缺失时补错误,处理重复及位置不正确的结果。采用 provider 请求投影修复;不覆盖原始真实记录,不把 heartbeat 等同于 Goal。
DeepSeek harness:中断关闭 · 续轮合同独占写入后追加修复;区分未开始和结果未知;关闭旧 turn,恢复后的 Goal 需明确授权继续。采用分层状态及幂等修复;不复制默认 round cap,也不采用重启后必须手动重新启用的产品策略。

以下是基于这些实现作出的 OpenProgram 设计选择,不声称五个项目具有相同的安全、验收或费用保证。参考源码固定到已检查的版本;未运行外部项目的测试。

Codex 的可确认边界:官方 App Server 文档区分 thread/resume、turn/start 和持久 Goal;公开扩展源码在恢复线程时加载 active Goal,在空闲时尝试续轮。这些证据没有证明任意桌面退出、系统重启和工具进程死亡均可恢复原内存或继续原工具。OpenProgram 将“此前运行意图仍有效时自动继续”定义为自己的明确产品合同,不依赖这个未经证实的更强假设。

现状:已有持久化,缺少一致的恢复决策

已检查的代码当前行为需要改变或验证的部分
execution/startup.py、execution/control/recovery.py已有 owner 核查、canonical 恢复、wait 回执恢复和投影重送;不是空白实现。未确认 effect 可使整个 execution 进入 reconciliation_required;要把“操作待核查”和“会话可继续”分开。
execution/restart.py已有重启暂停意图、去重续接命令和资源准入;默认无恢复期限,显式禁用和有限期限保留,要求无未决 effect。全状态恢复尚待验收;旧记录已保存的有限期限不自动延长,未决效果不因取消默认期限而获得重放权限。
workflow/goal/chat.py、_webui/_exec_dag.py聊天 Goal 不因停机或显示投影修复而暂停;执行完成前持久化通知,重启后按原策略续轮。缺失恢复来源的旧记录保留显式 Resume。完成通知与检查点恢复已有针对性测试;未知效果、新轮次恢复和完整子任务路径仍待实现及验收。
agent/job/runner/recovery.py、execution/control/waits.py已有 Job 恢复、延后 inbox、持久回答与去重 continue;普通聊天部分重启路径排除 spawn/merge。统一父子任务恢复决策及结果投递,不能假设已保存 Job 等于已完整恢复子 agent。
execution/waits.pydurable wait 与 live producer wait 不同;失去 producer 的 live wait 会取消。可恢复的审批和问题不能只依赖进程回调;失效的问题保留记录,重新确认而不是默认批准。
usage/context.py、usage/event.py已有会话、agent、Job 归属及账本;上下文未直接保存 Goal/revision/request-attempt 身份。请求前固定归属和唯一键,支持重启后的迟到回执;缺失用量不能作为零。
browser_resources.py、terminal_resources.py、Web session store已有资源身份、恢复状态及会话投影;不等于进程、网页状态和运行环境全部可重建。逐资源验收真实重连、失效报告和新资源身份;前端重连不能触发重复执行。

检查覆盖上述共享入口,不宣称所有资源适配器已经逐个完成故障测试。不能仅凭 UI 暂停推断历史数据已删除,也不能仅凭记录存在推断任务可自动继续。

自动恢复合同:运行意图不随进程消失

在现有 admission / command / restart intent 上补齐持久的 run_intent,不新建平行调度系统。它记录 work_id、原始输入与待消费消息、desired_state(run / paused / cancelled / done)、最近有效控制版本、权限范围、目标 revision、执行宿主身份、父子关系、最后提交进度及恢复策略。原用户请求被可靠保存后才能向客户端确认已接受。

默认自动恢复此前仍为 run 的已授权工作,普通会话与 Goal 一致,不依赖用户重新打开该会话。暂停、停止、完成、审批未通过和预算耗尽均保留。没有 Goal 的普通请求只继续到这次请求完成,不转成无限 Goal。后台任务沿用原有授权和并发额度;重启不允许生成额外子任务。

关闭窗口或前端重载只断开客户端;“退出并停止全部任务”必须持久化用户停止意图。普通 App 退出、升级维护、worker 崩溃和机器重启不隐式等同于用户 Pause。正常退出先停止新准入、保存已接受控制操作和检查点,再退出 worker;强制退出按最后已提交记录恢复。仅存在客户端草稿、尚未被服务端确认的输入不冒充已提交请求。

取消隐藏的两小时恢复有效期;长时间停机也保留运行意图,但继续前重新检查工作目录、宿主、模型和工具可用性、凭据、当前权限与预算。资源不存在或权限已撤销则显示准确等待原因,不自动切换项目、账号、模型或扩大权限。已有显式禁用自动恢复的设置仍有效;旧暂停记录原因不明时保持暂停并提示,不能猜成正在运行。

  1. 加载事实:读取运行意图、用户控制命令、消息、checkpoint、effects、waits、资源、用量和投影游标。读取或迁移失败时显示恢复失败,不清空旧状态。
  2. 确认所有权:存活执行者重新关联,死亡执行者被 generation fencing 排除;同一工作只由一个宿主恢复。单机恢复不偷偷变成跨主机接管。
  3. 修复上下文:合并真实结果,补齐缺失工具输出并记录中断;有完整安全检查点时从检查点继续,否则以相同 work_id 的新 turn 继续,不重复追加用户输入。
  4. 作出决定:用户停止优先;随后检查审批、权限、预算、资源和未知效果。可运行进入 queued;待依赖进入 waiting;故障给出可重试原因。所有决定保存到同一控制服务。
  5. 准入与续接:经现有公平调度和资源额度启动;按 work_id + 控制版本 + 前序提交点生成稳定 continuation key。保存准入和消费恢复意图不能留下重复窗口,跨库部分用可重试 outbox 收敛。
  6. 恢复界面:App/Web/TUI 从 canonical 快照及单调事件序号重建,显示恢复中、排队、工作、等待或失败;展示不是第二套控制逻辑。

恢复协调逻辑属于现有 execution control;服务器和 JobRunner 可以调用同一幂等入口,但不能各自作不同恢复决定。UI orphan cleanup 只修复派生投影,Goal.after_terminal 只提交当前版本的续轮请求。临时故障使用持久重试时间和有上限的退避间隔,不空转模型;持续故障保留待恢复记录,显示错误和 Retry / Pause / End,不删除任务。

全状态恢复矩阵

重启前重启后默认行为必须保留的限制
已接收、尚未调度的普通请求保留原输入顺序重新排队,只准入一次。以客户端请求 ID 去重;Stop 不被迟到重试覆盖。
模型流式回复中断保留已提交文本和工具结果;未完成输出明确标注,重新请求剩余工作。不能拼接成虚构的完整回复;新的 provider attempt 可新增成本。
active Goal 正在工作或两轮之间加载目标、Todo、证据、预算和原运行意图;自动继续工作或验收。不能因无当前 execution 漏掉空闲 active Goal;5/5 只触发验收。
用户 Pause / End / Stop保持暂停或终止,不受完成通知及自动恢复解除。停止命令一经接受即持久化;可见执行停止进度与业务意图分开。
待审批或待用户回答恢复原问题、请求摘要及作用范围;持久回答已提交则只消费一次。重启不是批准;工具实现、参数或权限变化时旧批准不适用于新动作。
父 agent 等待子任务恢复已有子任务身份、输出、inbox 游标及等待关系;父任务收到终态后按原意图继续。存活子任务重新关联,已结束子任务不重建;用户暂停策略传播给同一任务范围内的子执行,不误停独立任务。
外部进程、终端或远程作业运行中凭宿主、进程启动身份或作业 handle 查询,存活则继续观察。不能仅用 PID 判断;无法确定是否完成则保留 unknown,不重复提交。
浏览器 / MCP / 临时资源保留稳定资源引用,重连后核实身份;确实失效时报告并按授权新建资源。网页表单、登录、JS 内存、REPL 变量不保证恢复;新 tab 或新 session 不能冒充原对象。
context compaction 或消息持久化中使用最后已提交历史与摘要,未提交摘要不覆盖原历史。部分工具参数不可执行;权限配置取当前有效值,持久的工作配置与不可用依赖明确显示。
结果已写入、完成通知未送达重放终态投影与 inbox 投递,不重新运行任务。canonical 终态和投影版本防止 UI 回退;父级汇总不重复计费。
费用回执未到或仅在流中出现按 provider attempt 核查可取得的回执,已有记录去重汇总。无法取得的消耗保留未知;停机时间不计入 active time。

恢复承诺的是已确认保存的工作状态、运行意图与可重建执行,不是任意进程内存快照。未落盘流片段、已死亡 shell 的交互内存或外部服务丢失的回执必须如实说明,不能用清空任务掩盖,也不能用虚构成功补齐。

一个聊天执行层,五类持久数据

数据及唯一所有者保留内容不能承担的职责
Goal / 目标状态服务goal_id、revision、原目标、验收条件、status、显式 budget、阻塞原因。不持有 provider stream,不恢复函数调用栈。
Todo / 现有计划存储稳定 item_id、goal_id、revision、状态、证据引用;UI 从同一来源读取。不能通过删掉未完成条目缩小目标;计划编辑不是任务进展的充分证据。
轮次 / canonical execution输入来源、权限、目标归属、owner generation、轮次状态、子任务。interrupted 不等于 Goal 失败,不等于所有外部进程停止。
工具尝试 / 效果存储调用和实际工具实现身份、输入摘要、开始记录、真实或合成结果来源、效果确定性。结果未知不能伪装成成功或“从未执行”;工具名称不能证明只读。
Usage receipt / 用量账本request/attempt 唯一标识、turn/goal/revision 归属、模型、tokens、价格快照、金额和可信状态。不从会话总额猜 Goal 费用;不将估算伪装成实际结算。

继续复用现有 session、execution、effect、todo、usage 存储,不建设第二套事件平台。需要跨库更新时使用现有可重试通知及唯一操作键;不假设跨数据库原子事务。派生 UI 与统计可重建,原始记录不被派生状态覆盖。

Goal 状态保持 active / paused / blocked / achieved / cancelled / budget_exhausted;执行、等待、验收放在 phase 或既有等待记录中,不组合出重复状态机。兼容 paused_recoverable 的存量读取。revision 或权限改变使旧验收与自动续轮预约失效,旧用量仍归原目标。

中断恢复:先确认执行所有权,再恢复上下文

  1. 确认旧执行者:使用现有 owner lease / generation 判断;租约不明、存储不可读时暂不写修复。不能仅凭“连接断开”宣称旧进程死亡。旧 generation 的后续写入被拒绝。
  2. 核实子进程:可跟踪的存活进程重新关联并等待或显式取消;不能把仍运行的 shell 当作已停止。失联的远程操作保留未知效果记录。
  3. 选择唯一恢复方式:存活 owner 只重新关联;确认死亡且有可验证的安全 checkpoint 时,在同一 execution 下创建新 attempt;仅无可靠 checkpoint 时,取得独占恢复权,以稳定 repair key 补齐缺失输出、结束旧 turn 为 interrupted,再准入新 turn。三者互斥,选择绑定同一持久恢复决定、控制版本和 continuation key,不能既续 checkpoint 又新开 turn。checkpoint 必须覆盖已提交效果并满足现有权限、等待与安全点合同,不能借此重放未知写入。修复重复执行无副作用,真实结果优先,不写虚构用量;迟到且可验证的真实回执追加为核对事件,在后续上下文中替代合成占位。
  4. 恢复运行意图:此前仍在运行的普通请求和 active Goal 自动进入统一准入;用户主动暂停的不自动恢复。需要人工处理的只是具体权限、预算、资源或未知操作,不把重启本身作为手动 Resume 的理由。
  5. 决定工具行为:新轮次知道哪些调用未开始、哪些结果未知。继续核查和独立工作不受旧未知结果全局锁定;相关写入仍受原审批与恢复限制。
中断前状态恢复后的事实允许的后续操作
意图已保存,尚未记录 dispatchnot_started;所有 dispatch 必须先持久记录,否则不能作此判断。仍有必要时按当前权限重新调用。
dispatch 已记录,结果缺失outcome_unknown;包括记录开始与真正调用之间崩溃的情况。可信只读工具可重读;服务支持去重时用原幂等键;其他写入先核实。
结果已经持久化completed / error,保留实际返回值。复用结果,不因重启再次运行。
外部任务仍存活running_external + 可验证 handle。重新连接、等待或取消;不重复提交任务。
非幂等写入结果无法查询outcome_unknown + 待处理操作明细。允许读操作及核查;用户确认风险后才能重试或明确放弃该操作。

安全边界:read_only / idempotent / state_probe 能力来自受信工具注册信息及执行时保存的实现身份,不接受模型自称只读,不按 read 这个名字猜。一般 shell、第三方 MCP 与自定义工具默认未知。未知写入相关恢复轮次先限制为可信读取与状态查询;没有可靠相关性判断时,不自动开放写入,必须先核对或由用户明确授权。

请求历史修复先按原调用 ID 匹配最近的调用,再执行 provider ID 转换。已有真实输出优先,重复输出取最后保存的真实记录;缺失结果生成确定性的 unknown 占位。调用和结果在请求投影中相邻,用户消息顺序保留;原历史不变。没有对应调用的结果不作为有效工具协议项发送。中断回复保留部分文字并标注中断,不重用不完整的 reasoning 签名。同一回复内重复调用 ID 无法确定归属时明确报错,不猜测执行事实。该转换没有执行权限,也不能替代执行恢复决策。

恢复权限检查使用同一 conversation provenance 确定旧执行与所调用 Job 的范围,不扩大到被调用会话的全部执行。仅真实内置 read、grep、glob、list 的执行函数可作为只读核查;工具名称、acceptEdits 标记和插件自行声明不能替代实现身份。其余操作在下述适用执行范围内存在未知效果时必须获得单次审批,不能使用 bypass、自动分类或既有 allow 规则免除。持久审批绑定新工具调用与未知效果集合,集合变化后重新审批;不会消除旧效果记录。无法读取恢复状态时拒绝执行。此检查是受限新轮次恢复的前置条件,不单独改变旧执行状态或开启 Resume。

这不是针对某个会话放行,也不是只对白名单文件修复。普通聊天和 Goal 共享同一恢复入口。旧效果审计可继续是 unresolved,而其所属聊天轮次结束为 interrupted;相应调整“存在 unresolved 就不允许结束轮次”的旧约束。

只有显式启用的 Goal 才产生 Goal 界面。启动、执行、暂停和验收不会新增聊天卡片。结束时,在对应聊天位置保留一张简洁记录卡片,复用现有附件卡片样式,点击后打开同一个 Goal 详情窗口,以只读方式查看历史。每条记录保存自己的 Goal 快照和聊天位置,后续 Goal 不会替换其内容。输入框继续只显示当前 Goal。由权威执行身份识别的验收消息属于内部记录,不作为助手聊天正文;普通回复保持不变。聊天不会追加评估文本、证据标识或原始报告。终态历史随 Goal 状态通过乐观并发控制保存。实现通过独立规格与质量审查,覆盖终态快照持久化、稳定历史位置、只读详情窗口复用、键盘焦点恢复和普通 JSON 回复保留。完整验证和安装版 App 验收仍是独立发布检查。

Todo 管计划,验收管目标

目标创建时保留原文并提取可核实要求;不明确到会改变任务范围时才询问用户。多步骤任务由工作 agent 维护 Todo,简单任务允许无 Todo。每个必要要求都有证据检查点;新增或删除 Todo 不得隐式删除原要求。

普通工作轮次不运行第二个 judge。工作 agent 提交 complete 候选,或必要 Todo 全部完成且尚未验证时,进入 verifying。先检查当前 revision、必要 Todo、未结束子任务和相关未知效果,再运行一次独立的只读验收;工作 agent 的“完成”文本不是验收事实。

验收按要求输出 met / unmet / unknown 和证据引用;可确定判断的要求检查真实测试回执、文件版本、运行状态等。语义要求由独立模型审查。需要执行测试时沿用普通工具审批和预算;shell 不因为被称作“验证”就变成只读工具。缺少证据返回下一轮补充,不伪造通过。

仅当前 goal_id + revision + 已核验的结果版本允许提交 achieved;提交前重新核对证据版本并比较 Goal 控制版本。可控产物使用版本号或内容摘要,外部事实记录核实时间及查询回执,不声称跨所有外部系统原子验证。完成表示该次核实时条件成立;完成后不默认监控文件或重新开启目标。后续编辑、新请求或明确监控要求另行验收。人工豁免必须作为明确的目标修订并保留原因,agent 不能自行缩小范围。独立验收同样可能出错,不保证绝对正确。

无进展的判定看结果与证据变化,而不是是否调用工具。相同真实阻塞连续出现、且没有独立可做工作时才进入 blocked;有运行 handle 的等待进入 waiting,不空转模型轮次。不以“达到固定总轮数”冒充阻塞或完成。

等待使用既有持久 wait 与 execution 终态通知,保存 work_id / Goal revision、handle、已观察版本及唯一消费键。完成、失败或超时通知仅在运行意图仍为 run、版本相符且无其他当前执行时准入一次;缺失通知由既有 reconciler 按退避间隔查询。重启期间到达的结果先保存,恢复后按相同规则自动继续。暂停、取消或修订使旧唤醒失效,不丢弃结果本身;查询超时不推断外部操作已经停止。

费用:按请求归属,按回执结算

请求发出前固定 goal_id / revision / turn_id / request_id;暂停后的普通聊天没有旧 Goal 归属。子 agent 与验收请求显式继承归属,同一 receipt 只计一次,不同时加父项汇总与子项明细。重试是新的 provider attempt,若产生真实消耗则分别计入。

流式累计 usage 按同一 attempt 更新水位,不对每个累计快照求和。持久回执写入成功后再刷新 Goal 投影;临时失败由相同幂等键重试,重启可重建统计。迟到回执仍计入原 Goal,不因为 Goal 已暂停、结束或编辑就丢弃。

tokens 已知与价格已知分别保存。价格表换代不追溯改写历史报价;估算、已知值、部分未知分别显示,例如“已知 $0.42;另有 1 次请求用量未知”。历史游标数据保留,不推算无法证明的归属。主动运行耗时按持久开始/停止记录累计,暂停与停机不计 active time;恢复不清零。突然失去执行者时保留最后心跳时间,发现崩溃的时间不冒充停止时间;显示已知时长下限和中断时段未知。迟到用量不启动已暂停计时;显式时间限额无法核实时停止新准入,不增加默认限额。

预算默认不设限。用户设置硬费用预算时,未知价格或无法核实的消耗不能当作剩余额度;暂停新的付费准入并说明原因。能够计算请求最大额度时预留额度,否则不承诺绝对不超支。重新读取账本、恢复执行及验收前均重新检查显式预算。

后台 Job 在真实活动调用者的准入边界保存 Goal 身份,启动时恢复该身份并清除无关的临时归属。跨会话调用保存原调用者来源,但不创建跨会话 canonical parent。Goal 和 Job 共用 usage.db 的开始与结算事务;回执保存 Job 预留身份,重启后不依赖内存 governor 重建计量。未知 token 与未知费用分别保留预留额度,累计部分数据只保存下限。未开始的过期预留不能发送,已开始请求不会自动释放。硬预算仅接受已审计的输入与输出上限、明确价格和服务档位,不给未设置预算的 Goal 增加默认限制。

控制与界面:状态、原因、操作同时可见

状态前 → 操作 → 状态后用户看到什么执行约束
运行中 → 重启 → 恢复中 / 排队 → 核查 / 执行无需点击 Resume;具体阻碍显示原因、对应操作和 Retry。用户主动暂停时才显示 Resume。恢复运行意图但不盲目重发旧工具;同一工作只准入一轮。
Todo 5/5 → 发起验收 → verifying“5/5 · 验收中”,不是“已完成”。缺证据返回工作轮次;通过后才显示“目标已完成”。
active → Pause → paused立即停止自动续轮;独立显示当前执行是否仍在停止中。禁止新准入,取消当前执行;不假装撤销已发生效果。
任意未完成目标 → End → cancelled“目标已结束”;未结束进程或未知操作仍有提示。结束目标意图不依赖所有效果已核实,旧执行不再关联自动续轮。
有未决操作 → 查看 / 查询 / 人工确认 → 已核实或保留未知准确定位到调用、输入摘要、原时间和可用检查;不是只跳到整个 Activity 列表。风险重试需当前用户明确授权,不能由模型或页面内容代答。

空 Todo 不显示进度占位或分隔符。按钮权限由后端返回 can_resume / can_verify / can_end 及 reason_code,前端不按一组 status 字符串自行猜测。UI 读取失败显示“状态暂不可确认”和刷新入口,不显示永久无解释的灰色按钮。

用户输入优先于自动续轮;采用已有 steer/queue 语义。续轮去重键绑定 goal_id、revision 和前序已提交 turn;状态检查和准入必须共用版本比较。暂停、编辑、显式取消与新一轮准入竞争时,以持久状态及 generation 校验阻止过期动作。

实施顺序与必须通过的验收

阶段与改动位置必须证明的行为
1. 统一恢复决策:execution/startup、restart、control/recovery、JobRunner、_exec_dag 投影普通请求、active Goal、已存在子任务在重启后自动恢复;用户暂停不恢复。取消隐藏时间窗口,删除投影层业务状态改写,保持唯一准入与当前权限。
2. 共享执行恢复:agent/production_driver、上下文构造、effects、waits、资源适配器真实子进程在 dispatch 前、开始后、结果写入后被终止;重启后只追加一次修复,保留真实结果,可继续普通聊天。旧 owner 迟到写入、存活 shell 与未知非幂等写入不能被错误重试。
3. Goal 续轮与控制:workflow/goal、HTTP/WS/TUI/ACP 入口Resume 不重放工具;双击、重复完成事件、编辑/暂停竞争不产生双执行。旧 revision 不提交新目标完成。无 Todo 不显示占位;5/5 不直接显示 achieved。
4. 证据验收:Goal completion 候选与现有 agent 检查能力必要项未完成、证据缺失、测试失败、结果过期、相关未知效果分别拒绝完成;实际证据满足时只提交一次 achieved。验证不能提升工具权限。
5. 请求归属与统计:usage/recorder、ledger、Goal 投影重复/乱序 usage、并发子任务、流式累计值、重试、账本故障、暂停后迟到回执均正确;未知不为零,预算超限不继续付费请求。
6. 兼容与本机验收旧 Goal 可读取、未知效果无猜测迁移、Python Workflow 不受聊天恢复策略破坏。完整回归、独立规格/质量审查后更新唯一默认 App,并验收真实按钮、重启续接和费用显示。

每阶段先公共入口故障复现,再最小实现及回归。普通聊天也覆盖恢复测试,不能仅让一个特定会话通过。验收区分源码、自动测试、本机 App 和远端发布;没有测试或部署证据的设计不标已实现。

重启故障验收:不是只测一次 Resume

通过公开聊天、Goal、Job、审批与控制入口建立任务,在独立测试存储及非用户可见的进程测试中进行真实终止;不得终止用户的当前任务来证明故障恢复。最终可见 App 验收只使用默认实例,并先确认更新不会覆盖无关工作。

  • 覆盖前端重载、App 正常退出、worker 正常重启、worker 被强制终止、停机超过原两小时窗口、恢复过程中再次崩溃;宿主重启语义由进程身份变化测试,真实系统重启单列未验收,不自行重启用户机器。
  • 断点包括接收输入前后、provider 请求中、tool dispatch 前后、结果提交前后、父子消息投递中、Todo 全完成但尚未验收、完成提交后投影发送前、费用持久化前后。
  • 同时恢复多个会话,证明公平排队、共享额度、每个工作单一 owner、重复通知不双执行;恢复期间用户 Pause / End、修改权限或新输入优先,旧版本不得继续。
  • 存活子进程只重新关联,非幂等写入结果未知只核查;已接受审批不重复消费,审批未接受不自动批准;晚到结果与晚到费用归原身份。
  • 数据库不可用、损坏迁移、缺失凭据、目录不存在、工具版本改变和投影事件丢失均有明确状态及可恢复入口;不能清空历史或停留在无说明的禁用控件。
Python Workflow 兼容路径及既有详细图示(不定义上方聊天 Goal 合同)
实现调研 · 设计参考

Agent Goal 功能:实现方式对比

本文比较 Goal 在运行时中的真实职责:目标数据放在哪里、谁触发下一轮、谁判定完成、如何限制资源、如何处理等待与人工介入、进程重启后能否恢复。重点不是功能名称,而是控制流和状态所有权。

4 个原生 Goal 实现 2 个相邻机制实现 兼容路径参考,不作为聊天 Goal 实现证明 5 张 Archify SVG · 文档内嵌
已经具备独立、可使用检查工具的完成判定工作 agent 产出结果,inspection judge 检查证据,再决定继续或完成。
当前主要缺口外部事件唤醒尚未实现waiting_external 仍需显式 resume;同机共享目录的 live Goal 由独占 controller 锁保护。
当前设计持久快照、异步问题、独立 judge 与硬预算共用一个 controller重启转为可恢复暂停;等待不消耗轮次或 active-time 预算。

1. 范围与比较口径

一个系统只有在保存目标状态,并能在普通 agent turn 结束后根据该状态决定是否自动开始下一轮时,本文才把它记为“原生 Goal”。Todo、Plan、Task、Cron 可以参与 Goal,但单独存在时不等于 Goal。

比较对象

OpenProgram、Codex、Claude Code、Hermes Agent;OpenCode 与 OpenClaw 作为相邻实现;OpenAI Agents SDK、LangGraph、AutoGen、CrewAI 作为通用框架基线。

固定观察维度

入口、状态结构、循环触发、完成判定、预算、等待、人工介入、持久化、恢复、并发控制、事件与 UI。

证据优先级

公开源码与本仓库源码优先;官方运行文档用于闭源实现;产品表象只用于说明接口,不用于推断内部数据结构。

Claude Code 的实现源码不公开。本文对它只记录官方文档明确给出的控制合同:/goal 是 session-scoped prompt Stop hook、判定器输入、三种 verdict、恢复和后台任务等待规则;不推断它的数据库表或内部类名。

兼容 Python Workflow 的控制流程

本节描述保留的 Python goal() Workflow;普通聊天使用页首的聊天 Goal 合同,不经过以下 refine/work/judge 循环。

四个原生实现都包含“工作完成后决定是否再开一轮”,差别集中在状态由谁保存、完成由谁判断,以及等待是否会暂停执行。

一个 Goal 从输入到终止的最小闭环实线是当前工作路径;虚线表示未完成或外部条件变化后的再次执行。
工作判定等待停止
OpenProgram Goal 控制流程 由 Archify 生成的工作流图。 01 / Web / TUI 02 / Goal Controller 03 / Agent Roles 04 / Evidence & State EX / Wait / Stop 定义与恢复 执行与判定 继续或终止 Goal 输入 · 创建 / 编辑 / 继续 · Web / TUI › 定义与恢复 Goal 输入 创建 / 编辑 / 继续 持久化状态 · goal_id · version · checkpoint · Goal Controller › 定义与恢复 持久化状态 goal_id · version · checkpoint 原子状态转移 · CAS version + event · Goal Controller › 继续或终止 原子状态转移 CAS version + event Working Agent · 调用工具并推进任务 · Agent Roles › 执行与判定 Working Agent 调用工具并推进任务 确定性 Gate · 命令 · 文件 · 计数 · 权限 · Agent Roles › 执行与判定 确定性 Gate 命令 · 文件 · 计数 · 权限 Judge Agent · 只读检查与语义判定 · Agent Roles › 继续或终止 Judge Agent 只读检查与语义判定 证据与用量 · 结果 · 文件 · token · 时间 · Evidence & State › 执行与判定 证据与用量 结果 · 文件 · token · 时间 异步问题队列 · 累计 · 去重 · 稍后回答 · Wait / Stop › 执行与判定 异步问题队列 累计 · 去重 · 稍后回答 等待边界 · 无独立工作 / 外部事件 · Wait / Stop › 执行与判定 等待边界 无独立工作 / 外部事件 停止并保留证据 · blocked · stalled · failed · Wait / Stop › 继续或终止 停止并保留证据 blocked · stalled · failed unmet → next round terminal verdict 可验证条件 gate result create / edit / resume typed verdict needs_user waiting_external 无独立工作 可继续 → 独立工作 lease + checkpoint 结果 + 工具证据 图例 用户界面 Agent 逻辑 策略 工具操作 上下文 / 追踪 外部系统
判断一套 Goal 是否完整,主要看黄色等待分支能否真正暂停、红色停止分支能否区分原因,以及控制状态能否跨 turn 和进程恢复。只实现中间的工作—判定循环还不够。

五类实现模型

层级
输入
进度
终止
跨 turn
代表系统
Task input
用户消息作为本轮任务
无要求
模型停止
否
普通 agent turn
Progress ledger
任务 + items
Todo / Task供提示和 UI 使用
不参与总体终止
不自动续轮
OpenCode Todo
Graph termination
graph state
应用自定义
edge / condition
由应用实现
LangGraph · AutoGen
持久化控制器
objective
usage / status
agent 声明
idle 时自动续轮
Codex
Evaluator loop
Goal spec
evidence
独立 evaluator
未完成则续轮
OpenProgram · Claude · Hermes

D 与 E 可以组合。Codex把完成声明交给工作 agent 自身,但控制面负责生命周期和预算;另外三个实现把完成判定交给独立 evaluator。

四种原生 Goal 架构放在同一张图里

每一行都是一个完整实现。横向阅读可以直接看到它们把状态、工作、判定和续轮分别放在哪里。

原生 Goal 的状态所有权和判定路径青色表示独立判定器,蓝色表示工作 agent,黄色表示等待或受限状态。
四种原生 Goal 的控制结构 由 Archify 生成的工作流图。 01 / OpenProgram 02 / Codex 03 / Claude Code 04 / Hermes Agent 状态所有权 工作与判定 续轮与等待 Versioned Goal snapshot · goal/run ID · CAS · OpenProgram › 状态所有权 版本化 Goal 快照 goal/run ID · CAS Working Agent → Judge · 独立且可只读检查 · OpenProgram › 工作与判定 Working Agent → Judge 独立且可只读检查 Controller / Wait · 异步问题 · 重启恢复 · OpenProgram › 续轮与等待 Controller / Wait 异步问题 · 重启恢复 SQLite ThreadGoal · typed status · usage · Codex › 状态所有权 SQLite ThreadGoal typed status · usage Working Agent 自报 · update_goal · Codex › 工作与判定 Working Agent 自报 update_goal Idle Controller · pause · resume · limits · Codex › 续轮与等待 Idle Controller pause · resume · limits Session Goal Prompt · resume 保留 · Claude Code › 状态所有权 Session Goal Prompt resume 保留 Stop Hook Evaluator · 小模型 · 无工具 · Claude Code › 工作与判定 Stop Hook Evaluator 小模型 · 无工具 阻止停止或清除 · 后台任务 defer · Claude Code › 续轮与等待 阻止停止或清除 后台任务 defer GoalState + Contract · gates · waits · Hermes Agent › 状态所有权 GoalState + Contract gates · waits Gate → Judge · 机械检查优先 · Hermes Agent › 工作与判定 Gate → Judge 机械检查优先 Queue / Wait Barrier · 事件唤醒 · Hermes Agent › 续轮与等待 Queue / Wait Barrier 事件唤醒 three verdicts on Stop self-report run turn done / blocked / wait turn result verdict work + evidence 图例 Agent 逻辑 策略 工具操作 上下文 / 追踪

横向实现矩阵

图用于理解控制结构;表保留精确字段和边界,供设计核对。

查看完整横向矩阵
系统Goal 表示下一轮触发完成判定预算等待 / 人工介入持久化与恢复关键性质
OpenProgram Python Workflow 兼容路径session extra_meta.goal 版本化快照;含 goal/run ID、spec、checklist、问题队列和 checkpointgoal() controller 在边界提交状态后启动下一次 agent()独立、可使用只读检查工具的 judge;typed verdict 与 can_continue默认不限制轮数;可设 round/token/active-time/cost 总预算,resume 后累计问题异步累积;继续独立工作;仅剩依赖答案的工作时进入 waiting_userCAS 写入 session;页面重载保持状态;worker 重启把执行中状态转为 paused_recoverable完成判定、停止、恢复和 UI 已统一;外部自动唤醒与多 worker lease 尚缺
CodexSQLite ThreadGoal;有 goal_id 和 typed statusthread idle 生命周期读取 active Goal 并启动 turn工作 agent 调 update_goal(complete|blocked) 自报;无独立 judge可选 token budget;累计 tokens 与 elapsed timepause/resume/usage-limit 由用户或系统控制;blocked 有三轮审计规则SQLite 持久化;resume 恢复 active controller控制面和数据模型最完整
Claude Code每 session 一个 completion conditionprompt-based Stop hook 阻止停止并把 reason 作为下一轮指导small fast model:not met / met / impossible;无工具Goal 自身无结构化预算;条件可写停止条款;外层另有 max turns / USD后台任务在运行时延后判定;idle check-in 退避且有限次resume 恢复 active condition,但重置轮次、计时和 token 基线复用通用 Hook 协议,表面最小
Hermes AgentGoalState + contract + subgoals + gates + wait barrierCLI/gateway 在 turn 后排入普通 user-role continuation先执行 deterministic gates,再由 auxiliary judge 判定 done/blocked/continue/wait默认 20 个 Goal turn;gate 各自 timeout/retry可等待 PID、process session 或时长;用户消息优先SessionDB.state_meta;resume 与 compression session migration完成合同、确定性 gate 与 async wait 组合最完整
OpenCode用户 task + SQLite Todo rows同一 turn 内按 tool-call finish reason 继续模型停止调用工具即结束;Todo 完成不控制总循环agent steps 上限;默认无限question/permission 属于 turn;没有 Goal pause/resumesession、message、todo 持久化;没有 active Goal controller可靠的进度账本,不是 Goal
OpenClawautomation job、heartbeat scratch、commitment、background task 分开建模scheduler、事件或任务完成唤醒 sessionrun 成功/失败、脚本 exit code或模型本轮停止;无开放式 Goal evaluator按 automation run 的 timeout/tool budget;非 Goal 总预算天然支持定时等待、事件唤醒、delivery 与退避调度定义、运行状态与历史持久化;可跨 gateway restart适合长期调度,不负责开放式目标收敛

任务无法完成时,控制器如何停止

原生 Goal 会在普通 agent turn 结束后自动决定是否继续,因此必须同时处理“暂时没有完成”“缺少外部条件”“目标不可实现”和“持续没有有效进展”。只有轮数上限不能识别这些原因,只能限制最坏情况下的执行长度。

困难任务的状态机绿色是成功;黄色状态必须停止自动工作并等待明确事件;红色状态需要修改目标、预算或运行环境后才能继续。
判断暂停终止
OpenProgram Goal 生命周期 由 Archify 生成的生命周期图。 01 / 主生命周期 02 / 可恢复等待 + 困难任务分类 03 / 终态 Draft · 目标已保存 · 主生命周期 01 Draft 目标已保存 Refining · 形成 spec 与 checklist · 主生命周期 02 Refining 形成 spec 与 checklist Running · 独立工作继续,问题可累计 · 主生命周期 03 Running 独立工作继续,问题可累计 Evaluating · Gate + Judge · 主生命周期 04 Evaluating Gate + Judge Achieved · 证据满足完成合同 · 主生命周期 05 Achieved 证据满足完成合同 Paused · 用户暂停或重启恢复 · 可恢复等待 · recoverable Paused 用户暂停或重启恢复 recoverable Waiting User · 仅剩依赖回答的工作 · 可恢复等待 · event Waiting User 仅剩依赖回答的工作 event Waiting External · 等待作业或外部状态 · 可恢复等待 · event Waiting External 等待作业或外部状态 event Blocked · 缺少权限、依赖或输入 · 困难任务分类 · recoverable Blocked 缺少权限、依赖或输入 recoverable Stalled · 连续无有效进展 · 困难任务分类 · recoverable Stalled 连续无有效进展 recoverable Budget Exhausted · turn · token · time · cost · 困难任务分类 · recoverable Budget Exhausted turn · token · time · cost recoverable Impossible · 当前合同内无法满足 · 终态 · terminal Impossible 当前合同内无法满足 terminal Failed · 不可恢复执行错误 · 终态 · terminal Failed 不可恢复执行错误 terminal Cancelled · 用户明确终止 · 终态 · terminal Cancelled 用户明确终止 terminal 图例 开始 活动状态 等待 决策 成功终态 失败 / 退出 外部状态
查看各框架的困难任务停止机制
系统无法完成时的结果确定性停止机制是否仍可能长时间循环主要缺口
OpenProgram Python Workflow 兼容路径typed verdict 区分 blocked、impossible、waiting_external、needs_user、stalled、budget_exhausted 与 failed兼容 Workflow 默认不限制轮数;可设 token/active-time/cost 预算;连续 judge 失败 3 次;checklist 停滞 3 次;连续 2 轮没有工具且仍未完成未设置预算时没有固定轮数上限;当前停滞证据主要是 checklist 增量与工具使用尚无通用 deterministic gate executor;waiting_external 没有自动事件唤醒
Codex工作 agent 可声明 blocked;控制面可进入 paused、usage_limited、budget_limited 或 complete可选 token budget;同一阻塞条件需要连续三轮审计后才能认定 blocked;用户和系统可暂停会。没有配置 token budget 且 agent 不声明 blocked/complete 时,Goal controller 仍会续轮完成和阻塞依赖工作 agent 自报,没有独立 evaluator 验证是否真的没有进展
Claude Codeevaluator 返回 impossible 时清除 Goal;连续没有工具进展时停止续轮但保留 Goal通用 Stop hook 连续阻止停止 8 次后强制结束;后台 idle check-in 最多 3 次;外层可设置 max turns 和 USD budget会。Goal 自身没有结构化硬预算;持续产生工具行为且 evaluator 一直返回 not met 时依赖外层限制判定器没有工具,无法直接验证文件、测试和外部状态;Goal 预算与 runner 预算分离
Hermes Agentjudge 可返回 blocked 或 wait;达到 Goal turn 上限后不再继续默认最多 20 个 Goal turn;gate 有 timeout/retry;相同 workspace fingerprint 下不会重复执行同一个已失败 gate;等待不消耗工作轮次不会无限续轮,但可能在 20 轮内重复低价值工作缺少已确认的 Goal 级 token/cost 总预算;语义 judge 仍可能连续返回 continue
OpenCode模型停止调用工具后结束当前 turn;Todo 未完成不会自动开始下一轮可配置 agent steps 上限单个 turn 可能很长,因为 steps 默认可为无限;但 Todo 不形成跨 turn Goal 循环没有跨 turn 的 stalled、blocked、budget 和恢复合同
OpenClaw单次 automation 成功、失败或超时;之后是否再运行由显式 schedule 决定每次 run 的 timeout/tool budget、调度退避和持久化 run state不会因“目标未完成”自动无限续轮;Cron 可以按用户配置永久重复没有开放式 Goal evaluator,不能判断一个长期目标是否已经实现或不可实现

为什么“调用了工具”不是进展

工具调用只能证明 agent 执行了动作,不能证明验收条件更接近满足。停滞检测应比较连续轮次新增的 evidence refs、通过的 deterministic gates、未完成 checklist 项和外部状态变化。相同证据反复出现时,应进入 stalled,而不是重置停滞计数。

等待不能占用工作轮次

问题先进入持久化异步队列;只要还有不依赖答案的安全工作,controller 就继续执行。仅当全部剩余工作依赖答案时才进入 waiting_user。CI、后台进程、时间或外部事件进入 waiting_external;当前需要显式 resume。

结论:这些实现都不能仅凭语义 evaluator 保证收敛。可靠的控制器需要硬预算、基于证据的停滞检测、明确的 blocked/impossible/waiting 分类,以及只有外部事件才能解除的等待状态。

原生 Goal 实现细节

OpenProgram

一个公开 Workflow 同时承担 Goal 执行、判定循环和 session 状态投影。

原生 Goal · 开源源码
Entrygoal(prompt, ...)
State ownersession extra_meta.goal
Completiontool-capable judge
Resumecheckpoint 保留,新 execution 继续
写 active先持久化最小 GoalState,允许 status/clear 立即看到
refine独立 inspection turn 生成 spec 与固定 checklist
work公开 agent() 执行一个完整工具循环
collect记录工具使用信号与本轮结果,更新 turns
judge独立 sub-agent 读取证据,并可用 bash/read/grep 等检查
transitiontyped verdict、异步问题、预算与停滞检查
repeat继续独立工作,或写 waiting / achieved / stopped state

数据与判定

  • 入口只有一段 prompt;同一文本交给工作 agent,并由 refinement 生成完成规格与 checklist。
  • schema v3 快照包含 goal/run ID、revision/version、typed status、预算/用量、checkpoint、问题队列和待消费答案。
  • session 入口把 refinement 与 judge 作为不推进主线的独立 agent turn;无 session 的 programs run goal 也在当前 runtime 中执行带只读工具约束的独立 refinement/judge turn。
  • judge 不只阅读工作 agent 的声明,还能检查文件、命令输出和清单项;严格 JSON 解析失败会重试一次,连续 3 轮判定失败进入 failed。

停机与恢复

  • 兼容 Workflow 默认不限制工作轮数,并支持 token、active-time 与 cost 总预算;清单停滞和连续无工具轮次会进入 stalled。
  • /goal clear 写 cancelled,取消旧 execution;CAS version 防止旧 controller 覆盖新操作。
  • needs_user + can_continue 把问题加入队列并继续独立工作;没有独立工作时才进入真正的 waiting_user。
  • worker 重启时执行中 Goal 进入 paused_recoverable;目标、checklist、用量、问题和 checkpoint 保留,resume 创建新 run。
实现判断:OpenProgram 已具备独立 tool-capable judge、typed states、版本化持久快照、异步问题、硬预算和重启后显式恢复。仍未实现通用 deterministic gate executor、外部事件自动唤醒与独立 evidence repository;同机 multi-worker 由 OS 文件锁提供独占 ownership。

Codex

Goal 是 thread 上的持久控制实体;工作 agent 通过工具声明完成或阻塞。

原生 Goal · 开源源码
EntryUI/API + create_goal
State ownerSQLite ThreadGoal
CompletionAgent 自报工具
Resumeidle lifecycle 恢复
create/set校验 objective 与可选 token budget;一条 thread 仅有一个未完成 Goal
persist写 goal_id、status、usage 与时间字段
start turnGoal active 且 thread idle 时注入 continuation steering
work普通 Codex turn 使用现有工具、计划和上下文
accountturn 结束按基线累计 token 与 elapsed seconds
declareagent 只可调用 update_goal(complete|blocked)
idle again仍为 active 就继续;外部控制可 pause/resume/clear

数据与权限分离

  • ThreadGoal 是 typed record:thread_id、goal_id、objective、status、token budget、tokens used、time used、created/updated。
  • status 为 active、paused、blocked、usage_limited、budget_limited、complete。
  • 模型工具只允许创建、读取以及把状态改为 complete/blocked;pause、resume、budget/usage limited 由用户或系统控制。
  • 外部 app-server 提供 thread/goal/set|get|clear 与 updated/cleared 通知。

并发与完成语义

  • Goal mutation 与 idle continuation 共用 semaphore,写入使用 expected_goal_id 避免旧 turn 更新新 Goal。
  • resume 读取持久 Goal;只有 active 才重新登记 idle continuation。
  • completion audit 写在 continuation prompt 中,由同一个工作 agent 基于实际证据决定是否调用 update_goal,没有独立模型复核。
  • blocked 要求同一阻塞连续出现至少 3 个 Goal turn;token budget 耗尽由系统转为 budget_limited。
实现判断:Codex 的优势是 first-class state、权限边界、CAS 式更新、资源核算和 resume;风险是完成判断与执行者相同,主要依赖 prompt 约束和工具调用纪律。它累计 elapsed time,但当前结构没有 time budget,也没有等待外部进程的专门状态。

Claude Code

/goal 是通用 Stop hook 机制的 session-scoped prompt evaluator 配置。

原生 Goal · 官方运行合同
Entry/goal <condition>
State owner会话范围条件
Completionsmall fast model
Resume恢复 condition,重置计量基线
set每个 session 一个 condition;新值替换旧值并立即开始 turn
work普通 Claude Code turn;Goal 不改变 permission mode
Stop event主 agent 准备结束时触发 session-scoped prompt hook
defer若 background task 仍在运行,本轮跳过 evaluator
evaluatecondition + conversation 交给 small fast model;不能调用工具
verdictnot met / met / impossible,均带 reason
continue/clearnot met 把 reason 反馈给下一轮;另两种清除 active Goal

复用 Hook 协议

  • 普通 Stop hook 可返回 decision:"block" 和 reason;reason 进入 Claude 的下一轮上下文。
  • prompt hook 可由模型返回 ok、reason、impossible。/goal 在这一通用机制上增加 condition、状态显示和恢复。
  • stop_hook_active 防止扩展脚本无条件递归;通用 Stop hook 连续阻止 8 次后由运行时强制结束。
  • Goal evaluator 只看对话中已经出现的证据,不读取文件或运行测试。

等待、错误与预算

  • 后台 shell/subagent 运行时不判定;完成结果会触发新 turn。长时间等待使用退避 check-in,交互会话每次用户输入之间最多自动发起 3 次 idle check-in。
  • 连续多轮无工具进展时停止自动循环,但保留 Goal,等待下一次用户 prompt 后继续评估。
  • 不可恢复的 auth、余额、无法压缩的 context overflow、模型不可用会清除 Goal;瞬时错误保留 Goal。
  • Goal 没有独立 typed budget;可把 turn/time 终止条件写进 condition。外层 print mode 另有 --max-turns 和 --max-budget-usd。
实现判断:Claude Code 证明了 Goal 可以作为通用“停止拦截器”的特化,而不需要独立执行器。它对 background work 的 defer/check-in 处理完整,但 evaluator 无工具,可靠性依赖工作 agent 把验证证据写入 transcript。

Hermes Agent

GoalManager 把自由文本目标、结构化完成合同、确定性 gate 和异步等待统一到 turn 边界。

原生 Goal · 开源源码
Entry/goal / /subgoal
State ownerGoalState in SessionDB
Completion确定性检查 → 辅助判定器
Resume会话恢复 + 解除等待
set/draft自由文本或 completion contract;可追加 subgoal
work用普通 run_conversation 完成一轮
gate先运行有 timeout/retry 的 shell quality gates
judgeauxiliary model 判定 done/blocked/continue/wait
wait可绑定 PID、process session 或 deadline;等待不消耗 Goal turn
enqueuecontinue 作为普通 user-role message 进入 CLI/gateway 队列
persist每次转移写 state_meta[goal:session]

完成合同与 gate

  • GoalContract 把 outcome、verification、constraints、boundaries、stop_when 分开保存,并同时注入工作 prompt 与 judge prompt。
  • GoalGate 在 LLM judge 之前执行;失败时跳过 judge,限制输出尾部并把失败证据作为 continuation。
  • gate 记录 attempts、exit code、output tail 和 workspace fingerprint;工作区未变化时复用失败结果,避免重复运行同一检查。
  • subgoal 是用户追加的验收条件,不重启主 Goal,也不重置原始目标。

状态、等待和适配层

  • GoalState 保存 status、turn budget、judge failure counters、subgoals、wait barrier、contract 与 gates。
  • judge 输出 done、blocked、continue 或 wait;wait 可指定 PID、process session 或秒数。
  • CLI 与 gateway 共用 GoalManager,但各自负责把 continuation 排进现有消息队列;不修改 system prompt 和 toolset。
  • Goal 状态随 session resume 恢复;context compression 造成 session id 轮换时迁移 Goal 并清理旧记录。
实现判断:Hermes 当前方案把“可验证完成”和“外部工作尚未结束”分开:确定性 gate 对验证结果负责,judge 对开放式语义负责,wait barrier 对异步依赖负责。默认仍是单 session 单 Goal 与 turn budget;总 token/cost budget 不属于已确认的 GoalState 合同。

没有原生 Goal 的相邻实现

这两套系统提供了 Goal 所需的部分构件,但没有“一个开放式完成条件持续控制多个 turn,直到被独立判定为完成”的完整合同。

OpenCode

持久 Todo + 单 turn agent loop;Todo 是进度记录,不是循环终止条件。

相邻机制 · 开源源码
Task sourcelatest user message
Progress stateSQLite Todo rows
Loop stop提供商结束原因
Boundagent.steps

实现方式

  • SessionPrompt.run 循环读取最新消息;assistant 有非 tool-call finish reason 且不存在未处理 tool call 时退出。
  • 每轮解析 agent profile,解析工具,处理 compaction/subtask,然后调用 provider。agent.steps 默认无限;最后一步把 max-steps 提示加入模型消息。
  • Plan 是一个 primary agent profile:主要通过 permission 禁止 edit,只允许写特定 plan 文件;它不是 Goal 状态。

Todo 的边界

  • Todo item 只有 content、status、priority;按 session ID 存 SQLite,并发布 todo.updated。
  • todowrite 每次替换完整列表,UI 展示 completed/total;subagent 默认禁用。
  • Todo 是否全部 completed 不参与 SessionPrompt.run 的退出判断,也不会在 session idle 后自动启动新 turn。
  • 因此它适合成为 Goal 的 progress projection,但不能单独承担 Goal controller。

OpenClaw

把持久工作拆成 scheduler、background task、heartbeat、standing instruction 与 commitment,而不是提供通用 Goal evaluator。

相邻机制 · 开源源码
Persistent intent自动化 / 长期指令
Wake ownerGateway scheduler
ExecutionAgent 轮次 / 命令 / 脚本
Completionper-run outcome

调度与状态

  • Automation job 保存 id、name、enabled、schedule、session target、wake mode、typed payload、delivery、failure alert 和 run state。
  • payload 分为 system event、agent turn、command、script;session target 可为 main、current、isolated 或命名 session。
  • 运行结果区分 execution 与 delivery;持久化 job、运行状态和历史,gateway restart 后继续调度。
  • 脚本与 command 可以用 exit code 提供确定性成功,但这只判定一次 run,不判定开放式目标。

Heartbeat 与 commitment

  • Heartbeat 是系统拥有的 monitor automation;读取 scratch 或 HEARTBEAT.md,无到期任务时跳过模型调用。
  • 结构化 heartbeat task 只有 name、interval、prompt,按各自周期进入下一次 monitor turn。
  • Commitment 记录 agent promise 或从用户上下文推断的后续联系,包含 due window、confidence、status、attempts 与 delivery scope。
  • 这些机制擅长“何时再次执行/通知”,但没有 met/unmet evaluator,也不会把多个 run 约束为同一个完成条件。
实现判断:OpenClaw 最适合作为 Goal 的外部等待和调度参考。把它直接称为 Goal 会丢失完成判定语义;更合适的组合是 Goal controller 在需要未来时间或外部事件时创建/绑定 automation,收到事件后再恢复 Goal。

Python Workflow 的独立判定与兼容约束

以下独立 work/judge 合同仅属于 Python Workflow;聊天模式采用上方方案:普通工作轮次不运行 judge,仅在完成候选出现时作独立验收。

已经采用

Codex 的控制面数据模型

当前快照已有稳定 goal_id、每次执行独立的 run_id、typed status、budget/usage、时间字段和 CAS version;用户操作负责 pause/resume/edit/answer/limit/clear,judge 只提交候选 verdict。

直接采用

Hermes 的三段判定

completion contract 明确定义 outcome/verification/constraints/boundaries/stop_when;确定性 gate 先执行;只有 gate 通过后才使用语义 judge。异步依赖进入 wait barrier,不重复启动工作 turn。

直接采用

Claude Code 的后台任务 defer

工作 turn 结束但存在 background task 时,不立即判定完成,也不立即续轮。由完成事件恢复;长期等待时使用有上限的退避 check-in,并把运行中任务列表交给 controller。

已经保留

OpenProgram 的 tool-capable judge

独立 judge 使用只读检查工具直接验证文件和命令结果,并返回 typed verdict。deterministic gate executor 仍是后续工作。

组合使用

OpenCode Todo 作为进度投影

Goal checklist 应有独立 typed item 表和事件,UI 可稳定显示。但 checklist 的 completed 状态只是 evidence,不应直接等价于整个 Goal complete,也不应由 UI 状态驱动 controller。

按需组合

OpenClaw 调度作为等待适配器

未来时间、CI、外部事件或后台作业不应消耗 Goal turn。GoalRun 保存 wait handle;scheduler/task subsystem 负责唤醒;Goal controller 收到事件后重新判定或继续。

不采用

仅依据工作 agent 的完成声明

Codex 的 self-report 适合低成本通用控制面,但 OpenProgram 已有独立判定器,不应退回到仅靠 update_goal(complete)。该工具可作为候选信号,最终状态仍由 evaluator/controller 提交。

当前边界

版本化 session 快照

extra_meta.goal 已有 schema version、实体 ID、CAS 写入与迁移读取,足以承担当前单 session controller。它仍不是 append-only evidence repository;需要审计级证据历史时再拆分独立存储。

不采用

把 Todo、Plan 或 Cron 命名为 Goal

三者分别解决分解、变更权限和时序触发,不包含“完成条件 + 判定 + 自动续轮”的完整语义。API 与 UI 应保留这些边界。

兼容 Python Workflow 的合同与剩余扩展

本节的独立判定器、角色配置和恢复检查点属于 Python Workflow。聊天入口使用同一状态存储及预算控制,但不调用此控制器。

Goal 不新增第二套 agent loop。当前 controller 位于现有 session/dispatcher 之上,工作仍通过公开 agent() 执行;图中 implemented 是当前代码,target 是尚未实现的扩展。

OpenProgram Goal:当前控制器与剩余扩展 由 Archify 生成的架构图。 Goal entry · Programs / API / /goal · 架构组件 Goal entry Programs / API / /goal GoalSpec · objective · contract · scope · 架构组件 · target GoalSpec 目标 · 合同 · 范围 target GoalController · 唯一状态转移所有者 · 架构组件 · target GoalController 唯一状态转移所有者 target Working agent · agent() / turn dispatcher · 架构组件 Working agent agent() / 轮次派发器 Deterministic gates · tests · commands · typed checks · 架构组件 · target 确定性检查 测试 · 命令 · 类型检查 target GoalEvaluator · inspection judge + evidence refs · 架构组件 GoalEvaluator 检查判定器 + 证据引用 Terminal state · achieved · blocked · failed · 架构组件 Terminal state achieved · blocked · failed Async question queue · pending · answered · dependency · 架构组件 · implemented 异步问题队列 待答 · 已答 · 依赖 implemented External wake adapter · job · timer · event · 架构组件 · target 外部唤醒适配器 job · timer · event target Session Goal snapshot · version · checkpoint · usage · 架构组件 · implemented 会话 Goal 快照 版本 · 检查点 · 用量 implemented Goal projection · UI · goal.updated · 架构组件 Goal projection UI · goal.updated create / resume / clear 完成合同 启动一个工作轮次 new evidence verified results 类型化判定 + 证据引用 needs_user + can_continue 回答 / 安全续接 已接受终态判定 CAS version + usage 匹配的外部事件 版本化投影 图例 前端 后端 数据库 安全 消息总线 外部系统
Archify architecture · showcase 结构验证 9/9,0 errors,0 warnings。图中直接嵌入可缩放 SVG;typed source 与本文档同目录保存。紫色虚线表示等待与恢复路径。
  1. Spec 与 run 保存在一个版本化快照中。goal_id 跨 resume 保持稳定,run_id 标识一次 execution;编辑生成新 revision,并重新完善 spec/checklist。refinement 只转述用户要求与必要正确性检查,保留“约”等近似约束,不自行增加格式比例、基准名、数量门槛或参考作品比较;重要歧义作为待确认问题保留。
  2. Stop policy 在阶段边界检查累计预算。rounds、tokens、active elapsed time 和 cost 在 resume 后累计;等待和暂停不消耗 active-time 预算。工作轮次默认限时 300 秒,provider 静默流受整个调用的截止时间约束;累计预算不是对当前阶段的精确抢占上限。
  3. Controller 是状态转移提交者。每个阶段保存 checkpoint;pause/edit/answer/cancel 与旧 controller 使用 CAS version 竞争,旧执行不能覆盖新状态。
  4. Evaluator 是独立 inspection agent。它输出 met、unmet、blocked、impossible、waiting_external、needs_user 和 can_continue。本地检查之外提供 web_fetch、web_search,沿用现有 URL 与网络权限检查;网页工具的失败通过结构化 is_error 回执传递。一次判定含失败的工具检查回执时,controller 不接受 met,先重新判定;持续失败报告 judge failure。该规则保守地要求一次无检查错误的验收,不证明成功回执本身足以满足全部语义要求;通用确定性 gate executor 尚未实现。
  5. 异步问题队列不阻塞无关工作。问题可以累积并逐项回答;active execution 在下一个边界消费答案,只有所有剩余工作都依赖答案时才进入 waiting_user。问题只占用 Goal 详情面板,不替换或禁用普通 composer。
  6. 重启恢复采用显式新 execution。启动 reconciliation 把遗留执行状态改成 paused_recoverable;恢复沿用快照而不尝试复活旧调用栈。
  7. 外部 scheduler 是目标扩展。waiting_external 已有状态,但 job/timer/event 的自动 wake handle 尚未实现。同机共享 session store 的 Goal controller 使用独立 OS 文件锁,启动恢复持相同锁,避免改写 live sibling 的状态。
查看目标状态的完整转移表
状态进入者允许离开方式是否自动运行说明
active / running / evaluating创建/恢复;控制器waiting_user / waiting_external / paused / blocked / impossible / stalled / achieved / budget_exhausted / failed / cancelled是单个 controller 顺序启动工作 turn 与 judge;每个边界保存状态。
waiting_user判定器/控制器任意新答案触发 resume,或 edit/cancel否仅表示剩余工作全部依赖答案;部分答案可以解除部分依赖,其他问题保留。
waiting_externalevaluator显式 resume / edit / cancel否当前没有自动 wake handle;外部依赖变化后由用户恢复。
paused / paused_recoverable用户 / startup reconciliationresume / edit / cancel否保留预算、问题、checklist 和 checkpoint;等待时间不计入 active time。
blockedevaluator依赖变化后 resume、edit 或 cancel否不是成功;reason 记录当前阻塞事实。
impossibleevaluator只读终态;可创建新 Goal否当前目标与固定约束不能同时满足。
stalledcontrollerresume / edit / cancel否checklist 连续不增长或连续无工具工作达到阈值。
achievedcontroller 接受 evaluator 结果只读;新目标创建新 run否保存 evidence refs、gate results 和最终 usage。
budget_exhausted / failedcontroller / runtime调整预算后 resume,或 edit/cancel否预算耗尽与执行/判定错误分开记录。

Goal 控制界面与 Workflow 兼容字段

Web 与 TUI 的开始、恢复均提交普通聊天。下方角色字段仅用于兼容 Workflow 记录;聊天 Goal 隐藏角色配置,使用当前会话模型。

底部 Goal 状态条是详情入口,不是静态标签。重载页面或 worker 重启后,它从持久化 projection 恢复目标文本、状态、checklist、用量与最后原因;若先前 execution 已丢失,则显示 paused_recoverable,不显示为仍在运行。

Goal 在 Web 与 TUI 的一致交互 由 Archify 生成的工作流图。 01 / Web 02 / TUI 03 / Shared Goal Actions 04 / Durable State 底部 Goal 状态条 · 状态 · 进度 · 用量 · Web 底部 Goal 状态条 状态 · 进度 · 用量 Goal 详情面板 · prompt · checklist · 问题队列 · Web Goal 详情面板 prompt · checklist · 问题队列 /goal status · 完整状态与原因 · TUI /goal status 完整状态与原因 /goal action · 编辑 · 回答 · 恢复 · 清除 · TUI /goal action 编辑 · 回答 · 恢复 · 清除 Goal Action API · 同一校验与错误合同 · Shared Goal Actions Goal Action API 同一校验与错误合同 版本化转移 · expected_version · lease · Shared Goal Actions 版本化转移 expected_version · lease Goal 快照 · 检查点 + 问题队列 · 持久状态 Goal Snapshot 检查点 + 问题队列 Goal 投影 · 恢复 + goal_update · 持久状态 Goal Projection hydrate + goal_update validate click / keyboard typed action reload / live update committed state atomic save same action 图例 用户界面 Agent 逻辑 策略 工具操作 上下文 / 追踪
Web 面板和 TUI 命令都调用版本化 Goal Action API;状态迁移、并发检查和恢复规则不在界面层重复实现。
Web · 输入区 Goal 面板交互设计
◎ Goal · 重启后暂停 · 4/9
调研并完成一篇大模型知识综述goal_7f2a · run 2 · version 18
状态可恢复暂停:worker 重启中断了上一轮
进度清单 4 / 9 · 7 轮 · 38k tokens
最近证据新增 12 篇来源;方法分类 gate 已通过
恢复位置从已保存 spec、checklist 与 session evidence 创建新 execution
待答问题2 项;可以稍后逐项回答,不影响独立的来源核查
继续编辑目标调整预算终止
TUI · /goal同一合同
$ /goal status
Goal [paused_recoverable]
  调研并完成一篇大模型知识综述
  progress  4/9
  usage     7 rounds · 38k tokens
  reason    worker restarted during round 8

$ /goal resume
Goal resumed as execution goal-exec-02.

$ /goal edit 收窄到知识编辑与持续学习
Goal revision 3 saved; prior evidence retained.

$ /goal pause
Goal paused.

$ /goal
  pending questions: 2
  [?] scope: 是否纳入知识编辑?
  [?] date: 文献截止日期是什么?

$ /goal answer scope 纳入
Goal answer saved; resuming from the latest checkpoint.
编辑 Goal 增加 revision,并重新生成当前 spec/checklist;旧 revision 的未答问题保留为 superseded 审计记录,不再阻塞新 revision。继续操作保留 goal_id、累计用量和问题历史,同时创建新的 run_id。暂停、等待和重启恢复不重置已消耗预算;等待时间不计入 active-time 限制。

实现与验收合同

独立规格审查要求保证两项合同:真实人类依赖转入等待,不能被普通无进展计数覆盖;Web 操作成功后的 HTTP 快照立即更新可见状态与共享缓存,旧版本事件不能回退新状态。修复限定在 Goal 状态转换及前端投影,不改其他工作流。验收分别使用公开 Goal → 回答命令的回归测试,以及无 WebSocket 广播的操作响应与重新挂载测试;修复后需要原审查者复核,再做独立质量审查。

真实人类依赖不会被无进展计数错误覆盖,预算判断仍独立执行。前端通过共用 updateSessionGoal 按 session version 应用 HTTP、WebSocket 与 hydration 快照;无广播暂停、重新挂载、乱序消息、后台会话及迟到加载由 4 项组件测试覆盖。Web 测试合计 229 项通过,TypeScript、静态检查和 32 页生产构建通过;等待状态与前端修复的独立规格复核均通过。构建仍有既有 Next SWC lockfile 修复警告,未改依赖锁文件。

控制器保存使用 CAS;发生同运行并发更新时,以最近确认快照、本轮状态和磁盘最新状态合并,并在 session 写锁内提交,不执行无界重试。合并仅允许相同 goal_id/run_id 且最新状态仍在执行的情况;预算和新答案保留,本轮进度与已消费答案也保留。暂停、取消、替换运行仍拒绝旧控制器写入。终止保存共用此路径;新答案使旧终止判定失效,保存为 paused_recoverable / answer_received,用户可继续处理,不能误报 achieved。分批消费的答案共同进入后续工作提示;再次恢复时从当前 revision 的持久问题记录重建已确认决定,并恢复有长度上限的 evidence window。编辑目标隔离旧 revision 的决定和证据。

并发修复的独立质量复核为 PASS,覆盖原有“修改预算导致控制器退出但仍显示运行中”的复现。审查者独立执行 9 项针对性回归通过:预算/答案在 evaluating/terminal 的竞争、暂停/取消/替换运行、消费期间收到新答案及旧 CAS 拒绝。集成后的 Goal、存储和 Web API 相关测试通过,完整统计见下方全量验证。该结论限于已审修复,不能代替修复后全量验证、尚未实现的设计能力或默认 App 可视验收。

以下条目把设计要求绑定到公开入口和可观察结果。局部源码、测试及独立修复审查不代表完整验收:最终集成代码的全量测试已通过,默认 App 的刷新与可视验收单独记录。下表中的实现描述仅指工作树内已有代码,不表示已发布或已完成全部要求。

要求公开入口 / 证据可观察结果当前状态
单 prompt Goal,工作与判定分离goal(prompt, ...);judge_goal()Working Agent 执行;inspection judge 独立验证并返回 typed verdict已实现,单元测试覆盖
困难任务不会无限续轮round/token/active-time/cost budget;active-run usage cursor;stall 与 judge failure guards分别进入 budget_exhausted、stalled、failed、blocked 或 impossible;等待期间其他 session 用量不计入 Goal已实现,边界测试覆盖
无人值守时不打断,继续独立工作judge 的 needs_user + can_continue;持久 questions[]问题累积;依赖答案的事项不执行;安全独立工作继续;全部受阻后才等待已实现,队列与续轮测试覆盖
异步回答与并发安全Goal Action API;SessionStore CAS 版本active run 在边界消费答案;部分回答允许部分工作恢复;用户主动暂停保持暂停;旧 controller 不能覆盖新状态已实现,竞争路径测试覆盖
重载与 worker 重启可恢复会话恢复;启动核对;/goal resume重载后恢复完整投影;重启中断状态变为 paused_recoverable;resume 创建新 run组件测试通过;默认 App 已验证重启恢复状态、编辑重载及 Resume 实际执行
Web 与 TUI 控制一致Goal dialog;/goal 命令;同一 Action API查看目标、checklist、用量、问题;编辑、暂停、回答、预算、继续、终止类型检查与自动测试通过;默认 App 已验证编辑、预算、暂停、恢复和完成判定;异步回答完整界面流程尚未验收
外部事件自动唤醒目标:持久 wait handle + scheduler eventCI/job/timer 完成后幂等恢复,无需用户 resume未实现
共享状态目录多 worker ownershipownership.goal_owner();独立非阻塞 OS 文件锁同机同 store 独占 controller;startup reconciliation 跳过 live sibling;崩溃释放锁跨进程与异常退出测试覆盖;不支持跨主机分布式 lease
Deterministic gates 与独立证据仓库目标:gate runner + evidence refs/repository可复用命令检查先于 judge,完整证据不依赖 session 快照未实现
当前验证命令
  • python -m pytest tests/unit/agent/workflows/test_goal_loop.py tests/unit/agent/workflows/test_goal_functions.py tests/unit/agent/workflows/test_agentic_programming_goal.py tests/unit/agent/workflows/test_goal_single_workflow.py tests/component/webui/execution/test_goal_command_workflow.py -q
  • cd apps/web && npx tsc --noEmit
  • python -m scripts.docs_site.build,随后 python -m scripts.docs_site.checklinks

网页核查:judge 具有网页读取和检索工具,失败回执标记为 is_error=true。已有真实模型检查受到 arXiv 的 NON_GLOBAL_ADDRESS 拒绝与 Tavily 缺少凭据的限制;没有绕过网络策略,不能把这次研究产物视为来源已核验的综述。

集成代码执行 python -m pytest -q -n 4:7015 项通过、18 项跳过、1 项预期失败,包含暂停的执行身份和 Runtime 内检查路径修复。全量发现的 Goal 包装函数源码定位问题已修复;两组 agent 合同测试的执行数据库已按测试隔离,避免启动恢复读取其他测试的记录。TUI 测试 148 项通过、2 项跳过,类型检查通过。默认 App 的实际运行证据与自动测试分开记录。

真实模型验证:通过公开 programs run goal 入口,MiniMax-M3 完成约 300 字中文文章写作、文件读取核对与判定,命令正常退出;产物内容已另行读取检查确认。此例仅使用给定事实,不调用网络,不能替代来源核验。已有综述尝试受到外部来源访问和检索凭据限制,仍不能作为已核验的综述交付。失败回执防护会阻止包含错误检查回执的 met,不证明全部语义判定可靠。

默认 App 已验证测试 Goal 的重启恢复状态、编辑保存、页面重载、预算修改、暂停和恢复。暂停使对应 canonical execution 进入 cancelling,随后以 cancelled / cancel.user 停止,Goal 保持可恢复的暂停状态。再次恢复后,判定先因多余输出拒绝达成,再接受修正后的输出;最终 Goal 显示 achieved、checklist 4/4,判定解析错误计数为 0。这是短文本任务的实际运行验收,不代表外部研究或全部任务类型均已验证。

Goal 在已有 Runtime 中的 refiner/judge 使用公共 agent():各自保持工具、模型与阶段标签,共享当前执行所有者,不创建独立 Job,避免首次初始化 JobRunner 的全局启动恢复误判外层活跃执行。无 Runtime 的独立 session helper 保留原路径。该局部修复不解决其他进程调用全局恢复的风险。执行树摘要仍有字段映射缺陷:已持久化的 LLM 回复位于 raw_reply,摘要却读取 output;空输入参数不代表回复丢失。另有函数结果行显示 Completed、canonical execution 已 cancelled 的展示不一致,不能用该摘要标签证明执行成功。

完成验收还发现通用执行结束记录未一致收敛:Goal 为 achieved,但对应 canonical execution 的 completed 写入连续重试后留下 finish_repair_stalled,状态仍为 running。该未解决项不否定已生成的工作输出与 Goal 判定,但阻止“完整执行生命周期全部验收通过”的结论。

实现状态与证据边界

聊天 Goal 使用已有普通聊天执行与持久完成通知续轮,显示投影不改写运行意图;默认没有轮数或恢复期限限制,保留用户显式限制。共享历史配对、未知效果审批、持久去重新轮次、受限 Resume、检查点不兼容处理、后台 Job 原资源授权继续、独立只读完成验收、请求持久归属、迟到与部分未知用量、并发硬预算预留及联合结算通过独立规格和质量审查。后端统一操作条件、显式 Verify、精确执行检查、崩溃时间下限与相关后台工作完成限制也完成审查。完整 Python、Web、CLI、Desktop、文档检查及独立构建后的浏览器回归通过;测试跳过项不作为能力证明。普通聊天和 Goal 的隔离进程中断矩阵、macOS 存活后台进程重新关联有实际进程证据。该结论不延伸到 Windows 进程存活、系统重启、跨主机接管或通用外部事件调度。安装版本、默认 App 可视验收及远端提交需分别核对实施台账和实际源码标记,不能从源码测试推断本机已更新。

证据边界:未知结果始终保留在效果记录中;新的副作用需要针对当前操作的单次审批,普通聊天恢复不会重新执行旧工具调用。Todo 全完成只产生验收候选,独立普通聊天按原目标与固定要求检查实际读取或会话证据;提交前重新核对控制版本、证据摘要、相关后台进程和执行状态。同一已检查计划不会自动重复验收。请求统计保存 Goal/revision/execution 身份与价格,累计 usage 水位、子任务继承、预算预留及联合结算由持久账本恢复;缺少回执的请求保留未知,不把旧会话统计推算为新归属。突然失去执行者时只计入可核实的时间下限,不把停机时间计入运行耗时。完成验收仍是受证据约束的模型判断,不保证绝对正确。

兼容路径记录,不作为新方案证据

  • Python Workflow 的 work/refine/judge 控制器及预算策略保留。
  • 已有版本化 Goal 快照、goal/run ID、CAS 写入与旧数据读取。
  • 已有 Web/TUI 控件及重启暂停状态,但恢复能力存在上述缺口。
  • 既有详细图示保留于兼容参考;不证明聊天入口使用独立 Workflow。

不纳入本次方案的扩展

  • 跨主机分布式执行租约、通用工作流引擎、独立审计仓库。
  • 自动批量重写历史 Goal 费用或工具效果。
  • 给任意非幂等外部操作提供恰好一次执行保证。
  • 将 Python Workflow 的独立 judge 在每个普通聊天轮次重新执行。
版本边界:本地参考仓库用于读取可复现的具体代码路径;官方在线文档与公开仓库 main 用于确认后续新增合同。Hermes 本地快照的基础 GoalManager 不含当前上游的 completion contract、quality gate 与 wait barrier,因此相关段落以公开上游源码为准。Claude Code 以官方文档为准。

目标完成显示

已结束的历史目标在原会话位置显示为可点击的简洁状态行。成功目标使用 Lucide 动态勾选图标与目标已达成,用时 9m 42s,时间来自该目标的有效执行时间。缺失时间不显示为零,中断时间保留已知下限。其他终止状态显示自身状态,不显示成功。点击打开现有只读历史目标详情。完成、验收和用量以已有记录为准,不根据回复文字或待办数量推断完成。

实现状态

紧凑完成状态行使用实际记录的 Goal 状态与活动时长,打开原始只读详情。组件和浏览器检查覆盖这一显示;已安装 App 的验收属于发布验证记录。

新交互式 owner 轮次在 Auto 或 bypass 下,仅检查当前 execution 及其后代中结果不确定的操作。嵌套 Runtime 只有在持久化接收记录证明该轮来自同一 owner 时,才采用相同范围:保存的 actor 是交互式 owner,完整性校验后的 chat 输入具有相同 source,当前 execution、session 和 principal 均匹配。提交到执行线程时传递现有 ContextVars,使子进程启动前的 Page 范围读取使用同一当前执行。Runtime 仍为非交互来源,不获得批准权限。缺失或不匹配的证据保留原限制;无法读取或损坏的恢复状态拒绝执行。当前 execution 及其后代的不确定操作仍要求精确的一次性批准。该筛选不解决或重放旧操作。显式 ask/deny、来源约束、plan mode 和精确 Page 绑定继续生效。

验收:在旧中断操作之后创建新 owner 轮次,通过 permission_decision 和真实嵌套 Runtime 检查 Auto 分类、bypass、当前及后代的不确定操作、来源不匹配和显式规则,并通过真实子进程验证 Page 访问。此嵌套范围修正已实现。独立规格与质量审查、真实子进程 Page 访问、浏览器组件及最终组合检查通过。因环境而跳过的用例不证明对应能力。已安装 App 验收独立记录于发布证据。