Skip to content

fix(coordination): recover expired work through ordinary task claims - #7585

Merged
huangruiteng merged 3 commits into
mainfrom
codex/managed-task-interface-20261028
Oct 29, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/managed-task-interface-20261028

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Ordinary task callers were still directed through explicit execution-lease maintenance, while a crashed peer could leave expired work claimed indefinitely. This change makes normal claim the recovery operation and keeps execution generation checks in the control plane.

  • An eligible registered Agent can reclaim an expired hard-lease execution when its retained holder matches the Todo claimant. Claim ownership and the replacement generation commit atomically. Active execution cannot be preempted; task status, exclusion, acceptance, dependency, write-scope and provider CAS checks remain enforced. Missing, malformed, released or unrelated history does not authorize this takeover. Soft-claim behavior is unchanged.
  • Goal-mode MCP completion accepts the claim_operation_id returned by claim_task. Retired lease arguments are rejected before dispatch, including through FastMCP, rather than silently discarded. Ordinary CLI help, recovery instructions and Explore plans lead through task operations. Explicit Host supervision retains its existing fencing protocol.
  • Recovery advice is read-only. Old references cannot update, renew or release the replacement; successful operation replay does not reacquire or settle twice. Expiry cannot retract external effects already issued: native Hosts remain responsible for process supervision.

Breaking migration: replace MCP completion lease-key/version arguments with the returned claim reference. The Explore planner diagnostic flag is renamed from claim_and_lease_are_suggested_only to claim_is_suggested_only; plans no longer recommend a separate acquire command. Existing App manual completion and native Host supervision remain on their current owners; no new UI capability or configuration is introduced.

Core behavior validation on 12aaf34f571da95890db1c0c0799f6764300ff53, rebased onto target main 53dcb03082985bf894b1fca8813ab9f6e92503c5:

  • 504 TypeScript tests passed, including the real PostgreSQL authority integration suite plus Todo recovery/continuation and local runtime coverage; no skips. File and SQLite managed-execution conformance: 18 passed.
  • Python MCP/CLI/Explore real-path suite: 185 passed.
  • Control-plane typecheck, both Explore planner smokes, focused Ruff, bilingual diff check and public/private scan passed.
  • Risk-based premerge: 18 of 19 selected checks passed. The CLI output-budget check remains failing: quota_should_run/multi_agent/json is 25,836 characters against a 25,500 ceiling on both target main and this head. A separate base/head probe confirmed equal sizes; this is disclosed attribution, not a waiver or a passing gate.

The shared TypeScript claim/acquire owners retain authority; Python changes are existing transport/projection adapters. The local claim_task recovery action extends the existing recovery descriptor, and the diagnostic rename adds no separate shared vocabulary. The bounded cleanup removes the duplicate planner lease-command builder and redundant native-controller blocked-call signature. This proposal does not establish sustained agent efficiency gains, change benchmark scoring, launch experiments, install an upgrade or grant merge authority.

Latest head 4513bc992e71770ce6ac7942c7254b098655d5ba also moves explicit task-lease commands out of daily help and into the Host/adapter reference. Actual action-help and manual tests: 14 passed; Ruff and bilingual staged check passed. No additional execution semantics changed. The unchanged output-budget failure is addressed separately in #7587.

Follow-up validation: the command-budget manifest now classifies the hidden host lease command consistently with the maintainer catalog. The manifest coverage check passed at cc897054d.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

完成 cc897054d1a46962c69ad54f3f79683b41227132 全量 28 文件审阅,未发现当前实现的阻塞性缺陷。原生必需输出预算与最终 CQR 仍失败,其合并/资格 hold 在下文保留。

动机 / Motivation

负责继续已有工作的 Agent,在旧执行已过期、原进程不再响应时,需要恢复任务并交付已授权的结果。原来即使租约已经过期,保留的旧 claim 仍会拒绝替代 Agent,迫使它等待旧进程释放或人工交接;现在合格的注册 Agent 可用普通 claim 原子取得新执行,再凭原 claim 引用更新、完成并读回结果。

