Skip to content

fix(multi-subagent): distinguish configured and live child capacity - #4768

Merged
huangruiteng merged 4 commits into
mainfrom
codex/multi-subagent-native-capacity
Sep 20, 2026
Merged

huangruiteng merged 4 commits into
mainfrom
codex/multi-subagent-native-capacity

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

Summary

  • treat max_children as a configured upper bound instead of live native-host availability
  • add a typed, read-only agent-context --phase after_delegate_result observation for successful dispatch or agent_thread_limit_reached on native spawn/followup
  • project bounded recovery guidance: stop same-Turn retries, keep unlaunched work incomplete, continue useful parent work, and retry only after capacity changes
  • keep the typed contract in TypeScript; Python only adapts CLI inputs

Product boundary

This changes the coordinator CLI/managed context projection and bilingual operator documentation. No frontend or Lark control is added because native host capacity is an ephemeral per-attempt observation, while the existing settings UI continues to own the durable max_children ceiling. The interface is read-only and never deletes, imports, resumes, or rebinds sessions.

Validation

  • uv run --extra test python -m pytest -q tests/capabilities/test_codex_subagent_host_capacity.py tests/control_plane/test_agent_context.py tests/control_plane/test_delegation_context.py — 29 passed
  • node --no-warnings --experimental-strip-types --test tests/control_plane_ts/agent_context.test.ts — 12 passed
  • npm run typecheck:control-plane — passed
  • uv run ruff check loopx/cli_commands/agent_context.py tests/control_plane/test_agent_context.py — passed
  • uv run --extra test loopx canary premerge --from-git-diff — passed, 14 checks, no failures or manual holds
  • git diff --check — passed

Residual boundary

LoopX still cannot transparently intercept arbitrary native host tools. The current host must submit the bounded typed outcome after a native call; raw error text and session identities are not accepted.

@huangruiteng
huangruiteng force-pushed the codex/multi-subagent-native-capacity branch 3 times, most recently from 5916c03 to 3580711 Compare September 20, 2026 10:00
@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Rebased this PR onto current main (4eb6ea9eed3a2e374933b233b62bd46419046263) and pushed exact head 358071198d2e4f0779b8891d0f2097aa20621568.

Repair applied:

  • replaced the stale editorial assertion for parallel delegation with assertions on the shipped typed capacity contract (multi_subagent_capacity_v0, configured limit is an upper bound, live availability is not observed);
  • kept the behavioral guidance assertion on max_children is a configured ceiling.

Local validation at this exact head:

  • uv run --no-project --with pytest python -m pytest -q tests/control_plane/test_turn_envelope_budget_warning.py::test_installed_skill_defers_delegation_policy_to_enabled_provider tests/control_plane/test_agent_context.py → 12 passed;
  • node --no-warnings --experimental-sqlite --experimental-strip-types --test tests/control_plane_ts/agent_context.test.ts → 12 passed;
  • git diff --check → passed.

The maintainability ratchet still reports loopx/chat_server.py and loopx/extensions/lark/goal_topic_connections.py. Neither file is changed by this PR (git diff origin/main...HEAD -- is empty for both), so I did not add unrelated baseline-ceiling changes to #4768.

Entry-point scope: this remains a shared agent-context/CLI + managed-Turn projection change. It adds no new user-editable setting or card surface, so the existing frontend/Lark consumers continue to consume the common typed projection rather than gaining a second source of truth. No self-merge; exact-head review remains required.

huangruiteng added a commit that referenced this pull request Sep 20, 2026
Pull in the independently validated main-branch repairs for the module budget ratchet and time-dependent Lark context fixtures so this feature branch can exercise its own checks without duplicating the fixes.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng

Copy link
Copy Markdown
Collaborator Author

CI repair update for exact head 58c1c31e0d4a3a6307a09bb4bab1d2cd85b17901:

  • Reproduced all three prior failures on unchanged origin/main (4eb6ea9ee), so none was caused by this PR's six-file capacity projection diff.
  • Reused the already-reviewed causal repair ancestry from refactor(chat): remove inherited module-budget regressions #4793: it removes the two inherited module-budget overruns without raising ceilings and freezes the dated Lark context fixtures without changing production retention semantics.
  • Current-head focused validation: 32 passed for the three former failures plus the Python capacity suite; 12 passed for the TS capacity suite; control-plane typecheck and Ruff passed.
  • loopx canary premerge --from-git-diff: passed, 14 selected checks, 0 failures, 0 manual holds; public/private boundary scan passed.

Fresh GitHub checks are now queued. This PR remains review-required and is not self-merged.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng
huangruiteng force-pushed the codex/multi-subagent-native-capacity branch from 5efb3a2 to 2acb4f8 Compare September 20, 2026 14:58

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

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

Exact head: 2acb4f86428efa38d967c60578a955db75932ef4

动机

这个 PR 解决的是一个真实的多子 Agent 协调缺口:Goal 的 max_children 是持久配置上限,并不等于原生宿主当前仍有多少可用槽位。旧的 v3 context 只投影 max_children,当 native spawn / followup 返回线程上限时,没有稳定、可脱敏、可跨 Python/TypeScript 使用的结果输入,协调者容易把配置误当实时容量并在同一 Turn 内重复尝试。

当前 exact head 已完成该功能目标:新增只读 typed observation,把 agent_thread_limit_reached 投影为 capacity_exhaustedretry_same_turn: false 以及继续 parent work / defer 未启动 child / 容量变化后再试的恢复动作;成功结果只表示 attempt_observed,不会声称仍有槽位或授权继续重试。

改动思路

