Skip to content

agents_wait: wait for idle, dialog or text instead of polling snapshots (cx-ncc.93) - #20810

Merged
teamleaderleo merged 8 commits into
feat-cmux-nextfrom
feat-cx-cmux-agents-wait-tool
Oct 15, 2026
Merged

teamleaderleo merged 8 commits into
feat-cmux-nextfrom
feat-cx-cmux-agents-wait-tool

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

An agent that waits for another agent in cmux had to poll agents_snapshot. It can now call agents_wait (MCP) or cmux agents wait (CLI), which share one code path (cli/agents/wait.rs) and answer when the condition holds:

  • until: idle: the agent of a term_, tab_ or agent_ id, or an agent chat's session, stops working (idle, done, or blocked on a dialog; match.state says which).
  • until: dialog: a permission or question dialog is pending, a target's when given (the agents_dialog_list read).
  • until: text: literal text, or a regex with regex: true, appears on a terminal's screen.

timeout_seconds defaults to 30 and is at most 120. The receipt is {until, matched, waited_seconds, match, state}, where state is a fresh agents_snapshot-shaped snapshot cut by the #20609 receipt rule. A timeout is matched: false, not an error; a condition that already holds answers at once. Bad arguments, an invalid regex (checked with the regex crate, the daemon's own engine and limits) and an unknown target are refused as not_run before any wait. For until: dialog, a term_, tab_ or agent_ target that no owner knows is refused like idle and text; a target of another kind is taken as a dialog request id, which may name a dialog that has not appeared yet, so that wait runs to its timeout instead of being refused. A text target whose terminal closes mid-wait reports match.state: "closed", the same result idle gives.

cmux agents wait exits 1 on matched: false and still prints the JSON receipt, as screen wait does (docs/cli-contract.md and the cmux-workspace skill say so).

The MCP server answers one request at a time, so an agents_wait call holds later calls on the same connection for up to its timeout (at most 120 s). terminal_wait already behaves this way; this PR does not change it.

What wakes a wait:

  • text is event-driven: it is the daemon's own terminal.wait, which wakes on terminal output.
  • idle and dialog hold the daemon's session.events stream open and check on each event (at most every 200 ms). They also check every second, because an agent chat's state and the dialog feed live in the app, whose events.stream publishes no event for them. So dialogs and chat-only agent state are polled at 1 s; terminal agents (daemon agent records, OSC 7501 program status) wake on daemon events. With no daemon stream, the wait checks every second.

An MCP call with _meta.progressToken gets notifications/progress every 5 s (progress = seconds waited, total = timeout). The CLI shows the #20627 stderr notes for waits of 35 s or more (human output, or JSON with a TTY), with a new agents_waiting_progress string (English and Japanese).

Security: the tool is read-only (readOnlyHint, idempotent, no key). It reads other agents' state and pending dialogs, as agents_snapshot and agents_dialog_list already do, and a terminal's screen, as terminal_wait already does; its description says so. Chat transcripts are not readable for text, because no existing read exposes them. No socket method or relay policy changed; RemoteRelayCommandPolicy stays deny.

plans/cmux-next/mcp.md lists the tool.

Proof

Behavior tests: eleven at the MCP boundary (nine originally, two added in review) (cli/mcp/tests/agent_wait.rs, through Server::handle/run with the fake owners, whose daemon snapshot and dialog feed change mid-wait) and one CLI test through a real headless daemon (tests/cli/agents_wait_cli.rs: text written to a terminal, an agent reported working then idle, a 1 s timeout, a usage error).

  • Red, tests only at 33e0b44: dispatch.sh <wt> agents_wait, run 38651317708. The nine MCP tests failed on unknown tool: agents_wait (behavior, not compile).
  • Green: run 38654134200 at 45491f1 passed test (linux); its Linux clippy flagged two lints, fixed in c9ee02a; focused run 38656540524 on that head (c9ee02a) passed every job, with all ten agents_wait tests run and passing on Linux (macOS ran the same filter).
  • Full: run 38660253813 on the same head. Linux cargo test passed, including all ten agents_wait tests. The run is red on failures outside this diff:
    • Windows build and Windows tests: cli/wire/socket.rs calls crate::app_identity, which is #[cfg(unix)]. This is a base break from bc697be (cx-is1kf.5), and it stops the Windows Rust tests before they run.
    • Linux TUI smoke (smoke-tui.py:953): a workspace-order assertion after prefix-W, in TUI code this PR doesn't touch.
    • macOS jobs: the runner refused the job (Set up runner), so they never ran. The macOS clippy and focused filter passed in run 38656540524.
  • Local: scripts/cmux-next/crash_ratchet.py ok; check-no-godfiles.sh --only rust --base origin/feat-cmux-next passes (the first version grew cli/app.rs past 1000 lines; it no longer does).

Review fixups (one red, one green, same focused command dispatch.sh <worktree> agents_wait):

Changelog

Added: agents_wait MCP tool and cmux agents wait, which wait until an agent goes idle, a dialog appears or text reaches a terminal, instead of polling snapshots.

🤖 Generated with Claude Code

teamleaderleo and others added 4 commits October 14, 2026 15:59
…x-ncc.93)

Behavior tests at the MCP boundary (agents_wait listed as a bounded read,
idle mid-wait, already true, timeout as an unmatched receipt, dialog,
text through the daemon's terminal.wait, bad arguments refused as
not_run, progress notifications) and one CLI test through a real daemon.
They fail until the tool and the cmux agents wait verb exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cx-ncc.93)

One code path for the MCP tool and the CLI verb (cli/agents/wait.rs).
text waits on the daemon's terminal.wait; idle and dialog hold the
daemon's session.events stream open and check on each event, and every
second for app-only state (chat agent state, dialogs). A timeout is a
matched: false receipt with a fresh state. MCP calls with a
progressToken get notifications/progress; the CLI shows the long-wait
notes app waits show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 15, 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.

@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 15, 2026 00:29 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 47a5371c-e9fd-4d87-b3b0-202dd6846a89

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ed text target, CLI exit 1 (cx-ncc.93)

An invalid regex and an unknown agent named by a dialog wait are refused
as not_run before any wait; a text target that closes mid-wait reports
match.state closed as idle does; cmux agents wait exits 1 when it times
out, as screen wait does, and still prints the receipt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 15, 2026 01:32 — with GitHub Actions Inactive
teamleaderleo and others added 2 commits October 14, 2026 18:36
…orts a closed text target, CLI exits 1 on timeout (cx-ncc.93)

The regex is compiled with the daemon's crate and limits before any
wait. A dialog target that names a terminal, tab or agent must exist, as
for idle and text; other dialog targets may not exist yet and wait. A
text target that closes mid-wait reports match.state closed. cmux agents
wait prints the unmatched receipt and exits 1, as screen wait does
(docs/cli-contract.md, cmux-workspace skill).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 15, 2026 01:37 — with GitHub Actions Inactive
…d (cx-ncc.93)

No dialog feed item carries surface_id, and the resource API boundary
check refuses the legacy word in public code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 15, 2026 06:34 — with GitHub Actions Inactive
@blacksmith-sh

blacksmith-sh Bot commented Oct 15, 2026

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs

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

@teamleaderleo
teamleaderleo merged commit 7809102 into feat-cmux-next Oct 15, 2026
177 of 182 checks passed
@teamleaderleo
teamleaderleo deleted the feat-cx-cmux-agents-wait-tool branch October 15, 2026 08:27
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Landed on head e246a83 with the blocking gates green: crash ratchet, CmuxNextApp size cap and fast tier passed; react-apps-check didn't run because the PR has no web changes. The Rust build and tests passed on this exact head (focused run 38693394419; all 12 agents_wait tests ran). One red in 'cmux-next checks' comes from base: the package-conventions lint on BuiltInAdBlockerSetting.swift, which this PR doesn't touch. #20927 fixes it, and coord-standby confirmed it isn't a blocking check. The Swift Release compile doesn't apply because no Swift changed.

This branch was previously deployed

2 inactive deployments
artifacts — e246a833 Deployed Oct 15, 2026 by teamleaderleo via publish tree-addressed cmux-tui #16442
cmux-tui-merge-tree — e246a833 Deployed Oct 15, 2026 by teamleaderleo via publish the merge tree #1282
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant