Repository navigation
fix(acpmux): queue automatic messages after the original steering window - #27566
teamleaderleo wants to merge 1 commit into
Conversation
Bugbot needs on-demand usage enabledBugbot 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. |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
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 |
|
Found 6 test failures on Blacksmith runners: Failures
|
|
Owned by an agent session · session |
|
Closing as superseded; the branch is kept. #27520 (merged, d530240) already does what this PR does, in the general form. A session with 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. |
…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>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
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."
agentSteerWindowMsdefaults 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 -- --nocaptureon 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
Need help on this PR? Tag
@codesmith-botwith 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.
agentSteerWindowMsto change the window;0queues automatic messages immediately. Deferred messages do not use the interrupt fallback.Written for commit 111d4a9. Summary will update on new commits.