Skip to content

cmux-next: a fresh CLI or MCP call without a kind keeps the Chief owner from restarting - #25513

Merged
teamleaderleo merged 3 commits into
feat-cmux-nextfrom
owner-idle-cli-call
Oct 26, 2026
Merged

teamleaderleo merged 3 commits into
feat-cmux-nextfrom
owner-idle-cli-call

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

OwnerIdleProbe counted a fresh cmux CLI or MCP connection, one that has not sent a client kind, as idle. Its only caller is the DEV keyless Chief owner restart (ChiefConversationOwner+InstallKey.swift:25, from e859e33 by @lawrencecchen, with c6390e5 and 79ce2f2). So IdleOwnerRestart could restart the Chief owner while one of those connections was in the middle of a request.

Fix

  • OwnerIdleProbe: a local client that names no kind and connected less than callSeconds ago (a minute) counts as a call in flight, so the owner is busy. This is the rule 4f7d43f used for the quiet-restart path (closed cmux-next: local acpmux and cmux-tui move to the bundled build by themselves #23199 branch). An older kindless client is treated as a standing connection, because the daemon's own agent screen detector keeps two kindless connections open for its whole life and they must not block the restart forever. A new reading() returns .idle, .busy, or .callInFlight(seconds:). isIdle() still exists.
  • IdleOwnerRestart: when a kindless client crosses the callSeconds line, the owner sends no event. So on .callInFlight the restart sets a one-shot DemandTimer to try once more at that point. If the call ends sooner, its client-detached event triggers a new probe, as before.
    • Timer stop condition: it is one-shot (scheduleIfIdle, never repeats), and a fired attempt only reschedules if the probe still sees a call in flight.
    • Timer cleanup: it is cancelled once the outcome is decided, and when the actor goes away (DemandTimer.deinit). It holds the actor weakly.

Risk: low. This only affects the DEV keyless Chief owner restart, which becomes more conservative. An owner younger than a minute now waits up to about a minute before it restarts (the detector's connections are young then), where before it restarted immediately.

Test

OwnerRestartWaitsForChatTests.theRestartWaitsWhileACLICallWithoutAKindIsConnected (live daemon): it opens a second connection, clears its kind the way a CLI call has none, and checks that attempt() returns .waiting with the owner pid unchanged. It then closes the call and expects the restart to run. firstOutcome now also returns when the restart's own timer decides the outcome, and the timeout is 90 s for a fresh owner.

Fleet results (cmux-ci run ... package-test-lane.sh suite Packages/macOS/CmuxNext OwnerRestartWaitsForChatTests)

  • Red at 0eb6b8d (the new test only, on the old probe), step 4d2b80aa80caafa937909ebc on cmux12s-Mac-mini:
    ✘ Test theRestartWaitsWhileACLICallWithoutAKindIsConnected() recorded an issue at OwnerRestartWaitsForChatTests.swift:109:13: Expectation failed: await restart.attempt() == .waiting
    ✔ Test theRestartWaitsWhileACLIChatIsAttachedAndRunsAfterItDetaches() passed after 1.595 seconds.
    OwnerRestartWaitsForChatTests                    failed (exit 1)             162s
    
  • Green at 7bec44f (the final head), step 551e8af6334ad7e1691a860c on aws-m4pro-3:
    ✔ Test theRestartWaitsWhileACLIChatIsAttachedAndRunsAfterItDetaches() passed after 61.881 seconds.
    ✔ Test theRestartWaitsWhileACLICallWithoutAKindIsConnected() passed after 61.881 seconds.
    OwnerRestartWaitsForChatTests                    passed                       71s
    
    At 38237e6 the restart already ran, but the new test then shut down through the old owner's removed socket. 7bec44f waits for the new owner first, as the chat test does (shared expectNewOwner).
  • App compile: cmux-ci compile-check --app passed at 7bec44f (job 76a0ab9a59c699fda0235b32).
  • Review: Codex gpt-6-astra xhigh, SHIP at 7bec44f.

No capture: no UI changes. This is the daemon connection layer (CmuxNextDaemon idle probe and restart actor) plus a live-daemon test; nothing is drawn differently.

Credit: e859e33 (@lawrencecchen) built the idle-gated keyless owner restart; this closes the CLI/MCP-call gap in its probe.

Agent session: big-red
🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 26, 2026 08:47
…ief owner restart (red)

The DEV keyless Chief owner restart (e859e33) probes the owner with
OwnerIdleProbe, which counts a fresh local client that names no kind as
idle. A `cmux` CLI or MCP call names no kind, so the owner restarts in the
middle of its request. This test opens such a call and expects the restart
to wait while it is connected and to run after it ends. It fails on this
commit: attempt() returns .started.

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

The DEV keyless Chief owner restart (e859e33, c6390e5, 79ce2f2) asked
OwnerIdleProbe whether the owner is idle, and the probe let every local
client without a kind through. A `cmux` CLI or MCP call names no kind, so
IdleOwnerRestart could restart the owner in the middle of its request.

As in 4f7d43f (the quiet restart's fix on the closed #23199 branch), a
local client without a kind now holds the restart while it is younger than
callSeconds (a minute). An older one is a standing connection: the daemon's
own agent screen detector holds two for its whole life and must not hold
the restart forever. Such a client stops counting as a call without any
owner event, so when the probe sees only calls in flight it answers
callInFlight(seconds:) and IdleOwnerRestart schedules one more attempt for
then (a one-shot DemandTimer, cancelled when the outcome is decided and
with the actor). A call that ends sooner sends client-detached, which
probes again as before.

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

Copy link
Copy Markdown
Collaborator Author

Owned by hb-acpmux on big-red · session

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

Copy link
Copy Markdown
Collaborator Author

Bead cx-7awre created for this PR by the cmux coordinator.

…ner before it shuts down

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

blacksmith-sh Bot commented Oct 26, 2026

Copy link
Copy Markdown

Found 8 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpnf77z463/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpq3yfudin/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
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs
test_bot_attempt_three_drops_stale_owned_pool_placement (main.PathRoutingStructure.
test_bot_attempt_three_drops_stale_owned_pool_placement)/
test_bot_attempt_three_drops_stale_owned_pool_placement (main.PathRoutingStructure.
test_bot_attempt_three_drops_stale_owned_pool_placement)
View Logs

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

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next / cmux-next checks (god files, concurrency, crash safety, l10n) › Checks job structure is red on 6 of 10 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo
teamleaderleo marked this pull request as ready for review October 26, 2026 16:48
@teamleaderleo
teamleaderleo merged commit 93dd059 into feat-cmux-next Oct 26, 2026
138 of 145 checks passed
@teamleaderleo
teamleaderleo deleted the owner-idle-cli-call branch October 26, 2026 16:48
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 7bec44fd Deployed Oct 26, 2026 by teamleaderleo via namespace autofix #3468
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