code-yeongyu / code-yeongyu/lazycodex

subagent-limit-guard still unconditionally rewrites [features.multi_agent_v2] max_concurrent_threads_per_session = 1000 (v4.17.0) — v2 follow-up to #97

Open
#130 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3.5k
Forks
216
PR merge metrics
No merged PRs in 30d

Description

## Summary

`ensureSubagentConcurrencyLimit()` ends by calling `ensureMultiAgentV2ThreadLimit(result)` **unconditionally**, and that helper writes `[features.multi_agent_v2] max_concurrent_threads_per_session = 1000` into the user's `config.toml` on every run — creating the section if absent, and overwriting any user-set value if present. This happens regardless of the selected model, and there is no equivalent of the "hand-removed key stays removed" behavior that the same file deliberately implements for the legacy `agents.max_threads` path.

Pinned source at `v4.17.0` (f39306f):

- Constant `CODEX_SUBAGENT_THREAD_LIMIT = "1000"`: [subagent-limit-guard.mjs#L5](https://github.com/code-yeongyu/lazycodex/blob/f39306f1adab6ff155fd736cc7376d27156472bc/plugins/omo/scripts/migrate-codex-config/subagent-limit-guard.mjs#L5)
- Unconditional call at the end of `ensureSubagentConcurrencyLimit`: [subagent-limit-guard.mjs#L38](https://github.com/code-yeongyu/lazycodex/blob/f39306f1adab6ff155fd736cc7376d27156472bc/plugins/omo/scripts/migrate-codex-config/subagent-limit-guard.mjs#L38)
- Writer that inserts/overwrites the key: [subagent-limit-guard.mjs#L81-L90](https://github.com/code-yeongyu/lazycodex/blob/f39306f1adab6ff155fd736cc7376d27156472bc/plugins/omo/scripts/migrate-codex-config/subagent-limit-guard.mjs#L81-L90)

## Why it matters

On multi_agent_v2 sessions (e.g. `gpt-5.6-sol`), `max_concurrent_threads_per_session` is effectively the **only concurrency gate that holds**:

- `agents.max_depth` is not enforced on the v2 spawn path (openai/codex#32027, still open)
- the v2 non-root thread limit is derived from this cap (`cap − 1`)
- in our testing on codex-cli 0.144.1, `[features.multi_agent_v2] enabled = false` did not disable v2 for `gpt-5.6-sol` — model catalog metadata took precedence

We audited a runaway session on codex-cli 0.144.1 + `gpt-5.6-sol` where the injected runtime hint `"There are 1000 available concurrency slots"` appeared 23× in the rollout, alongside a spawn tree of 1,004 descendant threads (depth 11) and ~46 GB RSS before manual intervention. After we restored Codex's stock default (cap 4) by deleting the override, source inspection showed this migration would silently re-write `1000` on the next session start with the plugin enabled — i.e. a user who fixes their config gets re-broken.

## What v4.17.0 already improved (appreciated)

- v2-preferring models now get `agents.max_threads` **removed** instead of written (the `v2Preferred` branch in `ensureSubagentConcurrencyLimit`), and a hand-removed key stays removed on the no-model-evidence path
- the #118 stale `hide_spawn_agent_metadata` cleanup works as described

The v2 cap write is the remaining piece of #97.

## Suggested fix

Any of, in order of preference:

1. Stop writing `max_concurrent_threads_per_session` unless the user opts in
2. Honor existing / hand-removed user values, mirroring the `raiseExistingAgentsMaxThreads` philosophy already applied to the v1 key
3. At minimum, make the limit configurable instead of hard-coding `"1000"`

`LAZYCODEX_CONFIG_MIGRATION_DISABLED=1` exists but is all-or-nothing — enabling it also loses the genuinely useful guards (e.g. the #118 cleanup).

## Environment

- codex-cli 0.144.1, model `gpt-5.6-sol` (multi_agent_v2), macOS
- Originally observed with OMO 4.15.1; behavior confirmed by source inspection at `v4.17.0` (f39306f)

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with plugins/omo/scripts/migrate-codex-config/subagent-limit-guard.mjs at ensureSubagentConcurrencyLimit and ensureMultiAgentV2ThreadLimit, using the pinned v4.17.0 source. Trace the existing v1 hand-removed behavior and verify the migration across absent, existing, and removed max_concurrent_threads_per_session values; done means the guard no longer unconditionally overwrites user configuration.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.