实现复用了既有 loopx agent-contextmulti_subagent provider,没有新建 capacity store 或第二套权限来源。Python CLI 只负责接收 spawn|followupsucceeded|agent_thread_limit_reached 和可选非负 count,并校验参数成对出现、只能用于 after_delegate_result。真正的语义、脱敏和恢复事实仍由 TypeScript subagent_context.ts 统一拥有。

正向链路是:native host 显式提交一次操作观察 → Python 适配到 generic observations → TypeScript 白名单/限幅 → v4 contribution 返回只读事实。负向链路覆盖了半组参数、错误 phase、负数/孤立 count、disabled policy、伪造 raw error 与 success outcome:它们不会生成额外 authority、不会写 registry,也不会把 success 解释成可重试容量。

default-off 边界经过 base/head 公共 CLI 对照:spawn_allowed=false 且未提交 observation 时,base 与 head 都返回 ok: trueagent_context: null,不出现 capacity 字段;disabled 状态下显式提交 observation 会直接拒绝,而不是静默返回成功。

具体改动

  • loopx/cli_commands/agent_context.py:增加三个 typed CLI 参数,校验 co-presence、phase、count 与 capability enablement;只在真实提交 observation 时输出 host_capacity_observed
  • loopx/control_plane/subagent_context.ts:provider 升级到 v4;新增 capacity_contractboundedNativeCapacityObservation,过滤 raw/未知字段,count 上限为 10,000,并区分 not_observedattempt_observedcapacity_exhausted
  • 三个 Python/TypeScript 测试文件:覆盖公共 CLI、成功/限额、disabled、raw-error 脱敏、turn-envelope budget 与 provider size boundary。
  • docs/integrations/codex-subagent-orchestration.md:补充中英文命令、恢复行为、权限与隐私边界。

关键代码讲解

  1. register_agent_context 通过 argparse choices 建立第一层 typed boundary,不读取或解析宿主原始错误文本。
  2. handle_agent_context 保持命令 read-only,并在 supplied observation 被 disabled policy 吞掉时显式报错,避免“看似提交成功、实际没有投影”的假成功。
  3. subagentContextProvider 是唯一恢复语义 owner:max_children 明确标为 configured upper bound,只有 after-result observation 才能改变本次 projection 的 live status。
  4. boundedNativeCapacityObservation 是第二层 defensive boundary:只接受版本化 schema 与固定 enum,剥离 raw_error,且仅对 thread-limit 发出 retry_same_turn: false

提交历史也已清理并重新核对:origin/main..2acb4f86 只有 4 个 huangruiteng 的 DCO-signed commit;先前混入分支的 songoow commit 已从 PR 独有历史移除。当前可见的 songoow commit 只属于已合并的 main 基线,不会作为 #4768 的额外提交合入。

对主干的风险

功能侧最强风险是把一次成功调用误写成“仍有容量”,或把 typed observation 变成新的 spawn/session authority。当前实现避免了这两点:success 只产生 attempt_observed,没有 retry_same_turn;context 仍是 guidance_only / read_only,不删除、导入、恢复或 rebind Session,也不写 Todo、quota、journal 或 registry。

本 head 的 feature-local 验证通过:

  • Python focused suites:29 passed;
  • TypeScript provider:12 passed;
  • TypeScript typecheck、Ruff、py_compilegit diff --check:通过;
  • risk-based premerge canary:14 selected,0 failure,0 manual hold,public/private boundary 通过;
  • base/head 公共 CLI probe:enabled no-input 的行为变化符合 v4 disclosure,disabled no-input 保持 parity,base 对新 typed flags 明确拒绝,head 正确返回 bounded observation。

当前 blocker 不在本 PR 的 feature diff,而在其 base:main@6e5d5409 的 semantic inventory 实际值已是 17/39/10,预算仍是 18/41/11,所以现有 test_live_inventory_ignores_missing_or_stale_reports 两个参数化 mutation 在 base 上均复现 DID NOT RAISE Drift。这意味着 #4768 目前无法形成 required exact-head CI 结论;跳过或 admin bypass 会把已知主干回归误当成本功能验证通过。

最小修复是先由 maintainer 合入对应 semantic ratchet 修复(#4806),随后把 #4768 rebase 到新主干,并重新执行 exact-head review 与 required checks。由于 head 会改变,本次 review 不能沿用为最终 merge approval。

语义与 CI 对齐

该 PR 扩展既有 multi_subagent agent-context vocabulary,而不是创建新的 capability 或 authority model。版本化 observation 名称准确限定为单次原生 child 操作观察;公开文档、provider revision、typed enum、disabled parity 与 negative coverage 对齐。当前 REQUEST_CHANGES 仅来自外部 base/CI 依赖,并非发现 feature 语义或实现缺陷。

我的整体评价

REQUEST_CHANGES(依赖阻塞,非功能代码否定)。设计所有权正确、范围完整、隐私与权限边界清晰,feature-local 证据支持代码层面的正面评价;相关 future-facing refactor 也已做到位:配置上限、一次性观察和执行 authority 分离,不需要再引入新模块或持久状态。

但仓库 policy revision 7 要求 required validation 绑定 exact head。当前 base 回归尚未进入主干,且 CLI/control-plane 行为本身也属于 maintainer-only surface,因此不能自合并。依赖落地并 rebase 后应重新生成 packet、重跑验证并发布新的 exact-head 结论。

English verdict: REQUEST_CHANGES - exact head 2acb4f8 has no identified feature-code defect and passes 29 Python tests, 12 TypeScript tests, typecheck, lint, compile, diff checks, and 14 canaries; merge remains blocked until the known main-branch semantic-ratchet regression is fixed, the PR is rebased, and exact-head required validation is rerun.

@huangruiteng
huangruiteng merged commit a1d5113 into main Sep 20, 2026
11 of 26 checks passed
@huangruiteng
huangruiteng deleted the codex/multi-subagent-native-capacity branch September 20, 2026 15:09
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