acpmux: the daemon refuses a new session when the disk is under its floor or the host is at its max_lanes

Closed
TE
11d ago
+1955-117

deputy-2 (P0 enforcement, 2026-10-22): huge-blue had about 25 live Codex reviewers that other hosts started with a raw acpmux new over reach. They went around lane-place's cap of 12, filled the disk to 98-100% and pushed load to 50-80. Telling lanes didn't stop it, because new ones kept starting. Every path to a new session goes through the daemon's create, so this PR checks there. Scope from the coordinator: it applies on every lane host, with each host's own cap from the registry. cmux16 runs 16 live sessions against max_lanes 3.

What changes

hub/admission.rs checks every new session when it's created. It reads two files each time and adds no hard-coded cap:

  • ~/.cache/worktree-reclaim/under-floor: while this file exists, every new session is refused. worktree-reclaim writes it when the disk is under its floor.
  • lanes.max_lanes: a new session is refused while this host's live sessions (running, ready or waiting; a peer's sessions don't count) are at the cap.
    • The cap comes from this machine's entry in the fleet registry. The daemon reads FLEET_REGISTRY if set, else the first that exists of ~/.ssh/config.d/fleet-registry.json (the copy reach --install renders) and ~/Projects/leo-workspace/machines/fleet-registry.json. cmux16 has only the second.
    • The daemon finds this machine the way reach does: from FLEET_ORIGIN, or by the machine's name, its aliases or its origin hostnames (so Air-Blue.local is air-blue).
    • With no registry, or no lanes entry for this machine, the create is admitted and the log says why. acpmux outside the fleet behaves as before.

What the refusal looks like: the error is data.reason: admission_refused with why set to under_floor or max_lanes. The CLI exits 5, the same code lane-place uses when no host qualifies. The message names the count, the cap and where the cap came from, for example: cmux16 has 16 live sessions, at its cap of 3 (lanes.max_lanes of cmux16 in /Users/cmux/Projects/leo-workspace/machines/fleet-registry.json): stop one or start the session on another host; --force-admit creates it anyway. A Web client, whether connected here or through a peer, gets no host name or path.

What's checked:

  • session/new, which covers new, run and exec, plus an adopt with ifLive: fork.
  • session/fork.
  • The composer's aside (_acpmux/ask).
  • Sub-session starts.
  • A peer-routed new: the owning daemon checks it and returns its refusal through the peer.

What's never checked: sends, resumes, restarts and restart-resume, adopts that don't fork, imports, side chats (btw) and handoff targets. A host that is already over its cap keeps every session it has; nothing is evicted.

Overrides:

  • --force-admit on new, run and fork (_meta.acpmux.forceAdmit) admits past a refusal. The daemon logs it at warn level with the caller and what it overrode.
  • The person's own new chat on this host is admitted and logged. That means this host's app pane, or a connection that proved the person key. A peer's forwarded via: app is not trusted for this.

Concurrency: an admitted create counts as live until its handler returns. Concurrent creates at the cap therefore can't all pass the count.

Tests

The failing tests were committed before each fix: d7cdd312251, then d1aec83c5d9, then 6805ec2c9cf.

tests/admission.rs runs real daemon and CLI processes with the stand-in agent:

  • the under-floor flag refuses both new and run, and the next create after the flag is cleared goes through;
  • at the cap a create is refused, and stopping one session frees a place;
  • --force-admit creates and the daemon logs it;
  • a send, a restart and a send after the restart all work at the cap and under the floor, while a fork is refused unless forced;
  • with no registry, or no entry for this machine, creates are admitted;
  • a leo-workspace checkout's registry caps a host that has no rendered copy, and the refusal names that file;
  • 6 concurrent creates at max_lanes 2 give exactly 2 made and 4 refused.

The unit tests in hub/admission.rs cover each lane host's own cap (huge-blue 12, cmux16 3, big-red 6, air-blue 3), including a host already over its cap, and that a Web refusal contains no paths.

Focused command: cargo test -p acpmux --test admission

  • Base plus the first red commit (d7cdd312251): 5 of 5 fail, e.g. "a refused create exits 5" gets a created session back, and --force-admit is "unexpected argument".
  • Head: 7 of 7 pass.
  • Reservation removed (live count without creates in flight): the concurrency test fails 3 of 3, "two made, four refused".

Observed / Not run

  • Observed on huge-blue: cargo test -p acpmux --lib 575 passed; --test admission 7 of 7.
  • Observed on huge-blue: peer_integration, ephemeral_run, cli_agent and full_access_subsessions pass.
  • Observed on huge-blue: hub_integration 370 of 371. The one failure, preset_args::a_remote_origin_connection_never_uses_or_sets_args_or_a_system_prompt, fails the same way on base when TMPDIR is under ~/.cache ("cwd is refused: a remote WebSocket connection may use only a known project or a configured webRoots folder"). It passes with TMPDIR under /tmp, as does peer_integration's a_web_notification_cancel_forwarded_by_a_peer_keeps_web_control.
  • Observed: clippy --all-targets is clean for acpmux, and prepush-gate is clean.
  • Not run: the macOS and Windows builds; CI covers them. Hosted cmux-tui runs had been stuck in the queue tonight, so the evidence above is local.
  • Review: Codex at xhigh. The first review returned BLOCK with 5 findings, all fixed in c0abdb41231. The re-review result is in a PR comment.

risk: normal. This adds a refusal on create; it changes no socket policy, auth or relay allowlist, and the person exemption only narrows what is trusted.

Changelog

  • Added: the acpmux daemon refuses a new session while the disk is under its floor or the host is at its fleet max_lanes (--force-admit overrides).

Agent session: huge-blue

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

The acpmux daemon now refuses new sessions when its disk is under the free-space floor (a ~/.cache/worktree-reclaim/under-floor flag) or when this host is at its fleet registry's max_lanes. Previously, raw acpmux new over reach went around lane-place's cap of 12, filled the disk, and pushed load on huge-blue.

Scope

  • Checks every create path: session/new (new, run, exec, and forking adopts), session/fork, the composer's aside, and sub-session starts; a peer-routed new is refused by the owning daemon.
  • Sends, resumes, restarts, non-forking adopts, imports, side chats, and handoff targets are never checked; nothing is evicted.
  • Refusal exits 5 with reason: admission_refused and why of under_floor or max_lanes; --force-admit on new/run/fork overrides it and is logged.
  • In-flight creates count as live, so concurrent creates at the cap can't all pass.
  • The cap comes from FLEET_REGISTRY if set, else ~/.ssh/config.d/fleet-registry.json or a leo-workspace checkout's registry; no registry or entry admits.