Skip to content

refactor(cli): extract quota action selection owner - #4818

Merged
huangruiteng merged 5 commits into
loopx-project:mainfrom
Duang777:codex/repair-quota-module-budget
Sep 21, 2026
Merged

huangruiteng merged 5 commits into
loopx-project:mainfrom
Duang777:codex/repair-quota-module-budget

Conversation

@Duang777

Copy link
Copy Markdown
Contributor

Summary

  • move quota CLI action-selection request normalization, receipt adaptation, preflight, deferred retention, and receipt annotation into quota_action_selection.py
  • replace the correlated five-value receipt tuple with typed immutable state and result objects
  • keep status collection, monitor writeback, rollout logging, rendering, and command dispatch in quota.py
  • update the semantic producer anchor and the direct unit-test import

Observable result

loopx/cli_commands/quota.py drops from 1,114 to 779 lines. The new owner is 415 lines, so both modules pass the existing 1,000-line CLI command budget without adding an exception. Action-selection branch order, payload strings, receipt writeback, replay, and settlement behavior remain unchanged.

This repairs the cli-command-module-size-ownership-command-modularization-smoke.py failure on current main and lets #4803 sync main without inheriting that failure.

Validation

  • python -m pytest tests/control_plane/test_quota_action_selection_conflict.py tests/control_plane/test_heartbeat_receipt.py tests/control_plane/test_quota_settlement_cli.py -q - 76 passed
  • semantic production and vocabulary tests - 219 passed
  • quota boundary and replan selection tests - 6 passed
  • CLI entrypoint and import-boundary tests - 32 passed
  • maintainability and M6 quality-gate tests - 16 passed
  • CLI argument diagnostics - 95 passed
  • python examples/cli-command-module-size-ownership-command-modularization-smoke.py - passed
  • Ruff on changed Python files - passed
  • new module target Mypy - passed; quota.py retains the same five pre-existing target errors as main
  • loopx canary premerge --from-git-diff on the exact merged-main head - 18/18 passed, no manual holds

Delivery boundary

This is a control-plane CLI ownership change. It is ready for independent review and is not self-merged.

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…dule-budget

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Copy link
Copy Markdown
Contributor Author

@huangruiteng 请复审 #4818。远端 CI 已完成主要检查:静态、Dashboard、Node、Windows、E2E 和 3/4 pytest shards 全绿;唯一失败的 shard 只有两条 main@2caada69d 可复现的 post-#4771 旧断言,均已在独立小 PR #4819 修复。

本 PR exact head 的 quota 提取本地验证仍为:76 个冲突/heartbeat/settlement 测试、219 个 semantic 测试、6 个 boundary/replan、32 个 CLI/import、16 个 maintainability/M6、95 个 CLI diagnostics、Ruff、目标模块 Mypy、1000 行模块门禁和 premerge 全部通过。未自合并。

…dule-budget

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Copy link
Copy Markdown
Contributor Author

同步记录:已用普通、带 Sign-off 的 merge commit 合入 main@0ef7ebd74,新 head 为 92c514793,无冲突。新 head 本地复验:quota action-selection + settlement 69 passed,Ruff、目标模块 Mypy、CLI 1000 行门禁通过,exact-diff premerge 18/18 passed。远端 CI 已自动重跑。

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>

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

动机

这个 PR 解决的是一个真实且持续增长的维护问题:loopx/cli_commands/quota.py 同时承担命令分派、状态读取、渲染/日志,以及显式 Todo 选择与 heartbeat receipt 对账,已经超过仓库现行的 1000 行 CLI owner 预算。相比直接抬高预算或豁免该文件,把“action selection + receipt adaptation”作为一个完整变化原因抽出,能够让后续 quota 修改更容易定位、验证和回滚。

我按 exact head 92c5147934340debfd72f7c5ca6b4b9962e76d08 复核后,认为这不是为了过行数门禁而拆文件:新 owner 覆盖请求归一化、receipt 绑定读取、preflight、recovery、deferred retention 与最终 binding,形成了完整且已有生产调用方的边界;quota.py 保留 dispatch、status、stall writeback、rollout logging 与 rendering。该边界可独立审阅且没有新增用户协议、持久化字段或选择权限。

改动思路

入口仍是 handle_quota_command。它先通过 load_requested_quota_action_selection 把 CLI --todo-id 和同一 Turn 的 receipt 适配为 RequestedQuotaActionSelection,再把 receipt-bound/requested/retained 三种输入传给原有 build_live_quota_should_run_decision。live decision 仍是 eligibility/优先级的权威;新模块没有重建第二套决策。

live decision 返回后,reconcile_requested_quota_action_selection 保持原顺序执行:先校验 projected selection 与 receipt identity,再在 rejected/deferred 路径投影 recovery,必要时仅保留 pending_action_selection;只有 receipt reconcile/commit/readback 完成后,commit_requested_action_selection 才写入响应中的 selection_binding=heartbeat_receipt。失败和重试仍由既有的 typed error、recommended_actionhandle_quota_command 的 rendering/logging 负责。

我专门挑战了“这只是可达、但没有必要的新 helper”这一点。仓库搜索显示,新模块直接复用了 normalize_todo_id、heartbeat receipt typed accessors、QuotaActionSelectionConflictKindapply_action_selection_recovery 和 live decision;不存在第二个 eligibility、settlement 或 persistence owner。把预算提高或只拆一两个 helper 都会继续让 receipt 与 selection 的同一条状态机分散在 quota.py

具体改动

  • quota.py:删除原来内联的约 360 行 action-selection helper,改为持有一个 RequestedQuotaActionSelection,并在 live decision、automatic stall rebuild 和 receipt commit/readback 三处复用同一组绑定值。文件降到 779 行。
  • quota_action_selection.py:新增 415 行的内部 owner,集中处理请求规范化、receipt 读取、preflight、deferred retention 和结果适配。
  • vocabulary_v0.json:仅把既有 effective_action producer anchor 从旧文件路径迁移到新文件路径,没有新增词汇或改变语义。
  • test_quota_action_selection_conflict.py:把对私有 preflight helper 的直接导入迁到新 owner;断言语义未变。

关键代码讲解

  1. RequestedQuotaActionSelectionquota_action_selection.py:34)把过去相关的五元 tuple 变成具名状态。requested_todo_id_for_decision 在 receipt 已绑定 Todo 时抑制新请求;retained_todo_id_for_decision 只有在没有请求、Todo binding 或 replan binding 时才暴露保留选择,保持原互斥关系。
  2. load_requested_quota_action_selection:80)从真实 runtime root 读取 exact Turn receipt,并只从现有 typed accessors 派生 Todo/replan/pending binding;identity_upgrade 仍来自既有 receipt details,而不是引入新状态。
  3. _apply_requested_quota_action_selection_preflight:131)保留最敏感的分支顺序:settled Todo identity 冲突先 fail closed;autonomous replan replay 与 identity-upgraded retained selection 分开;只有 exact current obligation、pending delivery 或合法 workspace repair 才可通过。拒绝时仍生成相同的 quota_action_selection_deferred|rejected、reason 与重入建议。
  4. reconcile_requested_quota_action_selection:294)把原来的“preflight 后再 recovery/retain”两段编排收敛成 ActionSelectionPreflightResult;只有 rejected 分支会触发 recovery 或 pending receipt append。
  5. handle_quota_commandquota.py:322,主要接线在 :389-479:573-686)仍然是公共命令 owner,且 selection binding 仍发生在 receipt reconcile/append/readback 之后。

对主干的风险

最强回归场景不是 import 失败,而是抽取后不小心改变 branch order:例如在 receipt identity 对账前绑定新 Todo,或让 retained selection 抢占新出现的 monitor/user gate。其影响会扩散到所有 heartbeat host,并可能把工作或 spend 归到错误 Todo。

