Skip to content

daemon: set macOS LaunchAgent ProcessType and WorkingDirectory#58070

Closed
zssggle-rgb wants to merge 1 commit into
openclaw:mainfrom
zssggle-rgb:fix/launchd-interactive-workingdir
Closed

daemon: set macOS LaunchAgent ProcessType and WorkingDirectory#58070
zssggle-rgb wants to merge 1 commit into
openclaw:mainfrom
zssggle-rgb:fix/launchd-interactive-workingdir

Conversation

@zssggle-rgb

Copy link
Copy Markdown
Contributor

Summary

  • set generated macOS LaunchAgent plists to ProcessType=Interactive
  • always emit a WorkingDirectory, defaulting to / when no explicit directory is provided
  • cover the new plist defaults in launchd install tests

Testing

  • pnpm exec vitest run src/daemon/launchd.test.ts
  • pnpm lint

Closes #58061
Related to #54861

@greptile-apps

greptile-apps Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes two targeted improvements to generated macOS LaunchAgent plists: setting ProcessType=Interactive (ensuring the daemon gets foreground-class scheduling priority) and always emitting a WorkingDirectory key (defaulting to / when none is explicitly provided). Both changes are backed by new and extended tests.

  • ProcessType=Interactive is inserted after ThrottleInterval and before Umask in the plist template; key ordering is irrelevant to launchd since it reads plists as dictionaries, so the placement is fine.
  • WorkingDirectory is now unconditionally emitted via workingDirectory?.trim() || LAUNCH_AGENT_DEFAULT_WORKING_DIRECTORY, replacing the previous conditional "" guard. The round-trip reader (readLaunchAgentProgramArgumentsFromFile) already preserves truthy working directories, so plists written with WorkingDirectory=/ will correctly surface workingDirectory: "/" when read back — consistent with how the rest of the codebase handles it.
  • One minor UI side-effect: status display code that conditionally shows Working dir: (e.g., status.print.ts:86, daemon.ts:242) will now show Working dir: / for agents installed without an explicit directory, which is accurate and arguably an improvement.
  • Tests added: an extension to the existing "KeepAlive+umask" test to assert both new plist keys, and a dedicated new test confirming explicit working directories are preserved.

Confidence Score: 5/5

Safe to merge — changes are well-scoped, well-tested, and have no runtime regressions.

Both new plist keys (ProcessType and WorkingDirectory) are standard launchd fields with clear semantics. The implementation correctly handles the empty/whitespace input edge case, the plist round-trip is consistent, and the added tests cover both the default and explicit-directory cases. No P0 or P1 issues found.

No files require special attention.

Important Files Changed

Filename Overview
src/daemon/launchd-plist.ts Adds ProcessType=Interactive and unconditional WorkingDirectory (defaulting to /) to generated plists; logic is correct and handles edge cases cleanly.
src/daemon/launchd.test.ts Extends existing test to assert new plist keys and adds a dedicated test for explicit working directory preservation; coverage is appropriate.

Reviews (1): Last reviewed commit: "Fix launchd gateway defaults on macOS" | Re-trigger Greptile

@byungsker

This comment was marked as spam.

@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Rechecked CI on this PR.

Current failing jobs are still outside the launchd change scope:

  • CI/check fails in extensions/matrix/... test typing
  • CI/checks-node-test-4 fails in src/plugins/providers.test.ts
  • CI/checks-windows-node-test-3 fails in src/plugins/providers.test.ts

This PR only changes:

  • src/daemon/launchd-plist.ts
  • src/daemon/launchd.test.ts

Local verification for this change passed:

  • pnpm exec vitest run src/daemon/launchd.test.ts
  • pnpm lint

I also attempted to re-run the failed jobs, but GitHub rejected the re-run request for this workflow run (run 23777708072 cannot be rerun).

@openclaw-barnacle openclaw-barnacle Bot added size: S agents Agent runtime and tooling size: XS and removed size: XS size: S labels Mar 31, 2026
@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Following up on this one: the PR is still mergeable and the change remains tightly scoped to macOS launchd plist generation and its tests.

I rechecked the state here because the earlier failing jobs were outside these touched files, so if this looks good I would appreciate a merge/review when convenient. Thanks.

@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Following up here: this change is still narrowly scoped to macOS LaunchAgent plist generation and its tests.

I rechecked it because the earlier CI failures were outside the touched files, and local validation for this change passed. If it looks good from the maintainer side, I would appreciate a review or merge when convenient. Thanks.

@zssggle-rgb
zssggle-rgb force-pushed the fix/launchd-interactive-workingdir branch from 6cdc0f9 to e489f7e Compare April 4, 2026 03:40
@openclaw-barnacle openclaw-barnacle Bot removed the agents Agent runtime and tooling label Apr 4, 2026
@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Refreshed this branch on top of the latest upstream/main and force-pushed the update.

