Skip to content

fix(coordination): continue leased Todos across explicit Agent handoff - #4994

Merged
huangruiteng merged 3 commits into
mainfrom
codex/leased-continuation-0924
Sep 24, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/leased-continuation-0924

Conversation

@huangruiteng

@huangruiteng huangruiteng commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

  • Goal/source and gap: Related to [Roadmap]: LoopX overall delivery program / LoopX 整体路线与交付总跟踪 #4574 and the shared authority / TypeScript migration RFCs. The explicit handoff CLI rejected every leased Todo even after the canonical metadata writer gained execution-proof admission and lease lifecycle gained atomic claim transfer. It also left committed context changes waiting for the normal Markdown projection.
  • Observable before → after: On an already canonical hard-lease Goal, a source Agent can prepare bounded context with its current lease key/version; the existing task-lease transfer --transfer-claim moves claim and lease in one CAS; the receiver inspects and seals adoption with its own current proof. A current note is rebound in the transfer transaction. Stale notes remain stale. Adoption does not acquire, renew or transfer execution authority. See validation rows below.
  • Issue/task and intended base: Related to [Roadmap]: LoopX overall delivery program / LoopX 整体路线与交付总跟踪 #4574; based on 46280da6e from origin/main. This does not close the local default program.

Scope And Continuation

  • Completed scope: The CLI now composes TS-owned update, lease proof, claim transfer, receipt recovery and projection delivery. The Python host adapter reads context files and presents results; the closed context schema has one TS owner. Lease-free handoff keeps its existing claim result and behavior. A leased adoption returns a distinct adoption receipt and rechecks current authority after replay.
  • Remaining work: RFC checkpoint lists 5–8 conditional delivery packages: remaining CLI/Turn/Chat callers and external effects; consumer/readback integration; SQLite D2 evidence; complete capture and whole-Goal migration; qualified default selection and legacy writer retirement. The SQLite D2 work remains contributor-owned under [Task]: Qualify SQLite D2 capacity and crash/replay recovery on the merged provider #4224/perf(sqlite): reuse canonical proof encoding in retained reads #4931. PostgreSQL service operations remain a separate qualification.
  • Slice boundary: This is one complete CLI call path with real backend and display readback. It does not claim automatic delegation, receiver launch, result return to an original conversation, or a default provider switch. Its current note/lease contract is reversible independently of those later product journeys.

Review Follow-Up

Review on 2d3cd1d26 requested changes: the new CLI suite launched promisify(execFile)("python3", …), so the bare system interpreter (Python 3.9) ran loopx.cli, and the merged checkout guard missed that curried call shape. Both subprocesses now take their interpreter from scripts/test-python.mjs, and the guard in tests/control_plane_ts/test_python_runtime.test.ts sees through promisified and aliased launchers while still ignoring a resolved interpreter path or an unrelated helper argument. The branch is rebased onto current origin/main 46280da6e.

Validation

  • Tested revision: 553397c8a.
  • Run state: finished.
  • Input classes: synthetic, public_fixture, authorized_private_read_only.
