Repository navigation
perf(quota): load subcommand owners on demand - #7739
Conversation
Native context and replan-view return before any authority read, yet the quota handler eagerly imported status, quota planning, live decisions, Lark inbox, upgrade and capability hooks. Resolve those owners on first use through a module-level export table so patches on the handler module stay effective, and defer renderer, reward-memory and composition-frontier imports to the branches that need them. Authority, scheduling, settlement, defaults and output are unchanged. Signed-off-by: lusendong.6789 <lusendong.6789@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com>
|
Additional parity on the rebased head |
songoow
left a comment
There was a problem hiding this comment.
Reviewer: model_agent — GPT-6 Astra Pro — OpenAI — self_reported
动机 / Motivation
反复运行 quota status、plan、context-read、should-run 和具体写动作的 CLI 用户与自动执行器,目前都先加载无关的完整 quota owner 图。
原来导入 quota façade 就会导入所有子命令 owner;本 PR 让每个动作在真正调用时解析原 owner,并把 monitor、presentation、reward 的分支依赖留在所属分支。实际准入、结算和显示规则继续复用既有实现。
真实 File/SQLite 的每版本 28 次 CLI 调用在完整规范化输出、诊断与退出码上相同;例如 context-read 的 LoopX 模块数由 425 降到 61。这里验证的是无关导入减少,未宣称固定延迟或模型费用下降。
本次不改 quota 决策、读写范围、回执身份或外部执行权限,不新增缓存或 provider;也不声称整个 CLI、完整 CI 或长期模型性能已取得资格。
改动思路 / Approach
这个 façade 只负责把名字送到已有 owner,不承担准入、结算或状态判断。按需解析降低轻量命令的启动依赖,同时保留公开属性及动态替换约定;monitor、presentation 和 reward 的局部导入继续放在真正消费它们的边界。
范围是一个已有 quota façade 与三个辅助模块的依赖加载方式,以及真实入口回归。没有增加新的工作状态、权限、读回格式或恢复流程。
公开入口仍把动作分派到原函数;区别是需要哪个名字才加载哪个模块。_export 在实际调用时解析模块当前属性,避免破坏原替换接口。监视、呈现与 reward 的附属依赖只在原分支内出现,后续回执验证和失败行为仍由原实现决定。
所有目标函数原本已有模块和语义 owner。有限映射只延迟取出这些原对象,_export 在调用时读取 façade 上的现值,保留已有替换 seam;没有复制业务函数、包装另一套规则或构造全局 domain cache。
具体改动 / Changes
关键代码讲解
- getattr:按名字取得原 owner 对象。只解析有限映射中的原函数并缓存模块属性;不存在的名字仍报 AttributeError,旧 helper 别名继续指向原实现。
- _export:维持调用时的 façade 兼容性。每次调用读取模块上的现值,既沿用延迟加载,也保留既有调用方或测试对公开 helper 的替换;不提前固化另一份函数。
- handle_quota_command:沿用子命令分派。原参数、动作顺序和错误 owner 不变,只把 eager-import 名称替换为按需解析的同一函数。
- record_quota_monitor_poll_for_cli:缩小分支依赖的加载范围。monitor 路径继续使用原轮询与回执 owner;相关依赖留到实际需要该分支时导入,未把轮询结果变成准入依据。
规范基准:docs/quota-allocation.md;修订 8d48efa。按基线现有 Product Scope 与 Read-only observation scope 段落判断。下面使用原段落定位标签,不把导入优化扩张为新的 quota 或控制器协议交付。
| Criterion | 当前结论 | 对应实现或剩余边界 |
|---|---|---|
| Read-only observation scope | implemented | handle_quota_command dispatches to unchanged status/plan/readback owners |
| Product Scope | implemented | Existing quota, spend, void, monitor, scheduler and should-run owners resolved on demand |
| Existing façade compatibility | implemented | _LAZY_EXPORTS, getattr, _export and original helper alias |
实际验证 / Validation
本轮在 base 和 exact head 分别执行 projection、reward memory、monitor poll runtime 三个既有模块,各 100 个案例全部通过;另跑 head 的 6 个 quota selected-entrypoint 案例,覆盖延迟导入、原函数身份与动态替换。没有把作者历史 1151 个测试统计当成本轮结果。
每个版本额外执行 28 次真实公开 CLI,覆盖 File/SQLite 的 context-read、replan-view、status/plan、JSON/Markdown、spend、void、monitor、scheduler、should-run ordinary/envelope 和未知 Goal。完整规范化输出、诊断与退出码一致,SHA256 824ab45c41db902db7a1455ef7b42476bd3b66a86928be1bc2cce2a9802dae69;临时路径、生成身份和时钟之外未丢语义。File 上 context-read/replan 的 LoopX 模块数 425→61,status/plan 516→442,should-run 562→557。实际 context-read 的无关 owner 缺席断言在 base 失败、head 通过,这比单独检查 map 更有区分力。
对主干的风险 / Risks
主要风险在旧公开属性、动态替换与少见动作的延迟依赖;不是只看导入数字即可排除。已核对完整映射、调用方和别名,并执行包含真实拒绝路径的 base/head 配对与既有 consumer 测试。未发现阻断性实现问题;没有将保留重型依赖的 should-run 误报为优化失败,也没有夸大为全链路延迟保证。
语义与 CI 对齐
基线 quota 文档的读范围、权限和结算职责保持,完整 instruction/diagnostic 配对没有发现漂移;没有靠删判断或删返回字段达到数字目标。
当前远程 dashboard-browser(2) 在 goal-workspace-m2.mjs:206 的既有 1 秒 loaded-lens 切换预算失败,日志样本含 1515.93 ms;aggregate checks 红,其他分片未完成。该页面检查不在此改动的源码边界内,但本轮没有同负载 browser 基线证明,故保留未归因的合并风险,而非宣称历史失败已排除。
当前阻断是验证缺口,不是凭红灯虚构的代码 finding。 仓库当前 verdict_policy 明确未归因的 current failures 阻止批准;仅证明变更文件不在失败路径,尚不足以归类 pre_existing。最小解除条件是对上述具体失败提供不可变 base/head 的同命令、同签名对照,或独立证明外部/环境原因并补齐受影响合同的当前资格;若归因确属回归,再修相应代码。本轮不要求为未归因失败修改无关代码,也不放宽已有预算。
我的整体评价 / Verdict
REQUEST_CHANGES:未发现阻断性的代码缺陷;当前 CI 失败尚缺政策要求的归因证据,因此暂不具备批准资格。 审查绑定 exact head fbbacc8。
长期自动循环依赖原 quota 判定、回执恢复和失败诊断;这些规则继续由原 owner 负责。轻量读取减少重复导入且不新增同步状态,因此不会把性能优化换成另一套结算语义。
原命令、诊断、Markdown 和 JSON 结果保持,用户无需改操作顺序。收益是常用轻量读取不必加载完整决策图;对于确实需要 live decision 的 should-run,仍保留它所需的完整依赖。 改动仅为 CLI 分派与导入,不涉及页面或视觉交互。
有限映射和调用时解析足以保留旧 façade,不需要增加通用插件框架或重新划分 owner。剩余 should-run 仍加载重型决策图是它的职责;不应为追求导入数字而截掉所需判断。
这里只证明实际覆盖路径上的导入缩减与语义保持,未测模型采用、完整冷启动分布或生产长期成本。远程 browser 预算仍失败,其基线归因未完成;其余 CI 未结束,不能把局部通过写成全仓合格。
English verdict: REQUEST_CHANGES — exact head fbbacc8; Current required CI failures lack the repository-required attribution, so approval is withheld. No blocking code defect was found in the exercised change; resolve the named validation gap rather than changing unrelated code.
…ading-20261030 Signed-off-by: huangruiteng <huangrt01@163.com> # Conflicts: # loopx/cli_commands/quota.py
|
Attribution for the failing The CI failure occurred in This supports a cumulative browser-shard timing flake, not a behavior change from the quota demand-loading patch. No browser timeout or assertion is relaxed here. The failed GitHub job can only be rerun after the currently pending long test shards make the workflow terminal. |
songoow
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; GPT-6; OpenAI; self_reported.
动机 / Motivation
受影响的是执行quota轻量context和replan读取的Agent命令进程。这些命令在到达提前返回分支之前曾加载完整决策与能力图;本项把无关所有者推迟到实际需要。源码保留原业务处理器,并通过显式lazy export映射维持原模块patch点和对象归属。本项不缩减should-run所需的决策规则,不修改quota、scheduler或settlement语义。
这次判断绑定PR #7739的完整head 2c0c4cb。评价对象是已经存在的实际调用任务与局部可观察结果;重复调用带来的成本或错误恢复路线是本项动机,不能把较小响应或更少导入直接等同于长期任务质量。
改动思路 / Approach
以有限_LAZY_EXPORTS与_export调用解析原模块对象,局部导入仅移到实际分支;TYPE_CHECKING类型不再扩大运行时依赖。本 PR 的合理边界是quota facade与presentation/reward hook导入时机,实际业务owner没有迁移或复制。
沿入口跟踪到原所有者、返回值和失败恢复后,这个实现仍在现有边界上处理问题。无改动会保留原成本或错误指引;另起一套业务规则、持久化状态或通用缓存会增加同步义务,此处没有这类必要性。新增说明和投影应服务原调用方完成任务,不能改变原来的准入、权限、结算或来源完整性要求。
具体改动 / Changes
关键代码讲解
- _export:从当前模块取对象,保留测试/调用方对原facade的patch语义。 输入与拒绝分支沿用现有调用路径;这一处的返回内容或依赖时机改变,不把局部投影提升为新的业务判定。
- handle_quota_command:仍按原subcommand调用同一decider、settler与monitor owner,轻量分支可以提前返回。 输入与拒绝分支沿用现有调用路径;这一处的返回内容或依赖时机改变,不把局部投影提升为新的业务判定。
- _quota_renderer:只有需要输出quota视图时才加载原renderer,不发明另一套输出模板。 输入与拒绝分支沿用现有调用路径;这一处的返回内容或依赖时机改变,不把局部投影提升为新的业务判定。
输出模板、默认参数和业务函数保留;迁移的是依赖加载时间,完整运行时基线/当前对照需明确其覆盖边界。正向场景是:轻量读分支不需要加载未使用能力,实际quota命令仍解析到原所有者。负向场景是:实际context-read/replan-view不加载未用owner;公开导出仍为原对象,既有动态替换点继续工作。这些是依据实际源码与已有调用测试核对的行为边界;失败和恢复继续由原owner负责,没有以返回字段存在代替真实状态读取。
规范依据为原公开调用行为、既有所有者和相应回归;已检索改动路径与周边文档,没有为这次局部性能/适配修正找到另一个已接受专项RFC。作者的量测叙述不充当独立功能合同。
实际验证 / Validation
7项CLI quota/facade回归 PASS(96 deselected),覆盖lazy export身份和实际轻量CLI入口;Python编译与 diff hygiene PASS。
执行命令:python -m pytest -q tests/test_cli_entrypoint.py -k 'quota or turn_facade'。本轮统计只包含上述实际执行;作者PR内微基准、旧head完整回归和旧review的历史量测都已阅读,但不冒称本轮重新执行的结果。
对主干的风险 / Risks
输出模板、默认参数和业务函数保留;迁移的是依赖加载时间,完整运行时基线/当前对照需明确其覆盖边界。最需要防止的情况是:实际context-read/replan-view不加载未用owner;公开导出仍为原对象,既有动态替换点继续工作。已核对相关调用方和已有review,未重复发布旧head意见;本轮对新增head的源代码与局部回归单独作判断。原持久化状态和业务所有者保持,仍然不能由小范围通过推断整仓或所有部署入口已经合格。
当前精确head失败证据:test-shard (3)、chat-bundle-browser (2)。当前test-shard失败日志未返回;作者对research-display-language已有固定base/head单场景通过证据,但它不能替代无法读取的其他当前失败。 未取得的分片日志明确留作未知;同名错误或改动文件不相交都不足以建立pre_existing归因。
最小补齐是针对当前实际失败取得日志,并提供不可变base/head同命令同条件归因,或能独立覆盖该失败不变量的当前真实入口证据。已完成的聚焦回归不应无条件重做,也不要求无关功能重写;如果归因确认是回归,再修相应最小代码路径。未完成的检查不是单凭pending就要求改代码的理由。
我的整体评价 / Verdict
REQUEST_CHANGES:当前阻断是具体的验证证据缺口。聚焦审查尚未发现可复现的阻断性生产代码缺陷,不能把未归因红灯写成代码finding。 审查仅适用于exact head 2c0c4cb。
本 PR 的合理边界是quota facade与presentation/reward hook导入时机,实际业务owner没有迁移或复制。 源码保留原业务处理器,并通过显式lazy export映射维持原模块patch点和对象归属。 已检查 loopx/cli_commands/quota.py:_export;loopx/cli_commands/quota.py:handle_quota_command;loopx/cli_commands/quota_presentation.py:_quota_renderer;变更是CLI/内部读取或文本协议,没有修改浏览器页面布局,视觉截图不适用。
当前test-shard失败日志未返回;作者对research-display-language已有固定base/head单场景通过证据,但它不能替代无法读取的其他当前失败。 本项不缩减should-run所需的决策规则,不修改quota、scheduler或settlement语义。所有本轮探针使用合成fixture,没有运行真实模型任务或发起业务作业;本review陈述审查与验证事实,不声称已经发布部署或完成合并。
English verdict: REQUEST_CHANGES — exact head 2c0c4cb. Focused code review and the listed local regressions found no confirmed blocking implementation defect. Approval is held for the named current validation gaps; resolve their source-bound evidence rather than changing unrelated code.
Summary
quota context-readandquota replan-viewreturn before any authority read, but importing the quota handler eagerly pulled in status collection, quota planning, live decisions, the Lark inbox, upgrade, and several capability hooks. This PR makes the quota subcommands load those owners only when a route needs them:loopx/cli_commands/quota.py: authority, decision, and capability owners resolve through a module-level_LAZY_EXPORTStable. Call sites use_export(name), somonkeypatch.setattr(quota_module, ...)keeps working, and__getattr__and__dir__preserve attribute access and export identity. The turn-start Lark hook, goal-ref helpers, and the settlement-attachment projection now import inside the branch that uses them.quota_presentation.py,quota_reward_memory.py,quota_monitor_poll.py: renderer, compaction, reward-memory, and composition-frontier imports move into the functions and branches that use them. Type-only imports move underTYPE_CHECKING.Authority ownership (TS lease/CAS), scheduling, settlement, defaults, and output are unchanged.
handle_quota_commandkeeps its statement count.Measurements
These are paired fresh-process probes against the exact base
a2c8c940c, the parent before the final rebase; the rebase touched none of these files, using synthetic fixtures only.modscounts importedloopx.*modules.loopx.cli_commands.quotacontext-read(5 runs)replan-view(5 runs)status(10 interleaved runs)planspend-slotvoid-slotmonitor-pollscheduler-ackshould-runAccounting routes (
status,plan,spend-slot,void-slot,monitor-poll) no longer loadlive_decision,upgrade,periodic_report.pending_intent, orrepository_change_window.should-runstill needs nearly the full composition, as expected.I only report status wall time from the interleaved A/B run. The other accounting routes were measured sequentially on a loaded machine, and their wall-time differences were inside the noise, so the import counts are the reliable signal for them.
Behavior parity
Each of 14 quota invocations (
context-read,replan-view,status,plan,status --format markdown,spend-slotdry-run,spend-slotwithout a Todo,void-slot,monitor-poll,scheduler-ack,should-runJSON/markdown/--turn-envelope, unknown Goal) was run against the same fixture on the base and on the new head. After normalizing fixture-random revisions, ids, and timestamps, all 14 have identical exit codes and identical JSON structure. The only remaining differences arestaleness_seconds(wall-clock dependent, ±1 s) and the timestamp in the spend-record filename.Tests
tests/test_cli_entrypoint.pyadds 4 cases. All 4 fail on the base and pass on this head:context-readandreplan-viewskip those owners. Each keeps selected-versus-full stdout/stderr parity, leaves the registry untouched, and creates no runtime;spend-slot(dry-run),void-slot, andmonitor-pollskip the should-run-only composition.Validation
ruff checkon the changed files: passed.examples/cli-control-plane-command-modularization-smoke.py: passed.8d48efabb):tests/test_cli_entrypoint.py,tests/control_plane/test_quota_*.py,tests/cli_commands/test_quota_*.py, progressive native context, selection replan re-entry, control-plane import boundaries and the maintainability ratchet ran with 1151 passed, 1 failed. The failure,test_selection_replan_reentry.py::test_native_first_selection_publishes_only_final_bound_capture, also fails on base8d48efabbwithout this change. An earlier run ona2c8c940cthat also included Codex context lifecycle and registry-independent context capture had 1321 passed. Its 5 failures all also failed on that base: the one above, plus thetest_receipt_retry_keeps_open_vision_quiet_through_real_clicases that the current base has since fixed.loopx canary premerge --from-git-diff(run on the pre-rebase head; the rebase onto8d48efabbchanged none of these files): passed (6 direct checks, 18 selected catalog/risk-profile smokes; 0 failures, 0 warnings, 0 manual holds; surfacescontrol_plane,python; profilescore-control-plane,canary-runner). The first run failed only becausesemantic-vocabulary-drift-smoke.pyneeds the TypeScript dev dependencies; after a localnpm ci --ignore-scriptsit passed with nothing else changed.Follow-up and future-facing pass
TYPE_CHECKING, and the module boundaries stay unchanged. No new modules or wrappers.spend-slot,void-slot, andmonitor-pollstill loadreward_memory, becauseloopx/quota.pycalls_resolve_reward_memory_experiment_from_statusfromshould_run_prepare. Deferring that belongs to theloopx/quota.pyowner and is left for a separate change.Runtime self-merge is not requested; this needs ordinary review.