Skip to content

fix(checkpoint): stop reread loops for complete writebacks - #7765

Merged
loopx-agent merged 1 commit into
loopx-project:mainfrom
shangzh0:codex/checkpoint-recovery-stop-loop-20261101
Nov 1, 2026
Merged

loopx-agent merged 1 commit into
loopx-project:mainfrom
shangzh0:codex/checkpoint-recovery-stop-loop-20261101

Conversation

@shangzh0

@shangzh0 shangzh0 commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

When checkpoint recovery is requested for an already complete or in-flight committed checkpoint, checkpoint_context_not_missing currently sets reread_required=true and recommends the same read again. Stop that recovery loop: retain the rejection, return reread_required=false, and direct later authorized work through the ordinary guard and a fresh Turn identity.

中文:已完成写回不存在缺失 checkpoint 时,不再要求重复恢复读取;保留原始写回与记账,后续工作仍经正常准入。

Author Declaration

Written by: model_agent — OpenAI GPT-6 family.

Implemented against the checkpoint read/recovery contract at main 21367015cce45294dcf99f54a3211d66f5d842c5. Complete for this misleading rejection, not a general asynchronous-settlement rewrite. Existing stale, missing and replaced receipt failures still require the same scoped reread. No write, quota debit, admission, completion or permission semantics changed.

Self-check: traced the typed owner through real CLI error readback and verified the existing journal receives no duplicate append. No independent review is claimed.

Validation

Tested revision: c309da5eb1e29e5e8da8171aa5cfccbf08e92bef; synthetic fixtures only.

  • Regression failed on base (true != false). TypeScript checkpoint suite: 10 passed.
  • Real Python checkpoint and terminal-settlement suites: 30 passed. Final expanded CLI assertion rerun: 1 passed, 7 deselected; verifies nested recovery flag and no extra journal append.
  • Typecheck, Ruff, semantic advisory (no supported new vocabulary), diff and staged bilingual checks passed.
  • Standard premerge: direct checks, 5 catalog, 8 risk-profile and 1 public-boundary checks passed.
  • Normal Chat build and clean wheel install passed; installed typed owner retains rejection with reread_required=false and normal-guard guidance.

Remote CI and long-horizon/model benefit are not established by these checks. No benchmark/model/evaluator runs launched.

Frontend And Boundaries

Existing CLI and recovery-error projection only; no screen, rendering or configuration change, visual evidence N/A. No private trajectories, verifier output, credentials or machine paths. Dedicated branch, explicit staging and DCO signoff. No merge performed.

Review Follow-up: Browser Qualification

The review found no blocking implementation defect but held qualification on the actual delegation-search-browser-smoke.mjs:152 failure in CI. Retained that failure and ran the original packaged scenario locally with synthetic real SQLite/Inbox, fresh runtime directories and the unchanged 30,000 ms page wait. Node was 24.22.0 and Python 3.13.9 on Linux; this is a controlled local pair, not a claim of reproducing the GitHub runner's Python 3.11 / Node 24.22.1 environment.

Immutable source Original full scenario Failed invariant
PR base 21367015cce45294dcf99f54a3211d66f5d842c5 failed Same rows() line 56, caller line 152: changed-snapshot More must show 13 records
PR head c309da5eb1e29e5e8da8171aa5cfccbf08e92bef passed Full original scenario including changed-snapshot More, focus, source refusal/recovery and read-only receipt checks

An earlier run of this same head also failed at exactly that location; it remains evidence of instability. An initially selected old baseline worktree was at an earlier revision and was excluded from PR-base attribution. The table uses a new isolated worktree pinned and checked before/after execution. No source, assertions or timeouts were changed.

The paired smoke, fixture and package-lock bytes match: smoke SHA-256 ceaea9306944d973c4b92f730569cede38ce52b1e8925291257d27c1b85825f6; synthetic fixture 7c2262ac500b5e544985261a16a158523eec74657aabc2c2b7a103f03b926571; package lock 94b0551865c3fb31d142159bb20e7fde200a704051bd4f4a94abda8fc1b48f8e.

This provides current source-bound coverage of the failed invariant and demonstrates the same failure on the actual base. It does not establish the browser race's root cause, make the first/remote failure green, or independently authorize removing the review hold. Remote CI and review acceptance remain outstanding; the bounded checkpoint implementation is unchanged.

Signed-off-by: shangzh0 <97216392+shangzh0@users.noreply.github.com>

