fix(quota): preserve replan on selection reentry - #4868
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
结论:APPROVE。本次审阅绑定的 exact head 是 adf93d5acb3d34f1b446e1544fd15f387469bde0;该 head 已合并为 da49e490b4a8be523de3514d2558991d51097319。未发现需要阻塞或补修的问题。
动机
这个修复针对 selection reentry 的一个真实语义断层:typed decision 已经保留了上一次 action selection,并要求执行 autonomous replan,但 Python live-quota 适配层只在“本轮显式请求 selection”时刷新 canonical Todo。结果是 decision plane 已经要求继续 replan,canonical Todo 却可能仍指向旧选择,形成执行义务与可领取工作之间的不一致。
改动思路
修复没有在 Python 侧重建第二套 selection/replan 判断,而是继续消费 TypeScript decision 的既有输出:只要当前没有 receipt-bound Todo,且 decision 表明 selection 是本轮请求得到的或从上一轮保留下来的,就刷新 canonical Todo。这样既覆盖 retained-selection reentry,又保留 receipt-bound continuation 的优先级。
这条边界是合适的:TypeScript 仍拥有 retained-selection 与 replan obligation 的语义权威;Python 只负责把已经作出的 decision 投影到 live quota/Todo 读取路径。没有新增持久状态、协议字段或字符串启发式。
具体改动
loopx/control_plane/quota/live_decision.py将 canonical Todo refresh 条件从仅requested_action_selection扩展为requested_action_selection or retained_action_selection,同时保留not receipt_bound_todo保护。tests/control_plane/test_effect_turn_live_quota_decision.py新增 retained-selection reentry 回归:证明 provider 会被读取一次,旧 selection 被保留,autonomous_replan_required会投影,且must_attempt_work仍为真。- 回归敏感性已反证:把同一语义断言临时放到修复前基线会稳定失败(provider reads 为空),而 exact head 通过,因此测试不是仅复述当前实现。
关键代码讲解
build_live_quota_should_run_decision的条件变化很小,但修的是跨层语义一致性:retained_action_selection不是“没有发生 selection”,而是 typed decision 明确选择了沿用既有 action,并可能同时要求 replan。适配层必须把它当作需要刷新 canonical Todo 的输入。reconcileRetainedActionSelection仍是 retained-selection 判定的权威来源;本 PR 没有把 actor lifecycle、选择有效性或 replan 条件复制进 Python,因此避免了两套状态机逐渐分叉。- 新测试同时断言 provider read、decision reason、replan obligation 和执行义务,覆盖的是完整行为链,而不只是一个布尔字段或文案。
对主干的风险
风险较低且边界清楚:行为变化只发生在“没有 receipt-bound Todo + retained selection”这一此前漏掉的 reentry 分支。已有 receipt 的 continuation 不受影响;普通 requested-selection 路径保持原语义;未选择 action 的路径也不会被放宽。
验证结果:
- exact merged head:30 个相关 Python 测试通过;quota replan decision-plane smoke 通过;Ruff 与
git diff --check通过。 - 与最新主干重放后的同内容分支:47 个相关 Python 测试、mypy、control-plane TypeScript typecheck、13 个 action-portfolio TypeScript 测试均通过;change-quality receipt 有效;premerge canary 16/16 通过,无 warning 或 manual hold。
- 完整 control-plane TypeScript 套件在正确的
uv环境中为 2279 passed、20 skipped、1 failed;唯一失败是sqlite_capacity.test.ts,在origin/main上可同样复现,和本 PR 的 Python quota diff 无关。该基线失败没有被计作通过或隐藏。 - 按当前 capability 策略没有把 GitHub CI 轮询当作审阅证据来源。
我的整体评价
这是一个范围克制、架构方向正确的修复:它恢复 canonical Todo freshness,却没有把 TypeScript 的 typed decision authority 搬回 Python。测试覆盖了真实缺陷路径,也证明修复前会失败。面向下一步的重构检查后,我认为当前直接复用 retained-selection 输出比新增 helper、协议字段或抽象层更稳妥;本 PR 不需要为了“将来可能扩展”继续加结构。
English verdict: APPROVE - The exact merged head restores canonical Todo freshness for retained-selection reentry without moving typed replan authority or adding persistent state.
Goal And Delivered Outcome
selection required → selection deferred → selection required; after, retained-selection reentry refreshes the authoritative provider Todo fields and returns an executable replan obligation with settlement identity preserved. Thereal_entrypointandregression_parityrows prove this transition.main.Scope And Continuation
Validation
adf93d5acb3d34f1b446e1544fd15f387469bde0finishedsynthetic,authorized_private_read_onlyregression_paritypasseduv run --extra test python -m pytest -q tests/control_plane/test_effect_turn_live_quota_decision.py tests/control_plane/test_selection_replan_reentry.py: 30 passed. The new counterexample failed before the fix because retained reentry performed no provider read, then passed after the condition was repaired.real_entrypointpassedloopx quota should-runcompleted the three-step initial/selected/reentry flow against an isolated runtime copy: the final call returnedautonomous_replan_required,must_attempt=true, a non-empty obligation, and Todo-bound settlement. Live state was not modified; the authorized source state and identifiers are not published.unitpassednode --no-warnings --experimental-sqlite --experimental-strip-types --test tests/control_plane_ts/action_portfolio.test.ts: 13 passed, including retained-selection precedence.staticpassednpm run typecheck:control-planepassed after installing the repository-declared Node dependencies.staticpassedgit diff --checkpassed.staticpassedloopx checkfound both candidate public files clean. It also emitted unrelated local registry-state warnings outside this diff.integrationpassedloopx canary premerge --from-git-diff --goal-id loopx-meta: standard tier passed 16/16 selected canaries, 5 direct checks, zero failures/warnings/manual holds.manualpassedcqr_402fab973c9f7ae02919is valid for the exact committed diff.See validation disclosure guidance.
Frontend / Visual Evidence
nonenoneType of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
N/A. This PR neither claims TypeScript migration progress nor changes shared-authority storage, routing, or compatibility projection.
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).