在相同 File/SQLite 真实后端 fixture 上,旧版本拒绝的合法过期恢复现在完成了领取、进度、完成和释放;旧执行者的写入与释放均被拒绝,重放不产生新代次。本 PR 不改变 Goal 的 soft/hard policy,不自动启动 worker,不证明正式安装 App 或真实模型采用,也不能撤销旧进程已经发出的外部效果。

保持原状会让一次已经结束的执行占住后继工作。只改错误提示不能解决;仅放松 assignment 又会留下 lease 准备失败或分开提交的窗口。普通任务需要的是能恢复到实际结果的路径,而不是再抄一套 key/version。

改动思路 / Approach

核心不变量继续由同一 TS claim/acquire/CAS owner 决定;Python 只传输与投影,删除重复 planner lease builder,MCP 只补 SDK 丢参前的拒绝,维护成本与真实恢复问题相称。本 PR 的交付边界是普通 CLI/MCP 恢复到原任务结果读回,以及相关可选建议;外部进程监督、安装 App 和长期收益保留原 owner。

同一调用条件 immutable base 当前 head 的实际观察
注册 peer,hard 模式,过期 holder 与 claim 匹配 claim_owner_mismatch 一次 CAS 换 owner,version/epoch 各加一;原引用完成进度与完成释放
active 外主、soft 外主、缺失/已释放/不相干历史 拒绝 保持拒绝,canonical snapshot 不变
合法恢复后旧 owner 写入/释放 无法恢复,后继工作停滞 两项均拒绝,不影响新 owner;重试不生新代次
同样 80 条无关任务,目标最后或最前 合法恢复仍被挡住 两种顺序均恢复,81 条任务完整保留
Explore off/evidence;planning 仅建议 无执行;规划另建议 acquire off/evidence 完整输出等价;planning 删除重复 lease 命令,仍不启动 worker

表格来自 File/SQLite 公共 CLI 的同输入 base/head 对照。另探测了“没有 claim、仅留过期 lease”:当前可正常领取未分配任务,active 外主 lease 仍拒绝。这是现有 assignment 准入加正常 acquire,不等于允许不相干历史接管一个仍属于别人的 claim;文档的 reconcile 仍由 ordinary claim/lifecycle 完成。

具体改动 / Changes

独立规范为 docs/reference/handoff-mode.md,spec_revision:53dcb03082985bf894b1fca8813ab9f6e92503c5。先读修改前文本;原文无 criterion ID,以下 HM-* 是 reviewer labels:HM-claim 原子 self-claim 与 soft 不造 lease,HM-proof 原执行引用不能复活或借用新代次,HM-admission 状态/注册/排除/依赖/验收/scope/CAS,HM-supervision CLI 不监督空闲外部进程、Host 继续明确 proof 协议;这些本 head 均 implemented。过期跨主恢复是明确披露的有意行为变化,修订后的文档本身不是独立证明。

关键代码讲解

  1. evaluateCoordinationTodoClaimDecision 在现有 actor、状态和排除检查后,使用 canonical 派生的 expired holder;没有 caller bypass flag,active holder 与 soft 旧规则仍受保护。
  2. prepareClaimExecution 删除过宽的 retained-foreign 拒绝,把已获准的新 assignment 交给原 acquire owner,复用 scope/依赖/验收及 generation 检查;claim 和执行同次提交。更新/完成的原 receipt resolver 仍核对 actor、Todo、key、epoch、workspace 和当前执行。
  3. managedRecovery 只返回普通 claim 建议及其引用来源,明确没有执行授权。显式 stale/partial proof 保留原检查路径,不能在出错时悄悄退化为新执行。
  4. GoalModeServer.call_tool 在 FastMCP 丢弃未知字段之前拒绝旧 completion 参数;claim_task 返回的引用沿原 control/native CLI 完成。planner 的手工 lease builder 被删除;Explore result-link 已有当前 proof resolver 继续复用。

MCP complete_task 删除 key/version 是 breaking tool-schema change,文档给出迁移;旧参数报错,不静默忽略。普通 CLI 仍解析 Host proof,日常帮助移到任务引用,明确 Host 诊断保留。原操作 receipt 和显式 Host 生命周期有实际消费者,需要继续兼容;没有保留第二份日常 eligibility 规则。

对主干的风险 / Risks