Re-ran:

  • pnpm exec vitest run src/daemon/launchd.test.ts
  • pnpm lint src/daemon/launchd-plist.ts src/daemon/launchd.test.ts
  • pnpm check

@zssggle-rgb
zssggle-rgb force-pushed the fix/launchd-interactive-workingdir branch from e489f7e to 3ca7a8c Compare April 4, 2026 13:25
@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Followed up on the current CI failures after the refresh.

The failing jobs on the current head are pointing at files outside this PR's diff:

  • check: extensions/openrouter/index.ts, extensions/openrouter/index.test.ts
  • checks-fast-contracts-protocol: src/channels/plugins/contracts/channel-import-guardrails.test.ts, src/browser-lifecycle-cleanup.ts, extensions/msteams/src/config-schema.ts
  • checks-node-test: src/secrets/runtime.test.ts, src/secrets/plan.test.ts, src/secrets/exec-secret-ref-id-parity.test.ts

This PR only touches:

  • src/daemon/launchd-plist.ts
  • src/daemon/launchd.test.ts

Local verification on the refreshed branch is still green:

  • pnpm exec vitest run src/daemon/launchd.test.ts
  • pnpm check

So the current red checks look like unrelated repo-baseline failures rather than regressions from the launchd plist change itself.

@zssggle-rgb
zssggle-rgb force-pushed the fix/launchd-interactive-workingdir branch from 3ca7a8c to 7423755 Compare April 6, 2026 04:33
@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Refreshed this PR onto the latest main and force-pushed the branch.

Validation:

  • pnpm exec vitest run src/daemon/launchd.test.ts
  • pnpm check still fails on the current upstream baseline in unrelated files under src/config/*, extensions/*, and src/plugin-sdk/test-helpers.ts after rebasing onto latest main; there are no new failures in the files touched by this PR.

This is back in a mergeable state and ready for another review pass.

@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

CI note: the current red jobs still match the upstream baseline, not this PR diff.

Examples from this run:

  • build-artifacts / build-smoke / checks-fast-contracts-protocol all fail on src/plugin-sdk/test-helpers.ts(2,28): TS2459 about RmOptions from node:fs/promises
  • check-additional reports gateway-watch-regression outcome: failure, but its log shows pnpm build dies first on the same src/plugin-sdk/test-helpers.ts error before the harness completes
  • check is red on unrelated upstream errors in src/config/*, extensions/telegram/*, extensions/discord/*, etc.
  • extension shards are failing in unrelated packages like extensions/memory-core/* and extensions/zalo/*

This PR only touches:

  • src/daemon/launchd-plist.ts
  • src/daemon/launchd.test.ts

Focused validation for this PR is still green:

  • pnpm exec vitest run src/daemon/launchd.test.ts

@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Following up after #72616 landed in main: that PR explicitly kept #58070 separate and did not include the ProcessType/WorkingDirectory plist defaults from this branch.

I rechecked this PR against the current upstream main after #72616, and the branch still applies cleanly with no merge conflicts. The change remains limited to:

  • src/daemon/launchd-plist.ts
  • src/daemon/launchd.test.ts

Greptile previously rated this 5/5 and safe to merge, and the focused launchd test validation was green. If the maintainer side is comfortable with the scoped plist default change, I would appreciate a review/merge when convenient.

@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

Summary
The PR adds ProcessType=Interactive to generated macOS LaunchAgent plists, trims explicit WorkingDirectory values before serialization, and extends launchd plist tests.

Reproducibility: yes. A high-confidence source-level reproduction is to inspect current buildLaunchAgentPlist or the generated install path: current main omits ProcessType, while #58061 provides live A/B startup timing evidence for adding it.

Next step before merge
The remaining concrete blocker is a narrow required changelog entry that automation can add while maintainers choose between this PR and #62308.

Security
Cleared: The diff is limited to launchd plist generation and tests, with no dependency, workflow, lockfile, install-script, downloaded-artifact, package-publishing, or secrets-handling change.

Review findings

  • [P2] Add the required changelog entry — src/daemon/launchd-plist.ts:9
Review details

Best possible solution:

Land one canonical macOS LaunchAgent ProcessType=Interactive implementation that preserves the current state-dir WorkingDirectory behavior, includes the required changelog credit, and explicitly resolves the overlapping #62308 path.

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

Yes. A high-confidence source-level reproduction is to inspect current buildLaunchAgentPlist or the generated install path: current main omits ProcessType, while #58061 provides live A/B startup timing evidence for adding it.

Is this the best way to solve the issue?

Partly yes. Adding the key in the shared plist builder is the narrow maintainable runtime fix, and the branch now avoids the stale / working-directory fallback, but the required changelog entry and canonical PR choice remain unresolved.

Full review comments:

  • [P2] Add the required changelog entry — src/daemon/launchd-plist.ts:9
    This is a user-facing macOS Gateway fix, but the PR does not update CHANGELOG.md. Repo policy requires an active-version changelog entry for user-facing fixes; please add a single-line ### Fixes entry crediting @zssggle-rgb and referencing the launchd reports before merge.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.86

Acceptance criteria:

  • git diff --check
  • pnpm lint src/daemon/launchd-plist.ts src/daemon/launchd.test.ts
  • pnpm -s exec vitest run src/daemon/launchd.test.ts
  • pnpm check:changed in Testbox before merge

What I checked:

Likely related people:

  • steipete: Recent history and prior ClawSweeper review context point to repeated launchd plist, service environment, and daemon install hardening work in the same macOS Gateway service area. (role: recent maintainer; confidence: medium; commits: a6141a5a4196, 3ed3248d7bf5, 67f1266fe8a2; files: src/daemon/launchd-plist.ts, src/daemon/launchd.test.ts, src/daemon/launchd.ts)
  • vincentkoc: Merged fix(daemon): reconcile macOS LaunchAgent supervision state #72616 carried recent launchd supervision-state repair work touching the same macOS Gateway lifecycle surface, and the changelog credits adjacent launchd repair work. (role: recent launchd maintainer; confidence: high; commits: 1c6c538c2980; files: src/daemon/launchd.ts, src/daemon/launchd.test.ts, src/commands/daemon-install-helpers.ts)

Remaining risk / open question:

Codex review notes: model gpt-5.5, reasoning high; reviewed against f43a184103b6.

@zssggle-rgb
zssggle-rgb force-pushed the fix/launchd-interactive-workingdir branch from 7423755 to b4153d0 Compare April 27, 2026 12:25
@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Updated this PR after the clawsweeper review:

  • rebased onto current upstream main
  • kept the ProcessType=Interactive LaunchAgent plist default
  • removed the old unconditional WorkingDirectory=/ fallback so the plist builder now preserves caller-provided working directories without overriding current main’s macOS state-dir install-plan default
  • kept focused coverage for ProcessType=Interactive and explicit WorkingDirectory preservation

Validation:

  • pnpm -s exec vitest run src/daemon/launchd.test.ts (47 passed)
  • pnpm lint src/daemon/launchd-plist.ts src/daemon/launchd.test.ts

The branch is now mergeable on the current PR state, with new CI running.

@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Follow-up on the current CI run: the only failing check is checks-fast-protocol: https://github.com/openclaw/openclaw/actions/runs/24994878496/job/73189179668

The failure is from pnpm protocol:check, which regenerates the Swift protocol models and produces an unrelated diff adding NodePairRemoveParams in:

  • apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
  • apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift

This PR only updates the macOS launchd plist/test path (src/daemon/launchd-plist.ts, src/daemon/launchd.test.ts). The focused local validation for that scope passed:

  • pnpm -s exec vitest run src/daemon/launchd.test.ts
  • pnpm lint src/daemon/launchd-plist.ts src/daemon/launchd.test.ts

Could a maintainer confirm whether checks-fast-protocol is unrelated/base drift here, or whether you want that generated protocol diff folded into this branch?

@zssggle-rgb

Copy link
Copy Markdown
Contributor Author

Follow-up on the current CI run: the only failing check is checks-fast-protocol.\n\nThe failure is from

[email protected] protocol:check /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070
pnpm protocol:gen && pnpm protocol:gen:swift && git diff --exit-code -- dist/protocol.schema.json apps/macos/Sources/OpenClawProtocol/GatewayModels.swift apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift

[email protected] protocol:gen /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070
node --import tsx scripts/protocol-gen.ts

wrote /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070/dist/protocol.schema.json

[email protected] protocol:gen:swift /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070
node --import tsx scripts/protocol-gen-swift.ts

wrote /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070/apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
wrote /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070/apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift, which regenerates the Swift protocol models and produces an unrelated diff adding in:\n- \n- \n\nThis PR only updates the macOS launchd plist/test path (, ). The focused local validation for that scope passed:\n- \n-

[email protected] lint /Users/sjs/Documents/codex/2026-04-27/gmail-plugin-gmail-openai-curated-openclaw/openclaw-pr58070
node scripts/run-oxlint-shards.mjs src/daemon/launchd-plist.ts src/daemon/launchd.test.ts\n\nCould a maintainer confirm whether is unrelated/base drift here, or whether you want that generated protocol diff folded into this branch?

@obviyus

obviyus commented May 9, 2026

Copy link
Copy Markdown
Contributor

Closing this as superseded by #62308, which has now landed on main as a2b8f2a.

The landed change covers the shared generated LaunchAgent plist path and adds ProcessType=Interactive with launchd test coverage. I am not carrying over the WorkingDirectory=/ part here because the reproduced launchd/App Nap fix was the process classification, and keeping the landed patch narrow preserves the current launchd policy on main.

Thanks @zssggle-rgb for the original A/B launchd evidence and patch trail.

@obviyus obviyus closed this May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

launchd gateway startup is delayed for minutes unless plist sets ProcessType=Interactive

3 participants