fix(refresh): admit checkpoint-only validator recovery - #4841
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Exact-head self-review: 2929e87f2fb90185e2e76cf598d6634718345ef0
动机
#4840 reproduces an impossible documented recovery: the semantic writeback commits without a required vision checkpoint, mutation replay is correctly rejected, but the checkpoint-only retry is also blocked by the open Todo's completion validator. This PR completes that scoped recovery without changing Todo completion semantics.
改动思路
Reuse read_heartbeat_settlement as the authority for exact Goal/Agent/Todo/Turn, delivery, mutation and vision-digest admission. Compute its existing supplement_checkpoint decision before the terminal completion-validation fence, skip only that fence, and keep the later checkpoint-satisfied check plus original delivery attribution.
具体改动
refresh_state_run: derives the admitted supplement decision immediately after settlement readback; all non-supplement accountable refreshes still callrequire_accountable_completion_validation.- End-to-end CLI regression: open validation-bearing Todo + committed semantic replan + missing checkpoint; exact mutation-free supplement succeeds, while mutation replay, wrong Todo binding and conflicting vision remain rejected with zero spend.
关键代码讲解
loopx/state_refresh.py:933: consumes the existing typed recovery decision; no new CLI flag or persisted state.loopx/state_refresh.py:1129: documents and enforces the narrow validator bypass.tests/control_plane/test_refresh_checkpoint_recovery.py:298: proves the positive and negative same-Turn paths through the real CLI fixture.
对主干的风险
The material risk is accidentally bypassing validation for a normal open Todo. The bypass cannot be caller-set directly and is reached only after settlement-reader identity/mutation admission; build_vision_checkpoint must still satisfy the missing decision. Local evidence: 60 related tests passed, the focused recovery suite passed, and Ruff/compileall/diff checks passed. Remote full CI is still running and remains a merge hold.
语义与 CI 对齐
This reuses refresh_recovery_v0/supplement_checkpoint; it does not create or broaden an authority vocabulary. Normal completion validation, workspace attribution, quota spend and receipts are unchanged.
我的整体评价
APPROVE (self-review conclusion, COMMENTED state). The mechanism is proportional and domain-neutral, with no frontend/Lark companion required because those surfaces do not own same-Turn recovery payloads. Residual holds: remote CI and independent maintainer review. This control-plane PR must not be self-merged.
|
CI update for exact head
Other completed checks are currently green; independent maintainer review is still required. |
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Exact head reviewed: 2929e87f2fb90185e2e76cf598d6634718345ef0
动机
#4840 暴露的是一个真实的事务矛盾:首次语义 replan 写回可以合法提交并留下 missing_required Vision checkpoint;随后唯一正确的“只补 checkpoint”重试,却会先被仍为 open 的 Todo completion validator 拦截;如果重放首次 mutation,又会被 checkpoint_supplement_must_not_repeat_mutations 正确拒绝。结果是两种重试都不合法,Turn 无法完成已有契约明确允许的恢复。
这个 PR 在正确的边界解决了完整问题:允许的不是“绕过 Todo 验证的一般 refresh”,而只是 TypeScript settlement owner 已经判定为 supplement_checkpoint 的 exact Goal/Agent/Todo/Turn 恢复。没有新增 CLI 开关、持久化状态或第二套 recovery authority。
改动思路
权威链路保持为:refresh-state → quota.settlement.read → TypeScript refreshRecovery → Python orchestration。refreshRecovery 仍负责比较原写回、settlement identity、delivery fields、mutation digest、vision digest 与 later vision;只有 exact retry、原 checkpoint 确实缺失、无 mutation replay、无 delivery 冲突且无 vision 冲突时,才返回 supplement_checkpoint。
Python 现在在 require_accountable_completion_validation 之前读取这个既有 typed decision,只跳过这一个 terminal validation fence。随后仍必须通过 build_vision_checkpoint,并且 vision_checkpoint.satisfied 必须为 true;写回时继续恢复原 row 的 workspace、outcome、batch scale、progress observation 和 classification。因此 completion validation 仍归属于后来真正完成 Todo 的动作,不会被此次 checkpoint 修复“顺带满足”。
具体改动
loopx/state_refresh.py:把checkpoint_supplement的派生提前到 settlement readback 后;所有非supplement_checkpoint的 accountable outcome 仍执行原 completion-validation fence。- 同一函数保留原 checkpoint satisfaction guard,并在 supplement append 前复用原 delivery/accounting snapshot,避免把恢复调用者当前目录或参数重新归因给既有交付。
tests/control_plane/test_refresh_checkpoint_recovery.py:增加真实 CLI 回归,构造带validation_command的 open Todo,先提交 semantic replan,再验证 mutation-free Vision supplement 成功;同时覆盖 mutation replay、错误 Todo binding、冲突 Vision 和 zero-spend 负例。
关键代码讲解
refresh_state_run的 settlement readback(约 line 933)直接消费 TypeScriptrefresh_recovery_v0;reject/replay等分支仍会在refresh_recovery_payload返回,不会落入新例外。- completion-validation fence(约 line 1135)新增的条件是 exact typed token,而不是文本启发式、CLI flag 或调用者声明;普通 append/replay/workspace supplement 的行为不变。
- checkpoint satisfaction guard(约 line 1162)确保所谓 supplement 真的产生有效 Vision decision;没有 existing Vision 时,仅给 unchanged reason 仍会失败。
- 新回归(test line 298)跨过实际 Python CLI、TypeScript effect runtime、runtime receipt files 与 git fixture,不是 mock-only 证明。
对主干的风险
最强风险是把这个例外错误扩大成“open Todo 可以跳过 completion validation”。当前实现没有这个问题:开关来源是 TypeScript refreshRecovery 的 exact state transition;它在 Python fence 之前已经拒绝 binding/delivery/mutation/vision 冲突。相关 60 个 control-plane tests 全部通过,包含普通 completion-validation 路径与新增正负例;Ruff、compileall、git diff --check 也通过。
语义与 CI 对齐
本 PR 复用 refresh_recovery_v0/supplement_checkpoint 与 vision_checkpoint_v0,没有创建新 vocabulary,也没有把 machine obligation 写成 guidance。功能语义已经被 focused tests 验证;但 exact head 当前仍为 BEHIND,node-minimum-compatibility 被取消且 merge-gate 失败。因此这份 approval 只表示 diff/语义审阅通过,不表示 merge-ready;应在 rebase/required checks 恢复后重新运行 merge-readiness gate。
我的整体评价
这个修复规模与风险相称:生产改动仅 +14/-4,复用正确的 typed owner,把例外限制在已有 admission decision 上,并用真实 CLI regression 补上此前 tests 未覆盖的“open validated Todo”组合。我没有发现新的 actionable blocker;未来向重构也无需再抽象一层,因为 recovery rule 已集中在 TypeScript,Python 这里只保留必要的 orchestration adaptation。
English verdict: APPROVE for exact head 2929e87f2fb90185e2e76cf598d6634718345ef0. No actionable code finding remains. This is not merge-ready until the branch is updated and required checks, including node-minimum-compatibility/merge-gate, are green and the exact-head readiness gate is rerun.
Goal
Fix #4840 so an already-admitted checkpoint-only retry can repair a missing vision decision even when the bound open Todo declares controller completion validation.
Change
checkpoint_supplementimmediately from the exact settlement recovery decision;Validation
python -m pytest -q tests/control_plane/test_refresh_checkpoint_recovery.py tests/control_plane/test_replan_completion_validation.py tests/control_plane/test_completion_validation_lane_scope.py tests/control_plane/test_canonical_planning_consumers.py— 60 passedpython -m pytest -q tests/control_plane/test_refresh_checkpoint_recovery.py::test_checkpoint_only_recovery_bypasses_open_todo_completion_validation— 1 passedpython -m ruff check loopx/state_refresh.py tests/control_plane/test_refresh_checkpoint_recovery.pypython -m compileall -q loopx/state_refresh.py tests/control_plane/test_refresh_checkpoint_recovery.pygit diff --check origin/main...HEADProduct entry points
This changes the existing
refresh-state/managed-Turn settlement path only. No frontend or Lark companion change is needed: neither surface owns or edits the internal same-Turn recovery payload, and the existing shared receipt projection is preserved.Control-plane change: proposed for maintainer review; not self-merged.
Closes #4840.