我使用同一组五个公共 CLI/真实临时文件后端用例分别跑了 main@0ef7ebd749ec97a698a8fc7f2a29844dd368689b 与本 head,覆盖:未绑定 receipt 后选择新 Todo、未投影 Todo 拒绝、首次拒绝不得产生假 receipt、新 due monitor 抢占、以及新 user gate 抢占;两边都是 5/5 通过。head 上另外完整执行 action-selection conflict、heartbeat receipt 与 quota settlement CLI 套件,76 passed in 461.70s

仓库质量证据:changed-path Ruff 通过;CLI module-size smoke 通过;semantic-vocabulary drift smoke 通过;相关 boundary/replan/CLI diagnostics 测试通过;loopx canary premerge --from-git-diff 为 18/18 passed、0 manual hold;merge-tree 对当前 origin/main 无文本冲突。

语义与 CI 对齐

这个 PR 复用现有 action-selection/receipt 词汇,仅迁移 producer symbol;没有创建或扩展协议。语义注册表与 smoke 同步通过。需要说明的非阻塞 caveat 是:仓库配置的 mypy 只覆盖固定文件清单,新模块不在该清单;若把它作为孤立 strict target 并跳过 imports,会暴露 _requested_quota_action_todo_id 的一条 no-any-return,而同一 helper 在基线中已有相同类型形状,因此它不是这次抽取造成的运行时漂移,也不影响当前仓库必需检查的通过结论。PR 描述若保留“target Mypy passed”,建议补出确切命令,避免把不同检查口径混为一谈。

我的整体评价

没有阻塞性 finding。这个改动把已有、相互依赖的一组 quota CLI 适配规则搬到正确的内部 owner,同时保持 decision、receipt persistence、failure/retry 与公共输出的权威边界不变;规模与原问题相称,也没有为了将来可能的扩展引入框架或第二套状态。

未来向检查我认为本 PR 已经做了合适的 bounded refactor:具名 dataclass 取代 loose tuple,semantic producer anchor 随 owner 一起移动;继续抽象会开始跨越 quota decision/receipt 的既有边界,当前没有必要。残余风险主要是 focused suite 未枚举的 receipt/frontier 组合,但 76 项 settlement 回归、基线/head 公共入口对照和 18 项 risk-based canary 已把该风险压到可接受范围。

English verdict: APPROVE - head 92c5147; the extraction gives quota action selection a cohesive owner without changing decision or receipt authority, with 76 focused tests, baseline/head CLI parity cases, Ruff, semantic/module-budget smokes, and 18/18 premerge canaries passing.

@Duang777

Copy link
Copy Markdown
Contributor Author

@huangruiteng #4819 已合入后,我已用普通、带 Sign-off 的 merge commit 同步 main@09f10c4e3,当前 head 为 98e976ccf。上一轮两个失败断言现已包含主干修复。

本地 exact-head 复验:quota action-selection、settlement 与两条 priority 回归共 117 passed;Ruff、目标模块 Mypy、CLI 1000 行模块门禁通过;premerge 18/18 passed。远端 CI 已重跑,请复审。本 PR 不自合并。

huangruiteng
huangruiteng previously approved these changes Sep 20, 2026

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

动机

这个 PR 解决的是一个真实且持续增长的维护问题:loopx/cli_commands/quota.py 同时承担命令分派、状态读取、渲染/日志,以及显式 Todo 选择与 heartbeat receipt 对账,已经超过仓库现行的 1000 行 CLI owner 预算。相比直接抬高预算或豁免该文件,把“action selection + receipt adaptation”作为一个完整变化原因抽出,能够让后续 quota 修改更容易定位、验证和回滚。

我按当前 exact head 98e976ccff2ca41f9bfe5663a0326e2f0cf1960c 复核后,认为这不是为了过行数门禁而拆文件:新 owner 覆盖请求归一化、receipt 绑定读取、preflight、recovery、deferred retention 与最终 binding,形成了完整且已有生产调用方的边界;quota.py 保留 dispatch、status、stall writeback、rollout logging 与 rendering。该边界可独立审阅且没有新增用户协议、持久化字段或选择权限。

改动思路

入口仍是 handle_quota_command。它先通过 load_requested_quota_action_selection 把 CLI --todo-id 和同一 Turn 的 receipt 适配为 RequestedQuotaActionSelection,再把 receipt-bound/requested/retained 三种输入传给原有 build_live_quota_should_run_decision。live decision 仍是 eligibility/优先级的权威;新模块没有重建第二套决策。

live decision 返回后,reconcile_requested_quota_action_selection 保持原顺序执行:先校验 projected selection 与 receipt identity,再在 rejected/deferred 路径投影 recovery,必要时仅保留 pending_action_selection;只有 receipt reconcile/commit/readback 完成后,commit_requested_action_selection 才写入响应中的 selection_binding=heartbeat_receipt。失败和重试仍由既有的 typed error、recommended_actionhandle_quota_command 的 rendering/logging 负责。

我专门挑战了“这只是可达、但没有必要的新 helper”这一点。仓库搜索显示,新模块直接复用了 normalize_todo_id、heartbeat receipt typed accessors、QuotaActionSelectionConflictKindapply_action_selection_recovery 和 live decision;不存在第二个 eligibility、settlement 或 persistence owner。把预算提高或只拆一两个 helper 都会继续让 receipt 与 selection 的同一条状态机分散在 quota.py

具体改动

  • quota.py:删除原来内联的约 360 行 action-selection helper,改为持有一个 RequestedQuotaActionSelection,并在 live decision、automatic stall rebuild 和 receipt commit/readback 三处复用同一组绑定值。文件降到 779 行。
  • quota_action_selection.py:新增 415 行的内部 owner,集中处理请求规范化、receipt 读取、preflight、deferred retention 和结果适配。
  • vocabulary_v0.json:仅把既有 effective_action producer anchor 从旧文件路径迁移到新文件路径,没有新增词汇或改变语义。
  • test_quota_action_selection_conflict.py:把对私有 preflight helper 的直接导入迁到新 owner;断言语义未变。

关键代码讲解

  1. RequestedQuotaActionSelectionquota_action_selection.py:34)把过去相关的五元 tuple 变成具名状态。requested_todo_id_for_decision 在 receipt 已绑定 Todo 时抑制新请求;retained_todo_id_for_decision 只有在没有请求、Todo binding 或 replan binding 时才暴露保留选择,保持原互斥关系。
  2. load_requested_quota_action_selection:80)从真实 runtime root 读取 exact Turn receipt,并只从现有 typed accessors 派生 Todo/replan/pending binding;identity_upgrade 仍来自既有 receipt details,而不是引入新状态。
  3. _apply_requested_quota_action_selection_preflight:131)保留最敏感的分支顺序:settled Todo identity 冲突先 fail closed;autonomous replan replay 与 identity-upgraded retained selection 分开;只有 exact current obligation、pending delivery 或合法 workspace repair 才可通过。拒绝时仍生成相同的 quota_action_selection_deferred|rejected、reason 与重入建议。
  4. reconcile_requested_quota_action_selection:294)把原来的“preflight 后再 recovery/retain”两段编排收敛成 ActionSelectionPreflightResult;只有 rejected 分支会触发 recovery 或 pending receipt append。
  5. handle_quota_commandquota.py:322,主要接线在 :389-479:573-686)仍然是公共命令 owner,且 selection binding 仍发生在 receipt reconcile/append/readback 之后。

对主干的风险

最强回归场景不是 import 失败,而是抽取后不小心改变 branch order:例如在 receipt identity 对账前绑定新 Todo,或让 retained selection 抢占新出现的 monitor/user gate。其影响会扩散到所有 heartbeat host,并可能把工作或 spend 归到错误 Todo。

上一轮审阅使用同一组五个公共 CLI/真实临时文件后端用例分别跑了 main@0ef7ebd749ec97a698a8fc7f2a29844dd368689b 与旧 head 92c5147934340debfd72f7c5ca6b4b9962e76d08,覆盖:未绑定 receipt 后选择新 Todo、未投影 Todo 拒绝、首次拒绝不得产生假 receipt、新 due monitor 抢占、以及新 user gate 抢占;两边都是 5/5 通过。本次复审先做失效检查:当前 head 只是把 main@09f10c4e37b89c6ed25f2f2354f89d641662e83c 合入分支,quota.pyquota_action_selection.py、semantic vocabulary 和 direct unit test 四个 PR 自有文件的 blob id 与旧获批 head 完全一致,因此旧结论没有被 PR 自身改动推翻。