Check kind Result Public-safe evidence / limitation
static passed npm run typecheck:control-plane; Python Ruff and mypy on the changed CLI adapter; git diff --check.
integration passed 90 focused continuation, lease and CLI tests, including actual File/SQLite process entry points, projection failure then recovery, owner/proof/session rejection, lost ACK, CAS conflict and historical receipt readback.
real_backend passed Same complex public fixture executed on actual File, SQLite and isolated PostgreSQL 16 stores. PostgreSQL authority integration initially had 291 passes and two old stale-note expectations; both were updated for the disclosed contract and the changed conformance cases passed on SQLite and PostgreSQL.
regression_parity passed Read-only authorized source capture replayed on disposable File, SQLite and isolated PostgreSQL copies. The original implementation rejected the leased call without a write; this head completed prepare → transfer → adopt → replay and preserved unrelated Todo/lease facts. The snapshot and raw records are kept private. An intentionally invalid stale-note rebind made the regression test fail.
integration passed 16 Python projection-concurrency and canonical claim-proof cases; File claim-transfer conformance passed.
static passed Change-quality exact-scope receipt was recorded and verified.
integration passed Risk-selected loopx canary premerge --from-git-diff: 19 selected and executed checks, no failures or warnings; exact-scope quality receipt valid.
  • Reviewed-head evidence: bare node --no-warnings --experimental-sqlite --experimental-strip-types --test tests/control_plane_ts/leased_continuation.test.ts with the system Python 3.9 in PATH reports 10 passed / 1 skipped, and 11 passed / 0 skipped against a disposable PostgreSQL 16 cluster; postgresql_authority_store.integration.test.ts reports 293 passed / 0 failed on the same server; npm run test:control-plane reports 3056 tests (3027 passed, 0 failed, 29 skipped); the focused Python selection is 36 passed; typecheck:control-plane, Ruff and the goal-scoped premerge (19 checks, 0 failures) pass. Restoring the literal bare-python launch makes the interpreter guard fail and name the file.
  • Coverage and gaps: Remote CI lanes for this head are not awaited under the goal's review policy. No active Goal was promoted or changed. The frontend and Lark have no handoff control in this explicit CLI flow; the existing Todo Markdown consumer is exercised through its real projection. Automatic host delivery and independent result return remain separate acceptance work.

Frontend / Visual Evidence

  • UI impact: none.
  • Before: Existing CLI could not handle leased continuation.
  • After: The CLI reports execution admission and display delivery; existing Todo records project without a new view.
  • States and viewports shown: N/A; CLI JSON/digest and Markdown readback were exercised.
  • Source data: synthetic, public_fixture.
  • Attention review: N/A; no visual surface changed.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

Shared-authority RFC fixture impact

  • Production-scale fixture schema: loopx_coordination_production_scale_fixture_v0; the existing native/imported complete work graph is reused, with no speculative fixture field.
  • Semantic dimensions changed: current explicit continuation notes survive an authorized claim transfer; previously stale notes, unrelated work facts, old owner proof and released leases do not. Historical adoption receipts cannot grant current work authority.
  • Provider conformance arms run: File, SQLite and real isolated PostgreSQL 16; native and imported/legacy graph forms where the transfer contract applies.
  • Read-only legacy/file/PostgreSQL three-arm rehearsal: Performed on disposable copies of one authorized source snapshot. The baseline rejection, File/SQLite/PostgreSQL accepted flow, replay, and unrelated-state parity passed. No live promotion or cutover was attempted.

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths.
  • I did not duplicate maintainer-owned benchmark work.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

@huangruiteng huangruiteng 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.

动机

审阅 2d3cd1d26218df6e460b91317539913846a1cc65,对照 #4574、shared Goal authority 的 L2/L3/L5 和 TypeScript 控制面迁移。此前显式 handoff 遇到 hard-lease Todo 一律拒绝,即使来源 Agent 持有当前租约、现有 task-lease transfer --transfer-claim 已能原子转移认领和租约。这让已登记 Agent 之间无法沿这条 CLI 路径携带工作上下文继续执行。本 PR 给出一个可独立验收的显式 CLI 交接闭环;它没有宣称已完成自动调度、外部副作用隔离或整个 Goal 的迁移。

改动思路

执行权仍由现有 task-lease proof 和验收约束判断。来源用当前 proof 写入有界 continuation note,现有 lease lifecycle 在同一事务中转移认领和租约,只在原 note 有效且其他工作事实未变时重绑 note 指纹。接收者重新 inspect,凭自己的当前 proof 做 adopt;adopt 只提交上下文接收收条,不新增认领或租约。即使重放历史收条,最终也要重读当前 Todo 和租约。Python 负责 CLI 参数、上下文文件和投影交付,语义判定留在 TypeScript。

