Skip to content

fix(macos): LaunchAgent starts gateway on external home volumes#89967

Merged
steipete merged 1 commit into
openclaw:mainfrom
zhangguiping-xydt:feat/issue-87199
Jul 3, 2026
Merged

fix(macos): LaunchAgent starts gateway on external home volumes#89967
steipete merged 1 commit into
openclaw:mainfrom
zhangguiping-xydt:feat/issue-87199

Conversation

@zhangguiping-xydt

@zhangguiping-xydt zhangguiping-xydt commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #87199

Summary

  • Problem: macOS LaunchAgent plists with service environment entries made the generated env-wrapper script the executable that launchd spawned; on permission-constrained home/state volumes that can fail at posix_spawn before the gateway starts.
  • Solution: Generate shell-first LaunchAgent ProgramArguments (/bin/sh, wrapper path, env file path, then the gateway command) and keep legacy wrapper-first plists readable/rewriteable.
  • What changed: src/daemon/launchd.ts, src/daemon/launchd-plist.ts, and src/daemon/launchd.test.ts now share the shell-first env-wrapper contract.
  • What did NOT change: Service environment values still live in the owner-only generated env file, not in the plist; gateway CLI command construction remains the existing supported gateway --port <port> run path.

Real behavior proof

  • Behavior or issue addressed: A generated macOS LaunchAgent must no longer directly spawn the generated env-wrapper from the user's home/state volume. The LaunchAgent should bootstrap and kickstart under macOS launchd, load the env file, start the gateway, and answer gateway health/status without Permission denied, EX_CONFIG, or posix_spawn failure.

  • Real environment tested: macOS Darwin 25.5.0 arm64, Node v24.15.0, OpenClaw 2026.6.2 from PR worktree SHA e977dc1fc177. The proof used a temporary HOME/OPENCLAW_HOME/OPENCLAW_STATE_DIR and unique label ai.openclaw.launchd-proof-fa9d9c1f, then changed the generated wrapper mode from 0700 to 0600 before launchctl bootstrap to exercise the direct-wrapper-spawn permission surface.

  • Exact steps or command run after this patch:

    PROOF_REPO=/Users/zhangguiping/daily_pr_work/openclaw-87199-proof \
    PROOF_PORT=19532 \
    PROOF_PRINT_CLEANUP=1 \
      node --import tsx /Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-87199-evidence/macos-launchd-live-proof.mjs \
        > /Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-87199-evidence/macos-launchd-live-proof-2.out \
        2> /Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-87199-evidence/macos-launchd-live-proof-2.err
    
    launchctl bootout gui/501/ai.openclaw.launchd-proof-fa9d9c1f
    launchctl bootstrap gui/501 /var/folders/76/w5rbbmt53d9f9wzqs3kzq3580000gn/T/openclaw-launchd-proof-fa9d9c1f-As3pt8/Library/LaunchAgents/ai.openclaw.launchd-proof-fa9d9c1f.plist
    launchctl enable gui/501/ai.openclaw.launchd-proof-fa9d9c1f
    launchctl kickstart -k gui/501/ai.openclaw.launchd-proof-fa9d9c1f
    launchctl print gui/501/ai.openclaw.launchd-proof-fa9d9c1f
    node --import tsx src/entry.ts gateway call health --json --url ws://127.0.0.1:19532 --token <redacted> --timeout 5000
    node --import tsx src/entry.ts gateway status --json --url ws://127.0.0.1:19532 --token <redacted>
    launchctl bootout gui/501/ai.openclaw.launchd-proof-fa9d9c1f
    
    node scripts/run-vitest.mjs src/daemon/launchd.test.ts src/daemon/program-args.test.ts src/commands/daemon-install-helpers.test.ts
    pnpm format:check src/daemon/launchd.ts src/daemon/launchd-plist.ts src/daemon/launchd.test.ts
    node scripts/run-oxlint.mjs src/daemon/launchd.ts src/daemon/launchd-plist.ts src/daemon/launchd.test.ts
    git diff --check
  • Evidence after fix: Live macOS launchd proof output from macos-launchd-live-proof-2.out:

    {
      "platform": "Darwin 25.5.0",
      "arch": "arm64",
      "node": "v24.15.0",
      "head": "e977dc1fc177",
      "label": "ai.openclaw.launchd-proof-fa9d9c1f",
      "serviceTarget": "gui/501/ai.openclaw.launchd-proof-fa9d9c1f",
      "port": 19532,
      "programArguments": [
        "/bin/sh",
        "/var/folders/.../.openclaw-state/service-env/ai.openclaw.launchd-proof-fa9d9c1f-env-wrapper.sh",
        "/var/folders/.../.openclaw-state/service-env/ai.openclaw.launchd-proof-fa9d9c1f.env",
        "/Users/zhangguiping/.nvm/versions/node/v24.15.0/bin/node",
        "--import",
        "tsx",
        "/Users/zhangguiping/daily_pr_work/openclaw-87199-proof/src/entry.ts",
        "gateway",
        "--port",
        "19532",
        "--allow-unconfigured"
      ],
      "plistExecutable": "/bin/sh",
      "secretInPlist": false,
      "envFileExists": true,
      "envFileContainsToken": true,
      "wrapperModeBefore": "0700",
      "wrapperModeAfter": "0600",
      "bootstrap": { "code": 0 },
      "enable": { "code": 0 },
      "kickstart": { "code": 0 },
      "runtime": { "status": "running", "state": "active", "pid": 85513, "cachedLabel": false },
      "gatewayHealth": { "code": 0, "stdout": { "ok": true } },
      "gatewayStatus": { "code": 0, "rpc": { "ok": true } },
      "gatewayStatusRpcOk": true,
      "noPermissionDenied": true
    }

    launchctl print gui/501/ai.openclaw.launchd-proof-fa9d9c1f showed the real service running from /bin/sh:

    state = running
    program = /bin/sh
    arguments = {
      /bin/sh
      /var/folders/.../.openclaw-state/service-env/ai.openclaw.launchd-proof-fa9d9c1f-env-wrapper.sh
      /var/folders/.../.openclaw-state/service-env/ai.openclaw.launchd-proof-fa9d9c1f.env
      /Users/zhangguiping/.nvm/versions/node/v24.15.0/bin/node
      --import
      tsx
      /Users/zhangguiping/daily_pr_work/openclaw-87199-proof/src/entry.ts
      gateway
      --port
      19532
      --allow-unconfigured
    }
    working directory = /Users/zhangguiping/daily_pr_work/openclaw-87199-proof
    pid = 85513
    

    Gateway RPC proof from the launchd-started process:

    gateway call health: code=0, ok=true, durationMs=43
    gateway status: code=0, service.runtime.status=running, service.runtime.state=active, rpc.ok=true, port.listeners[0].pid=85513, ppid=1
    launchd stdout tail: [gateway] ready; [heartbeat] started; [ws] ⇄ res ✓ health 50ms cached=true
    cleanup: launchctl bootout gui/501/ai.openclaw.launchd-proof-fa9d9c1f code=0
    
  • Observed result after fix: macOS launchd successfully bootstrapped and kickstarted the generated LaunchAgent even after the generated wrapper was made non-executable (0600). The service ran as /bin/sh, loaded environment values from the generated env file, started the gateway on port 19532, and gateway call health plus gateway status both succeeded against the launchd-owned process. The live proof also confirms secrets stayed out of the plist (secretInPlist=false) while the env file contained the token (envFileContainsToken=true). The gateway command remains the existing supported gateway --port <port> form; this PR does not change it to a literal gateway run subcommand, and the launchd health/status proof shows that command starts the gateway correctly.

  • What was not tested: I did not mount a separate external home volume. Instead, the proof used a temporary macOS HOME/state directory and changed the generated wrapper to 0600 before launchd bootstrap to cover the same direct-spawn permission failure surface that this patch removes. No other known gaps.

  • Fix classification: Root cause fix.

Review findings addressed

  • The LaunchAgent proof now runs on macOS with real launchctl bootstrap, launchctl kickstart, launchctl print, gateway call health, and gateway status against the generated service.
  • The proof verifies the raw plist shape launchd consumes, confirms /bin/sh is the program launchd starts, confirms owner-only env-file loading, and confirms there is no Permission denied, EX_CONFIG, or posix_spawn failure in the launchd-started gateway path.

Regression Test Plan

  • Coverage level: Unit test plus live macOS launchd proof.
  • Target test file: src/daemon/launchd.test.ts.
  • Scenario locked in: A LaunchAgent with service environment entries serializes raw ProgramArguments as /bin/sh, generated wrapper path, generated env file path, then the original gateway command; an old wrapper-first plist reads back and restart-rewrites into that same shell-first shape.
  • Why this is the smallest reliable guardrail: The unit regression sits at the plist writer/readback boundary that launchd consumes, while the live proof exercises the macOS launchd runtime path without mocking launchd.
  • src/daemon/program-args.test.ts remains green to confirm the existing gateway --port <port> command form is unchanged.
  • src/commands/daemon-install-helpers.test.ts remains green to confirm service env planning still passes wrapper/env values through correctly.

Root Cause

  • Root cause: When service environment entries existed, LaunchAgent generation wrote ProgramArguments as [wrapperPath, envFilePath, ...gatewayCommand]. On macOS setups where the generated wrapper lives on a permission-constrained home/state volume, launchd could fail at posix_spawn before the wrapper loaded the env file or execed the gateway. Status/readback code normalized the command for display, which hid the raw plist shape that launchd actually executes.
  • Missing detection / guardrail: Tests asserted normalized program arguments but did not assert the raw generated plist array, and the earlier proof did not run real macOS launchctl bootstrap/kickstart against the generated LaunchAgent.

Merge risk

  • Why it matters / User impact: Affected macOS users with service env entries, especially external-home setups, can get an immediately exiting gateway LaunchAgent. This keeps the gateway unavailable after install/restart.
  • What did NOT change: This only changes macOS LaunchAgent env-wrapper serialization/readback; it does not change gateway CLI command construction, service env collection, provider auth, plist inline EnvironmentVariables, Linux/Windows service behavior, or the gateway --port <port> command shape.
  • Architecture / source-of-truth check: The source-of-truth boundary is prepareLaunchAgentProgramArguments plus readLaunchAgentProgramArgumentsFromFile; generation and restart repair now share the same canonical shell-first wrapper contract while legacy wrapper-first plists are normalized only during read/rewrite.
  • Risk labels considered: merge-risk:platform, merge-risk:compatibility.
  • Risk explanation: The change affects macOS LaunchAgent plist generation and legacy plist rewrite behavior. It does not change gateway CLI command construction or embed env values into the plist.
  • Why acceptable: The patch is limited to the launchd env-wrapper boundary, keeps old wrapper-first plists readable, preserves owner-only env-file loading, and now has focused tests plus a live macOS launchd proof for the generated command shape.
  • Maintainer-ready confidence: High for the LaunchAgent env-wrapper root cause. The only remaining scope note is intentional: the gateway command remains the existing supported gateway --port <port> run path rather than changing CLI command construction in this PR.
  • Patch quality notes: Minimal root-cause change at the LaunchAgent generation/readback source of truth; no fallback, retry, timeout, or status-only workaround.

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: S proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 3, 2026
@clawsweeper

clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 4:53 PM ET / 20:53 UTC.

Summary
The PR changes macOS LaunchAgent service-env plist generation/readback to launch the generated env wrapper through /bin/sh and adds regression tests for shell-first and legacy wrapper-first layouts.

PR surface: Source +30, Tests +59. Total +89 across 3 files.

Reproducibility: yes. at source level: current main still puts the generated wrapper in ProgramArguments[0] when service env entries exist, and the linked issue plus PR proof cover the launchd failure path. I did not run a fresh live external-home reproduction in this read-only review.

Review metrics: 1 noteworthy metric.

  • LaunchAgent executable layout: 1 executable position changed; 1 legacy layout preserved. The executable launchd spawns is compatibility-sensitive for service-env installs, and the PR keeps legacy wrapper-first plists readable for restart rewrite.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #87199
Summary: This PR is the open candidate fix for the canonical env-wrapper direct-spawn failure; external-APFS plist placement and status-audit issues share daemon symptoms but have distinct roots.

Members:

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

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

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

Risk before merge

Maintainer options:

  1. Accept Shell-First LaunchAgent Layout (recommended)
    Maintainers can land this focused fix after accepting that existing service-env LaunchAgents will be rewritten so launchd spawns /bin/sh instead of the generated wrapper.
  2. Request Exact External-Home Proof
    Maintainers can ask for one additional macOS proof using a migrated external-home volume before accepting the shell-first serialization change.

Next step before merge

  • [P2] No repair lane is needed because there is no concrete code finding; the remaining action is maintainer acceptance and landing of a compatibility-sensitive LaunchAgent layout change.

Security
Cleared: No concrete security or supply-chain concern found; the diff changes daemon LaunchAgent serialization/tests, adds no dependencies or workflows, and keeps secrets out of the plist.

Review details

Best possible solution:

Land the shell-first LaunchAgent env-wrapper fix after maintainer acceptance of the compatibility tradeoff, while keeping external-APFS plist-location work separate.

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

Yes, at source level: current main still puts the generated wrapper in ProgramArguments[0] when service env entries exist, and the linked issue plus PR proof cover the launchd failure path. I did not run a fresh live external-home reproduction in this read-only review.

Is this the best way to solve the issue?

Yes. Fixing the raw launchd executable shape at the LaunchAgent generation/readback boundary is narrower than changing gateway command construction or status parsing, while the external-APFS plist-location problem remains separate.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: The PR targets a bounded macOS gateway LaunchAgent startup failure with a clear linked bug and limited platform/setup blast radius.
  • merge-risk: 🚨 compatibility: The diff changes macOS LaunchAgent plist serialization and restart rewrite behavior for existing service-env managed installs.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body and maintainer comment include after-fix macOS launchd live output plus gateway health/status results showing the shell-first LaunchAgent starts and keeps secrets out of the plist.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and maintainer comment include after-fix macOS launchd live output plus gateway health/status results showing the shell-first LaunchAgent starts and keeps secrets out of the plist.
Evidence reviewed

PR surface:

Source +30, Tests +59. Total +89 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 2 41 11 +30
Tests 1 63 4 +59
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 104 15 +89

What I checked:

  • Repository policy read: Root AGENTS.md was read fully and applied; no scoped AGENTS.md owns src/daemon, and the root policy treats setup/startup compatibility changes as merge-risk review surfaces. (AGENTS.md:29, 010b61746379)
  • Current main behavior: Current main still prepares service-env LaunchAgent ProgramArguments as wrapper path, env file path, then the gateway command, so launchd directly spawns the generated wrapper. (src/daemon/launchd.ts:277, 010b61746379)
  • Latest release behavior: The latest release tag v2026.6.11 has the same wrapper-first service-env LaunchAgent ProgramArguments, so this PR is not obsolete in shipped code. (src/daemon/launchd.ts:277, e085fa1a3ffd)
  • PR head generation fix: PR head returns ProgramArguments as /bin/sh, wrapper path, env file path, then the original gateway command when service env entries exist. (src/daemon/launchd.ts:280, cf2a74c999ab)
  • PR head readback compatibility: PR head recognizes both shell-first and legacy wrapper-first generated env-wrapper layouts and unwraps from the corresponding command start index. (src/daemon/launchd-plist.ts:105, cf2a74c999ab)
  • Regression coverage: PR head asserts raw plist ProgramArguments are shell-first for service-env installs and that legacy wrapper-first plists rewrite to shell-first on restart. (src/daemon/launchd.test.ts:849, cf2a74c999ab)

Likely related people:

  • steipete: CONTRIBUTING.md lists steipete, the PR is assigned to steipete, and GitHub file history shows multiple recent launchd lifecycle and macOS update hardening commits in the central files. (role: listed project owner and recent launchd lifecycle contributor; confidence: high; commits: 975d40d47483, ca236d098d62, 49e5091f180e; files: src/daemon/launchd.ts, src/daemon/launchd-plist.ts, src/daemon/launchd.test.ts)
  • vincentkoc: Recent history includes service-state cutover and launchd helper refactor work touching the same launchd service-env/readback files. (role: adjacent service-state and launchd contributor; confidence: medium; commits: a15797ad1129, 900a834c6088; files: src/daemon/launchd.ts, src/daemon/launchd-plist.ts, src/daemon/launchd.test.ts)
  • frankekn: CONTRIBUTING.md lists frankekn for Gateway, and earlier merged history touched LaunchAgent restart and proxy env passthrough in the same launchd/plist area. (role: listed Gateway owner and adjacent service-env contributor; confidence: medium; commits: b9757114290f; files: src/daemon/launchd.ts, src/daemon/launchd-plist.ts, src/daemon/launchd.test.ts)
  • TurboTheTurtle: Recent merged work added generated-wrapper overwrite warnings and status diagnostics in the same launchd service-env area. (role: recent adjacent contributor; confidence: medium; commits: ca2f4c0d6772, 49e5091f180e; files: src/daemon/launchd.ts, src/daemon/launchd.test.ts)
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.

@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: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 3, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 8, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 8, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jun 15, 2026
@zhangguiping-xydt zhangguiping-xydt changed the title fix #87199: [Bug]: macOS LaunchAgent generated by 2026.5.22 uses env-wrapper and missing gateway run, causing EX_CONFIG / Permission denied on external home volumes fix(macos): LaunchAgent starts gateway on external home volumes Jun 22, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 23, 2026
@zhangguiping-xydt
zhangguiping-xydt force-pushed the feat/issue-87199 branch 2 times, most recently from 5d98e18 to 9a5d665 Compare June 23, 2026 15:41
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jun 24, 2026
@steipete steipete self-assigned this Jul 3, 2026
@steipete

steipete commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Maintainer live proof

Land-ready review complete at 9a5d665faa2200db803d614101cfaab796ceaa0a.

  • Best-fix review: Apple launchd uses ProgramArguments[0] as the executable when Program is absent. Putting /bin/sh there fixes the reported spawn boundary; moving the plist or changing gateway arguments would not.
  • Focused regression proof: node scripts/run-vitest.mjs src/daemon/launchd.test.ts src/daemon/program-args.test.ts src/commands/daemon-install-helpers.test.ts — 143 tests passed.
  • Real macOS proof: Crabbox Tart lease cbx_3af0722cade5 (tidal-shrimp-555b), Darwin 24.6.0 arm64, Node 24.16.0. The proof used stageLaunchAgent, changed the generated wrapper to mode 0600 before bootstrap, then ran real launchctl enable, bootstrap, kickstart -k, print, and bootout.
  • Observed after fix: plist executable /bin/sh; launchctl print state running with program /bin/sh; file-backed environment reached the launched process; readback recovered the original command and environment; secret marker was absent from the plist; cleanup succeeded.
  • Fresh autoreview: clean, no accepted/actionable findings (019f29b2-2d72-73c1-936f-7820f986ba26).
  • Exact-head hosted CI/Testbox gates: passed.

Known proof boundary: this VM does not have a literal migrated external-home volume. Making the generated wrapper non-executable exercises the same direct-wrapper posix_spawn boundary. External-APFS plist placement remains separate work in #60398 / #90923.

@steipete
steipete force-pushed the feat/issue-87199 branch from 9a5d665 to cf2a74c Compare July 3, 2026 20:43
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 3, 2026
@steipete
steipete merged commit 1755a9d into openclaw:main Jul 3, 2026
106 of 108 checks passed
@steipete

steipete commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: S 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 LaunchAgent generated by 2026.5.22 uses env-wrapper and missing gateway run, causing EX_CONFIG / Permission denied on external home volumes

2 participants