我仍在当前 exact head 上重新执行了 action-selection conflict、heartbeat receipt、quota settlement CLI 和此次主干合入涉及的 team-plan priority integration,结果为 91 passed in 488.15s;另有 semantic production/inventory/Python production 132 passed in 17.67s。这不是只凭“代码没变”复用旧审阅,而是把旧 head→新 head 增量和整个当前 diff 都重新落到了真实 CLI/临时文件 receipt 后端上。

仓库质量证据:changed-path Ruff 通过;CLI module-size smoke 通过;semantic-vocabulary drift smoke 通过;loopx canary premerge --from-git-diff 为 18/18 passed、0 manual hold;git diff --check 通过;merge-tree 1ce7936222a0b1bf338e1544321b06a57f0e407d 对当前 origin/main 无文本冲突;分支四个 commit 都带 DCO sign-off。能力契约设置 wait_for_ci=false,因此我没有等待或轮询仍在运行的远端 CI,也没有把 CI 作为本次 verdict 的替代证据。

语义与 CI 对齐

这个 PR 复用现有 action-selection/receipt 词汇,仅迁移 producer symbol;没有创建或扩展协议。语义注册表与 smoke 同步通过。需要说明的非阻塞 caveat 是:仓库配置的 mypy 只覆盖固定文件清单,新模块不在该清单;若把它作为孤立 strict target 并跳过 imports,会暴露 _requested_quota_action_todo_id 的一条 no-any-return,而同一 helper 在基线中已有相同类型形状,因此它不是这次抽取造成的运行时漂移,也不影响当前仓库必需检查的通过结论。PR 描述若保留“target Mypy passed”,建议补出确切命令,避免把不同检查口径混为一谈。

我的整体评价

没有阻塞性 finding。这个改动把已有、相互依赖的一组 quota CLI 适配规则搬到正确的内部 owner,同时保持 decision、receipt persistence、failure/retry 与公共输出的权威边界不变;规模与原问题相称,也没有为了将来可能的扩展引入框架或第二套状态。

未来向检查我认为本 PR 已经做了合适的 bounded refactor:具名 dataclass 取代 loose tuple,semantic producer anchor 随 owner 一起移动;继续抽象会开始跨越 quota decision/receipt 的既有边界,当前没有必要。残余风险主要是 focused suite 未枚举的 receipt/frontier 组合,但 91 项 exact-head settlement/priority 回归、132 项 semantic 检查、旧/新 head blob 等价性和 18 项 risk-based canary 已把该风险压到可接受范围。

English verdict: APPROVE - head 98e976c; the extraction gives quota action selection a cohesive owner without changing decision or receipt authority, with all PR-owned blobs unchanged from the prior approved head, 91 exact-head focused tests, 132 semantic tests, Ruff, semantic/module-budget smokes, and 18/18 premerge canaries passing.

…dule-budget

Reconcile the quota action-selection extraction with main's post-refactor
preflight: keep the extracted quota_action_selection owner (typed
RequestedQuotaActionSelection + ActionSelectionPreflightResult) and adopt
main's delegated admission and recovery construction
(current_action_selection_admission, build_action_selection_recovery_fields,
bind_action_selection_recovery_command) instead of the retired
apply_action_selection_recovery helper.

Signed-off-by: LoopX Agent <agent@loopx.local>

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