具体改动

  • todo_continuation.ts 将 leased prepare/inspect/adopt 接到共享执行 proof;保留 lease-free 的原有 claim 分支,并在结果返回前复核当前权威状态。
  • continuation_adoption.ts 新增 receipt-only CAS,绑定 operation、Todo、Agent、会话、revision 和 note 指纹;不通过收条授予工作权。
  • continuation_note.ts 统一上下文允许键与封闭校验;lease_claim_transfer.ts 在授权转移中重绑有效 note。Python 删除重复的字段白名单,增加成对 proof 参数,成功提交后用现有 canonical Todo projection 做交付及恢复。
  • 文档覆盖中英文 RFC、交接操作合同及后续阶段;测试覆盖 File/SQLite 进程路径、真实 PostgreSQL、旧格式、租约失效、过期 note、CAS/收条重放和投影恢复。无新增前端、Lark 或自动加载的指导面。

对主干的风险

主要风险是“有旧收条就误判仍可执行”或“转移时把早已过期的 note 刷新”。实现中的转移前有效性检查、工作事实比较和 adopt 后重新读取当前权威状态分别挡住这两条路径;故意放松 stale-note 检查时,回归测试会失败。真实 File、SQLite 和隔离的 PostgreSQL 16 三臂演练均完成 prepare → transfer → adopt → replay,且无关 Todo/lease 事实保持不变;未改写活动 Goal。旧的 lease-free 路径继续通过。尚未覆盖自动接收者启动和独立结果回传;全量 PostgreSQL 293 用例初跑为 291 通过、2 个旧 stale-note 预期失败,更新预期后重跑了变更相关用例,没有把这说成全套重跑。

我的整体评价

对这个明确的 CLI 缺口,改动比例合理:新增的收条合同很窄,重复的 Python schema 决策被移除,既有 proof、转移和投影 owner 被复用。90 个聚焦 TypeScript 测试、16 个 Python 投影/认领用例、File claim-transfer conformance、SQLite/PostgreSQL 变更用例、类型/静态检查与风险选择的 premerge canary(19/19)通过。依照当前审查合同逐项核对了复用、状态规则、默认行为、权限命名、领域中立性及交付比例;本次未发现需阻止此 head 的问题。它只完成明确交接这一个阶段,File/SQLite 默认切换仍须后续独立验收。运行时控制面 PR 留给维护者合并。

English verdict: APPROVE - exact head 2d3cd1d26218df6e460b91317539913846a1cc65; no blocking finding, focused real-provider checks and 19/19 premerge canary passed; default cutover remains separate.

@huangruiteng huangruiteng 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.

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

动机

#4574 G1/G2 的显式 Agent 交接需要跨越已有的硬租约 Todo,而原 handoff 对这类 Todo 一律拒绝。本 PR 交付的是可独立调用的同机 CLI 路径,不是自动派工、跨主机身份认证或整个管家协作目标的完成;这个边界是合理的。

改动思路

来源 Agent 凭当前 lease proof 准备 note;认领和租约仍由原 task-lease transfer --transfer-claim 在同一 CAS 转移;接收者凭自己的 proof 读取并封存一个只表示“接收上下文”的 receipt,之后再读当前权威状态。没有把 receipt 当成新的执行授权,也没有在 Python 复制租约决策。原 lease-free 路径保留。

具体改动

关键代码讲解

  • todo_continuation.ts:122:将原硬租约 blanket rejection 改为当前证明约束下的 prepare/inspect/adopt;adopt 不再偷偷转移认领。
  • continuation_adoption.ts:17,31:复用现有 lease/验收判断,写入 receipt-only 的接收决策;历史回执还要经当前状态回读验证。
  • continuation_note.ts:303 与 lease_claim_transfer.ts:13:只有原 note 对旧工作事实仍有效、且除认领外的工作事实未变时,才在原子转移中重绑指纹;过期 note 不被“洗新”。
  • Python CLI 只做 host JSON 输入与 Markdown 投影交付;新增 File/SQLite/PostgreSQL 和反例测试。

