Repository navigation
fix(cli): preserve explicit runtime through claim and lease recovery - #7885
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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,不把完整宿主迁移或安装采用当成本切片义务。
关键代码讲解
TaskLeaseArgumentError.recovery把 route selector 放进 option-onlycli_args,并使用同一 route 生成command。原始 owner、idempotency key、CAS=0、重复 scope 等仍走已有 grammar,未获得自动重试权限。handle_task_lease_command仅为拒绝后的 inspection 补齐 selector;execution_authority_granted=false及 native refusal 保留,wrong owner 不会被换成当前 holder。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
left a comment
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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 自行创造验收标准。
关键代码讲解
TaskLeaseArgumentError.recovery在 command 与 option-only cli_args 中复用 route;原 owner、key、零值 CAS、重复 scope 和 requires/remove flags 沿用原 grammar。拒绝本身不修改租约。handle_task_lease_command为 refusal inspection 保留 selector;render_task_lease_markdown同样使用所选 executable。wrong owner 不会被换成当前 holder,execution_authority_granted=false保持。TodoClaimArgumentError.recovery把相同规则带入 claim grammar,保留 Goal/Todo/actor、registry/runtime、原 proof 与 dry-run;调用者仍需显式补齐 missing flags。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.
Goal And Delivered Outcome
--cli-binselected the intended runtime, but lease grammar repairs/refusal inspections, Todo claim grammar repairs, and accepted claims' progress/completion commands returned the global executable.main(867615e2c3aa2a32516a71d46f11a20d6fcb3289).Author Declaration
Implemented against
TaskLeaseArgumentError.recovery,handle_task_lease_command, Markdown rendererTodoClaimArgumentError.recovery,handle_todo_commandloopx_cli_argvand 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
531097610does not qualify the new head.Validation
66c86b04be9a6ebe6bb5d908dd5f811e2dd8601d.cqr_3af26518c8eb2a4a93e3verifies valid with zero blockers/warnings and one platform/CI qualification advisory.Full research questionbutton 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
Type of Change
LoopX Area
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