refactor(quota): unify typed capability resolution and repair bindings - #4254
Conversation
…ecisions Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-review)
复审绑定 exact head:057d8c09ad333f905a555f03dfa46d2ef22479e8。结论:APPROVE。
动机
这个 PR 解决的是 capability gate 的重复决策权:Python 过去分别计算 missing capabilities、repair owner、resolution bindings,quota 又消费 Python 预计算出的 Monitor missing 列表。这样的多处 rule ownership 会让同一组 Todo/availability facts 在不同入口产生语义漂移;已有的三个具体症状是共享 binding 依赖展示顺序、同一 Todo 的展示变体可能重复计数,以及显式空 backlog 仍可能复活 stale first item。
把这些纯决策统一到 TypeScript owner 是合适的 T3 迁移切片。关键产品边界也保持清楚:target_capabilities 是 repair 输出,不是当前可用能力或权限授予;credentials/production access 仍路由给用户,其余缺口才是 Agent repair;存在 capability gap 的 Todo 也不能压住独立可运行工作。
改动思路
agents/capability_gate.ts 统一拥有 missing-set、action/owner resolution 和 impacted-Todo bindings,todos/quota_selection.ts 的 v1 请求从 normalized requirement facts 与 observed availability 原地复算 Monitor 分区。Python 只保留 legacy source/eligibility/profile 的适配和一个以完整 missing tuple 为 key 的有界纯值缓存,不再悄悄重建第二套决定逻辑。
兼容边界是可审的:v0 planning 输入仍保留;新规则不写 canonical Todo、不改变 availability、不 claim/lease,也不隐式 enable capability。三个行为修正都在 PR 描述和协议文档中明确披露,不是藏在“纯重构”名下的 silent default change。
具体改动
真实 base fa57253a7888a33eb98b3b6d49d69726f54e5034 到 head 为 13 个文件、+416/-380;生产代码净减少约 193 行,新增量主要是 parity/regression tests 与协议说明。
关键代码讲解
missingRequiredCapabilities:把 required、target 与 available 明确分开;repair Todo 可以把自己的 target 当作本 Todo 的修复前提,但 target 不能替另一个 Todo 宣称已经安装或授权。bindings:聚合 blocked candidates 时按 typed priority 选 primary Todo,同时保留完整 identity;反转输入顺序的回归用例证明 P0 不再被展示顺序覆盖。- Python
build_capability_gate:把 source/eligibility facts 批量适配给 typed evaluator;同 Todo ID 去重,并把显式空 evaluated backlog 当作权威空集。 - quota
decodeRow:v1 必须携带 availability,并调用共享 missing-set rule;v0 继续接受既有 precomputed 形状。
我在 exact head 上运行了 48 个 focused Python tests、13 个 focused TypeScript tests,以及完整 control-plane TypeScript suite:1,130 passed / 1 platform skip / 0 failed。typecheck:control-plane、Ruff 和 git diff --check 均通过;四个 hosted test shards、Stage2c e2e/mutants/installed、DCO 与 builds 也都通过。真实 markdown/file/sqlite quota CLI 路径覆盖了 availability 开关、provider/source、owner/Agent repair 和不写状态的边界。
对主干的风险
未发现 branch-attributable blocker。当前 aggregate checks / pytest / merge-gate 仍为红,但失败日志只包含 decision_scope.py 的 7 个 no-any-return;我对 exact base 与 head 分别执行 mypy,得到完全相同的 7 个错误,因此这是共享基线问题,不是本 PR 引入。这个 approval 不把红色 required rollup 解释为 merge-ready;合并前仍应在基线修复后重新确认 required checks。
剩余风险是私人 snapshot parity 与 paid-model soak 本轮没有独立重跑;对于本次 read-only typed rule,真实 CLI provider matrix、完整 TS suite 和 hosted shards 已经提供了足够的可归因证据。
Future-facing pass:边界已经是合适的最小形状——typed TypeScript 决策 owner、Python source adapter、无持久化迁移。后续只应在真实 caller 随 parity 迁移时继续删除 adapter,不需要再造 capability/provider 或参数化的泛化层。
我的整体评价
这不是为了“有 TypeScript”而搬代码,而是用净删生产代码的方式消除一项会在 quota/Monitor/repair 热路径反复漂移的规则所有权。三个细微语义修正都有反例、真实 caller 覆盖和清晰的 authority 解释;默认关闭与权限边界也成立。因此我批准这个 exact head,同时保留“required rollup 修复后再判定 merge readiness”的独立门槛。
English verdict: APPROVE on exact head 057d8c09ad333f905a555f03dfa46d2ef22479e8. The PR consolidates missing-capability, resolution-owner, binding, and quota Monitor decisions in the typed TypeScript owner while keeping Python as a bounded source adapter. It fixes priority-order, duplicate-identity, and explicit-empty-source semantics without granting capabilities or mutating Todo/lease state. Forty-eight focused Python tests, 13 focused TypeScript tests, the full 1,130-pass control-plane suite, typecheck, Ruff, diff check, all hosted shards, and Stage2c passed. The remaining red rollup is the same seven decision_scope.py mypy errors reproduced on the exact base, so it is not attributable to this branch, but merge readiness must still be rechecked after that shared baseline is repaired.
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
复审绑定 exact head:057d8c09ad333f905a555f03dfa46d2ef22479e8。结论:APPROVE。
动机
这个 PR 解决的是 capability gate 的重复决策权:Python 过去分别计算 missing capabilities、repair owner、resolution bindings,quota 又消费 Python 预计算出的 Monitor missing 列表。这样的多处 rule ownership 会让同一组 Todo/availability facts 在不同入口产生语义漂移;已有的三个具体症状是共享 binding 依赖展示顺序、同一 Todo 的展示变体可能重复计数,以及显式空 backlog 仍可能复活 stale first item。
把这些纯决策统一到 TypeScript owner 是合适的 T3 迁移切片。关键产品边界也保持清楚:target_capabilities 是 repair 输出,不是当前可用能力或权限授予;credentials/production access 仍路由给用户,其余缺口才是 Agent repair;存在 capability gap 的 Todo 也不能压住独立可运行工作。
改动思路
agents/capability_gate.ts 统一拥有 missing-set、action/owner resolution 和 impacted-Todo bindings,todos/quota_selection.ts 的 v1 请求从 normalized requirement facts 与 observed availability 原地复算 Monitor 分区。Python 只保留 legacy source/eligibility/profile 的适配和一个以完整 missing tuple 为 key 的有界纯值缓存,不再悄悄重建第二套决定逻辑。
兼容边界是可审的:v0 planning 输入仍保留;新规则不写 canonical Todo、不改变 availability、不 claim/lease,也不隐式 enable capability。三个行为修正都在 PR 描述和协议文档中明确披露,不是藏在“纯重构”名下的 silent default change。
具体改动
真实 base fa57253a7888a33eb98b3b6d49d69726f54e5034 到 head 为 13 个文件、+416/-380;生产代码净减少约 193 行,新增量主要是 parity/regression tests 与协议说明。
关键代码讲解
missingRequiredCapabilities:把 required、target 与 available 明确分开;repair Todo 可以把自己的 target 当作本 Todo 的修复前提,但 target 不能替另一个 Todo 宣称已经安装或授权。bindings:聚合 blocked candidates 时按 typed priority 选 primary Todo,同时保留完整 identity;反转输入顺序的回归用例证明 P0 不再被展示顺序覆盖。- Python
build_capability_gate:把 source/eligibility facts 批量适配给 typed evaluator;同 Todo ID 去重,并把显式空 evaluated backlog 当作权威空集。 - quota
decodeRow:v1 必须携带 availability,并调用共享 missing-set rule;v0 继续接受既有 precomputed 形状。
我在 exact head 上运行了 48 个 focused Python tests、13 个 focused TypeScript tests,以及完整 control-plane TypeScript suite:1,130 passed / 1 platform skip / 0 failed。typecheck:control-plane、Ruff 和 git diff --check 均通过;四个 hosted test shards、Stage2c e2e/mutants/installed、DCO 与 builds 也都通过。真实 markdown/file/sqlite quota CLI 路径覆盖了 availability 开关、provider/source、owner/Agent repair 和不写状态的边界。
对主干的风险
未发现 branch-attributable blocker。当前 aggregate checks / pytest / merge-gate 仍为红,但失败日志只包含 decision_scope.py 的 7 个 no-any-return;我对 exact base 与 head 分别执行 mypy,得到完全相同的 7 个错误,因此这是共享基线问题,不是本 PR 引入。这个 approval 不把红色 required rollup 解释为 merge-ready;合并前仍应在基线修复后重新确认 required checks。
剩余风险是私人 snapshot parity 与 paid-model soak 本轮没有独立重跑;对于本次 read-only typed rule,真实 CLI provider matrix、完整 TS suite 和 hosted shards 已经提供了足够的可归因证据。
Future-facing pass:边界已经是合适的最小形状——typed TypeScript 决策 owner、Python source adapter、无持久化迁移。后续只应在真实 caller 随 parity 迁移时继续删除 adapter,不需要再造 capability/provider 或参数化的泛化层。
我的整体评价
这不是为了“有 TypeScript”而搬代码,而是用净删生产代码的方式消除一项会在 quota/Monitor/repair 热路径反复漂移的规则所有权。三个细微语义修正都有反例、真实 caller 覆盖和清晰的 authority 解释;默认关闭与权限边界也成立。因此我批准这个 exact head,同时保留“required rollup 修复后再判定 merge readiness”的独立门槛。
English verdict: APPROVE on exact head 057d8c09ad333f905a555f03dfa46d2ef22479e8. The PR consolidates missing-capability, resolution-owner, binding, and quota Monitor decisions in the typed TypeScript owner while keeping Python as a bounded source adapter. It fixes priority-order, duplicate-identity, and explicit-empty-source semantics without granting capabilities or mutating Todo/lease state. Forty-eight focused Python tests, 13 focused TypeScript tests, the full 1,130-pass control-plane suite, typecheck, Ruff, diff check, all hosted shards, and Stage2c passed. The remaining red rollup is the same seven decision_scope.py mypy errors reproduced on the exact base, so it is not attributable to this branch, but merge readiness must still be rechecked after that shared baseline is repaired.
Summary
agents/capability_gate.ts; retire the Python decision builders.Issue Or Task
Owner-requested next substantive TS/shared-authority refactor, including authorized read-only snapshot regression. No automatic merge or installation requested.
Semantic corrections
first_executable_items. Absent backlog still permits the existing compatibility source; active-next and due-Monitor lanes keep their separate source contracts.Three focused regressions fail on the baseline and pass on this implementation. These are disclosed behavior corrections, not a claim of universal zero-difference parity.
Preserved: a repair target is not its own prerequisite. Declaring
target_capabilities=networkdoes not add network to availability or unblock another Todo requiring it. Owner-held capabilities still route to the owner; missing runtime capabilities route to Agent repair. A blocked candidate does not suppress independent runnable work. The projection grants no enablement, credentials, write scope, claim, lease or business commit.Architecture / scope fit
Placement is the existing built-in Agent capability-gate read boundary; no new capability ID, extension, provider, module family or second inventory is introduced. Python retains source selection/eligibility, legacy normalization, node-independent runtime-capability filtering and the shared profile/rank adapter. The TS projection consumes those facts in one batch. Quota computes per-row missing capabilities in-process, not via one RPC per Todo. The retained bridge caches only normalized requirement/target/available tuples, never Todo state or approval.
This removes duplicate rule orchestration and the separate Python resolution builders without widening native mutation fields. Full-source candidate expansion, remaining T1/T2/T3 consumers and D1-D3 qualification remain open. Permanent Markdown display, provider defaults and promotion holds are unchanged.
Diff: 13 files, +416/-380 overall. Product code is +187/-380 (net -193); tests add 166 lines and protocol/RFC documentation adds 63. The old 531-line Python gate becomes a 200-line adapter with a 127-line TS owner.
Validation
057d8c09ad333f905a555f03dfa46d2ef22479e8(final source tree tested before committing).finishedsynthetic,public_fixture,authorized_private_read_onlynpm run typecheck:control-plane, Ruff on changed Python paths, compilation, diff/public-boundary scans.npm run test:control-plane: 1,172 passed, zero failed/skipped. Focused Python regression suites: 95 passed. Requirement/target semantics, owner and mixed-blocker routing, priority/order, malformed input, v1 quota recomputation, reentry and selected-Todo binding covered.quota should-run --include-detail agent-todoscases across Markdown, File and SQLite with availability on/off. Canonical cases remove display; outputs preserve repair-only readiness and owner routing, and neither canonical state nor display is rewritten.loopx canary premerge --from-git-diff: 17/18 selected checks passed and all four direct checks passed. The only failure is the unchanged heartbeat prompt budget, reproduced on exact basefa57253a7888a33eb98b3b6d49d69726f54e5034: 3,825 JSON characters against 3,600. No prompt or budget weakening is bundled. The standalonemonitor-scheduler-contract-smoke.pyalso passed.Type of Change
LoopX Area
Technical Direction
mainShared-authority RFC fixture impact
productionScaleCoordinationFixture; schema and record contract unchanged.Boundary Checklist