impl-maxagents-authority-fix

Impl: fix the max_agents authority/reload-override bug (shared prerequisite)

Metadata

Statusfailed ‖ paused
Created2026-07-25T20:56:54.917684992+00:00
Started2026-07-26T06:09:58.433670256+00:00
Completed2026-07-27T15:48:41.489684274+00:00
Tagscoordinator, config, bugfix
Tokens5591331 in / 27129 out
Failure reasonrequired evaluation gate rejected: evaluator verdict-evalp-fd5da61975fbab269deb9f97-evaluate-f3154d11cfa45430 score=0.64 threshold=0.70 FAIL; FLIP verdict-evalp-fd5da61975fbab269deb9f97-flip-935878596618c786 score=0.72 threshold=0.70 PASS

Description

Objective

Fix the max_agents four-source-of-truth authority bug so a runtime override survives a flagless wg service reload / profile swap. This is the SHARED PREREQUISITE for the adaptive-parallelism controller (T4) — without it, the controller's writes are silently clobbered. It is a pure correctness fix valuable independently (fixes the observed "start with --max-agents 2, wg profile use, observe 8" bug).

Context: docs/studies/adaptive-parallelism-budget-design.md §8 (the bug + the fix), docs/studies/roadmap-rate-limit-and-distribution.md §2.2/§3.

What to build

There are FOUR sources of truth for max_agents today with no defined precedence: (1) CLI launch arg --max-agents (daemon memory only, src/commands/service/mod.rs:~2415), (2) [coordinator].max_agents in merged config.toml (src/config.rs:~4089), (3) the active profile overlay (src/profile/named.rs:~473,479, written into config.toml on activation), (4) runtime IPC Reconfigure { max_agents } (src/commands/service/ipc.rs:~1095). The bug: the launch arg (1) is never persisted, so a flagless reload sends Reconfigure { max_agents: None } (src/commands/service/mod.rs:~3891, src/commands/profile_cmd.rs:~1205), handle_reconfigure takes its else-branch, re-reads config.toml, and does daemon_cfg.max_agents = config.coordinator.max_agents (src/commands/service/ipc.rs:~1111) — silently replacing the launch arg's value with the profile's.

Implement the fix exactly as specified in the study §8.2:

  1. Add runtime_max_agents: Option<usize> to CoordinatorState (src/commands/service/mod.rs:~710). This is the new single transient-but-persisted authority. It survives daemon restart (on disk in the coordinator state file).
  2. In handle_reconfigure's else-branch (src/commands/service/ipc.rs:~1109-1113): after re-reading config, if a runtime_max_agents is present in CoordinatorState, KEEP it instead of clobbering with config.coordinator.max_agents.
  3. At daemon start (src/commands/service/mod.rs:~2415): if cli_max_agents is Some(n) AND no runtime_max_agents is already on disk, write runtime_max_agents = n into CoordinatorState (so the launch intent survives reload) and arm a session pin.
  4. config.coordinator.max_agents becomes the ceiling + cold-start default only.
  5. Add a --no-pin escape on service start for tests wanting the old behavior.
  6. An explicit --max-agents flag on reload is a human action and wins (it takes the has_overrides branch and should be recorded as a pin).

No schema migration needed (the field is Option, defaults to None = today behavior).

File scope

  • src/commands/service/ipc.rs (handle_reconfigure else-branch)
  • src/commands/service/mod.rs (CoordinatorState field + daemon-start pin logic)
  • src/config.rs (if a --no-pin flag / config key is needed)
  • New unit test(s)

Implement directly. Do not decompose further unless you hit genuine context pressure.

Validation

  • New unit test reproduces the reload-clobber: start with --max-agents 2, simulate a flagless Reconfigure { max_agents: None }, assert daemon_cfg.max_agents == 2 (preserved), NOT 8.
  • Unit test: an explicit --max-agents reload flag overrides the runtime value and is recorded as a pin.
  • Unit test: daemon restart restores runtime_max_agents from disk.
  • --no-pin escape restores today behavior for tests.
  • cargo build + cargo test pass with no regressions.
  • cargo fmt --check + cargo clippy clean (CI fast-fails on fmt).
  • No model pin in the task; routes through the active zai profile.

Depends on

Required by

Log