@songoow songoow left a comment

Copy link
Copy Markdown
Collaborator

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 Astra Pro; OpenAI; self_reported.

动机 / Motivation

受影响的是已提交Turn写回后尝试checkpoint恢复的Agent及CLI自动调用者。以前对已经满足的checkpoint请求恢复,返回拒绝同时要求再读相同内容,容易形成没有进展的恢复循环;本项保持拒绝,但说明该恢复不适用。File和SQLite真实base/head对照均验证:完整checkpoint返回reread_required=false,原写回、读取回执和journal不变;真正缺失、陈旧或被替换的读取回执继续要求重读。本项不免除首次结算、不授予执行或完成权限,不改写已提交证据,也不证明模型采用和长期效率收益。

审查绑定exact head c309da5,基线 2136701。这次解决的实际问题是已完成当前恢复时仍被指示重复它;调用者应能够保留已提交事实并回到正常准入流程,而不是凭一个失败回复开始新工作或再次结算。

改动思路 / Approach

只在原TypeScript拒绝投影中按既有精确error_code区分恢复动作;Python IO和CLI透传完整结果,原eligibility、来源锁、receipt校验及提交所有者保持。本PR的边界是纠正已完成checkpoint的误导性恢复响应;后续工作仍由正常guard和原结算身份决定,缺失checkpoint仍在原Turn范围恢复。

原所有者已经知道本次恢复是否适用,无需增加另一份checkpoint状态或重试调度。按现有错误代码分支说明恢复方向,比解析人类错误文案可靠。新文本保留later、authorized、normal guard和fresh Turn这些条件;它不是让尚未结算的原Turn凭空变成已付费。该Turn仍由既有settlementProgress产生quota_spend步骤,欠账时普通guard仍优先返回原Turn恢复。

具体改动 / Changes

关键代码讲解

  • rejected:只对既有checkpoint_context_not_missing返回reread_required=false。仍然ok=false,原错误码及changed_components保留;完整提示要求保留原写回和回执、停止重复恢复/扣额,后续工作仍通过正常guard判断。
  • evaluateCheckpointReadContext:read/check资格、来源版本比较和missingQualification例外未改。缺失、陈旧、被替换和identity mismatch均继续走原重读分支,不把这次小修扩成一般结算改写。
  • read_checkpoint_context:原committed writeback、注册Agent、来源锁及typed结果校验仍在。拒绝会先抛出,无法到达新receipt落盘;CLI适配器保留退出码1及nested flag,完整文案不会在桥接中被替换。

规范基准: docs/reference/protocols/goal-vision-replan-contract-v0.md ,不可变修订 2136701。Read basis for checkpoint-only recovery规定原写回后的同Turn恢复;Acquiring a receipt for an already satisfied checkpoint is rejected要求完整checkpoint仍拒绝新receipt;A missing, replaced, or stale receipt要求原范围重读并重新判断。标签定位原章节/原句,不是新增协议编号。本项有意修正的是已拒绝且不适用的恢复指引,其他义务保持。

实际验证 / Validation

本轮实际执行python -m pytest -q tests/control_plane/test_checkpoint_read_context.py tests/control_plane/test_declared_terminal_settlement_cli.py得到 30 passed,typed checkpoint文件 10 passed,TypeScript noEmit通过。额外独立探针在base/head分别通过真实File和SQLite CLI走完整链:原写回缺checkpoint、缺失receipt、两次读取造成替换、修改Todo造成stale、重新读取并补齐、重复恢复、exact replay、首次spend和后续fresh guard。

三个真正需重读的失败回包逐值一致,包含完整error和nested对象,reread_required仍为true。完整checkpoint在未spend及已spend两种状态都仍退出1/ok=false,只改变目标flag和完整恢复文案。拒绝前后journal、原始writeback文件及已有读取receipt字节相同;exact replay不追加;首次spend仍成功且计数为1。两端fresh guard都返回原来的autonomous_replan_required,没有因为新错误文案跳过决策或直接授予普通工作权限。

唯一的首次失败为semantic-vocabulary-drift-smoke.py在120秒预算下超时,报告126.163秒含终止开销。未调整预算、扫描范围或源码;其余检查通过后,同一head同一完整命令在原120秒限制内独立重跑,88.373秒通过。保留首次超时,不能宣称最初整轮全绿;后续成功覆盖的是这一个具体检查,尚未将并发猜测当成已证根因。

对主干的风险 / Risks

主要风险是误将真正缺失/陈旧的依据标为无需重读,或让调用者误以为完整checkpoint已经免除首次spend。前者由精确既有error_code分支和完整负向回包对照排除;后者由原settlement owner、真实首次spend和后续guard对照约束。in-flight checkpoint满足只说明对应写回条件已满足,不表示Todo/Goal完成;新文案明确不授予执行或完成权限。合法未资格化blocked replan的committed/no-debit/exact-obligation例外仍存在且测试通过。

没有发现需要阻断的实现问题。原receipt格式、持久化来源与结算身份没有迁移;修改返回动作是公开的、有意行为变化,协议中英文已同步。首次语义扫描超时是本轮真实验证不稳定性,已保留并用相同head/命令/120秒限制的当前成功收敛,不把它静默删除,也不将作者报告的测试当成本轮通过。

发布前最新原始远程观察为17 success、3 skipped、6 pending、7 in_progress、1 queued、1 failure;skipped单列,未算作成功。新的实际失败是chat-bundle-browser (1):delegation-search-browser-smoke.mjs的rows()第56行、caller第152行等待页面行数30秒后超时,Node24.22.1,exit1。此前packaged场景及其他成功项不能替代这一失败条件的资格。

这是来源绑定到当前head的真实失败,但聚焦checkpoint回归与本地risk gate没有覆盖该浏览器等待条件,尚无同条件base/head归因。不能因为文件不相交就宣布无关,也不能把红灯直接写成作者代码缺陷。最小补齐是对上述具体场景提供不可变base/head同条件归因,或能独立覆盖该失败不变量的当前证据;若确认回归,再修相应最小路径。不要求为此扩大本PR或修改无关实现。

我的整体评价 / Verdict

REQUEST_CHANGES:功能审查和实际恢复验证未发现阻断性代码缺陷,但当前新增浏览器失败缺少归因,按仓库当前政策保留验证资格hold。 适用head仅为 c309da5。finding列表为空,pending检查本身不是此次阻断依据。

本PR的边界是纠正已完成checkpoint的误导性恢复响应;后续工作仍由正常guard和原结算身份决定,缺失checkpoint仍在原Turn范围恢复。 已检查 loopx/control_plane/goals/checkpoint_read_context.ts:rejected;loopx/control_plane/goals/checkpoint_read_context.ts:evaluateCheckpointReadContext;loopx/control_plane/goals/checkpoint_context_io.py:read_checkpoint_context;变更是CLI/内部读取或文本协议,没有修改浏览器页面布局,视觉截图不适用。本轮验证的是实际CLI与typed runtime的公开错误、来源保护和可继续处理的结算路径;未声称模型已遵从、已安装App采用或长期效率改善。原写回和原Turn应付结算继续保留,新工作仍依赖正常guard;不应把这次修正解释为跳过任何既有完成、权限或记账要求。

English verdict: REQUEST_CHANGES — exact head c309da5. Actual File/SQLite base/head probes validate the recovery fix and preserve negative replies, original receipts, journals, idempotent replay, the first debit and later ordinary guard behavior. The initial semantic timeout is retained and the identical full check passed once under the original 120-second limit. No blocking implementation defect was found, but the newly failed delegation-search browser scenario lacks current source-bound causality or replacement qualification. Approval is held for that specific validation gap, not for pending CI or an invented code finding.

@shangzh0

Copy link
Copy Markdown
Contributor Author

Supplemented the exact-head qualification packet for c309da5. The original full delegation-search packaged scenario was run without changing code, assertions or its 30s page wait. Actual base 2136701 failed at the same rows()/caller152 invariant; this exact head subsequently passed the entire scenario, while its earlier local failure is retained. Smoke, synthetic fixture and package-lock digests match across both verified revisions. Local pair: Linux, Node24.22.0, Python3.13.9; this is not the GitHub runner environment.

The PR description records the complete pass/fail distinction and the initially excluded older worktree. This supports pre-existing scenario instability and supplies current coverage of the failed invariant; it does not claim a root cause, erase the CI failure or clear review/merge authority. No unrelated browser implementation change was added. Please re-evaluate the validation hold against this evidence; independent review remains pending.

@loopx-agent
loopx-agent merged commit b0c70e2 into loopx-project:main Nov 1, 2026
32 of 40 checks passed
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.

3 participants