Skip to content

fix(quota): preserve deferred replan before execution preparation - #8066

Merged
huangruiteng merged 1 commit into
mainfrom
codex/deferred-guard-recovery-20261104-195830
Nov 5, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/deferred-guard-recovery-20261104-195830

Conversation

@loopx-agent

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

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

Due deferred work needs a planning/recovery turn before it can execute again. The generic execution-preparation adapter was also preparing that planning route, replacing its runnable decision with a deferred-Todo refusal. The next replay could then settle as a skip instead of retaining the replan obligation.

This change applies execution preparation only when the existing typed normal_delivery_allowed flag authorizes normal delivery. Deferred planning and recovery keep their original route; actual hard-lease execution still requires an ordinary claim and a fresh guard in the same Turn.

Author Declaration

  • Written by: model_agent — OpenAI Codex.

Implemented against

The reproduced defect and the existing execution-preparation contract at 886f2cdff4b2daad642f08f1b9bcffc0edf66359 are the implementation basis. No new product specification is introduced.

Criterion Disposition Symbol / path Evidence
Planning/recovery does not acquire business-execution authority implemented apply_selected_todo_execution_preparation Four File/SQLite × soft-claim/hard-lease due-planning cases
Hard-lease normal execution needs a valid ordinary claim implemented test_quota_settlement_cli.py Preparation receipt, claim, same-Turn positive guard; peer rejection retained
Due planning replays preserve identity until the same task is reopened implemented Both changed test modules Replay, future wait, reopen and successor identity assertions
Required validation before merge not_met Validation table below Full lint/type/budget and standard premerge remain blocked

Self-check: reviewed all three final files, repository instructions, lease/lifecycle boundaries and original assertion parity. This is author verification; independent review and merge readiness remain outstanding.

Scope And Continuation

One adapter condition and two existing workflow test modules change. The tests now enter through native capture decoding and ordinary lease prerequisites. A hard-lease timer rewrite follows the existing fresh-read → reopen → reviewed-deferral recovery; it gains no execution authority.

Original identity, recovery, authority and once-only settlement assertions remain. Two heartbeat-count assertions change from one to two because preparation and positive admission append separate receipts for the same effect. The adjacent module retains all 32 original assertions.

The repair is complete within this behavioral scope and reversible as one commit. Broader transport qualification remains with #7430/#8059, type/lint repair with #8050/#8059, and quota-plan smoke repair with #8061. Existing typed ownership is reused; further extraction would obscure a single condition. No schema, mode vocabulary, flag, default, store implementation or TypeScript lease rule changes.

Validation

  • Tested revision: bd8273d1e978c012f87f3d1b4eadecee0dd5fe3a. Earlier uncommitted runs are tied to byte-identical final production/test hashes where reused.
  • Run state: finished.
  • Input classes: synthetic, public_fixture.
Check kind Result Public-safe evidence / limitation
regression_parity passed Same final six-case oracle: historical production 2 passed / 4 failed, candidate 6 passed. Covers File/SQLite, both handoff modes, planning replay and normal claim recovery.
integration passed tests/control_plane/test_recovery_due_successor_identity.py: 4 passed after restoring native reader/claim prerequisites; original assertions retained.
integration failed Initial six-module quota/preparation/receipt/recovery/replay run: 243 passed / 4 raw-navigation fixture read failures. The repaired four-case module passed separately; other 243 results reused with unchanged production and other test hashes. No single final 247-pass full run is claimed.
real_entrypoint / real_backend passed Isolated built wheel, packaged CLI and its own packaged TypeScript runtime: the same 10 cases passed, including native default full/delta context delivery, File and real SQLite. This does not prove model retention or installed-App adoption.
static passed Ruff on all three changed Python files; diff hygiene, compilation, bilingual RFC check and diff semantic advisory. Public scan: zero errors, one pre-existing nonliteral Authorization-example warning. No RFC changed.
static failed Required full Ruff: existing tests/test_manager_context_roundtrip.py:289 E731. Required mypy: existing task_orchestration_admission.py:110 no-any-return. These remain blocking.
regression_parity failed examples/control_plane/cli-output-budget-regression-smoke.py: immutable base probe lacks expected inline policy fields and fails before candidate measurement. Frozen criteria unchanged.
integration failed Standard canary premerge --from-git-diff --git-diff-base origin/main: all six direct checks passed; catalog 7 passed / 2 failed; eight risk-profile smokes passed. Hot-path payload is 20,509 / 20,500 characters; quota-plan smoke raises a native-navigation KeyError. Matched native-runner base/head both measure 20,509; direct base/head both measure 20,341. The extra nested temporary-path length explains this measurement difference; no payload field or obligation was removed. Both checks remain blocking.
manual blocked Exact-scope change-quality result records failure; verification returns invalid_receipt, and premerge preserves that hold. No baseline waiver or quality-gate bypass.
real_entrypoint passed First wheel build rejected a stale generated Chat bundle. Repository Chat build and wheel rebuild then passed; 1,821 packaged product files byte-match source. No generated assets are committed or globally installed.
integration not_run Full repository pytest, remote CI, integration with later main, PostgreSQL, installed App, model/peer-host adoption, independent exact-head review and merge-readiness qualification.

Coverage and gaps: source and packaged entrypoints cover the changed route and existing negative authority boundaries. Required failures above still prevent merge. This is a correctness repair; no long-horizon effectiveness, latency, token-cost or total-cost improvement is claimed.

Supplemental Composed-Source Qualification

The remaining integration question was exercised on a clean local composition of public main 0423908e9cf46afd7a765552323b842441bd6512 followed, in order, by the exact public commits below:

  1. test(quota): read captured policy in lifecycle smokes #8061 — f5f9d70e3320ce4c5eaf549aa8d0e8f8c9895f61
  2. This PR — bd8273d1e978c012f87f3d1b4eadecee0dd5fe3a
  3. test(canary): calibrate quota fixture budget for native isolation #8069 — 9b0dfe46e51943215b9a297da78a5f49b2c24893

All six affected files byte-match their public component revisions. This composition introduces no additional source changes and has not been pushed as an integration proposal.

Check Observed result and boundary
Complete source workflow suite 247 passed in one final run (639.01 s pytest; 639.730 s process wall): test_quota_settlement_cli, test_quota_execution_preparation, test_codex_execution_preparation, test_heartbeat_receipt, test_recovery_due_successor_identity and test_settled_replay_construction, all under tests/control_plane/.
Public source callers Complete quota-plan-smoke.py passed. The native-runner hot-path budget smoke passed, including its oversized negative case: quota 20,509 / 21,000 characters, 565 / 575 nested keys and 54 / 55 top-level keys. Status remains 24,879 / 25,000, 339 / 350 and 26 / 27.
Packaged workflow Wheel build and isolated installation passed. 1,821 packaged product Python/TypeScript/JSON files byte-match source; module and process provenance confirm the isolated packaged TypeScript runtime. The ten original guard/deferred/successor cases passed. The unchanged public quota-plan smoke also passed through ten real wheel CLI subprocess calls, changing only the subprocess interpreter/isolated environment in the temporary validation adapter.
Required gates Still failed. Standard premerge passed 6/6 direct, 9/10 catalog, 8/8 risk-profile and 1/1 public-boundary checks; the CLI-output differential still loses the expected interaction_contract, scheduler_hint and selected_todo fields. Full Ruff still fails E731 at tests/test_manager_context_roundtrip.py:289; required mypy still fails no-any-return at task_orchestration_admission.py:110. The final exact-composition change-quality receipt records failure and verifies as invalid_receipt.

These are supplemental composition results. The historical 243-pass/4-failure run above remains a failed run, and the new 247-pass result does not qualify this PR's standalone exact head, current remote CI or merge readiness. Full repository pytest, PostgreSQL, installed App, model/peer-host adoption and independent exact-head review remain unqualified. No frozen output criterion was changed or waived; overlapping validation timings do not establish complete cost or a performance/effectiveness gain.

Remote CI Failure Attribution

Completed CI for the three existing public heads stops at the same shared lint gate:

PR / exact head Recorded run base CI run
#8061 / f5f9d70e3320ce4c5eaf549aa8d0e8f8c9895f61 886f2cdff4b2daad642f08f1b9bcffc0edf66359 41900227859
#8066 / bd8273d1e978c012f87f3d1b4eadecee0dd5fe3a 6a92640346051b79d08fb369354180b613c8fa46 41911562837
#8069 / 9b0dfe46e51943215b9a297da78a5f49b2c24893 0423908e9cf46afd7a765552323b842441bd6512 41915317508

