Skip to content

fix(macos): reduce idle CPU wakeups#100463

Merged
steipete merged 7 commits into
mainfrom
codex/reduce-mac-idle-cpu
Jul 5, 2026
Merged

fix(macos): reduce idle CPU wakeups#100463
steipete merged 7 commits into
mainfrom
codex/reduce-mac-idle-cpu

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Closes #100451

What Problem This Solves

The macOS menu-bar app performed avoidable work while idle. Its node-mode coordinator reread configuration and queried macOS permissions once per second even while connected, and the critter animation task woke every 350 ms even when its next randomized idle animation was seconds away.

Why This Change Was Made

Node registration refresh is now event-driven for configuration, endpoint, permission, preference, and app-activation changes. A disconnected-only 30-second probe preserves recovery for Gateway sessions paused by authentication or pairing failures without polling during normal connected operation.

The critter now sleeps until its nearest animation deadline while idle, retains the existing 350 ms working cadence, and reschedules elapsed animation deadlines after a pause.

This adds some coordinator code while removing the steady-state polling path and consolidating node input gathering into one canonical refresh flow.

User Impact

Users can leave the macOS app running with fewer idle CPU wakeups and less repeated configuration/TCC work. Node registration still refreshes when relevant inputs change, and active-work animation behavior is unchanged.

Evidence

  • Developer ID-signed branch app passed deep/strict codesign verification and launched successfully.
  • Installed-build 45-second Time Profiler baseline showed the one-second node loop repeatedly entering MacNodeModeCoordinator, config loading, and permission checks.
  • Signed branch-build 30-second idle sample recorded zero matching frames for MacNodeModeCoordinator, OpenClawConfigFile, PermissionManager.status, AppleScriptPermission, or CritterStatusLabel tick/body work. At 39 seconds it reported 0.0% CPU and 0:00.35 total CPU time including startup; sampled top stacks were sleeping syscalls.
  • swift build --package-path apps/macos --build-path apps/macos/.build/arm64
  • swift test --package-path apps/macos --build-path apps/macos/.build/arm64 --filter CritterIconRendererTests — 5 passed. The current main test target has an unrelated missing OnboardingView.hasCrestodianSetupAuth symbol, so this focused run used and then removed a test-only compile bridge.
  • Targeted SwiftFormat and SwiftLint — clean, 0 violations.
  • Blacksmith Testbox tbx_01kwsydbsd5yg0vprs6pb21rhp (coral-prawn) — check:changed apps lane passed all 5 shards.
  • Fresh autoreview — no accepted/actionable findings after fixes for endpoint changes, pause/resume deadlines, live permission changes, notification isolation, and paused Gateway reconnect recovery.

Known proof gap: this host's configured localhost Gateway was unavailable/rejected its existing configuration, so sustained connected-state and live node-registration refresh observation were not possible. The signed app launch, disconnected backoff, focused tests, review, and idle samples passed.

No changelog entry: this repository updates the changelog during release preparation.

Agent transcript: not included.

@openclaw-barnacle openclaw-barnacle Bot added app: macos App: macos size: S maintainer Maintainer-authored PR labels Jul 5, 2026
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready verification for head fc5696a1f51; the PR was synced unchanged onto current main, and the follow-up commit only synchronizes the native i18n source inventory required by CI.

  • Developer ID-signed dist/OpenClaw.app passed codesign --verify --deep --strict --verbose=4 and launched.
  • Installed baseline: 45-second Time Profiler plus process sample showed the one-second coordinator loop repeatedly loading config and querying permissions.
  • Branch result: 30-second idle process sample recorded zero matching frames for MacNodeModeCoordinator, OpenClawConfigFile, PermissionManager.status, AppleScriptPermission, and critter tick/body work. Top stacks were sleeping syscalls; at 39 seconds the process reported 0.0% CPU and 0:00.35 total CPU time including startup.
  • swift build --package-path apps/macos --build-path apps/macos/.build/arm64 — passed.
  • swift test --package-path apps/macos --build-path apps/macos/.build/arm64 --filter CritterIconRendererTests — 5 passed. Current main has an unrelated test-target compile hole (OnboardingView.hasCrestodianSetupAuth), so the focused run used a temporary test-only compile bridge that was removed immediately afterward.
  • Targeted SwiftFormat and SwiftLint — clean.
  • Blacksmith Testbox tbx_01kwsydbsd5yg0vprs6pb21rhp (coral-prawn) — apps check:changed passed all 5 shards.
  • Fresh autoreview — no accepted/actionable findings.