对主干的风险

[P1] 新增 CLI 测试绕过本机 Python 发现机制,当前 main 的防回归单测也漏掉这种调用形态。 tests/control_plane_ts/leased_continuation.test.ts:196,224 两次写成 promisify(execFile)("python3", ...)。在此机直接执行
node --no-warnings --experimental-sqlite --experimental-strip-types --test tests/control_plane_ts/leased_continuation.test.ts
得到 8 通过、2 失败、1 跳过;两个失败均启动系统 Python 3.9,在 @dataclass(slots=True) 报错。通过 uv run --extra test node ... 则是 10 通过、1 跳过,说明该通过依赖了临时 PATH 注入,并未修复测试自身的解释器选择。当前 main 已合并 #4980 的 scripts/test-python.mjs,但 test_python_runtime.test.ts 的 direct-call 正则对 promisify(execFile)("python3") 返回 false,因此 guard 也会放行这次回归。

最小修复:把分支更新到当前 main,两个子进程统一使用 resolveTestPython();再给 Python 启动 guard 增加这种 curried/promisified 调用的负例。用系统 Python 3.9 在 PATH 的直接 Node 命令及 guard 测试复跑,不能仅用 uv run 代替。

其余核心路径已独立检查:todo_continuation.test.ts 在所选 Python 下 37/37 通过;新增套件 File/SQLite 10 通过、1 个 PostgreSQL 环境跳过,随后我在一次性隔离的真实 PostgreSQL 实例上单独跑 PostgreSQL 用例 1/1 通过;TS typecheck 与 diff check 通过。失效证明、旧 owner、旧回执、并发编辑、过期租约和验收 hold 均有反例覆盖。自动 host 续跑和外部副作用 fencing 仍是明确非目标。

我的整体评价

REQUEST_CHANGES,针对精确 head 2d3cd1d26218df6e460b91317539913846a1cc65。交接状态机和现有权威边界总体成立,范围也与真实 CLI 缺口相称;阻断点是新增测试重新引入用户已明确要求消除的 Python 3.9 误选,而且绕过了刚合入 main 的约束。先修这一处并在当前 main 上复跑,再重新审阅精确 head。相关的未来向重构判断:TS note/lease/receipt 所有权已足够集中,无需为此扩展新框架;测试解释器应复用已落地主干的单一 selector。

English verdict: REQUEST_CHANGES — exact head 2d3cd1d; the new CLI test launches bare Python 3.9 and evades the current-main interpreter guard.

@huangruiteng
huangruiteng force-pushed the codex/leased-continuation-0924 branch from 2d3cd1d to 553397c Compare September 24, 2026 15:49

@huangruiteng huangruiteng 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.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval). Approved exact head 553397c8a55be91ee0cb482a3add2460f3d8975c, rebased onto origin/main 46280da6e0cf1dd5a044cc26dab7a9d4bf53dbc5. This head resolves the blocking finding from my review on 2d3cd1d26 and re-runs the whole evidence pass on the new base.

[P1 resolved] The new CLI test no longer launches a bare interpreter, and the guard that missed it now catches the shape. tests/control_plane_ts/leased_continuation.test.ts takes its interpreter from scripts/test-python.mjs for both subprocesses, and tests/control_plane_ts/test_python_runtime.test.ts now sees through promisify(execFile)("python3", …) and aliased-launcher bindings while still ignoring a resolved interpreter path or an unrelated helper argument. Verified without any PATH injection: a bare node --experimental-strip-types --test run of the new suite reports 10 passed, 1 skipped (with the isolated PostgreSQL arm: 11 passed, 0 skipped), and restoring the literal python3 launch makes the guard fail and name the file.

动机

#4574 G1/G2 的显式 Agent 交接需要跨越已有的硬租约 Todo,而原 handoff 对这类 Todo 一律拒绝:来源 Agent 即使持有当前租约、现有 task-lease transfer --transfer-claim 也能原子转移认领与租约,这条 CLI 路径仍然不可用。本 PR 交付的是可独立调用的同机 CLI 交接闭环,不是自动派工、跨主机身份认证或整个管家协作目标的完成;这个边界在 RFC checkpoint 里写清楚了。

改动思路

执行权仍由现有 task-lease proof 与验收约束判断,本 PR 不新增第二套规则。来源用当前 proof 写入有界 continuation note;认领和租约仍由原 transfer planner 在同一 CAS 转移,且只把「转移前仍然有效、且只有认领变化」的 note 重绑指纹;接收者重新 inspect,再凭自己的当前 proof 封存一个只表示「接收上下文」的 receipt,之后调用方再读一次当前权威状态。即使重放历史 receipt,也要通过当前 Todo/租约重新判定。Python 只做参数传输、上下文文件读取与投影交付,语义判定留在 TypeScript。

具体改动

关键代码讲解

  • todo_continuation.ts:146:用 leased 取代原来的 blanket rejection,leased 时把 prepare/inspect/adopt 接到共享执行权判定;非当前持有者被明确要求先走 task-lease transfer --transfer-claim;adopt 返回独立的 adoption receipt 而不是 claim,并在提交与重放之后再次读当前权威。
  • continuation_adoption.ts:17,31:continuationExecutionAuthority 复用 evaluateCanonicalTaskLeaseProof 与 acceptanceWorkGuard;sealLeasedContinuationAdoption 用 CoordinationCommandReceipt 做 receipt-only CAS,校验 operation/goal/request 摘要/Todo/Agent/note facts,并在 replay 时解码比对,历史回执不能授予当前执行权。
  • continuation_note.ts:303:只有原 note 对旧工作事实仍有效、且除认领外的工作事实未变时才重绑 todo_facts,因此过期 note 不会被「洗新」;:63 把 CONTEXT_ROOT_KEYS 导出为生产者与校验器共享的唯一封闭 schema。
  • loopx/cli_commands/todo_continuation.py:158,164:CLI 以 --task-lease-idempotency-key/--task-lease-expected-version 成对传递当前 proof,删除 Python 侧的封闭字段白名单副本,并在提交成功后用 settle_canonical_todo_projection 交付(重试只投影当前 head,不重放写入)。
  • tests/control_plane_ts/test_python_runtime.test.ts:84 与 leased_continuation.test.ts:26:本次修复点——测试用统一 selector 选择解释器,guard 覆盖 promisified/aliased 启动形态。

对主干的风险

主要风险是「有旧 receipt 就误判仍可执行」和「转移时把早已过期的 note 刷新」。前者由 receipt 身份解码加调用后的当前权威重读挡住,后者由转移前的有效性与工作事实比较挡住;两条都有反例测试(历史回执在租约释放或验收 hold 后失效、并发 canonical 编辑无法被 receipt 掩盖、过期 note 不被刷新)。真实 provider 证据:file/sqlite 裸 node --test 10 通过 1 跳过;一次性隔离的真实 PostgreSQL 16 上 11 通过 0 跳过,另外 postgresql_authority_store.integration.test.ts 293 项全通过;control-plane 全量 3056 项(3027 通过、0 失败、29 跳过,其中一次满载运行出现 1 个 90 秒子进程超时,隔离复跑 3.2 秒通过、重复全量也通过);聚焦 Python 36 项、typecheck、ruff 与 goal 作用域 premerge(19/19、0 失败、0 人工挂起)均通过,质量回执 cqr_262ae289e6d10c4c6c36 有效。未验证项据实记录:本 goal 不等待远端 CI(上一 head 的红灯在干净 merge base 上同样复现:canonical snapshot 请求预算、runtime-shadow e2e、仓库级 mypy,以及一个与本 diff 无关的 dashboard 场景);仓库级 mypy 在 merge base 上就失败且涉及文件不在其配置清单内。边界未扩大:adopt 不新增认领或租约,不启动接收者,不外发结果,也不改变默认 provider。

