diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21e75f9ab6d..90f019acc78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,7 @@ Docs: https://docs.openclaw.ai
### Fixes
-- Daemon/macOS launchd: forward proxy env vars into supervised service environments, switch LaunchAgent keepalive policy to crash-only with throttling, and harden restart sequencing to `print -> bootout -> wait old pid exit -> bootstrap -> kickstart`. (#27276) thanks @frankekn.
+- Daemon/macOS launchd: forward proxy env vars into supervised service environments, keep LaunchAgent `KeepAlive=true` semantics, and harden restart sequencing to `print -> bootout -> wait old pid exit -> bootstrap -> kickstart`. (#27276) thanks @frankekn.
- Android/Node invoke: remove native gateway WebSocket `Origin` header to avoid false origin rejections, unify invoke command registry/policy/error parsing paths, and keep command availability checks centralized to reduce dispatcher/advertisement drift. (#27257) Thanks @obviyus.
- CI/Windows: shard the Windows `checks-windows` test lane into two matrix jobs and honor explicit shard index overrides in `scripts/test-parallel.mjs` to reduce CI critical-path wall time. (#27234) Thanks @joshavant.
diff --git a/src/daemon/launchd-plist.ts b/src/daemon/launchd-plist.ts
index 7918e1c8a37..e685cd9941c 100644
--- a/src/daemon/launchd-plist.ts
+++ b/src/daemon/launchd-plist.ts
@@ -1,7 +1,5 @@
import fs from "node:fs/promises";
-const LAUNCHD_THROTTLE_INTERVAL_SECONDS = 5;
-
const plistEscape = (value: string): string =>
value
.replaceAll("&", "&")
@@ -108,5 +106,5 @@ export function buildLaunchAgentPlist({
? `\n Comment\n ${plistEscape(comment.trim())}`
: "";
const envXml = renderEnvDict(environment);
- return `\n\n\n \n Label\n ${plistEscape(label)}\n ${commentXml}\n RunAtLoad\n \n KeepAlive\n \n SuccessfulExit\n \n \n ThrottleInterval\n ${LAUNCHD_THROTTLE_INTERVAL_SECONDS}\n ProgramArguments\n ${argsXml}\n \n ${workingDirXml}\n StandardOutPath\n ${plistEscape(stdoutPath)}\n StandardErrorPath\n ${plistEscape(stderrPath)}${envXml}\n \n\n`;
+ return `\n\n\n \n Label\n ${plistEscape(label)}\n ${commentXml}\n RunAtLoad\n \n KeepAlive\n \n ProgramArguments\n ${argsXml}\n \n ${workingDirXml}\n StandardOutPath\n ${plistEscape(stdoutPath)}\n StandardErrorPath\n ${plistEscape(stderrPath)}${envXml}\n \n\n`;
}
diff --git a/src/daemon/launchd.test.ts b/src/daemon/launchd.test.ts
index 7465666a158..ac092536c5a 100644
--- a/src/daemon/launchd.test.ts
+++ b/src/daemon/launchd.test.ts
@@ -185,7 +185,7 @@ describe("launchd install", () => {
expect(plist).toContain(`${tmpDir}`);
});
- it("writes crash-only KeepAlive policy with throttle interval", async () => {
+ it("writes KeepAlive=true policy", async () => {
const env = createDefaultLaunchdEnv();
await installLaunchAgent({
env,
@@ -196,10 +196,9 @@ describe("launchd install", () => {
const plistPath = resolveLaunchAgentPlistPath(env);
const plist = state.files.get(plistPath) ?? "";
expect(plist).toContain("KeepAlive");
- expect(plist).toContain("SuccessfulExit");
- expect(plist).toContain("");
- expect(plist).toContain("ThrottleInterval");
- expect(plist).toContain("5");
+ expect(plist).toContain("");
+ expect(plist).not.toContain("SuccessfulExit");
+ expect(plist).not.toContain("ThrottleInterval");
});
it("restarts LaunchAgent with bootout-bootstrap-kickstart order", async () => {