Known environment gap: the host's configured localhost Gateway was unavailable/rejected its existing configuration, preventing sustained connected-state and live registration-refresh observation. Signed app launch, disconnected backoff, focused scheduler behavior, remote changed gates, and before/after idle profiling passed.

@steipete
steipete force-pushed the codex/reduce-mac-idle-cpu branch from 76be675 to a1504da Compare July 5, 2026 21:22
@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 6:30 PM ET / 22:30 UTC.

Summary
This PR changes the macOS node coordinator to refresh registration from events instead of steady polling, adjusts the status-label animation scheduler to sleep until animation deadlines, and updates focused native inventory/test coverage.

Reproducibility: yes. for a source-level path: current main still reads config/permissions in the Mac node loop and ticks the critter every 350 ms while idle. I did not run a signed macOS profiler capture in this read-only review, but the PR includes before/after profiler and sample evidence.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/tui/tui-pty-local.e2e.test.ts, serialized state: test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts, unknown-truncated-pull-files. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100451
Summary: This PR is the candidate fix for the linked macOS idle polling and animation wakeup bug; no separate canonical remaining item was established.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Have the macOS owner either add connected-state registration-refresh proof or explicitly accept that proof gap before merge.

Risk before merge

  • [P1] The PR body notes that sustained connected-state and live node-registration refresh observation were not possible; if a refresh trigger is missed, the macOS node could keep stale capabilities, permissions, or endpoint state until another activation or reconnect event.

Maintainer options:

  1. Prove Connected Refresh Before Merge (recommended)
    Capture connected-state node registration refresh after a relevant config, endpoint, preference, or permission change so the removed polling path is covered by real behavior proof.
  2. Owner-Accept The Gap
    A macOS owner can accept the idle-profiler and focused-test evidence as enough and own any remaining refresh-path risk after merge.

Next step before merge

  • [P2] This open PR needs macOS owner review of the availability/proof gap; there is no narrow automated repair to queue from this review.

Maintainer decision needed

  • Question: Is the macOS owner comfortable merging the event-driven node refresh with the documented connected-state proof gap, or should connected-state registration-refresh proof be required first?
  • Rationale: The code removes steady polling from an availability-sensitive node registration path, and the contributor proved idle wakeups but explicitly could not observe sustained connected-state refresh behavior.
  • Likely owner: steipete — steipete is the current PR author and the strongest recent-history owner for the macOS node/critter code path.
  • Options:
    • Require Connected-State Proof (recommended): Ask for a signed-app or Testbox run showing config, endpoint, preference, or permission changes refresh node registration while already connected before merge.
    • Accept Current Proof: Merge with the existing signed-app idle profiling, focused tests, and Testbox evidence while the macOS owner accepts the connected-state proof gap.

Security
Cleared: No concrete security or supply-chain concern was found in the current-main merge delta, which is limited to macOS Swift runtime/scheduler changes and native source inventory.

Review details

Best possible solution:

Land the macOS event/deadline-driven fix after the macOS owner accepts or fills the connected-state registration-refresh proof gap, with release-note context staying in the PR body or squash message.

Do we have a high-confidence way to reproduce the issue?

Yes for a source-level path: current main still reads config/permissions in the Mac node loop and ticks the critter every 350 ms while idle. I did not run a signed macOS profiler capture in this read-only review, but the PR includes before/after profiler and sample evidence.

Is this the best way to solve the issue?

Yes, this is the right layer: the node coordinator should refresh when registration inputs change, and the critter should sleep until animation deadlines while preserving the Swift-concurrency task used to avoid the TimerPublisher crash path. The only remaining gap is live proof for connected-state registration refresh.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c4a862ab53c5.

Label changes

Label changes:

  • add merge-risk: 🚨 availability: The PR removes the steady macOS node polling fallback, so missed refresh events could leave node registration stale or disconnected despite green CI.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body/comment provide after-fix real behavior proof through signed-app launch, before/after Time Profiler and process-sample output, focused Swift validation, and Testbox apps checks; the connected-state registration gap remains a merge-risk item, not a proof absence for the reported idle wakeups.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body/comment provide after-fix real behavior proof through signed-app launch, before/after Time Profiler and process-sample output, focused Swift validation, and Testbox apps checks; the connected-state registration gap remains a merge-risk item, not a proof absence for the reported idle wakeups.

Label justifications:

  • P2: This is a concrete macOS performance and energy fix with limited blast radius, not a crash, security issue, or blocked onboarding path.
  • merge-risk: 🚨 availability: The PR removes the steady macOS node polling fallback, so missed refresh events could leave node registration stale or disconnected despite green CI.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body/comment provide after-fix real behavior proof through signed-app launch, before/after Time Profiler and process-sample output, focused Swift validation, and Testbox apps checks; the connected-state registration gap remains a merge-risk item, not a proof absence for the reported idle wakeups.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body/comment provide after-fix real behavior proof through signed-app launch, before/after Time Profiler and process-sample output, focused Swift validation, and Testbox apps checks; the connected-state registration gap remains a merge-risk item, not a proof absence for the reported idle wakeups.
Evidence reviewed

What I checked:

Likely related people:

  • steipete: Recent GitHub history shows steipete owning the macOS gateway/node coordinator and critter files, and this PR also fixes the linked macOS idle-wakeup report. (role: feature owner and recent area contributor; confidence: high; commits: 6a7b62889e8c, 330ba1fa3194, 46a67eea4c4c; files: apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift, apps/macos/Sources/OpenClaw/CritterStatusLabel+Behavior.swift, apps/macos/Sources/OpenClaw/PermissionManager.swift)
  • BunsDev: GitHub path history shows BunsDev recently changed adjacent Mac node TLS and screen capability behavior in the same coordinator area. (role: adjacent macOS node contributor; confidence: medium; commits: 6a41a5421265, f377db101564; files: apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift)
  • thewilloftheshadow: Older path history shows thewilloftheshadow carried the previous Moltbot macOS critter path through a rename, but not the current idle-polling behavior itself. (role: adjacent rename contributor; confidence: low; commits: c1a7917de73c; files: apps/macos/Sources/Moltbot/CritterStatusLabel+Behavior.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-05T21:30:47.873Z sha 06b64f5 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T21:39:04.682Z sha 06b64f5 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T21:48:05.582Z sha 12e0aee :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T21:55:29.631Z sha 12e0aee :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 5, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12e0aeec28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CHANGELOG.md

### Fixes

- **Agent empty replies:** surface a visible failure when a completed interactive turn has no deliverable reply, including queued follow-ups, while preserving explicit silence, pending continuations, and committed side effects. (#100456) Thanks @mushuiyu886.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the hand-written changelog entry

The root AGENTS.md says CHANGELOG.md is release-only and that release generation owns entries for normal fixes/direct commits. Adding this Unreleased line here means the release generator can later duplicate or conflict with this note; keep the release-note context in the commit/PR metadata instead and leave the changelog untouched until release prep.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation extensions: qa-lab extensions: codex labels Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot added channel: imessage Channel integration: imessage app: android App: android app: web-ui App: web-ui labels Jul 5, 2026
@clawsweeper clawsweeper Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jul 5, 2026
@clawsweeper clawsweeper Bot removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord channel: slack Channel integration: slack gateway Gateway runtime scripts Repository scripts docker Docker and sandbox tooling labels Jul 5, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 5, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc5696a1f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Boolean(prepared.ackReactionPromise) &&
Boolean(reactionMessageTs) &&
cfg.messages?.statusReactions?.enabled !== false;
cfg.messages?.statusReactions?.enabled === true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve Slack status reaction default

For existing Slack installs that have ack reactions enabled but never set messages.statusReactions.enabled, this flips the shipped behavior from enabled-unless-false to opt-in. Those users silently lose the queued/thinking/tool/done/error lifecycle reactions after upgrade, and the paired prepareSlackMessage change now sends only a static ack instead, so this default change needs a compatibility path or an explicit pre-merge release decision rather than changing the runtime default here.

Useful? React with 👍 / 👎.

@steipete
steipete merged commit 37c67b0 into main Jul 5, 2026
164 of 172 checks passed
@steipete
steipete deleted the codex/reduce-mac-idle-cpu branch July 5, 2026 22:35
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
* fix(macos): reduce idle CPU wakeups

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: android App: android app: macos App: macos app: web-ui App: web-ui channel: discord Channel integration: discord channel: imessage Channel integration: imessage channel: slack Channel integration: slack docker Docker and sandbox tooling docs Improvements or additions to documentation extensions: codex extensions: google extensions: openai extensions: qa-lab gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: XL status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: macOS app performs avoidable idle polling and animation wakeups

1 participant