我的整体评价

阻断点已按最小方式修好并有反向验证(恢复裸解释器启动即让 guard 指名该文件),其余核心路径在 file/sqlite/真实 PostgreSQL 三臂上复跑通过。改动比例合适:新增的 receipt 合同很窄,重复的 Python schema 判定被删除,既有 proof、transfer 与投影 owner 被复用;相邻的未来向重构也做了(统一上下文键集合、统一解释器选择器)。剩余工作(其余 CLI/Turn/Chat 调用方、外部副作用隔离、消费者集成、SQLite D2、默认切换)都在 checkpoint 里明确列为后续独立验收,不影响本 head 的合并判断。可交维护者合并。

English verdict: APPROVE - exact head 553397c8a55be91ee0cb482a3add2460f3d8975c; the requested-changes item (bare python3 launch plus the guard gap) is fixed and mutation-verified, and the leased handoff path passes on file, sqlite and an isolated real PostgreSQL 16 with the full control-plane suite and goal-scoped premerge green.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
…ogram

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Review follow-up. The new CLI test started `promisify(execFile)("python3", …)`,
so the bare system interpreter (Python 3.9 on this host) ran `loopx.cli` and
failed on `@dataclass(slots=True)`; only a PATH-injected `uv run` hid it. The
merged checkout guard in `test_python_runtime.test.ts` also missed the curried
call shape, so it let the regression through.

Both subprocesses now take their interpreter from
`scripts/test-python.mjs`, and the guard sees through promisified and aliased
launchers while still ignoring a resolved interpreter path or an unrelated
helper argument.

Verified with the system Python 3.9 in PATH and no `uv` wrapper: the bare
`node --experimental-strip-types --test` run of the new suite reports 10
passed, 1 skipped (PostgreSQL), and restoring the literal `python3` launch
makes the guard name the file.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng
huangruiteng force-pushed the codex/leased-continuation-0924 branch from 553397c to f4e6eeb Compare September 24, 2026 16:07

@huangruiteng huangruiteng 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.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval). Approved exact head f4e6eeb2a4a0b3ea2f3ff8eb8b084eeff252d544, rebased onto origin/main 6d298821e8960ff71d2fac9dcbdffb3deb5ac6d3. This head resolves the blocking finding from my review on 2d3cd1d26; the branch-owned file content is byte-identical to the earlier rebased head, and the evidence pass was re-run on this base (full control-plane suite 3056 tests / 0 failed, focused continuation and guard suites, goal-scoped premerge 19/19, receipt cqr_21f6f48828cad45457f7).

[P1 resolved] The new CLI test no longer launches a bare interpreter, and the guard that missed it now catches the shape. tests/control_plane_ts/leased_continuation.test.ts takes its interpreter from scripts/test-python.mjs for both subprocesses, and tests/control_plane_ts/test_python_runtime.test.ts now sees through promisify(execFile)("python3", …) and aliased-launcher bindings while still ignoring a resolved interpreter path or an unrelated helper argument. Verified without any PATH injection: a bare node --experimental-strip-types --test run of the new suite reports 10 passed, 1 skipped (with the isolated PostgreSQL arm: 11 passed, 0 skipped), and restoring the literal python3 launch makes the guard fail and name the file.

动机

#4574 G1/G2 的显式 Agent 交接需要跨越已有的硬租约 Todo,而原 handoff 对这类 Todo 一律拒绝:来源 Agent 即使持有当前租约、现有 task-lease transfer --transfer-claim 也能原子转移认领与租约,这条 CLI 路径仍然不可用。本 PR 交付的是可独立调用的同机 CLI 交接闭环,不是自动派工、跨主机身份认证或整个管家协作目标的完成;这个边界在 RFC checkpoint 里写清楚了。

改动思路

执行权仍由现有 task-lease proof 与验收约束判断,本 PR 不新增第二套规则。来源用当前 proof 写入有界 continuation note;认领和租约仍由原 transfer planner 在同一 CAS 转移,且只把「转移前仍然有效、且只有认领变化」的 note 重绑指纹;接收者重新 inspect,再凭自己的当前 proof 封存一个只表示「接收上下文」的 receipt,之后调用方再读一次当前权威状态。即使重放历史 receipt,也要通过当前 Todo/租约重新判定。Python 只做参数传输、上下文文件读取与投影交付,语义判定留在 TypeScript。

具体改动

关键代码讲解

  • todo_continuation.ts:146:用 leased 取代原来的 blanket rejection,leased 时把 prepare/inspect/adopt 接到共享执行权判定;非当前持有者被明确要求先走 task-lease transfer --transfer-claim;adopt 返回独立的 adoption receipt 而不是 claim,并在提交与重放之后再次读当前权威。
  • continuation_adoption.ts:17,31:continuationExecutionAuthority 复用 evaluateCanonicalTaskLeaseProof 与 acceptanceWorkGuard;sealLeasedContinuationAdoption 用 CoordinationCommandReceipt 做 receipt-only CAS,校验 operation/goal/request 摘要/Todo/Agent/note facts,并在 replay 时解码比对,历史回执不能授予当前执行权。
  • continuation_note.ts:303:只有原 note 对旧工作事实仍有效、且除认领外的工作事实未变时才重绑 todo_facts,因此过期 note 不会被「洗新」;:63 把 CONTEXT_ROOT_KEYS 导出为生产者与校验器共享的唯一封闭 schema。
  • loopx/cli_commands/todo_continuation.py:158,164:CLI 以 --task-lease-idempotency-key/--task-lease-expected-version 成对传递当前 proof,删除 Python 侧的封闭字段白名单副本,并在提交成功后用 settle_canonical_todo_projection 交付(重试只投影当前 head,不重放写入)。
  • tests/control_plane_ts/test_python_runtime.test.ts:84 与 leased_continuation.test.ts:26:本次修复点——测试用统一 selector 选择解释器,guard 覆盖 promisified/aliased 启动形态。

对主干的风险

主要风险是「有旧 receipt 就误判仍可执行」和「转移时把早已过期的 note 刷新」。前者由 receipt 身份解码加调用后的当前权威重读挡住,后者由转移前的有效性与工作事实比较挡住;两条都有反例测试(历史回执在租约释放或验收 hold 后失效、并发 canonical 编辑无法被 receipt 掩盖、过期 note 不被刷新)。真实 provider 证据:file/sqlite 裸 node --test 10 通过 1 跳过;一次性隔离的真实 PostgreSQL 16 上 11 通过 0 跳过,另外 postgresql_authority_store.integration.test.ts 293 项全通过;control-plane 全量 3056 项(3027 通过、0 失败、29 跳过,其中一次满载运行出现 1 个 90 秒子进程超时,隔离复跑 3.2 秒通过、重复全量也通过);聚焦 Python 36 项、typecheck、ruff 与 goal 作用域 premerge(19/19、0 失败、0 人工挂起)均通过,质量回执 cqr_262ae289e6d10c4c6c36 有效。未验证项据实记录:本 goal 不等待远端 CI(上一 head 的红灯在干净 merge base 上同样复现:canonical snapshot 请求预算、runtime-shadow e2e、仓库级 mypy,以及一个与本 diff 无关的 dashboard 场景);仓库级 mypy 在 merge base 上就失败且涉及文件不在其配置清单内。边界未扩大:adopt 不新增认领或租约,不启动接收者,不外发结果,也不改变默认 provider。

我的整体评价

阻断点已按最小方式修好并有反向验证(恢复裸解释器启动即让 guard 指名该文件),其余核心路径在 file/sqlite/真实 PostgreSQL 三臂上复跑通过。改动比例合适:新增的 receipt 合同很窄,重复的 Python schema 判定被删除,既有 proof、transfer 与投影 owner 被复用;相邻的未来向重构也做了(统一上下文键集合、统一解释器选择器)。剩余工作(其余 CLI/Turn/Chat 调用方、外部副作用隔离、消费者集成、SQLite D2、默认切换)都在 checkpoint 里明确列为后续独立验收,不影响本 head 的合并判断。可交维护者合并。

English verdict: APPROVE - exact head f4e6eeb2a4a0b3ea2f3ff8eb8b084eeff252d544; the requested-changes item (bare python3 launch plus the guard gap) is fixed and mutation-verified, and the leased handoff path passes on file, sqlite and an isolated real PostgreSQL 16 with the full control-plane suite and goal-scoped premerge green.

@huangruiteng
huangruiteng merged commit 2e1e632 into main Sep 24, 2026
13 of 18 checks passed
@huangruiteng
huangruiteng deleted the codex/leased-continuation-0924 branch September 24, 2026 16:10
@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Merged as 2e1e632603f4a7acf996a6fa3fd9c7d09404ca86 with the exact reviewed head f4e6eeb2a4a0b3ea2f3ff8eb8b084eeff252d544 (rebased onto origin/main 6d298821e). The merge commit's tree is 5eb51092c16e7889ede7e916acb2eb6c437b737e, identical to the reviewed head's tree, and every changed path matches the reviewed head, so no unreviewed content entered main. Published review: approval on the exact head.

Changed surfaces: the canonical continuation command and its TypeScript decision path (loopx/control_plane/coordination/todo_continuation.ts, continuation_adoption.ts, continuation_note.ts, lease_claim_transfer.ts, local_authority_runtime.ts), the CLI host adapter (loopx/cli_commands/todo_continuation.py), the checkout interpreter guard and new provider suites (tests/control_plane_ts/**), and the bilingual RFC/reference checkpoints.

Checks run on the reviewed head: bare node --test for leased_continuation.test.ts with the system Python 3.9 in PATH (10 passed, 1 skipped; 11 passed, 0 skipped against a disposable real PostgreSQL 16), todo_continuation.test.ts (37 passed), test_python_runtime.test.ts (5 passed plus a mutation that reintroduces the bare launch and fails), npm run test:control-plane (3056 tests: 3027 passed, 0 failed, 29 skipped), postgresql_authority_store.integration.test.ts on the same isolated server (293 passed, 0 failed), a focused Python selection (36 passed), typecheck:control-plane, Ruff, and the goal-scoped premerge gate (19 selected checks, 0 failures, 0 manual holds) with change-quality receipt cqr_21f6f48828cad45457f7.

Mutation/counterfactual evidence: restoring promisify(execFile)("python3", …) makes the interpreter guard name the offending file; the stale-note, released-lease, acceptance/expiry hold and concurrent-edit cases fail closed by design.

Skips and holds: remote CI lanes for this head were not awaited under this goal's review policy; the previous head's lanes were red for failures reproduced on a clean merge base (canonical snapshot request budget, runtime-shadow e2e, repository mypy) and one dashboard scenario this diff does not touch. No manual holds. Coverage is adequate because the CLI path was exercised on three real providers, the negative authority cases have dedicated reproductions, and the tree that main now contains is byte-identical to the validated head.

Residual risk: automatic host-driven continuation, external-effect fencing, the remaining CLI/Turn/Chat callers, SQLite D2 evidence and the provider default switch remain separate packages recorded in the RFC checkpoint; the adoption receipt is additive and grants no execution authority.

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.

1 participant