Repository navigation
cmux-next: keep the Mac awake while agents work - #21730
Conversation
New Settings > Agents > Agent Sessions row, "Keep Mac Awake While Agents Work": Off, While Plugged In (default) or Always. While a local agent runs a turn (an acpmux session, or a tab's agent hooks or OSC 7501 working record), idle system sleep stays off. The display can still sleep and closing the lid still sleeps the Mac. - schemas/settings/source/sessions.json is the row's source; the Swift descriptor, parser constants and choice enum are generated. - KeepAwakeService holds one ProcessInfo activity for every reason, so the Keep Mac Awake action and the setting never end each other's hold. The action now goes through it and still holds on battery. - PowerSourceMonitor follows IOKit's power-source notification on the main run loop (no polling); unplugging releases a While Plugged In hold. - Agents may not set the key (userOnly). - Strings in all 21 locales of the settings catalog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ce when shown again (GhosttyNextKit a19c884fa, cx-8w027.19.1) A terminal the warm set evicted showed an empty pane until its new session attached and drew. Ghostty emptied every released drawable (kIOSurfacePurgeableEmpty in IOSurface.deinit), and a hidden surface releases its swap chain, so even the layer's presented frame was blank (ghostty-next PR 42: a plain release; the last owner frees the pages). - A paused surface marks its presented frame volatile and makes it non-volatile before it shows again; a purged one leaves the layer empty until Ghostty's next frame, as before. - Eviction keeps the presented IOSurface (no copy, volatile), at most the warm set terminal capacity, oldest first; a frame dropped by the bound leaves a 480 px hover picture; memory pressure drops them with no renders. - The new session shows it over its first surface (TerminalFrameHold begin(lastFrame:)) until its first content is parsed and drawn, at most 3 s; a purged frame or a hidden mount shows nothing. Hover cards picture it on demand. - debug.surfaces: last_frames outcomes, per pane last_frame_holds, frame_held. Proof: scripts/cmux-next/evicted-terminal-frame-live.py. Pins GhosttyNextKit release xcframework-a19c884fa8d132378ae838dcba95654b177b6723-apple-v6 (checksum 94ff3178... from SHA256SUMS, matching the downloaded zip) and moves the ghostty-next gitlink, package-notices.json and vt-link-graph.json to it (only pkg/macos/iosurface/iosurface.zig changed since e6a27a1fb). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Awake Exports from the fleet export step at 4beacc0 (run-swift-testing-suites.sh, export-settings); defaults snapshot from defaults_guard.py snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s last frame at its reveal (cx-8w027.19.1) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
|
Bead |
…essions-keep-awake # Conflicts: # schemas/settings-export/settings-schema.sources.sha256 # schemas/settings/settings-schema.json
…rame for the read; a frame in flight at the pause is not reclaimed; no last frame at capacity 0 (cx-8w027.19.1, review) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Receipt for
|
|
all web/size checks green |
Exports from the fleet export step at 011a67c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by |
|
|
… sources that moved (cx-8w027.23)
…LastFrames evict/show/report); the frame shows at the reveal; CmuxNextApp does not grow (cx-8w027.19.1) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e strip's window, one topology per turn for every pane that changed (cx-8w027.23) - PaneController.Snapshot.connected is gone: apply never read it, and the read re-ran every pane's snapshot when the daemon connected (16 per 16-pane restore). A reconnect with a new daemon still re-maps through generation and surfaces. - BrowserProfileService.roomDefault takes the room of the window the strip or sidebar avatar draws in (WindowState.profileID, observed), so a room's profile badge follows that window; the lookup of WindowManager state (not observed) stays only for one-time choices (a new tab's profile). - A pane whose part of the focus topology changed marks the workspace (setNeedsTopology); FocusCoordinator builds and sends one topology per owner for the whole main-actor turn, at its end or before any state read or event (I4), instead of one per pane.
#20765 made the not-connected screen's status label selectable without focusRingType = .none, so check:text-focus fails every feat-cmux-next PR. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… the pending topology; the turn-end reduction runs detached; what the settled observer queues runs (review of cx-8w027.23 slice 1)
…21716) * release-notes(next): fit browser highlights to the What's New limits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * release-notes(next): live links, dev-build wording for remote tabs Replaces cmux.com/whats-new (404) with real try-it actions, says the remote browser tab entries are development-build features (their action is DEV/Nightly only), and drops 'instant' from the tab-switch entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) * release-notes(next): fit app highlights to the What's New limits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * release-notes(next): live links and exact profile-menu wording Replaces two 404 links (cmux.com/whats-new, docs/agent-integrations) with real actions or docs pages, and says what the profile button opens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…57) (#21648) * feat(next): workspace name source and revision, like tab names (hq#1957) Workspaces now record whether their name came from a person or from auto-naming, the way tab names do (NameSource { User, Auto } and a name_revision), and the daemon decides whether an automatic rename lands. - RegistryWorkspace and the mux Workspace carry name_source and name_revision, stored in two additive workspaces columns (legacy rows read user/0). Both commit paths re-check the stored row's name, source and revision inside the transaction. - rename-workspace and workspace.rename accept source, expected_generation, expected_name_revision and release. An automatic rename never replaces a person's name (operation.failed, reason_code name_pinned), never empties one (name_empty), and loses to any rename after the revision it read (revision.conflict). source auto with release hands a pinned name back. - Workspace projections (raw tree, list-workspaces, resource extra) expose name_source and name_revision; the daemon advertises workspace-name-source-v1. - CLI: cmux workspace rename --source auto --expected-generation G --expected-name-revision N, and --release-to-auto. - Spec, regenerated SDK bindings, cmux-app.d.ts and resource descriptor hashes follow; optchat-chief's RenameWorkspaceRequest literal gains the new fields. - The app's DaemonCapabilities moves workspace-name-source-v1 from unservedByBundledDaemon to optional, since the bundled daemon now serves it. Carved from #20710 onto current feat-cmux-next. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): project workspace name provenance like the journal states it (hq#1957) feat-cmux-next tests that landed after #20710's base failed on this slice: - batch_close and resource_effects: the journal decorates every stored workspace with extra.name_source/name_revision, but the projected workspace values had no extra, so the public fold never matched and every commit restated every workspace. Every workspace value builder (deltas, full and scoped projection, normalized registry deltas, resource snapshots) now carries the same extra. - key_close_cannot_rebind_a_live_durable_workspace_identity: creating a workspace at a key bound to another live workspace hit the name fence (revision.conflict) before the identity check. The name fence now applies only to the same workspace (numeric id), and the resource store checks identity before the name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(next): workspace_resource_upsert lives with workspace renames (hq#1957) Its name provenance parameter pushed mux.rs past the 1000-line god-file budget (check-no-godfiles.sh); the helper moves to mux/workspace_rename.rs unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…quash (#21690) * test(cmux-next): older history is asked for once per page Fails on feat-cmux-next: a streaming commit near the top asks for the same older page again, because 50a0c60 (#21194) restored the effect #21369 had keyed on the first row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(cmux-next): avoid duplicate older-history loads (#21369) (cherry picked from commit 8f6f9cb) * perf(cmux-next): gate find highlight repaints by transcript changes (#21384) * perf(cmux-next): gate find highlight repaints by transcript changes * fix(cmux-next): preserve find repaint triggers after fold reveals * style(acpmux): format find highlight effect * test(next): carry apps empty-state selector through PR 21384 * test(next): carry apps empty-state selector through find highlight PR (cherry picked from commit afec4de) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(acpmux): start a no-ask mode from a session in it or an approved preset
A `session/new` that asks for a mode that doesn't ask, without the
person, now has two ways through:
- Inherit: a caller that is itself an acpmux session in that exact mode on
the same harness family. Each harness gets ACPMUX_SESSION_TOKEN, an HMAC
of its session id under a per-run in-memory secret, and
ACPMUX_SESSION_TOKEN_SOCKET. The token is read only from a unix socket
connection's first `initialize`. The caller's mode is read at request
time.
- Approved preset: `_acpmux/presets {name, approveMode: true}` from the
person records the sha256 of the preset's contents. The approval counts
only while the resolve and the spawn both used those exact contents, for
the preset's own mode, with no request overrides other than a folder.
A start mode never applies to an adopt without the person, and a proven
caller session that asks never gets the full-access default for its
chats. The refusal names where to approve (cmux NEXT on this host, or the
preset to approve there once), with {reason, host, mode, preset} in
error.data. Web and peer clients never get the host name.
person_auto_start.rs runs in the hermetic test environment, and its
person-key pipe is close-on-exec so parallel tests' daemons never hold
each other's key pipe open.
Carved from #20653.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(acpmux): an approved preset with a route, and env that names the caller token
Red on 116ab01:
- an approved preset plus a request `route` passes the start gate and
reaches the handler ("no route"), where it should need the person;
- a harness profile env that sets ACPMUX_SESSION_TOKEN reaches the agent
in place of acpmux's caller token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(acpmux): a route counts as an override, env never sets the caller token
Review fixes for the start gate:
- A request `route` on an approved preset now needs the person, like its
own model, effort, policy or env: a route swaps the provider base URL
and keys.
- A profile's, preset's or request's env no longer replaces
ACPMUX_SESSION_TOKEN or ACPMUX_SESSION_TOKEN_SOCKET. That env is
layered after `caller_env`, so the spawn drops both keys from it.
- The CLI's daemon readiness pipe is close-on-exec from creation
(`std::io::pipe`, pipe2(O_CLOEXEC) where the OS has it) instead of a
`pipe` then `fcntl`, which raced with a fork on another thread.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tate (cx-sya4n) (#21664) * test(cmux-next): the static look reaches tabs, the attention ring, the agent pane and every label (cx-sya4n) Red: tabs keep their icon set's marks and colored dots, the attention ring blinks, the agent pane's theme has no statusIndicators look and indicators have no tooltip or VoiceOver label (compile failure). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: the static status look everywhere, and every indicator names its state (cx-sya4n) Tabs draw the static look's still marks (the badge too, never a dot told apart by color alone); the pane attention ring is the steady ring under Static; the agent pane's theme sends statusIndicators (static under Static or Reduce Motion). Every StatusIndicatorView's tooltip and VoiceOver label is the state's short name (StatusIndicatorState .shortLabel, nine strings in every catalog locale), and a tab's needs-input VoiceOver text names the blocked kind. Carved from #20511. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ief Dock squash (#21699) * test(cmux-next): every URL chip hover card class has a rule Fails on feat-cmux-next: 50a0c60 (#21194) dropped the .cv-link-preview rules #21199 added, while LinkChips.tsx still renders those classes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cmux-next): restore the URL chip hover card styles (#21199) 50a0c60 (#21194, a stale-base squash) removed the nine .cv-link-preview rules while LinkChips.tsx still renders them, so the card drew unstyled. Restored byte for byte from 5106cc9. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test(acpmux): a saved model or effort pick is announced to watchers A New Tab prewarmed before a pick draws the old start effort and the chat then starts on the pick. Fails: note_pick saves the new start default but sends no _acpmux/harnesses_changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(acpmux): announce a saved model or effort pick to watchers note_pick makes the pick the harness's start in _acpmux/harnesses, but told nobody, so a New Tab prewarmed before the pick kept drawing the old start effort until the chat started on the pick. It now sends _acpmux/harnesses_changed, as a saved mode pick already announces start_mode_changed; pages re-read the catalog on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…essions-keep-awake
Review of #21730: CmuxNextApp only shrinks (check-app-size.sh), so KeepAwakePolicy, PowerSourceMonitor and KeepAwakeService move to a new CmuxNextKeepAwake target with their tests. The App keeps a one-line start and the Keep Mac Awake binding; its source is 10 lines under the base. The power-source callback now hops to the main actor with a Task instead of MainActor.assumeIsolated (a banned crash class). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r change Review of #21730: a CmuxNextSidebar change now also selects CmuxNextKeepAwakeTests (CmuxNextKeepAwake depends on CmuxNextBridge), so test_a_shared_module_selects_its_dependents lists it. KeepAwakeService sets the setting and the agents-working fact in one policy write, so the hold cannot drop between the two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
cmux-next tour of The tour job failed before the tour ran (build or setup); the run log has the output. The tour produced no media. Tours are data in |
* cmux-next: keep the Mac awake while agents work (sessions.keepAwake) New Settings > Agents > Agent Sessions row, "Keep Mac Awake While Agents Work": Off, While Plugged In (default) or Always. While a local agent runs a turn (an acpmux session, or a tab's agent hooks or OSC 7501 working record), idle system sleep stays off. The display can still sleep and closing the lid still sleeps the Mac. - schemas/settings/source/sessions.json is the row's source; the Swift descriptor, parser constants and choice enum are generated. - KeepAwakeService holds one ProcessInfo activity for every reason, so the Keep Mac Awake action and the setting never end each other's hold. The action now goes through it and still holds on battery. - PowerSourceMonitor follows IOKit's power-source notification on the main run loop (no polling); unplugging releases a While Plugged In hold. - Agents may not set the key (userOnly). - Strings in all 21 locales of the settings catalog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate settings exports and defaults for sessions.keepAwake Exports from the fleet export step at 4beacc0 (run-swift-testing-suites.sh, export-settings); defaults snapshot from defaults_guard.py snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate settings exports after merging feat-cmux-next Exports from the fleet export step at 011a67c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: phone access is opt-in, with a start-workspaces switch and keep-awake Settings > Accounts > Phone Access, the Codex-style model: - phone.allowConnections, "Let Your Phone Use This Mac": the phone listener runs only while it is on. Off on a fresh install; a Mac whose phone host already ran (a v2 cache in its state directory) keeps serving phones, written on once (PhoneAccessMigration), so no shipping phone link breaks. Its help is the privacy disclosure: only the Mac's name goes to the cmux account; workspace names, folders and terminal output go only over the encrypted link; branch names and repo URLs are never uploaded. - phone.startSessions, "Let Your Phone Start New Workspaces" (on): off, a phone can still list, follow, type into and close what runs, but workspace and terminal creation is refused on the compat RPC (MobileCompatMethods.startsSessions) and on daemon lanes (DaemonLanePolicy.startsSessions). Read per request, so it applies to connected phones at once. - phone.keepAwake, "Keep Mac Awake for Your Phone": Off, While Plugged In (default) or Always, while phones can reach this Mac. A new reason in KeepAwakePolicy. The transport stays swappable (cmuxterm-hq#2499): PhoneAccessGate and the settings name no transport; MobileHostService and MobileIrxHost are the only Iroh-aware parts. No agent may set the keys (network, userOnly). Strings in all 21 locales. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate settings exports and defaults for phone access Exports from the fleet export step at caa8806. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: keep awake lives in its own target (CmuxNextKeepAwake) Review of #21730: CmuxNextApp only shrinks (check-app-size.sh), so KeepAwakePolicy, PowerSourceMonitor and KeepAwakeService move to a new CmuxNextKeepAwake target with their tests. The App keeps a one-line start and the Keep Mac Awake binding; its source is 10 lines under the base. The power-source callback now hops to the main actor with a Task instead of MainActor.assumeIsolated (a banned crash class). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: phone lane never takes a program; phone access lives in its own target Review of #21741: - Security: DaemonLanePolicy refuses respawn, env, shell_args, argv and command on every phone command. move-tab-to-split and move-tab-to-column take `respawn` (a fresh shell with its own cwd, env and shell_args), which the creation-field allowlist did not cover, so a phone could start a shell with DYLD_* in its environment whatever phone.startSessions said. That hole predates this PR. move-tab(-group)-to-new-workspace now count as starting a workspace. Tests cover respawn with env, with starting on and off. - Privacy copy: the Mac's name, platform, app version and relay address go to the account; workspace names, folders, full paths and terminal output only over the encrypted link; none of it, and no branch name or repo URL, is sent to cmux servers. 21 locales. - Size cap: MobileHostService, MobileReadinessRelay and PhoneAccessFollower move to a new CmuxNextPhoneAccess target (the App injects the Mac's name). CmuxNextApp source is 77 lines under the base. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 8a504de - regenerated webviews/src/pages/settings/generated/strings.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39168490067 * cmux-next: route test knows the keep-awake tests; one policy write per change Review of #21730: a CmuxNextSidebar change now also selects CmuxNextKeepAwakeTests (CmuxNextKeepAwake depends on CmuxNextBridge), so test_a_shared_module_selects_its_dependents lists it. KeepAwakeService sets the setting and the agents-working fact in one policy write, so the hold cannot drop between the two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: phone access disclosure names the device ID and bundle ID too Review of #21741: the v2 device registration also carries the Mac's device ID and the app's bundle ID, so the copy lists them. 21 locales. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate settings exports for the phone access copy and the security fix Exports from the fleet export step at 3786631. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate settings exports after merging feat-cmux-next Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: phone access disclosure lists everything the registration sends Review of #21741: the v2 device registration (MobileIrxHost) also carries the build channel (tag and environment), the Mac's connection key (Iroh endpoint public key) and the account and team IDs. The copy now lists all of it. 21 locales. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 8018780 - regenerated webviews/src/pages/settings/generated/strings.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39173203742 * cmux-next: regenerate settings exports for the fuller phone access disclosure Generated only: fleet export step at 8018780. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at c469a0b - regenerated webviews/src/pages/settings/generated/strings.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39175821839 * cmux-next: regenerate settings exports after merging feat-cmux-next Generated only: fleet export step at c469a0b. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: settings page strings for the exported phone rows The autofix at 9d39f9d ran before the settings export at c469a0b and dropped the phone rows' strings; regenerated from the current schema. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: route test knows the phone access tests CmuxNextPhoneAccess depends on CmuxNextKeepAwake (and so on CmuxNextBridge), so a CmuxNextSidebar change also selects CmuxNextPhoneAccessTests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: regenerate settings exports after merging feat-cmux-next Generated only: fleet export step at 83932f8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com>
Summary
A long agent turn can stall when the Mac goes to idle sleep. Settings > Agents now has an "Agent Sessions" group with Keep Mac Awake While Agents Work (
sessions.keepAwake). The choices are Off, While Plugged In (default) and Always. While a local agent runs a turn, idle system sleep stays off. That covers an acpmux session, whether or not a tab shows it, and a tab whose agent hooks or OSC 7501 record say it's working. The display can still sleep, and closing the lid still sleeps the Mac. A While Plugged In hold ends as soon as the Mac is unplugged.How it works (all in a new
CmuxNextKeepAwaketarget; CmuxNextApp keeps a one-line start and the action binding, and its source shrinks by 10 lines):KeepAwakeServiceholds oneProcessInfoactivity for every reason. The existing Keep Mac Awake action now goes through it too, so the action and the setting never end each other's hold. The action still holds on battery, because the person asked for it.PowerSourceMonitorfollows IOKit's power-source notification on the main run loop and hops to the main actor with a Task, so nothing polls and nothing callsassumeIsolated.KeepAwakePolicyis the pure rule, and it's table-tested.schemas/settings/source/sessions.json; the Swift descriptor, parser constants and choice enum are generated from it. Agents may not set the key (userOnly). Strings are in all 21 locales of the settings catalog.This is the first of six settings PRs that bring Claude-desktop-style session settings and a Codex-style phone flow to cmux NEXT. The plan is in Leo's brief.
Privacy disclosure copy for Leo (lands with the phone PR, not this one)
This is the draft footer for the "Phone access" group under Settings > Accounts, for your edits:
What is sent where today (checked in
CmuxNextMobile):cmux-v2.debussy.workers.dev): the Mac's display name, platform, app version and its relay address. Nothing about folders or workspaces.Testing
run-swift-testing-suites.sh,export-settings) built the package and its tests, then regenerated the settings schema, MDM docs and stamp, which are committed here.package-test-lane.sh suiteat 39e6b33:SessionKeepAwakeSettingTests(5),KeepAwakePolicyTests(5),SettingsSchemaExportTestsandManagedPreferencesManifestTestspassed on aws-m4pro-2.check-no-godfiles.sh --base,check-concurrency.sh,gen-settings-sources.py --check,localization_catalog.py check(no findings in this catalog), anddefaults_guard.py snapshot/check-fresh.bun test(no install on this box), and no tagged build, so the real sleep hold is unverified live. Runpmset -g assertionsduring an agent turn to see it.workingstate can hold the Mac awake. The hold follows acpmux's indicator and the tabs' status; a time cap is a follow-up.sessions.keepAwake = pluggedIn.Changelog
Added: Settings can keep the Mac awake while agents work: off, while plugged in (default) or always.
Proof
Settings row only, no screenshot yet (no tagged build from this Linux box).
🤖 Generated with Claude Code