最强反例是新 owner 已恢复,旧进程仍持原 key/version 回来写入;另一个是 SDK 丢掉旧 MCP proof 后偷偷调用完成。实际 CLI 拒绝旧更新及 release,TS 覆盖 missing/foreign/expired/replaced references、并发 CAS 与 stale snapshot;SDK 边界证明旧字段在写入前拒绝,MCP 控制器经真实 source CLI 的 File/SQLite 路径完成并一次结算、重放无新增效果。不能由此推断旧进程已经终止,或撤销其先前已提交的外部效果。

PASS:197 项定向 Python;1,628 项 TS;隔离真实 PostgreSQL 16.15 的 378 项,零 skip,临时容器已停止;strict typecheck、mypy 17 sources、全部改动 Python 的 Ruff;semantic advisory/full-tree drift、双语及公开边界检查。独立公共 CLI 对照共 104 次调用,32 个 matched 场景各在 base/head 检查;另 16 次 planner 调用比较完整输出和 canonical 无变化。只归一化测试私有位置的四个 route hash 与 fixture root,未删除决定、诊断、指令或状态。

语义与 CI 对齐

claim_task 复用既有动作名,扩展 task-edit 的本地只读恢复分支;expiry 仍从 canonical typed facts 派生,没有新权威状态库或 prose heuristic。actor、顺序、原 Turn/验证/结算、scope 与失败恢复逐条对照;建议不是执行,硬检查也未被叫成建议。Explore off/evidence 完整输出等价,显式 planning 的命令变化为预期;核心过期恢复本来就是对 hard self-claim 的有意修复,没有冒称 default-off。

**FAIL 保留:**native standard premerge 的 6 项直接检查通过,19 项所选检查中 18 项通过,CLI output-budget 失败。不可变 base 53dcb03082985bf894b1fca8813ab9f6e92503c5 与当前 head 的同命令 python examples/control_plane/cli-output-budget-regression-smoke.py 均为 quota_should_run/multi_agent/json emitted 25836 chars; baseline ceiling is 25500。改动的 budget 文件仅删除 task-lease 的 cold-path classification,不改这个失败的 quota fixture/尺寸路径;更改不变量另有上述实际通过。没有放宽预算或删除语义。最终 cqr_8c1e2e07816e42bfa05b 已记 FAIL,必需资格继续 hold;不能用初始局部通过 receipt 代替最终结果。wait_for_ci=false,未查询或等待远端 CI。

首个自写探针误将 completion-identity-key 用在未带 no-follow-up 的调用,得到合法参数拒绝;保留该 driver 失败,修正探针后在新隔离 fixture 重做,未当产品缺陷。标准预算失败的归因保留,未因后来局部通过而消失。

我的整体评价 / Verdict

APPROVE 本次实现,Goal slice 已达成:普通恢复贯通实际工作与结果读回,长程可恢复性和用户路径在该边界 improved;净长期成本和模型行为尚无实验结论。核心不变量继续由同一 TS claim/acquire/CAS owner 决定;Python 只传输与投影,删除重复 planner lease builder,MCP 只补 SDK 丢参前的拒绝,维护成本与真实恢复问题相称。本 PR 的交付边界是普通 CLI/MCP 恢复到原任务结果读回,以及相关可选建议;外部进程监督、安装 App 和长期收益保留原 owner。

已有明确消费者的 Host proof 和历史 receipt 继续保留,日常协议收敛为原 claim reference。未发现需要在本 PR 再造框架或加确认的理由。预算/CQR 的 required FAIL 是独立合并资格 hold,批准 review 不授权合并或绕过该失败。

visual_review:CLI/MCP/内部 owner/帮助及规范无当前渲染页面或图片变更,现有 App caller proof 边界不变,故 not_applicable。未验证范围:正式安装 App/Host、真实模型、Windows、真实外部效果监督;未将这些计通过。

English verdict: APPROVE the validated recovery implementation; the pre-existing required CLI budget and final CQR remain failed and hold merge qualification.

@huangruiteng
huangruiteng merged commit 602fab9 into main Oct 29, 2026
32 of 44 checks passed
@huangruiteng
huangruiteng deleted the codex/managed-task-interface-20261028 branch October 29, 2026 03:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants