Skip to content

fix(cli): preserve explicit runtime through claim and lease recovery - #7885

Merged
huangruiteng merged 2 commits into
mainfrom
codex/cli-recovery-runtime-route-20261102
Nov 2, 2026
Merged

huangruiteng merged 2 commits into
mainfrom
codex/cli-recovery-runtime-route-20261102

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

  • Outcome basis: reproduced CLI runtime-routing defects; roadmap S4/S10 single-session recovery.
  • Goal/source and gap: an explicit --cli-bin selected the intended runtime, but lease grammar repairs/refusal inspections, Todo claim grammar repairs, and accepted claims' progress/completion commands returned the global executable.
  • Before → after: executing the generated commands with a poisoned global executable previously escaped to that executable. The commands now preserve the selected executable and selector through repair, claim, progress and completion, retaining original identities, CAS and scopes.
  • Intended base: main (867615e2c3aa2a32516a71d46f11a20d6fcb3289).

Author Declaration

  • Written by: model_agent — OpenAI GPT-6 family / Codex.

Implemented against

  • Specification and revision: the existing invocation contract in command_invocation.py at the base. Controller/executor recovery acceptance supplies context; this does not qualify the full RFC.
Criterion Disposition Symbol / path Evidence
Preserve explicit runtime through lease recovery implemented TaskLeaseArgumentError.recovery, handle_task_lease_command, Markdown renderer Execute generated JSON/Markdown repair and inspection commands with a quoted alias and poisoned global executable
Preserve runtime through Todo repair and continued work implemented TodoClaimArgumentError.recovery, handle_todo_command Execute the returned repair, then its accepted claim's progress/completion commands; verify the original claim reference and wrong-actor refusal
Preserve authority, replay and default behavior implemented Existing typed lease/Todo owners remain unchanged Real File/SQLite actor/CAS rejection, unchanged state after refusal, exact progress/completion replay, default route checks and immutable-base grammar parity
  • Self-check: reviewed the complete seven-file diff and owning instructions. Reused loopx_cli_argv and the existing current-capture reader; no new state, schema, setting, permission or decision owner. Direct helper expansion needs no new wrapper or unrelated refactor.

Scope And Continuation

  • Complete for the named CLI generation paths. The existing quota route test consumes the current compact rejection fields and current-capture reader while retaining exit status, zero-admission, original-Turn and once-only settlement assertions.
  • Other command families and Todo authority-refusal presentation are outside this repair. Full controller/executor adoption, Windows execution, full CI and independent review retain their own qualification. The existing review of 531097610 does not qualify the new head.
  • No active runtime is switched or installed. No long-horizon benefit or PostgreSQL migration claim. No new successor is needed for this bounded adapter repair.

Validation

  • Tested revision: 66c86b04be9a6ebe6bb5d908dd5f811e2dd8601d.
  • Run state: finished.
  • Input classes: synthetic, public_fixture.
Check kind Result Public-safe evidence / limitation
regression_parity passed Lease alias regressions and four Todo File/SQLite base probes actually hit the poisoned global executable. Ten default lease JSON/Markdown responses were byte-identical on base/head; six default Todo grammar payloads are byte-identical, and real default managed claims retain the default executable without a selector.
integration passed Eight related Python modules: 132 passed, 1 Windows-specific skip, 95.99s. Covers CLI route, lease lifecycle, independent worktrees, repair → claim → progress → completion and unchanged state on rejected actors.
real_backend passed Disposable real File and SQLite 3.53.4 authorities through Node 24.21.0. Invalid owner/CAS remain invalid; progress/completion retries do not duplicate effects. No live Goal data.
real_entrypoint passed Fresh wheel with source-verified unchanged frontend assets; four packaged File/SQLite alias cases passed outside the checkout in 10.49s. All four changed product modules match final source bytes. Source virtualenv supplies pytest only; candidate module provenance is checked. This is packaged qualification.
static passed Ruff on seven changed files, configured mypy (17 sources), diff-scoped semantic advisory plus manual vocabulary review, explicit public-boundary scan, staged/committed bilingual and diff checks. No paired RFC changed; typing coverage is not expanded.
integration passed Standard Goal-enforced premerge: 6 direct checks + 18 selected canaries, 96.50s, zero failures or holds. Exact change-quality receipt cqr_3af26518c8eb2a4a93e3 verifies valid with zero blockers/warnings and one platform/CI qualification advisory.
regression_parity passed Earlier base/initial related-suite runs had 8 failures/58 passes/1 skip from retired quota rejection fields; the current consumer correction retains the behavioral assertions. The initial new Todo run had 2 failures/22 passes because external-cwd execution imported an ambient old package; binding the test to its candidate source resolves that provenance error. Both observations remain recorded.
manual not_run Windows execution, full new-head CI, independent exact-head review and installed-user adoption remain unqualified.
  • Prior-head CI: Release Artifacts build failed at the unchanged Research Full research question button lookup. PR #7880 already proposes that focused browser-smoke repair; this PR does not duplicate it. New-head CI must be assessed separately.

Frontend / Visual Evidence

  • UI impact: none. Existing CLI recovery commands and validation only.
  • Before / after / first viewport / preview / viewports: N/A; no graphical surface changed.
  • Source data: synthetic.
  • Attention / craft review: N/A for this CLI repair.

Type of Change

  • Bug fix
  • Test update

LoopX Area

  • Control plane (CLI adapter only)
  • Host or runtime integration

Technical Direction

Core control-plane hardening; S4/S10 recovery. Existing TypeScript lease/Todo authority remains the owner.

Shared-authority RFC fixture impact

N/A: no authority-store, provider-selection, promotion or shared-persistence changes.

Boundary Checklist

  • No credentials, private operating context, raw traces or machine paths in the diff or evidence.
  • No maintainer-owned benchmark execution or scoring change.
  • Scope follows reproduced runtime-route defects.
  • No paired RFC changed; staged and committed bilingual checks pass.
  • No graphical UI change.
  • Both commits have a DCO sign-off.

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.

1) 问题定义(为什么改、要解决什么)

  • 修复 loopx task-lease 在参数语法修复(grammar repair)与所有权拒绝检查(refusal inspection)输出中硬编码 "loopx" 可执行文件名、丢失调用方显式指定的 --cli-bin 或候选运行时路径的问题。

2) 改动摘要(按模块分组)

  • 保留显式 CLI 路由 (loopx/cli_commands/task_lease.py, loopx/cli_commands/task_lease_arguments.py):通过 loopx_cli_argv() 构造 inspection 与 recovery 的 command、cli_args 及 Markdown 提示行,确保 --cli-bin 及候选运行时入口在恢复闭环中不丢失。
  • 端到端防逃逸测试 (tests/control_plane/test_task_lease_argument_recovery.py, tests/control_plane/test_cli_program_route.py):新增毒化全局 PATH 下 loopx 的回归测试 test_explicit_runtime_survives_grammar_repair_and_refusal_inspection,验证 JSON 与 Markdown 恢复命令均严格停留在显式运行时。

3) 逐点审阅结论(架构、语义、正确性、测试、风险)

  • 正确性与测试充分性:复用 command_invocation.loopx_cli_argv() 统一权威入口,测试覆盖了含空格/单引号的候选程序名("candidate's cli")及 shlex.join 往返解析,无副作用。

4) 建议修改项(分 P0/P1/P2,带文件路径和行号)

  • 无阻塞项。

5) 最终结论(Verdict)

Approved — ready to merge once CI completes (exact head 531097610f883bd840c4c4840753d945f8f6e9a8 verified).

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)

精确 head:531097610f883bd840c4c4840753d945f8f6e9a8;比较 base:867615e2c3aa2a32516a71d46f11a20d6fcb3289。未发现阻塞项;本结论来自当前独立验证,未查询、轮询或等待 CI。

动机 / Motivation

通过显式 --cli-bin 试用指定 runtime,并根据 task-lease 拒绝提示修复命令的操作者。
用户选择了候选 CLI,原样执行拒绝输出里的修复或检查命令,旧版却返回全局 loopx;一次恢复会跳到另一套 runtime,增加误操作与人工重建命令的成本。
当前修复把所选 executable 与 --cli-bin 一起保留到下一进程;真实 File/SQLite 恢复、拒绝及重放通过,十组默认输出逐字节不变。
本 PR 不切换已安装的默认 runtime,不授权租约变更,不扩展其他命令族,也不证明 Windows、安装后采用或长期成本收益。

改动思路 / Approach

这里的 runtime route 指“由哪个可执行文件继续运行下一条命令”,不是租约权限。现有 cli_invocation_route 已把本次 --cli-bin 放进 invocation ContextVar,loopx_cli_argv 负责生成 executable 和后续 selector;本 PR 在原有 grammar、refusal inspection 与 Markdown renderer 中复用它。无操作会留下确定的恢复缺陷;改全局 PATH 或新增 wrapper 则扩大影响。既有 invocation owner 已拥有 executable 选择;在原 renderer 中复用即可修复,租约准入与持久化继续由现有 typed owner 决定。
保留两处 CLI adapter 修复和现有测试 consumer 更新;不推广全局 runtime、不新增配置或权限。
状态、身份、CAS(版本匹配)与 once-only receipt 继续由既有 typed lease owner 决定,没有新增确认轮次或手工配置。

具体改动 / Changes

完整 diff 为四文件 +78/-11;production 两文件 +11/-7,其余是实际 CLI 回归与现有 capture-reader consumer 修正。独立规范为 docs/reference/automation-prompt-upgrades.md,不可变 spec_revision:867615e2c3aa2a32516a71d46f11a20d6fcb3289,Product contract 的要求在本轮映射为:route-retention(显式 executable 和 selector 传到下一进程)、route-authority(routing 不改变权限)、route-default(未指定时保留 default,invocation 结束不泄漏);三项均 implemented,不把完整宿主迁移或安装采用当成本切片义务。

关键代码讲解

  1. TaskLeaseArgumentError.recovery 把 route selector 放进 option-only cli_args,并使用同一 route 生成 command。原始 owner、idempotency key、CAS=0、重复 scope 等仍走已有 grammar,未获得自动重试权限。
  2. handle_task_lease_command 仅为拒绝后的 inspection 补齐 selector;execution_authority_granted=false 及 native refusal 保留,wrong owner 不会被换成当前 holder。
  3. render_task_lease_markdown 用当前 executable 和 shlex.join 输出可执行命令,保留空格、apostrophe 与原有 warning;canonical-authority migration 分支未改。route 测试改读当前 compact rejection 和真实 capture reader,仍断言零 admission、原 Turn identity 与一次 settlement。

对主干的风险 / Risks

最强反例是“第一条命令用了候选 runtime,但返回的 repair/inspection 在下一进程又掉回全局程序”。我把新增测试原字节复制到不可变 base,两个真实 provider 都因 poisoned global executable 返回 exit 97;当前对应场景通过。测试原样执行返回命令,并验证 grammar 拒绝不改变 lease、renewal 只递增一次、exact replay 不再递增、wrong-owner release 被拒,后续 inspection 仍读同一状态;不会只以 argv 字符串相等当作执行证据。

PASS:四个完整相关模块 86 passed,native CLI/worktree 两模块 14 passed,共 100 passed。另做五种 action × JSON/Markdown 的 base/head 对照,10/10 逐字节相同,未做归一化,malformed grammar 未创建 runtime。PASS:本地 standard premerge 6 direct + 9 selected canaries,四文件 Ruff 与配置范围内 mypy 17 sources。CI 保持 UNVERIFIED,wait_for_ci=false;没有以未知 CI 阻止批准。Windows 与独立 wheel 重建未在本轮执行;实际 source console、外部工作目录与真实 File/SQLite 路径已经覆盖受影响行为,持久化实现未改,不扩展为 PostgreSQL 迁移资格。

我的整体评价 / Verdict

problem_context=goal_achieved;long_horizon 与 user_experience 均为 improved:恢复保留原 runtime,并能继续原身份的后续工作与一次结算,操作者无需手工拼回已知信息。结构与比例合适;沿用现有 route helper,顺便合并重复的局部 shlex import,并复用现有 reader,未引入平行 owner。semantic vocabulary 复用现有合同,默认关闭路径已通过逐字节对照。完整四文件 diff 只修改 CLI 输出与测试,未改变任何 App、Dashboard 或 Lark 图形页面。Windows 执行、独立 wheel 重建、安装后用户采用和长期收益未在本轮验证。批准仅针对此 head 的代码,GitHub 正式 approval、review threads 与 merge readiness 另行读回。

English verdict: APPROVE — 531097610f883bd840c4c4840753d945f8f6e9a8 preserves explicit runtime routing through task-lease recovery without changing default output or native lease authority.

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

1) 问题定义(为什么改、要解决什么)

  • 在 531097610 修复 task-lease 显式运行时保留的基础上,进一步补齐 loopx todo(含 todo claim 参数校验恢复与受管执行路由)对 loopx_cli_argv() 显式运行时的保留。

2) 改动摘要(按模块分组)

  • Todo CLI 恢复命令保留显式运行时 (loopx/cli_commands/todo.py, loopx/cli_commands/todo_argument_validation.py):使用 loopx_cli_argv() 构造受管执行提示与 todo claim 参数错误恢复命令(command 与 cli_args)。
  • 回归测试 (tests/control_plane/test_todo_claim_argument_recovery.py):新增显式候选运行时防逃逸回归测试。

3) 逐点审阅结论(架构、语义、正确性、测试、风险)

  • 正确性:使 todo claim 与 task-lease 的参数恢复路径在显式 --cli-bin 下完全一致。

4) 建议修改项(分 P0/P1/P2,带文件路径和行号)

  • 无阻塞项。

5) 最终结论(Verdict)

Approved — ready to merge once CI completes (exact head 66c86b04be9a6ebe6bb5d908dd5f811e2dd8601d verified).

@loopx-agent loopx-agent changed the title fix(cli): preserve explicit runtime in task lease recovery fix(cli): preserve explicit runtime through claim and lease recovery Nov 2, 2026

@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)

精确 head:66c86b04be9a6ebe6bb5d908dd5f811e2dd8601d;base:867615e2c3aa2a32516a71d46f11a20d6fcb3289。未发现阻塞项;本结论重新核验当前七文件,不沿用 531097610 的批准,未查询、轮询或等待 CI。

动机 / Motivation

通过显式 --cli-bin 试用指定 runtime、随后按返回命令修复参数并继续 Todo 的操作者与 Agent。
第一条调用选择了候选 executable,但 lease/Todo repair 或 accepted claim 的下一条命令返回全局 loopx;直接执行会跳到另一套 runtime,恢复需要人工重新拼接路由。
同一独立测试在 immutable base 的六个真实 File/SQLite 场景均实际调用 poisoned global executable(exit 97);当前 head 六项全部通过,并保留原 claim identity、拒绝与 exact replay。
范围为四个既有 CLI adapter 的路由生成与消费验证;不切换已安装 runtime、不授权 lease/Todo 操作,不扩展其他命令族或 Todo authority-refusal 的呈现。Windows、独立 wheel 重建、安装采用与长期净收益未在本轮验证。

改动思路 / Approach

这里的 route 指下一条命令由哪个 executable 运行。既有 invocation ContextVar 和 loopx_cli_argv 已拥有 executable 与 selector 的选择;四个 adapter 直接复用即可,租约和 Todo 准入仍交给原 typed owner。
保留 lease grammar/inspection、Todo grammar 和 accepted-claim continuation 的修复;不推广全局 runtime、不新增 wrapper、持久状态、设置或权限。
只修 lease 会留下 Todo 后续进程的缺口;改全局 PATH、推广安装或增加另一层路由状态都会超出这个问题。实现保持 grammar repair 的显式缺失值、原始 actor/claim reference、CAS 和 native refusal;successful managed claim 才生成继续工作的命令。JSON 的 cli_args 仍为 option-only,command 提供程序;lease Markdown 和 accepted Todo 的 shell blocks 消费相同 route。无新增确认轮次。

具体改动 / Changes

完整 diff 为七文件 +148/-14:production 四个既有 adapter +18/-10,三个测试 consumer +130/-4。独立规范为 docs/reference/automation-prompt-upgrades.md 的 Product contract,不可变 spec_revision:867615e2c3aa2a32516a71d46f11a20d6fcb3289;本轮映射 runtime-route(executable/selector 跨进程)、runtime-authority(路由不授权限)、runtime-default(默认与 invocation isolation),三项 implemented。command_invocation.py 在 base 已定义这组合同;未以作者测试或新 helper 自行创造验收标准。

关键代码讲解

  1. TaskLeaseArgumentError.recovery 在 command 与 option-only cli_args 中复用 route;原 owner、key、零值 CAS、重复 scope 和 requires/remove flags 沿用原 grammar。拒绝本身不修改租约。
  2. handle_task_lease_command 为 refusal inspection 保留 selector;render_task_lease_markdown 同样使用所选 executable。wrong owner 不会被换成当前 holder,execution_authority_granted=false 保持。
  3. TodoClaimArgumentError.recovery 把相同规则带入 claim grammar,保留 Goal/Todo/actor、registry/runtime、原 proof 与 dry-run;调用者仍需显式补齐 missing flags。
  4. handle_todo_command 仅在 accepted、execution_managed 且非 dry-run 分支,为 update/complete 加上同一 executable 与 selector;原 claim_operation_id 不变。当前 route test 改用已有 read_cli_policy_payload 读取 compact capture,仍验证零 admission、原 Turn identity 和一次 settlement。

对主干的风险 / Risks

最强反例是“argv 看起来带了 selector,实际执行仍先调用全局程序”。我另写六项 source-pinned 实际子进程检查,复用未改的 disposable provider fixture,只替换被评审 production root。File/SQLite 的 claim repair、accepted continuation、lease repair/inspection 三类场景,在 immutable base 都实际命中 poisoned global executable 并 exit97;head 六项全过。head 继续执行原返回 progress/completion,仅填要求的显式值;wrong actor 被拒、snapshot 不变,exact update/completion replay 不重复写。

默认路径另做五种 lease action 与三种 Todo grammar 的 JSON/Markdown 对照:16/16 stdout 逐字节相同,无归一化;malformed grammar 未创建 runtime。当前十个完整相关 Python 模块 152 passed、1 Windows-specific skip,含 source CLI、真实 File/SQLite、worktree、full/selected dispatch、current-capture 与 once-only settlement。source provenance 已核;Python3.14.8、Node24.21.0、SQLite3.53.4。本地 standard premerge 6 direct + 10 catalog + 8 risk-profile checks 全过、零 hold;七文件 Ruff、配置范围 mypy 17 sources 通过。

作者此前的旧 quota consumer 与 ambient-package 失败仍是历史记录;本轮通过不改写它们,也未采用作者四项 wheel 测试作为独立证据。作者给出的旧 head Release Artifacts failure 仅保留为诊断,未推断当前 CI 的原因。CI 保持 UNVERIFIED,wait_for_ci=false;Windows execution、独立 wheel 重建与安装采用保留为未验证维度。remediation 的 actor、先修 grammar 再 retry、scope、原 claim continuation 与 stop/settlement 条款未被缩短;变化是由既有合同授权的 executable 选择。

我的整体评价 / Verdict

problem_context=goal_achieved;long_horizon 与 user_experience improved:恢复和继续工作的实际进程保留原 runtime,减少人工重建命令,同时现有权限与重放约束保持。局部重构已应用:直接复用 invocation owner,合并重复局部 shlex import、使用既有 capture reader;不需要新增通用 wrapper 或语言迁移。semantic vocabulary 复用现有合同。完整七文件只修改 CLI 命令生成与验证测试;App、Dashboard、Lark 的布局、控件和图形页面没有变化。真实 Windows、独立 wheel、安装采用与长期净收益本轮未证;批准不授 merge/dismiss/resolve 或运行模型/评测的权限。

English verdict: APPROVE — 66c86b04be9a6ebe6bb5d908dd5f811e2dd8601d preserves explicit executable routing through the named lease/Todo repair and managed continuation paths, with current real-provider, negative, replay and default-parity evidence.

@huangruiteng
huangruiteng merged commit aaf6888 into main Nov 2, 2026
17 of 34 checks passed
@huangruiteng
huangruiteng deleted the codex/cli-recovery-runtime-route-20261102 branch November 2, 2026 12:20
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