Each run has one successful job, five failed required checks and fourteen skipped jobs. The first failure is kernel-static-checks / Lint test suite: one E731 at tests/test_manager_context_roundtrip.py:289:5. That file and the workflow are byte-identical between each run's recorded base and public head.

The existing workflow then skips chat-bundle, runtime test shards, TypeScript and Stage 2C workers. Their required aggregate checks remain red; stage2c-correctness-e2e explicitly receives STAGE2C_RESULT=skipped. Runtime tests did not execute in these runs.

The existing #8059 proposal includes the lint repair and remains open at eb4470126819b6131dc1b2db9282af814f999325. Preserve that owner's repair and requalify downstream jobs when the relevant integration changes. Frozen CLI-output qualification, type checks, strict change-quality and merge-readiness holds remain separate. This attribution does not certify the skipped tests or waive any failed gate.

Frontend / Visual Evidence

UI impact: none. Existing CLI planning/recovery behavior is repaired; no frontend or Lark interface, presentation text or layout changes. Before/after viewport, preview, attention and craft review: N/A. Source data: none. The Chat build was a packaging prerequisite only.

Type of Change

  • Bug fix
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)

Technical Direction

Core control-plane recovery correctness. The existing typed lease owner remains authoritative; no shared-authority or TypeScript migration promotion is claimed.

Shared-authority RFC fixture impact

N/A: no store/routing promotion or compatibility-projection change. File and isolated SQLite workflow coverage is reported above; PostgreSQL promotion is not qualified.

Boundary Checklist

  • Diff and public evidence exclude private state, credentials, raw traces, internal links and local machine paths.
  • Maintainer-owned benchmark work is not duplicated.
  • Scope stays within the reproduced routing defect and its existing workflow validation.
  • No paired RFC changed; exact-head bilingual check passed.
  • UI impact is none.
  • The single commit includes a DCO Signed-off-by trailer.

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)

动机 / Motivation

等待条件已满足、需要重新规划后续工作的 Agent,以及恢复中断 Turn 的 Host。旧路径把仍处于 deferred 的任务交给业务执行准备检查,规划请求会被“任务未开放”拒绝并在 replay 变成安静跳过;新路径保留规划或恢复指令,任务正式重新开放后仍须经过原有 claim 和 guard。同一任务从到期规划、再次等待到重新开放后能继续,原 Turn 的结算身份不被新到期任务抢走,未验证阶段不扣额度。本 PR 只修正执行准备的适用边界,不自动重开任务、授予 lease、完成任务或证明模型长程收益。不修复会让必要规划反复跳过,或让中断后的已发生结果缺少正确收口;这个共享边界修复有独立价值。

改动思路 / Approach

复用现有 typed lane 判定来限定执行准备;规划权与业务执行权不混用,canonical IO 和 lease 策略仍由原 owner 处理。当前 PR 只有共享 quota 执行准备的一条适用条件及其恢复测试;不新增模式、权限或存储。should_run=true 表示本轮需要尝试,normal_delivery_allowed=true 才表示可进入正常业务执行准备,两者不能互相替代。Python 仅组合既有判定,TypeScript 的 lane 与 lease owner 保持不变。

旧路径:到期规划 → 检查 deferred 任务是否可业务执行 → 拒绝/skip。新路径:到期规划保留原指令 → 真实等待仍停止 → 合法 reopen → 必要 claim → 同 Turn guard 为 ready。这里是源码推导的文字示意;验证依据是下述真实 CLI 对照。

具体改动 / Changes

审查 head bd8273d1e978c012f87f3d1b4eadecee0dd5fe3a,实际目标 base 6a92640346051b79d08fb369354180b613c8fa46,merge-base 886f2cdff4b2daad642f08f1b9bcffc0edf66359。PR 三点 diff 仅三个文件 +64/-7;head 尚未包含目标分支后来合入的 manager-return 改动,那些文件不是本 PR 删除。

规范 docs/heartbeat-automation-prompt.md,版本 6a92640346051b79d08fb369354180b613c8fa46:Agent Checklist 要求按 execution obligation 执行规划/恢复,通知安静不等于可跳过;Static semantics retained across hosts 要求中断工作保留原 Turn 身份、恢复选择幂等且无提前 spend。这两项在本范围 implemented;不把上层完整产品验收当作此维护修复的承诺。

