fix(quota): keep boundary repair selection unbound - #4387
Conversation
c4b4d0c to
2dc1e64
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
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。
具体改动
关键代码讲解
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 或其他更高优先级动作覆盖后仍错误要求选择。loopx/control_plane/quota/should_run.py:75的_apply_selected_todo_guards未修改,仍是 boundary authority owner:它在选定 Todo 后生成 repair,关闭正常 delivery,并输出最终有效动作。本 PR 只消费它的结构化结果,不复制写范围规则。loopx/control_plane/quota/settlement_cli.py:185的quota_rollout_settlement_binding未修改,继续用 typed portfolio 的requires_explicit_turn_binding决定首回执无身份。这证明修复复用了既有 append-only settlement contract。tests/control_plane/test_quota_boundary_projection_selection.py补了 action portfolio、agent selection flag 和 managed TurnEnvelope 传播断言。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.
2dc1e64 to
da97658
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
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。
具体改动
关键代码讲解
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 或其他更高优先级动作覆盖后仍错误要求选择。loopx/control_plane/quota/should_run.py:75的_apply_selected_todo_guards未修改,仍是 boundary authority owner:它在选定 Todo 后生成 repair,关闭正常 delivery,并输出最终有效动作。本 PR 只消费它的结构化结果,不复制写范围规则。loopx/control_plane/quota/settlement_cli.py:185的quota_rollout_settlement_binding未修改,继续用 typed portfolio 的requires_explicit_turn_binding决定首回执无身份。这证明修复复用了既有 append-only settlement contract。tests/control_plane/test_quota_boundary_projection_selection.py补了 action portfolio、agent selection flag 和 managed TurnEnvelope 传播断言。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>
da97658 to
9bb93db
Compare
动机 / 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。产品入口 / Product entry points
quota_action_portfolio_v2、interaction contract 和 TurnEnvelope 生效。验证 / 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.风险 / 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 broaderself_repair_allowedflag.