Exact head: d67590c4c0961b573d8f94f82395c3c554f41f89(merged origin/main@997294303

动机

loopx/cli_commands/quota.py 已经越过仓库 1000 行 CLI 命令模块预算。更难的是:当前 main 在这条门禁上就是红的——我在一个干净的 origin/main worktree 上复现:

AssertionError: quota.py has 1023 lines, above budget 1000; extract a cohesive command owner before adding more code

同时,action-selection 的准入判定在 CLI 里被复制了一份(selection_binding / pending_selection_delivery_qualified / pending_selection_workspace_repair_qualified / exact_current_obligation_qualified),和 loopx/control_plane/work_items/action_selection_contract.py 里的真实 owner 是同一套语义。本 PR 用一个内聚的命令 owner 模块同时解决这两件事:把预算修回去,并删掉重复的判定规则。

改动思路

按"文字搬迁 + 语义归位"来拆:

  1. 搬走请求归一化(_requested_quota_action_todo_id)、receipt 读取与绑定(原五元组 _heartbeat_quota_action_selection_bindings)、准入 preflight、拒绝字段绑定、未提交 receipt 标注、已提交选择投影、deferred 保留,全部进入新模块。
  2. 留在 quota.py:命令分发、状态收集、monitor writeback、rollout 记录、渲染——即"传输与展示"的部分。
  3. 顺手收紧类型:用冻结的 RequestedQuotaActionSelection 取代互相关联的五值元组,用 ActionSelectionPreflightResult 取代"bool + 四处散落的 receipt 变量",把 requested_todo_id_for_decision / retained_todo_id_for_decision 变成具名属性,handle_quota_command 不再在每个调用点重算一次 requested id。

具体改动

新 owner:loopx/cli_commands/quota_action_selection.py(314 行)

  • load_requested_quota_action_selection:仅在 --codex-app / --trae-app / guided runtime profile 下读取 --todo-id,并把当轮 heartbeat receipt 折叠成一个不可变读模型(含 settlement_receipt_revision == "identity_upgrade")。
  • _requested_quota_action_selection_preflight:判定顺序保持——receipt 绑定身份冲突 → 抛 HeartbeatReceiptIdentityConflictError;replan 绑定且未发生身份升级 → 视为 settled replay;升级后请求了不同 Todo → 抛 retained-selection 冲突;被准入 → None;缺 qualification → UNQUALIFIED;qualification 不在 {deferred, rejected}CONFLICT
  • reconcile_requested_quota_action_selectionpayload.update(recovery)bind_action_selection_recovery_command(重写 cli_channel.next_cli_actionsagent_channel.primary_action)→ deferred 保留 → 返回 ActionSelectionPreflightResult
  • attach_uncommitted_action_selection_receipt / commit_requested_action_selection:把 heartbeat_receipt.status=not_committedselection_binding=heartbeat_receipt 的投影保留在搬运后的位置,调用点不变。

loopx/cli_commands/quota.py 1114 → 779 行:只保留 handle_quota_command_record_automatic_heartbeat_stall、渲染/失败上报等职责,调用新模块的五个入口;_record_automatic_heartbeat_stall 直接接收 typed selection,不再传四个字符串。

合并时的语义归位(这是本 head 的关键差异)

本 PR 原 head 98e976ccf 早于 mainecb84c4ae / e3d101e6e。那两个提交把准入规则移入 contract owner,删除了 apply_action_selection_recovery,并让 preflight 返回 recovery 字段而不是 bool。因此合并不能机械取一侧,我把 main 的新语义移植进被抽出的模块:

  • 准入改为 current_action_selection_admission,拒绝字段改为 build_action_selection_recovery_fields,绑定改为 bind_action_selection_recovery_command;模块内那份约 110 行的重复判定块被删除,不再存在第二个规则 owner。
  • 同步更新两处测试导入(test_quota_action_selection_conflict.pytest_unadmitted_selection_construction.py),并保留 mainis None 期望。
  • loopx/semantics/vocabulary_v0.json 的 producer anchor 最终不需要改动:main 已把 quota_action_selection_deferred/rejected 的产者登记为 contract 的 build_action_selection_recovery_fields,合并后与 main 一致(drift smoke 通过)。

净 diff(对 main):quota.py −299/+55、新模块 +314、两个测试各 4 行。

两条路径的验收:准入路径——请求的 Todo 被准入时不改 payload、receipt 以 replayed 复用,commit_requested_action_selection 只在 receipt 对账之后打 selection_binding=heartbeat_receipt拒绝路径——payload.update(recovery) 关闭 spend_after_validation / safe_bypass_allowed / 各类 delivery 授权,再绑定一条不含 --todo-id 的恢复命令,deferred 时追加一条待选 Todo 供下一轮读回。

对主干的风险

  • 最低风险面:无新增 CLI flag、无新增持久化字段、无 schema/receipt 形状变化;新模块的五个入口各只有一个生产调用点(rg 全仓确认无其他导入)。回滚就是普通 revert:语义移植只有一个函数。
  • 已验证test_quota_action_selection_conflict.py + test_unadmitted_selection_construction.py 18 passed;再加 heartbeat receipt 与 settlement CLI 共 90 passed(含作者声明的 76 条集合与 main 新增用例);tests/architecture/test_semantic_vocabulary_drift.py 114 passed;semantic-vocabulary-drift-smoke.py ok(26/26 vocabularies、51/51 owner symbols);cli-command-module-size-ownership-command-modularization-smoke.py ok;Ruff clean;loopx canary premerge --from-git-diff --git-diff-base origin/maingate.status=passedself_merge_allowed=true、0 failures、0 manual holds(3 项 direct diff/compile、maintainability ratchet、10/10 catalog canary、8/8 risk-profile smoke)。
  • 未验证:新 head d67590c4c 的远端 CI 复核在发布本评审时仍未跑完(此前绿灯属于 98e976ccf),这是本 head 最强的证据缺口;另外本轮的验证是单元 + settlement CLI + 公共 smoke 层,未跑真实 runtime root 的整轮 heartbeat 宿主 turn,也未覆盖 PostgreSQL authority 路径。
  • 非阻塞 P3attach_uncommitted_action_selection_receiptcommit_requested_action_selection 本质是 receipt/payload 投影(receipt 的 owner 是 loopx/control_plane/quota/heartbeat_receipt.py),留在 CLI owner 里意味着将来改 receipt 形状时多一处要记得同步。建议后续再做一次有界搬迁,由既有 test_quota_settlement_cli.py 断言保护,不必在本 PR 内扩展。
  • 重复度说明:本 PR 的主要价值就是消重——合并前的分支 head 拥有一份与 contract 并行的准入实现;本 head 只保留 contract 一个 owner,CLI 侧退化为输入适配、preflight 调用、拒绝绑定与 deferred 保留。

我的整体评价

方向正确、边界清晰:它把一个语义敏感的 CLI 流程从"超预算 + 双份规则"收敛成"一个 typed owner + 一个规则来源",并且顺手把 main 当前红灯的模块预算门禁修好,不需要任何预算例外。合并期的语义归位处理得当——没有把 main 已落地的 owner 覆盖回旧实现,也没有留下死符号。

结论:APPROVE。在 d67590c4c 这个 exact head 上无阻塞问题;发布前仍建议等该 head 的远端 required checks 跑绿,再按维护者流程合并。


English verdict: APPROVE - Reviewed exact head d67590c (merged up to origin/main@997294303). The extraction is a cohesive, behavior-preserving ownership move (quota.py 1114 -> 779 lines, new 314-line owner) that repairs a currently red required gate on main ("quota.py has 1023 lines, above budget 1000") without a budget exception; the merge correctly ports main's newer admission owner (current_action_selection_admission / build_action_selection_recovery_fields / bind_action_selection_recovery_command) instead of the retired apply_action_selection_recovery, deleting ~110 lines of duplicated admission rule and leaving no second decision owner. Validation: 18 passed (two direct suites) and 90 passed (plus heartbeat receipt + settlement CLI), 114 passed vocabulary architecture suite, semantic-vocabulary-drift smoke ok, CLI module-budget smoke ok, ruff clean, and the exact-diff canary premerge gate passed with 0 failures and 0 manual holds. One non-blocking P3: the two receipt/payload projection helpers still live in the CLI owner and are better placed with the receipt owner later. Residual risk: remote CI for this new head was not finished at publication time, and no full live host heartbeat turn was exercised.

@huangruiteng
huangruiteng merged commit 855c8ca into loopx-project:main Sep 21, 2026
15 of 20 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.

2 participants