关键代码讲解

apply_selected_todo_execution_preparation 在既有检查中加上 exact-true 的 normal_delivery_allowed 条件,避免业务准备覆盖非业务路线。project_selected_todo_execution_preparation 仍从 canonical Todo/lease 读取事实,再调用原 TypeScript readiness owner;它不会获取 lease。共享 packet builder 在 interaction contract 之前调用该边界。

测试保留原断言,并补上合法 claim、同 Turn ready 与完整 native full/delta capture 解码。heartbeat receipt 数从 1 改为 2 对应“准备不足的 guard + 准备完成的 guard”,结算 identity 仍是同一个;不是增加一次可花费工作,也不是删除去重要求。

对主干的风险 / Risks

PASS:四个完整模块共 203 项、0 跳过,覆盖 quota settlement、due successor identity、quota execution preparation 和 Codex preparation,使用隔离 File/SQLite authority 与合成 Host manifest。PASS:同一源码路由、同一隔离的六例 oracle,在 base 为 2 过/4 失败(到期规划的 should_run 变 false),head 为 6 过;File/SQLite × soft claim/hard lease 都覆盖到规划 replay、未来等待、reopen 和 claim/ready。新到期任务/80 条已完成记录不抢原身份、peer 不接管、提前 spend 为零也有完整模块验证。

保留全部失败观察:初次测试命令误写文件名,未收集测试;外部对照副本最初在函数默认 cwd 绑定后才替换根目录,错误指向原工作区,两次得到 2 过/4 失败。最终在绑定默认值前固定源码路由,并使用仓库隔离 fixture,才形成上述相同 base/head 对照;未删断言或放宽 oracle。

本地检查 base / head 观察 处理
三个改动文件 Ruff head PASS 当前范围静态检查通过
宽范围 Ruff 同一 E731,test_manager_context_roundtrip.py:289,完整失败文本一致 保留 FAIL
mypy --no-incremental 同一 task_orchestration_admission.py:110 no-any-return,17 文件,完整失败文本一致 保留 FAIL;默认增量 base 曾通过,不能据此认证实际源码
标准 premerge head 6 direct PASS、catalog 8 PASS/1 FAIL、risk 8 PASS;失败 quota-plan-smoke 的 KeyError quota 在 base/head 完整文本一致 整体仍 HOLD

语义与 CI 对齐

复用既有 normal_delivery_allowed 词汇与 TS owner,无 action 字符串/正文推断、领域特例或新 schema。上述红项的路径与因果链不由此三行改动产生;当前受影响不变量由真实入口正反例独立覆盖。严格 CQR cqr_9143e94ecd84cb7c34cb 仍为 fail,verify 为 invalid_receipt;premerge 当次的 stale receipt 与其他失败均保留,后来记录精确失败 receipt 也没有把它变绿。本次未查询 CI,不豁免合并检查。

我的整体评价 / Verdict

未发现当前可行动回归,局部修复 goal_achieved,代码结论 APPROVE。long_horizon 为 improved,限于反复 guard、等待、恢复与重新开放能继续且原身份/账目不丢;模型采用、完整成本净益和真实长期成果仍 UNVERIFIED。user_experience 为 improved:机器收到正确规划/恢复路线,无新增人工设置或确认轮次。视觉 not_applicable:只改变 CLI admission projection,没有渲染界面;已安装 Host/App 的采用及模型理解属于 unverified_scope,未声称验证。

这个修复使用一个现有派生字段,机制与问题相称;无需另建策略、状态或兼容分支。普通业务 hard lease 仍强制 claim 和 ready,规划不授予业务执行权限。批准不代表可合并:严格质量门禁和 premerge hold 仍有效,本次没有 merge、dismiss 或 resolve。

English verdict: APPROVE — Deferred planning and original-Turn recovery are preserved without bypassing normal execution leases; existing validation failures and strict merge holds remain explicit.

@huangruiteng
huangruiteng merged commit 8cf2874 into main Nov 5, 2026
22 of 27 checks passed
@huangruiteng
huangruiteng deleted the codex/deferred-guard-recovery-20261104-195830 branch November 5, 2026 03:26
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