Skip to content

cmux NEXT: one queue that brings other machines' daemons to the app's build - #25387

Merged
teamleaderleo merged 6 commits into
feat-cmux-nextfrom
lane/hb-daemon-update-policy
Oct 26, 2026
Merged

teamleaderleo merged 6 commits into
feat-cmux-nextfrom
lane/hb-daemon-update-policy

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Part 4 of the rebuild of #23199 and #24070 (adopted by hb-acpmux). Builds on #25386 (merged), and is rebased onto feat-cmux-next.

The queue that brings other machines' daemons to the app's build. Nothing offers it a machine yet: acpmux ssh peers and Cloud machines are the next PRs.

Leo: "BRO CANT YOU JUST LIKE SUSPEND SHIT AFTER A TOOL CALL/TURN THEN JUST GO AND AUTOUPDATE OUR TEAMMATES NEED ACPMUX UPDATING TOO..."

Leo: "OUR SHIT IS HARDLY EVER GOING TO GO IDLE. IT JUST WONT. YOU'LL JUST HAVE TO ACCEPT IT BREAKING AT SOME POINT BUT IT RESUMES WHATEVER IT INTERRUPTED. END OF STORY FOR THE DAEMON UPDATE."

Leo-ask: ask-48bbaec1d4
Leo-ask: ask-061e3574a6

Change

