Skip to content

fix(acpmux): queue automatic messages after the original steering window - #27566

Closed
teamleaderleo wants to merge 1 commit into
feat-cmux-nextfrom
lane/audit-coord-resume-20261029
Closed

teamleaderleo wants to merge 1 commit into
feat-cmux-nextfrom
lane/audit-coord-resume-20261029

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Automatic agent messages can keep a steer-capable turn open indefinitely while older prompts wait in its durable queue. Bound automatic steering to the first ten minutes of the original turn; after that, retain new agent messages in the normal queue and let existing work finish.

Leo asked: "Audit the last ~36 hours of Leo's agent fleet and remove the causes of the delays at the source."

agentSteerWindowMs defaults to 600000; zero queues automatic agent messages immediately. Human steering and explicit Send now remain available. Steer-only requests receive an explicit refusal when the window is closed. Budget deferral never takes the interrupt fallback. There is no new timer, forced completion, or task cancellation; the existing queue owns persistence and continuation. The age uses the persisted original turn start and the system clock.

Risk: normal. This bounds admission, not execution time; work already accepted must finish. Clock changes affect the wall-clock age calculation. Non-steering explicit interrupts keep their existing semantics.

Validation

Focused regression: cargo test -p acpmux --lib agent_steer_window -- --nocapture on hosted Linux or the supported fleet Rust lane. The fixture holds an active tool, accepts a fresh steer, ages the turn, mixes an older unsteered prompt with later steers (including interrupt fallback), then releases the tool normally. It checks order, prompt IDs, exactly-once delivery, one final result per turn, human/Send now behavior, and steer-only refusal.

Red/green exact-head receipts: pending.
Independent Claude Opus 5.5 exact-head review: pending.

Observed / Not run

Prepared regression and inspected all steering/queue paths at base 34e31e4. No local Rust build or suite. Remote runtime checks and final exact-head review are pending.

Changelog

Fixed: Automatic agent messages no longer extend the same running turn indefinitely and starve queued prompts.
Agent session: agent session


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


Summary by cubic

Automatic agent messages can no longer keep a turn open indefinitely. After 10 minutes from the original turn start, they enter the durable queue behind existing prompts, while current work finishes normally.

  • Human steering and explicit Send now remain available; steer-only requests are refused when the window has closed.
  • Set agentSteerWindowMs to change the window; 0 queues automatic messages immediately. Deferred messages do not use the interrupt fallback.

Written for commit 111d4a9. Summary will update on new commits.

View guided diff Turn on auto-fix

@cursor

cursor Bot commented Oct 29, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 111d4a9: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr27566 -f ref=lane/audit-coord-resume-20261029 -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 719c550 to compare; do not merge until green; see lane-rules

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 29, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 29, 2026

Copy link
Copy Markdown

Found 6 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp_faz7zyv/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpzsvewtwh/summary-missing.json (live):/summary-missing.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Closing as superseded; the branch is kept.

#27520 (merged, d530240) already does what this PR does, in the general form. A session with turnCapMs stops taking other agents' steers once its running turn is past the cap. Those messages wait in the durable queue and the next turn takes them together. The person's own steers and the queue's Send now still go in, the hub steers one notice into the turn, and it never cancels the turn. agentSteerWindowMs would be a second setting for the same bound.

The one thing here that #27520 lacks is a default for every session (10 min). That moves into the follow-up that routes every session's agent messages through an inbox: one digest at the next tool step, never a queued turn per message. That follow-up carries this PR's scenario (an older queued prompt must not starve behind later agent steers) as a test.

teamleaderleo added a commit that referenced this pull request Oct 30, 2026
…n of its own (A1) (#27686)

* test(acpmux): other agents' messages go into an inbox, never a turn of their own (red)

300 agent messages waiting while the agent reads the one before them go
in as one notice at its next tool step; an idle chat wakes for a blocker
or its first work only, as one turn; a prompt queued behind a running
turn never waits behind agent messages (#27566's case). The fake agent's
FAKE_STEER_STEP answers a steer at the test's next tool step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux: every chat's inbox; another agent's plain send is never a turn of its own

A plain send from another agent (acpmux send, the MCP send tool) goes into the
receiving chat's inbox, in a thread (--pr / --thread, else the sender and the PR
its first line names, else the sender). The agent hears of new messages as ONE
notice at its next tool step; an idle chat wakes as one debounced turn only for
a blocker, a report of work it gave, its first work, or an action from its
parent or delegator; an FYI never wakes it, and anything left waits at most 10
minutes. MCP inbox_read / inbox_reply and _acpmux/inbox_threads, inbox_thread
and inbox_reply read and answer threads. Withdraw unsends an inbox item until a
notice carried it, then retracts it into its thread. agentInbox: false puts
plain sends back on the queue.

Supersede-keyed, steer-only and team sends, peer and mesh forwards, lane
reports, task cards and pair releases keep the queue path for now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: answer every sender on close, notice only what went in, back off refusals

- A chat closing or closed takes an agent's message as before the inbox; one its inbox
  holds, or a notice in flight carries, is answered with the closing error.
- A notice turn's messages are noticed (logged) once its prompt is written, not at its
  turn's start; a Stop or failure before that leaves them new.
- A refused steer backs off REFUSED_RETRY_MS within a turn; a turn's start or end clears it.
- A resend of a noticed item says duplicate/noticed; a closed chat's inbox restores and the
  inbox methods wait for the chat's log load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: a notice turn answered without a written prompt still counts as in

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: drop the unused notice_done steer flag; send_async reads the inbox record

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: round-2 review fixes

- A notice turn counts as delivered once the harness writer confirmed its prompt
  (confirmed write), and each notice keeps its own landing/written mark.
- inbox_review arms or disarms the wake timer under the lock it decided under, so an
  older review never aborts a newer timer.
- trim never drops a message a notice in flight or landing carries.
- A notice checks the queue and the turn cap again at dispatch (notice_held).
- A chat closing meanwhile answers a notice's senders with the closing error.
- A resend of a noticed item answers with its notice's logged outcome.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: round-3 review fixes

- A notice goes in only once the agent's writer confirmed its prompt, a steer's too
  (steer_turn confirms an inbox notice's write); notice_done no longer counts an
  answer as delivery.
- One notice in flight: a turn of its own until its prompt is written, a steer until
  the agent took it at its tool step.
- notice_held is checked again while the steer holds the input handoff.
- A notice's waiting senders live in the inbox (Inbox::carrying), so a close answers
  them; notice_done answers under the inbox lock after the closing check.
- A notice that went in logs inbox_answered; a resend, before or after a restart,
  answers with it.
- A message withdrawn before any notice carried it is tombstoned: a resend answers
  withdrawn and never goes back in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: round-4 review fixes

- inbox_answered keeps an error too: a resend of a message whose notice went in
  and then failed answers with that error, before or after a restart.
- logged_prompt answers an inbox message from its records (withdrawn, its notice's
  answer, or interrupted), so a resend after a restart or ledger eviction never
  re-enters the inbox.
- trim lets go only of answered messages and remembers their ids (Inbox::trimmed):
  a resend answers from the log, never runs again.
- Withdrawn ids are kept whole (no rolling cap), so a resend never resurrects one.
- A withdraw of a message a notice carries that is not written yet waits (bounded,
  outside the withdraw lock) for it: unsent if it did not go in, retracted if it did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: round-5 review fixes

- A resent inbox message whose notice failed answers with the same RPC error from
  any path: in memory, after trim, after a restart (logged_inbox_answer; prompt_with
  answers a resend from it before logged_prompt).
- A noticed message no notice carries and with no answer (its notice was cut by a
  restart) answers interrupted, never a made-up end_turn.
- A withdraw by msgId also waits for a notice on its way to settle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux inbox: pass the held check to base's new carried-turn prompt hook

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux tests: base's new queue tests (inbox digest, stop, session queue CLI) pin agentInbox off

They send plain agent messages to test the queue path, as the other queue tests do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux cli: the inbox's flags are flattened Args, so the CLI parses in a 2 MiB test thread

After the merge with base, the derived clap builder's single frame for every inline flag
overflowed libtest's 2 MiB thread in a debug build (cli::command tests aborted with
signal 6; base alone passes). send's --pr/--thread, session inbox's
--thread/--mark-read/--digest/--dry-run and the hidden SessionInboxCmd are now Args
structs of their own, built in their own frames. A test pins the session inbox routing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

* acpmux tests: base's peer_person_stop pins agentInbox off

It holds a plain agent message queued behind the person's Stop, as the other queue
tests do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 111d4a9d Deployed Oct 29, 2026 by teamleaderleo via cmux-tui tree preflight #78094
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant