Repository navigation
cmux-host: report the machine's workload so a Cloud idle pause never freezes a dev server, build or cron job - #36511
Conversation
… the Cloud idle decision The Cloud agent probes every 30 s and adds activity.workload to cloud.vm.status.report under the capability activity-workload: processes above 2% of one CPU, TCP listeners and user timers (cron, cron.d, at, systemd), excluding a documented allowlist of system processes and timers. Names only (comm, port, timer name), never command lines. A probe that cannot read /proc drops the capability, so the Cloud reads the machine busy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
|
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)
web and size checks: green Shipped in:
|
|
Owned by an agent session · session |
…sient timers Review F1/F2 on #36511: a listener table or a process stat that exists but does not read now makes the workload unknown (only an exited process or a missing IPv6 table is skipped), and `systemd-run --user` timers under /run/user/<uid>/systemd/transient count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
|
Found 11 test failures on Blacksmith runners: Failures
...and 1 more test failures. View all on Blacksmith
|
|
Review (codex, router-review): SHIP at 6efd5b2 Reviewer: codex gpt-6-astra high, fast tier. Follow-ups: 3. They land as checklist items in this PR's one follow-up tracking issue in this repo ( SHIP at 6efd5b2 Visual verdict: no images; Leo tries the build
Follow-ups:
|
…onotonic last_busy_at - to_json inserts last_busy_at without indexing (clippy::indexing_slicing, cmux-host is at deny). - Review follow-ups on #36511: /proc/net/tcp is required (only tcp6 may be absent), a /proc entry that does not read makes the workload unknown, and last_busy_at never moves earlier when the clock steps back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
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. |
|
Review (codex, router-review): SHIP at ee4996d Reviewer: codex gpt-6-astra high, fast tier. Follow-ups: 3. They land as checklist items in this PR's one follow-up tracking issue in this repo ( SHIP at ee4996d Visual verdict: no images; Leo tries the build The requested cargo test could not run because
Follow-ups:
|
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Why
Leo, on Cloud work: "If I tell you to do something, don't stick it into dev. Put it into prod. There's nobody else using prod."
The Cloud's idle decision looked only at input and running agent turns. A machine with a dev server, a build or a cron job an agent left running read as idle, and an idle pause would freeze it. This PR makes the guest report what it runs, so the platform can call a machine idle only when nothing is running (the platform side follows in manaflow-ai/cmux-platform).
What changed
cmux-host(the Cloud agent,cloud/workload.rs) probes the machine every 30 s and addsactivity.workloadtocloud.vm.status.report, with the daemon capabilityactivity-workloadwhile the probe reads:busy_processes: processes above 2% of one CPU between two probes. Reaped children count toward their parent, so amakewhose compilers each live a second still reads busy. A process new since the last probe counts all its ticks; pid reuse is caught by the start time.listening_ports: TCP sockets in LISTEN (IPv4 and IPv6, loopback included). A socket with no owner found counts.timers: user crontabs,/etc/cron.dentries, at jobs, transient (systemd-run) timers, and timer units under/etc/systemd/systemor a user's~/.config/systemd/user(masked units skipped).comm, a port number, or a timer name. Never a command line, so no secrets travel.last_busy_atis the last probe that found the machine busy, so the idle period starts no earlier.SYSTEM_PROCESSES,SYSTEM_PROCESS_PREFIXES,SYSTEM_TIMERS,SYSTEM_CRON_D): kernel threads, systemd and its daemons, sshd, cron and atd, journald, dbus, cmux-host, the terminal daemon and its hosts, acpmux, machine health, the image's desktop and the distribution's housekeeping timers./procmakes the workload unknown. The report then dropsactivity-workload, and the platform treats the machine as busy.The block is an extra key in
activity(whose schema allows additional properties), likephasesandlast_person_prompt_at, so the op catalog and the generated clients are unchanged.Changelog
Tests
cargo test -p cmux-host --lib cloud::(fleet): newworkload_tests.rs(stat and/proc/net/tcpparsing, the CPU threshold, pid reuse, the allowlists, the timers reader under a fake root with crontabs, systemd units, masked units and at jobs) and asession.rstest for the report and capability rules.Leaned on
Agent session: agent session
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Stops the Cloud's idle pause from freezing a machine that's actually working:
cmux-hostnow probes the machine every 30 s and reports busy processes, listening ports, and user timers asactivity.workloadunder theactivity-workloadcapability, so a dev server, build, or cron job keeps the machine awake.systemd-run --user). System work is excluded via documented allowlists.comm, port number, timer name), never command lines; anything unreadable in/proc— a listener table or a process stat — marks the workload unknown and drops the capability, so the platform treats the machine as busy. Only an exited process or a missing IPv6 table is skipped; IPv4's listener table is required.last_busy_atis monotonic, so a stepped-back clock never lengthens the idle period. Reports go out when the machine turns busy or quiet or when ports or timers change, not on every probe.Written for commit ee4996d. Summary will update on new commits.