DaemonUpdatePolicy (from #24070 at bd4892c), one per app (shared), fed by offer(_:):

Timers and their stop conditions

  • The drain loop. It ends when the queue is empty, which happens when every machine is done, left for the next launch, or the toggle went off.
  • The backoff nap (clock.sleep, at most 30 minutes). It ends at its deadline or when a new offer cancels it. Its machines stop after 6 hours of not being able to update.

Tests

DaemonUpdatePolicyTests (fake machines, an auto-advancing test clock):

  • an old machine is updated; a machine on the build, of unknown build or nogit is left alone; a dirty bundled build pushes nothing;
  • aTargetOnANewerOrItsOwnBuildIsLeftAlone (red first: 03733e8 is cmux NEXT: update acpmux ssh peers and Cloud machines to the app's build, also mid-turn #24070's policy, which updates them; CI at that commit's earlier copy f56f2c5 showed this test failing);
  • aBusyTargetIsUpdatedMidTurnOnTheFirstAsk (red first: 59e2fba has these tests on the 10-minute default, and this test fails there; the next commit sets the default to zero);
  • withACapANeverIdleTargetIsUpdatedWhileBusyAtTheCap: with the optional cap, idle asks at 0, 2 and 6 minutes, then mid-turn at 10;
  • aTargetBusyAlsoWhileBusyIsLeftAfterSixHours: 2, 4, 8, 16, then 11 × 30 minutes, all mid-turn; unrecorded; it leaves the board;
  • one at a time;
  • a retried machine that reached the build meanwhile leaves the board;
  • a failure is recorded and asks for one notice, also after a relaunch; a rollback is retried only on the next build; no binary is not recorded; a machine handled elsewhere leaves no state;
  • an urgent machine goes first and doesn't wait behind a busy one's backoff;
  • offers are deduped while running; the toggle off runs nothing; a machine offered while the toggle-off is reported still updates.

Observed / Not run

  • CI at c7b8f0a (run 40301784433): DaemonUpdatePolicyTests and DaemonUpdateTargetTests passed, among them aBusyTargetIsUpdatedMidTurnOnTheFirstAsk, aFailureWhoseLedgerCannotBeWrittenIsNotRetried and aBundledVersionThatNeverAnswersEndsAtItsBound. The daemon tests passed.
  • The swift test job is red the way it is on other PRs today: the test process is killed (exit 143), and the failing tests (AppKit commit boundary, sidebar rows, panel warm-up, browser tab mirror, ActionRunCreated) are in code this PR does not touch and fail on other PRs' runs too.
  • Not run: no real daemon or peer was updated.

No capture: no visible UI.

Agent session: big-red
🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

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

Review a417ed5: 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=pr25387 -f ref=lane/hb-daemon-update-policy -f platform=macos -f backend_mode=local

web and size checks: green

Tour of c7b8f0a0ee (run): no media. The tour job failed before the tour ran (build or setup); the run log has the output.

@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
@blacksmith-sh

This comment has been minimized.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-405df created for this PR by the cmux coordinator.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next / cmux-next checks (god files, concurrency, crash safety, l10n) › Script tests (pin-cmux-tui, embed-cef, ensure-cef store) is red on 11 of 12 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 added a commit that referenced this pull request Oct 26, 2026
An acpmux ssh peer of the app's daemon (`acpmux host add NAME ssh://host`)
becomes a DaemonUpdateTarget: `acpmux --json host update NAME --binary-dir
DIR [--if-idle]` on the bundled CLI, with the published
cmux-tui-acpmux-<target> staged when the peer asks for its platform's
binary. The CLI's reply (acpmux cli/host_update.rs) and the daemon's
`_acpmux/status` peers are read in one place each. Nothing offers these
targets yet: the launch wiring and the reconnect sweep come next.

From #24070 (daemon-peer-update bd4892c), on the queue of #25387, whose
default asks idle first and mid-turn after 10 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo force-pushed the lane/hb-daemon-update-policy branch 2 times, most recently from 38b2f1b to b417291 Compare October 26, 2026 08:33
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
An acpmux ssh peer of the app's daemon (`acpmux host add NAME ssh://host`)
becomes a DaemonUpdateTarget: `acpmux --json host update NAME --binary-dir
DIR [--if-idle]` on the bundled CLI, with the published
cmux-tui-acpmux-<target> staged when the peer asks for its platform's
binary. The CLI's reply (acpmux cli/host_update.rs) and the daemon's
`_acpmux/status` peers are read in one place each. Nothing offers these
targets yet: the launch wiring and the reconnect sweep come next.

From #24070 (daemon-peer-update bd4892c), on the queue of #25387, whose
default asks idle first and mid-turn after 10 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo and others added 2 commits October 26, 2026 09:20
… test that it never moves one back

DaemonUpdatePolicy (from #24070, daemon-peer-update bd4892c) brings other
machines' daemons to the app's build, one at a time: idle first, and
mid-turn once a machine stayed busy 10 minutes. Nothing offers it a
target yet.

The new aTargetOnANewerOrItsOwnBuildIsLeftAlone fails here: a Linux host's
own acpmux-update.timer (#24232) keeps it on the newest feat-cmux-next
build, and the policy as #24070 wrote it moves such a host back to the
app's older build (the timer then moves it forward again: two restarts
for nothing).

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

A Linux host whose acpmux-update.timer (#24232) already moved it to a
newer feat-cmux-next build, or one running a build with local changes,
is dropped from the queue instead of moved back to the app's build.
aTargetOnANewerOrItsOwnBuildIsLeftAlone passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo force-pushed the lane/hb-daemon-update-policy branch from b417291 to a417ed5 Compare October 26, 2026 09:21
teamleaderleo and others added 2 commits October 26, 2026 09:31
…n from the first ask

Leo: "OUR SHIT IS HARDLY EVER GOING TO GO IDLE. IT JUST WONT. YOU'LL JUST HAVE TO ACCEPT IT
BREAKING AT SOME POINT BUT IT RESUMES WHATEVER IT INTERRUPTED. END OF STORY FOR THE DAEMON
UPDATE." The default asks no idle question first; the 10-minute cap stays an option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…for idle

updateBusyAfter defaults to zero: every machine is updated mid-turn when the policy reaches it,
and the restarted daemon resumes the turn it interrupted. A machine that cannot update now
(unreachable, another update running) keeps the bounded backoff. The toggle's help says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
An acpmux ssh peer of the app's daemon (`acpmux host add NAME ssh://host`)
becomes a DaemonUpdateTarget: `acpmux --json host update NAME --binary-dir
DIR [--if-idle]` on the bundled CLI, with the published
cmux-tui-acpmux-<target> staged when the peer asks for its platform's
binary. The CLI's reply (acpmux cli/host_update.rs) and the daemon's
`_acpmux/status` peers are read in one place each. Nothing offers these
targets yet: the launch wiring and the reconnect sweep come next.

From #24070 (daemon-peer-update bd4892c), on the queue of #25387, whose
default asks idle first and mid-turn after 10 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo and others added 2 commits October 26, 2026 09:43
… --version that never answers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…undled --version probe is bounded

A target with a final outcome is settled for this run as well as written to the ledger, so a
ledger that could not be written never lets the next drain retry a rollback. The bundled
acpmux --version the queue waits on before its first target gets a 10 s bound.

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

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra xhigh): SHIP at c7b8f0a

teamleaderleo added a commit that referenced this pull request Oct 26, 2026
An acpmux ssh peer of the app's daemon (`acpmux host add NAME ssh://host`)
becomes a DaemonUpdateTarget: `acpmux --json host update NAME --binary-dir
DIR [--if-idle]` on the bundled CLI, with the published
cmux-tui-acpmux-<target> staged when the peer asks for its platform's
binary. The CLI's reply (acpmux cli/host_update.rs) and the daemon's
`_acpmux/status` peers are read in one place each. Nothing offers these
targets yet: the launch wiring and the reconnect sweep come next.

From #24070 (daemon-peer-update bd4892c), on the queue of #25387, whose
default asks idle first and mid-turn after 10 minutes.

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

Copy link
Copy Markdown
Collaborator Author

high-signal review link / link is red on 16 of 18 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 10:30
@teamleaderleo
teamleaderleo merged commit 8abc52e into feat-cmux-next Oct 26, 2026
148 of 154 checks passed
@teamleaderleo
teamleaderleo deleted the lane/hb-daemon-update-policy branch October 26, 2026 10:30
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
An acpmux ssh peer of the app's daemon (`acpmux host add NAME ssh://host`)
becomes a DaemonUpdateTarget: `acpmux --json host update NAME --binary-dir
DIR [--if-idle]` on the bundled CLI, with the published
cmux-tui-acpmux-<target> staged when the peer asks for its platform's
binary. The CLI's reply (acpmux cli/host_update.rs) and the daemon's
`_acpmux/status` peers are read in one place each. Nothing offers these
targets yet: the launch wiring and the reconnect sweep come next.

From #24070 (daemon-peer-update bd4892c), on the queue of #25387, whose
default asks idle first and mid-turn after 10 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
* cmux NEXT daemon update: acpmux ssh peers as update targets

An acpmux ssh peer of the app's daemon (`acpmux host add NAME ssh://host`)
becomes a DaemonUpdateTarget: `acpmux --json host update NAME --binary-dir
DIR [--if-idle]` on the bundled CLI, with the published
cmux-tui-acpmux-<target> staged when the peer asks for its platform's
binary. The CLI's reply (acpmux cli/host_update.rs) and the daemon's
`_acpmux/status` peers are read in one place each. Nothing offers these
targets yet: the launch wiring and the reconnect sweep come next.

From #24070 (daemon-peer-update bd4892c), on the queue of #25387, whose
default asks idle first and mid-turn after 10 minutes.

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

* cmux NEXT daemon update: tests for a held update lock, --keep-newer and a run past its deadline

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

* cmux NEXT daemon update: --keep-newer on every peer update, a held lock is busy, a stopped run is gone

Every host update passes --keep-newer (#25425), so a peer its own self-update moved past the
app's build after the app read it is left alone under the host's lock. failed/updateRunning
(another update holds the lock) reads as busy and is asked again, never recorded. The CLI runs
through AsyncProcess: past its deadline it gets SIGTERM, then SIGKILL, and the run returns only
once the child is gone.

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

* cmux NEXT daemon update: tests that a stopped host update confirms its child exited

Red: the run returns at the SIGKILL without waiting for the exit, and
there is no exit watch yet. The next commit adds it.

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

* cmux NEXT daemon update: a stopped host update returns once its child exited

The kernel's exit event is armed at the launch (AcpmuxChildExit), and a run
past its deadline waits for it, at most 10 s after the SIGKILL, before the
queue moves on. A child that outlives even SIGKILL is reported as such.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@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 — c7b8f0a0 Deployed Oct 26, 2026 by teamleaderleo via namespace autofix #3294
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