Skip to content

fix(quota): keep boundary repair selection unbound - #4387

Merged
huangruiteng merged 1 commit into
mainfrom
codex/fix-boundary-repair-reselection
Sep 14, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/fix-boundary-repair-reselection

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

动机 / Motivation

当默认 Todo 因 Goal 写范围不足进入 boundary_projection_repair,但同一 Agent 仍有其他可正常执行的 Todo 时,首轮 quota should-run 曾把受阻 Todo 直接绑定到 heartbeat receipt。随后在同一 Turn 显式选择正常候选会被误判为 heartbeat_receipt_identity_conflict。

This is a focused follow-up to #4327 and #4335: recommendation order must not become settlement authority before the agent has chosen among multiple eligible actions.

改动 / Changes

  • 仅当最终有效动作确实是 boundary_projection_repair 时,复用现有 TypeScript-owned action portfolio projection。
  • 当存在可选替代项时,让现有 settlement binding 保持首轮 receipt 无身份;显式选择后再追加确定性的 identity upgrade,不修改原事件。
  • 保留所有原有失败关闭边界:仍越界或后来才出现的 Todo 继续 deferred;真正已绑定后的跨 Todo 切换继续 hard conflict。
  • 在纯决策层验证 action portfolio 与 managed TurnEnvelope 投影,在真实 CLI 层验证 append-only 两事件回执链。
  • 将该故障沉淀为公开、无私有上下文的 self-repair pattern。

产品入口 / Product entry points

  • CLI / managed Turn:行为修复通过同一 quota_action_portfolio_v2、interaction contract 和 TurnEnvelope 生效。
  • Frontend / Lark:无需新增控制或第二套状态源;本次没有 schema 变化,只让现有 typed portfolio 在一个既有 agent-only repair route 上正确出现。直接 Lark 卡片交互不参与该同 Turn quota binding 路径。

验证 / Validation

  • 59 passed — full quota settlement CLI regression under a qualified Node/SQLite runtime.
  • 7 passed — focused boundary, workspace, late-selection and bound-conflict regression set on the final condition.
  • 12 passed — TypeScript action portfolio contract tests.
  • Ruff passed for all changed Python files.
  • Premerge canary: 17/17 checks executed, 0 failures, 0 warnings; merge gate and self-merge gate passed.
  • Public boundary scan for the four changed files is clean.

风险 / Risk

The production change is one exact route predicate. It does not change schemas, receipt storage, conflict rules, write-scope admission, or candidate eligibility. The main risk is accidentally projecting selection on unrelated self-repair routes; the implementation therefore keys off the final effective_action, not the broader self_repair_allowed flag.

@huangruiteng
huangruiteng force-pushed the codex/fix-boundary-repair-reselection branch from c4b4d0c to 2dc1e64 Compare September 14, 2026 16:10

@huangruiteng huangruiteng 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.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

评审对象:4387@2dc1e64507853fa5de201caa740c214f293b9ef1

动机

这次修复针对一个真实的结算身份错误:默认 Todo 因 Goal 写范围不足进入 boundary_projection_repair 时,只要同一 Agent 还有一个正常可运行的替代 Todo,首轮 guard 就不应把“推荐顺序”当成已选择的结算身份。基线实跑证明旧行为会遗漏 action portfolio、把受阻 Todo 写入首回执,并让同 Turn 的有效重选稳定失败为 heartbeat_receipt_identity_conflict。这不只是交互不便,还会迫使调用方开启新 Turn,或错误地考虑修改 append-only 历史。

最强的反对理由是 quota hot path 不应为单一事故增加特殊机制;但本 PR 没有新增机制。它只在现有 planning projection owner 上补一个精确路由条件,复用 #4327/#4335 已交付的 typed portfolio、显式选择和回执升级契约。修改 conflict writer 或覆盖旧回执都会扩大权限风险,因此当前位置是更小且更正确的修复边界。

改动思路

权威输入仍是当前 Goal boundary、Agent Todo inventory、所选 Todo 的写范围和既有 heartbeat receipt。_apply_selected_todo_guards 先对实际选中的 Todo 生成 boundary repair,并重算最终 route;本 PR 只让 _planning_projections 在最终 effective_action 精确等于 boundary_projection_repair 时,把该 Turn 视为“仍可选择”。随后继续调用已有 TypeScript action_portfolio owner;当确有替代项时,它输出 requires_explicit_turn_binding=true。

既有 quota_rollout_settlement_binding 会因此让首轮 guard receipt 保持无身份。调用方带 --todo-id 重入后,仍必须经过当前 eligible set、workspace 和 Goal boundary 的最终校验;合法替代项追加一个确定性的 upgraded receipt,原事件不修改。晚到且仍越界的 Todo 继续 deferred,已经真正绑定后的不同 Todo 继续 hard conflict。没有第二套选择器、状态源、队列或 receipt writer。

具体改动

关键代码讲解

  1. loopx/control_plane/quota/should_run_packet.py:737 的 _planning_projections 增加三行生产逻辑:只有 route.effective_action == "boundary_projection_repair" 且存在结构化 boundary repair 时,才允许复用 portfolio projection。这里刻意不用宽泛的 self_repair_allowed,避免 autonomous replan 或其他更高优先级动作覆盖后仍错误要求选择。
  2. loopx/control_plane/quota/should_run.py:75 的 _apply_selected_todo_guards 未修改,仍是 boundary authority owner:它在选定 Todo 后生成 repair,关闭正常 delivery,并输出最终有效动作。本 PR 只消费它的结构化结果,不复制写范围规则。
  3. loopx/control_plane/quota/settlement_cli.py:185 的 quota_rollout_settlement_binding 未修改,继续用 typed portfolio 的 requires_explicit_turn_binding 决定首回执无身份。这证明修复复用了既有 append-only settlement contract。
  4. tests/control_plane/test_quota_boundary_projection_selection.py 补了 action portfolio、agent selection flag 和 managed TurnEnvelope 传播断言。
  5. tests/control_plane/test_quota_settlement_cli.py:2953 用真实 CLI/File authority/receipt writer 覆盖完整两步链路:首次 boundary guard 无身份,同 Turn 选择替代 Todo 后 normal_run + upgraded,总计两个 append-only 事件。self-repair reference 同步沉淀了公开、无私有上下文的复现与修复模式。

整份 diff 为 3 行生产代码、73 行测试和 1 行文档,无 schema、CLI 参数、持久状态、provider 或 UI 控件新增。

对主干的风险

主风险是共享 quota 路由上的误投影:如果边界 gap 仅作为残留诊断存在、而最终动作已被 replan/inbox 等路由覆盖,portfolio 不应出现。精确 effective_action 条件和原有 receipt-bound、explicit-request、replan-bound、monitor-only 排除共同限制了影响面。另一个风险是“为了可重选”放松最终写范围或已绑定冲突;开发中曾考虑过更宽的绑定特殊分支,但既有 late-selection 回归立即暴露它会让仍越界 Todo 获得不当绑定,因此该分支已删除。

验证包括:内容相同提交上的 59 项完整 quota settlement CLI 回归;最终 exact head 的 7 项边界/workspace/late-selection/bound-conflict 回归;12 项 TypeScript portfolio 契约;17/17 premerge canary;Ruff、diff hygiene、DCO 和四文件公共边界扫描。相同 fingerprint 的 baseline/head 公共 CLI 对比得到:baseline portfolio=false, bound=true, selected=identity_conflict, events=1;head portfolio=true, bound=false, selected=normal_run, receipt=upgraded, events=2。剩余风险仅是既有字符串动作名未来重命名时需要连同回归更新,不构成本次阻塞。

我的整体评价

未发现阻塞项。改动解决的是可重复、可观测的真实缺陷,并且选择了最小的现有 owner:boundary guard 继续拥有权限判断,TypeScript portfolio 继续拥有候选投影,settlement writer 继续拥有不可变回执和真实冲突。没有以“更灵活”为由放宽授权,也没有为通过测试增加平行状态。baseline/head 对照证明了预期语义变化,负向回归证明了未改变的拒绝边界,改动规模与故障成本相称。

结论:APPROVE。由于提交者与评审账号相同,GitHub 不允许正式 self-approve,因此以 COMMENTED review 记录同等的 exact-head 审批结论。

English verdict: APPROVE 4387@2dc1e64507853fa5de201caa740c214f293b9ef1. No blocking findings. The exact route predicate reuses the existing typed action portfolio and append-only receipt upgrade path; baseline/head CLI evidence proves the intended conflict-to-upgrade change, while late invalid selections and genuinely bound identity conflicts remain fail-closed.

@huangruiteng
huangruiteng force-pushed the codex/fix-boundary-repair-reselection branch from 2dc1e64 to da97658 Compare September 14, 2026 16:22

@huangruiteng huangruiteng 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.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

评审对象:4387@da9765862d1470410f1475364a8b36d08e362ca7

动机

这次修复针对一个真实的结算身份错误:默认 Todo 因 Goal 写范围不足进入 boundary_projection_repair 时,只要同一 Agent 还有一个正常可运行的替代 Todo,首轮 guard 就不应把“推荐顺序”当成已选择的结算身份。基线实跑证明旧行为会遗漏 action portfolio、把受阻 Todo 写入首回执,并让同 Turn 的有效重选稳定失败为 heartbeat_receipt_identity_conflict。这不只是交互不便,还会迫使调用方开启新 Turn,或错误地考虑修改 append-only 历史。

最强的反对理由是 quota hot path 不应为单一事故增加特殊机制;但本 PR 没有新增机制。它只在现有 planning projection owner 上补一个精确路由条件,复用 #4327/#4335 已交付的 typed portfolio、显式选择和回执升级契约。修改 conflict writer 或覆盖旧回执都会扩大权限风险,因此当前位置是更小且更正确的修复边界。

改动思路

权威输入仍是当前 Goal boundary、Agent Todo inventory、所选 Todo 的写范围和既有 heartbeat receipt。_apply_selected_todo_guards 先对实际选中的 Todo 生成 boundary repair,并重算最终 route;本 PR 只让 _planning_projections 在最终 effective_action 精确等于 boundary_projection_repair 时,把该 Turn 视为“仍可选择”。随后继续调用已有 TypeScript action_portfolio owner;当确有替代项时,它输出 requires_explicit_turn_binding=true。

既有 quota_rollout_settlement_binding 会因此让首轮 guard receipt 保持无身份。调用方带 --todo-id 重入后,仍必须经过当前 eligible set、workspace 和 Goal boundary 的最终校验;合法替代项追加一个确定性的 upgraded receipt,原事件不修改。晚到且仍越界的 Todo 继续 deferred,已经真正绑定后的不同 Todo 继续 hard conflict。没有第二套选择器、状态源、队列或 receipt writer。

具体改动

关键代码讲解

  1. loopx/control_plane/quota/should_run_packet.py:737 的 _planning_projections 增加三行生产逻辑:只有 route.effective_action == "boundary_projection_repair" 且存在结构化 boundary repair 时,才允许复用 portfolio projection。这里刻意不用宽泛的 self_repair_allowed,避免 autonomous replan 或其他更高优先级动作覆盖后仍错误要求选择。
  2. loopx/control_plane/quota/should_run.py:75 的 _apply_selected_todo_guards 未修改,仍是 boundary authority owner:它在选定 Todo 后生成 repair,关闭正常 delivery,并输出最终有效动作。本 PR 只消费它的结构化结果,不复制写范围规则。
  3. loopx/control_plane/quota/settlement_cli.py:185 的 quota_rollout_settlement_binding 未修改,继续用 typed portfolio 的 requires_explicit_turn_binding 决定首回执无身份。这证明修复复用了既有 append-only settlement contract。
  4. tests/control_plane/test_quota_boundary_projection_selection.py 补了 action portfolio、agent selection flag 和 managed TurnEnvelope 传播断言。
  5. tests/control_plane/test_quota_settlement_cli.py:2953 用真实 CLI/File authority/receipt writer 覆盖完整两步链路:首次 boundary guard 无身份,同 Turn 选择替代 Todo 后 normal_run + upgraded,总计两个 append-only 事件。self-repair reference 同步沉淀了公开、无私有上下文的复现与修复模式。

整份 diff 为 3 行生产代码、73 行测试和 1 行文档,无 schema、CLI 参数、持久状态、provider 或 UI 控件新增。

对主干的风险

主风险是共享 quota 路由上的误投影:如果边界 gap 仅作为残留诊断存在、而最终动作已被 replan/inbox 等路由覆盖,portfolio 不应出现。精确 effective_action 条件和原有 receipt-bound、explicit-request、replan-bound、monitor-only 排除共同限制了影响面。另一个风险是“为了可重选”放松最终写范围或已绑定冲突;开发中曾考虑过更宽的绑定特殊分支,但既有 late-selection 回归立即暴露它会让仍越界 Todo 获得不当绑定,因此该分支已删除。

验证包括:内容相同提交上的 59 项完整 quota settlement CLI 回归;最终 exact head 的 7 项边界/workspace/late-selection/bound-conflict 回归;12 项 TypeScript portfolio 契约;17/17 premerge canary;Ruff、diff hygiene、DCO 和四文件公共边界扫描。相同 fingerprint 的 baseline/head 公共 CLI 对比得到:baseline portfolio=false, bound=true, selected=identity_conflict, events=1;head portfolio=true, bound=false, selected=normal_run, receipt=upgraded, events=2。剩余风险仅是既有字符串动作名未来重命名时需要连同回归更新,不构成本次阻塞。

我的整体评价

未发现阻塞项。改动解决的是可重复、可观测的真实缺陷,并且选择了最小的现有 owner:boundary guard 继续拥有权限判断,TypeScript portfolio 继续拥有候选投影,settlement writer 继续拥有不可变回执和真实冲突。没有以“更灵活”为由放宽授权,也没有为通过测试增加平行状态。baseline/head 对照证明了预期语义变化,负向回归证明了未改变的拒绝边界,改动规模与故障成本相称。

结论:APPROVE。由于提交者与评审账号相同,GitHub 不允许正式 self-approve,因此以 COMMENTED review 记录同等的 exact-head 审批结论。

English verdict: APPROVE 4387@da9765862d1470410f1475364a8b36d08e362ca7. No blocking findings. The exact route predicate reuses the existing typed action portfolio and append-only receipt upgrade path; baseline/head CLI evidence proves the intended conflict-to-upgrade change, while late invalid selections and genuinely bound identity conflicts remain fail-closed.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng
huangruiteng force-pushed the codex/fix-boundary-repair-reselection branch from da97658 to 9bb93db Compare September 14, 2026 16:46
@huangruiteng
huangruiteng merged commit d5d19a9 into main Sep 14, 2026
20 checks passed
@huangruiteng
huangruiteng deleted the codex/fix-boundary-repair-reselection branch September 14, 2026 16:52
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.

1 participant