Skip to content

fix(desktop): recover from stale openclaw launchd state#734

Merged
lefarcen merged 7 commits intomainfrom
fix/desktop-openclaw-stale-launchd-recovery
Apr 1, 2026
Merged

fix(desktop): recover from stale openclaw launchd state#734
lefarcen merged 7 commits intomainfrom
fix/desktop-openclaw-stale-launchd-recovery

Conversation

@mrcfps
Copy link
Copy Markdown
Contributor

@mrcfps mrcfps commented Apr 1, 2026

What

Make launchd startup recover from stale OpenClaw partial-state leftovers instead of attaching to a broken packaged runtime.

Why

Packaged desktop could fail to start when controller remained launchd-managed but OpenClaw was left behind as stale launchd/orphan state. In that case the app attached to inconsistent runtime metadata until users manually booted out the job and killed lingering OpenClaw processes.

How

  • detect partial launchd state before attach and force a clean cold start instead of reusing recovered runtime ports
  • expand packaged OpenClaw process matching so stale openclaw.mjs, openclaw-gateway, and extracted sidecar paths are cleaned up proactively
  • add a startup regression test covering packaged partial-state recovery and runtime-ports cleanup

Affected areas

  • Desktop app (Electron shell)
  • Controller (backend / API)
  • Web dashboard (React UI)
  • OpenClaw runtime
  • Skills
  • Shared schemas / packages
  • Build / CI / Tooling

Checklist

  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes
  • pnpm generate-types run (if API routes/schemas changed)
  • No credentials or tokens in code or logs
  • No any types introduced (use unknown with narrowing)

Notes for reviewers

The key path to review is the launchd attach decision in apps/desktop/main/services/launchd-bootstrap.ts, especially the new partial-state cleanup before recovered ports are reused.

Copy link
Copy Markdown

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

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: 3f278473bf

ℹ️ 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 apps/desktop/main/services/launchd-bootstrap.ts Outdated
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 1, 2026

Deploying nexu-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 92786e4
Status: ✅  Deploy successful!
Preview URL: https://faaff29f.nexu-docs.pages.dev
Branch Preview URL: https://fix-desktop-openclaw-stale-l.nexu-docs.pages.dev

View logs

Copy link
Copy Markdown

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

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: 92786e4766

ℹ️ 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 apps/desktop/main/services/launchd-bootstrap.ts Outdated
Copy link
Copy Markdown

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

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: b817eb2f70

ℹ️ 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 apps/desktop/main/services/launchd-bootstrap.ts Outdated
Copy link
Copy Markdown
Collaborator

@lefarcen lefarcen left a comment

Choose a reason for hiding this comment

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

Review

The partial launchd state detection (controllerRunning !== openclawRunning → force cold start) is the right fix for the reported issue. A few things to address:

P0: Process patterns narrowed too far — dev mode orphan cleanup regressed

The old patterns matched both dev and packaged mode:

"node.*controller/dist/index.js",
"node.*openclaw.mjs gateway",
"openclaw-gateway",

The new patterns only match ~/.nexu/runtime/ (packaged) paths:

"\\.nexu/runtime/controller-sidecar/dist/index\\.js",
"\\.nexu/(runtime/)?openclaw-sidecar",

This means killOrphanNexuProcesses() and ensureNexuProcessesDead() can no longer detect dev-mode orphans via the pgrep fallback path. The safety net in teardownLaunchdServices() is also affected.

Suggest keeping both dev and packaged patterns:

const NEXU_PROCESS_PATTERNS = [
  "\\.nexu/runtime/controller-sidecar/dist/index\\.js",  // packaged
  "\\.nexu/(runtime/)?openclaw-sidecar",                  // packaged
  "node.*controller/dist/index\\.js",                     // dev
  "node.*openclaw\\.mjs gateway",                         // dev
] as const;

P1: Partial state bootout doesn't wait for process exit

The new partial-state cleanup calls bootoutService() then immediately runs killOrphanOpenclawProcesses():

await Promise.allSettled([
  controllerRunning ? launchd.bootoutService(labels.controller) : Promise.resolve(),
  openclawRunning ? launchd.bootoutService(labels.openclaw) : Promise.resolve(),
]);
await killOrphanOpenclawProcesses({ ... });

bootoutService() sends launchctl bootout but doesn't wait for the process to actually exit. The orphan kill and subsequent cold start may race against the still-exiting process. Same gap exists in the stale session (line 467) and version mismatch (line 530) bootout paths.

Consider using bootoutAndWaitForExit here, or at minimum adding a short delay.

Minor: Scenario 27 test doesn't assert orphan kill

The test verifies bootout and runtime-ports.json deletion, but doesn't assert that process.kill(77777, "SIGKILL") was called. Since killing the stale orphan is the core fix, this assertion would strengthen the test.

Minor: NEXU_MANAGED_OPENCLAW_PATH_PATTERNS duplicates entry from NEXU_PROCESS_PATTERNS

The single entry "\\.nexu/(runtime/)?openclaw-sidecar" is identical in both arrays. Could extract a shared constant or filter from NEXU_PROCESS_PATTERNS.


Everything else (net mock refactor, scenario renumbering, findProcessPidsByPatterns extraction) looks good.

Copy link
Copy Markdown

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

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: cb8d485245

ℹ️ 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 tests/desktop/launchd-integration.test.ts
@mrcfps
Copy link
Copy Markdown
Contributor Author

mrcfps commented Apr 1, 2026

@lefarcen Addressed your review items:

  • partial/stale launchd cleanup now consistently uses bootoutAndWaitForExit(..., 5000), so we do not race a fresh cold start against processes that are still exiting after bootout
  • the startup scenario assertions were updated to cover those teardown paths that now wait for exit
  • the launchd-integration orphan-process test no longer writes under the real ~/.nexu/runtime/...; it now uses an isolated test process whose argv contains the matching path token, so the suite cannot corrupt a local Nexu install

I re-ran the relevant validation set:

  • pnpm vitest tests/desktop/launchd-startup-scenarios.test.ts
  • pnpm vitest tests/desktop/lifecycle-teardown.test.ts tests/desktop/launchd-integration.test.ts
  • pnpm typecheck
  • pnpm lint

The review comments from this round should now be fully addressed.

Copy link
Copy Markdown

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

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: 1abb4d7907

ℹ️ 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 apps/desktop/main/services/launchd-bootstrap.ts
Copy link
Copy Markdown

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

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: 8a953d2c27

ℹ️ 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 apps/desktop/main/services/launchd-bootstrap.ts
@lefarcen lefarcen merged commit 025a8b6 into main Apr 1, 2026
11 checks passed
@mrcfps mrcfps deleted the fix/desktop-openclaw-stale-launchd-recovery branch April 1, 2026 08:16
@lefarcen lefarcen mentioned this pull request Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants