Repository navigation
fix(leases): explain execution key mismatches during recovery - #7997
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.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; runtime_reported; observation_id=48066dcce14f546cb8b6a1dbe5a7b15b73e5c20f2b2441640ffbbe4f7a30f1de
Exact head 0b6527bd0b09033361c8364362f387ffb561c0b2;base 6a6a8590e09822b254ae615fd4b64c9e047508f1。未发现阻断性问题,结论 APPROVE。
动机
需要续租、转交或释放任务租约的 Agent 和 CLI 操作者。版本号正确但误用新的操作 key 时,原提示只给 lease_cas_mismatch;操作者容易继续改版本号,仍无法恢复。新提示明确复用当前租约代次的原 owner 和执行 key,并保留只读 inspect 路由;使用原 key 可成功续租,原请求重试不会再续一次。不改变租约资格、版本比较、写入、回执或权限,也不自动替换凭证或重试。
改动思路
只补现有 CLI 参数说明和 canonical refusal 分支,直接修复恢复信息缺口;保留已有 TS 裁决及存储 owner,新增框架或恢复 API 均无必要。当前 PR 边界为三文件 +33/-1 的租约诊断修复;不扩展 Host 自动续租、迁移、UI 或合并权限。 拒绝条件继续由 decideTaskLeaseLifecycle 决定;版本不匹配仍先返回 version_mismatch,只有 owner/key 不匹配才走新增说明。没有把错误文案变成新的权限或重试 owner。
规范为 docs/reference/canonical-lease-renew.md,spec_revision 6a6a8590e09822b254ae615fd4b64c9e047508f1,在 diff 前读取。逐项依据原规范标题:Operate the current lease 要求使用当前 owner/key/version;Action help and argument recovery 要求帮助不读写状态、保留路由与凭证且不自动重试;Commit, retry and readback 要求原 intent 的幂等重放。这三项都由当前 CLI 和 TS 路径验证。
具体改动
register_task_lease_command 把 acquire 选择的执行 key、同一代次维护复用的 key 和 transfer 接收方的新 key 分清。executeCanonicalTaskLeaseLifecycle 仅补 canonical 拒绝说明;既有 inspection.cli_args 和 JSON/Markdown 输出路径继续使用原路由。新增测试为 File/SQLite × renew/transfer/release 六组,验证拒绝无写入、原 key 恢复以及原请求重放。全 PR 三文件 +33/-1,没有新 schema、持久状态或 helper。
独立从源码目录外执行安装 console:两种 provider 上,base 错误只给通用拒绝,head 明确原 owner/key;随后执行返回的 inspect,租约及 provider revision 不变;原 key 续租只递增一次版本,重复同一请求返回同一租约。另用错误版本确认优先级没有被新提示覆盖。未把消息包含关键词当成完整恢复证明。
对主干的风险
PASS:head 两个 Python CLI 模块50项,base相同模块44项;两边各83项 TS lifecycle、真实进程竞争及提交前后崩溃测试;head TypeScript typecheck、两份改动 Python 的 Ruff、standard premerge。premerge 六项 direct 全通过,17项所选检查中16项通过、一项保留 advisory,manual holds=0。
advisory 来自未修改的 render_canonical_todo_sections oversized-function ratchet;同一命令在不可变 base 和 head 产生相同完整失败签名,magnitude regressions=0。它没有被说成全绿,也不要求本 PR 修复无关 formatter。CI 按 wait_for_ci=false 未查询、轮询或等待;未知 CI 不影响已证明的诊断/恢复结论。
我的整体评价
只补现有 CLI 参数说明和 canonical refusal 分支,直接修复恢复信息缺口;保留已有 TS 裁决及存储 owner,新增框架或恢复 API 均无必要。当前 PR 边界为三文件 +33/-1 的租约诊断修复;不扩展 Host 自动续租、迁移、UI 或合并权限。 最强反例是提示改变了版本优先级或诱导重复续租;两者已通过实际 CLI 和现有并发/崩溃/重放路径排除。新说明减少恢复所需的猜测,不增加人工确认轮次;没有声称测得模型采纳或长程收益。
没有页面或可视 UI 变更,已检查 CLI 帮助、拒绝与恢复文本,因此 visual review 不适用。未验证原生 Windows、PostgreSQL、安装发行包或模型理解与长期采纳;本次验证使用当前源码的安装 console 和真实隔离 File/SQLite authority。 review 通过不授予 merge/install 权限;closeout 和 merge readiness 另行读回。
English verdict: APPROVE. The exact head clarifies the existing execution-key contract; independent File/SQLite console recovery, replay and unchanged rejection precedence pass. The inherited formatter advisory remains disclosed. Remote CI was not consulted; no merge was performed.
当前 CI 归因与接续
准确 head
0b6527bd0b09033361c8364362f387ffb561c0b2保持不变;已有绑定该 head 的公开COMMENTED / APPROVEreview。review 与 CI、当前基线资格和 merge authority 各自保留。原 Python CI 的
kernel-static-checks因 Lark 测试的两处 imported-fixtureF811失败,已由 main 上的 #7991 修复。原 Release Artifacts 在 worker status row flex 断言失败;main 的 #7995 已恢复该规则,当前6f90e561上对应 source contract 检查通过。这些是当前源码对照,两个旧 run 仍保留失败状态。当前 main 的另一处新 fixture F811 与同一测试的 E731 由 #8000 @
d46c25c00e6232f9c93a9f42e897a7e8d9c796bb提案修复;完整 Ruff 与原回复恢复 15 个分支通过。该依赖尚未合并。下文保留原 head/base 的局部证据;目标 main 前进后的适用 CI/readiness 仍须据实核验,不把 review 或归因当成合并许可。Problem and result
在租约版本和 owner 都正确时,给
renew/transfer/release传一个新 operation key,现有 authority 会正确拒绝;canonical CLI 却只返回lease_cas_mismatch,并同时显示相等的 expected/actual version。调用方无法从错误说明看出还必须保留原执行 key。既有保留路径已经明确提示 owner/key,这里补齐 canonical 拒绝说明。本改动在现有 TypeScript lifecycle owner 的拒绝分支直接说明 owner / idempotency key 不匹配,以及当前 lease generation 的原执行身份要求。CLI 帮助区分 acquire 的 execution key、维护操作复用的原 key 和 transfer 的新 receiver key。保留原错误码、检查次序、CAS、拒绝状态、持久化和重放规则;inspection 仍明确不授予执行权限,也不会替换 owner 或借用别人的凭证。
Scope and validation
三个现有路径形成完整可逆切片:TS 错误解释、CLI 参数帮助、既有真实 CLI recovery fixture。复用原 decision、store、receipt 与 inspection;未增加 capability、schema、helper 或恢复器。相邻改进就是参数帮助,更大重构没有本次必要性。
0b6527bd0b09033361c8364362f387ffb561c0b2。mainat6a6a8590e09822b254ae615fd4b64c9e047508f1。资格化 target 已前进到cf9b20cd2d11b996c633ad8dd0088df454262353,三个修改路径均无 target 增量;未把新 target 的全部行为宣称为已测试。cqr_5e3e0d5b87d45e2a196d,绑定上述 head / target / 三路径,verify valid。safe-fix 未额外应用。最终标准 premerge:6 direct checks 通过,17 selected checks 全部执行(16 通过、1 项 owner 标注的 inherited maintainability advisory)。该项原始 exit 1 为未触及的 oversized
render_canonical_todo_sections,magnitude regression 为 0,未改写为原始检查通过。无 blocking failure 或 manual hold;本地 gate 通过,self_merge_allowed=false。Product and remaining acceptance
CLI/API 的既有失败恢复入口已走完整 packaged journey;没有新增页面、设置或 caller capability,UI impact 为
none。本改动不改变 authority-store 实现或 decision;没有重跑真实 PostgreSQL,也不声明新的 PostgreSQL 资格。独立评审、实际必检 CI、精确 head readiness 和受保护合并权限仍各自成立。控制会话的共享生命周期仍保留原执行身份及 once-only 结算要求;本提案只交付诊断恢复这一边界,不宣称完整 C4、canary 采用或整体目标完成。已有 fixture/布局 CI 修复继续由 #7991 / #7995 各自交付;没有把它们合并进本提案。