Skip to content

Desktop boot: show window immediately, self-heal stale launchd state, fix boot-path latency#1303

Merged
RhysSullivan merged 3 commits into
mainfrom
rs/desktop-boot-fixes
Jul 4, 2026
Merged

Desktop boot: show window immediately, self-heal stale launchd state, fix boot-path latency#1303
RhysSullivan merged 3 commits into
mainfrom
rs/desktop-boot-fixes

Conversation

@RhysSullivan

@RhysSullivan RhysSullivan commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Incident

A plist can exist at ~/Library/LaunchAgents/sh.executor.daemon.plist while the service is not loaded in launchd. On boot the desktop app paid a failing launchctl kickstart and then a dead waitForSupervisedAttach(15_000) before falling back to managed spawn, and the window was only created after a connection resolved. Users saw a menu bar and no window for ~17s on every boot. Separately, login-shell PATH capture ($SHELL -ilc, 5s timeout) ran on every bundled-CLI call, including the read-only service status on the boot path.

Fixes

  • Startup window immediately: a lightweight local "Starting Executor" screen is shown at app.whenReady(), before any service/sidecar work; the real web UI loads into the same window (no second-window flash). second-instance now focuses the startup window while the connection is still pending.
  • Supervised-state classifier + self-heal: the desktop now uses both Registered and Running from service status instead of ignoring Running:
    • registered + running: attach; kick only if the attach misses.
    • registered + not running (the stale case): service restart; if the OS manager cannot start it, reinstall the service (install is idempotent bootout/enable/bootstrap); if that also fails, fall back to managed spawn immediately. The 15s attach wait is only paid after a kick or install actually succeeds.
  • PATH capture off the read path: service status no longer captures the login-shell PATH, and the capture is memoized so install/restart pay it at most once per process.
  • Inverted e2e repro: e2e/desktop-packaged/stale-launchd-registration.test.ts now guards the fixed behavior (startup window < 3s, stale boot < 10s and close to the clean control, kickstart failure followed by self-heal-or-fallback logging, recovery never attaches to the stale plist port).

Verification (all behavioral runs in VMs; nothing was launched on the dev host)

Platform What ran Result
macOS (tart guest) vitest run --project desktop-macos (packaged bundle pushed into guest, driven over CDP) green, 1/1
macOS (tart guest) stale-launchd scenario matrix in-guest: (a) clean, (b) stale plist not loaded, (c) registered+running install all fast, self-heal path logged (details below)
Linux (tart guest) vitest run --project desktop-linux green, 1/1
Linux (tart guest) systemd side of the classifier: install, stop unit, service status, service restart in-guest Registered: yes / Running: no when stopped; restart brings it back to running
Windows dockur guest reachable, but no Windows bundle was built for this PR; behavioral run not performed. schtasks classification (locale-invariant running detection, backend dispatch) covered by apps/cli/src/service.test.ts (18/18) unit-level only
Host-safe gates bun run typecheck, lint, format:check all green

Measured durations (macOS guest)

Scenario Boot to window Boot to ready
Clean control 1.3s 2.1s
Stale plist (before fix, from the repro run on the parent branch) ~15s+ >= 14s
Stale plist (after fix) 1.6s 5.2s
Registered + running n/a (window flips fast) 8.9s

In-guest log lines from the stale boot (the self-heal path, no dead wait):

[warn] Failed to restart registered supervised service; reinstalling Error: launchctl kickstart failed ...
[warn] Failed to install supervised service after registered service restart failure; using managed sidecar ...
[info] (sidecar) Daemon ready on http://localhost:4789

(In a tart guest the launchctl asuser session fails the kickstart with exit 125 instead of production's exit 113; the test matches the desktop's own classification line so it holds in both environments.)

Recording of the stale-plist boot in the guest (window up in under 2s): e2e/recordings/stale-launchd-fast-boot.mp4 (440KB, 12s), replacing the old slow-boot recording.

Gaps

  • Windows behavioral verification was not performed (no Windows bundle built for this run); the schtasks backend classification the desktop branch consumes is pinned by host-safe unit tests.
  • The Linux guest check proves the classifier signal and the restart self-heal at the CLI layer; the full desktop-app-driving-systemd path is exercised only insofar as desktop-linux boots the packaged app against a supervised daemon.

Stack

  1. e2e: repro stale launchd registration slow-boot #1297
  2. Desktop boot: show window immediately, self-heal stale launchd state, fix boot-path latency #1303 👈 current
  3. Desktop updater: keep checking after a declined update, surface errors, fix install-on-quit leak #1305

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 4, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing 12e7d75 Commit Preview URL

Branch Preview URL
Jul 04 2026, 05:38 AM

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 4, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud 12e7d75 Jul 04 2026, 05:38 AM

@pkg-pr-new

pkg-pr-new Bot commented Jul 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@1303

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@1303

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@1303

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@1303

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@1303

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@1303

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@1303

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@1303

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@1303

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@1303

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@1303

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@1303

executor

npm i https://pkg.pr.new/executor@1303

commit: 22ac04e

@RhysSullivan RhysSullivan force-pushed the rs/e2e-stale-launchd-repro branch from c433090 to 13eca55 Compare July 4, 2026 05:33
@RhysSullivan RhysSullivan force-pushed the rs/desktop-boot-fixes branch from 22ac04e to 4121d9a Compare July 4, 2026 05:33
@RhysSullivan RhysSullivan marked this pull request as ready for review July 4, 2026 05:34
@RhysSullivan RhysSullivan changed the base branch from rs/e2e-stale-launchd-repro to main July 4, 2026 05:34
…tate

Two boot-time fixes in the desktop main process:

Show a lightweight "Starting Executor" window at app.whenReady, before any
service or sidecar work, then load the real web UI into the same window once
the connection resolves (no second-window flash). A pending second-instance
now focuses that startup window instead of no-opping while connection is null.

Classify the supervised service by both registered and running instead of
ignoring the running signal:
- registered and running: attach; only kick if the attach still misses it.
- registered but not running (the stale plist/unit/task case): restart, and
  if the OS manager cannot start it, reinstall the service (install is already
  idempotent) before waiting. If install also fails, fall back to managed
  spawn immediately. The 15s attach wait is only paid after a kick or install
  actually succeeds, so a stale registration no longer costs a dead wait.
captureUserPath shells out to $SHELL -ilc on every bundled-executor call,
including read-only `service status` that boot runs first. Skip the capture
for `service status` (process env PATH is enough for a read) and memoize it
for the rest of the process lifetime so install/restart pay the shell probe
at most once instead of on every call.
The repro pinned the broken behavior (stale plist forces a >=14s dead wait).
Flip it to guard the fix: the startup window must appear within a few seconds,
the kickstart failure must be followed by a self-heal-or-fallback log line
rather than a dead wait, boot-to-ready must stay under the fast budget and
close to the clean control, and recovery must either repair launchd or fall
back cleanly to managed spawn without attaching to the stale plist port. The
E2E_RECORD recording now captures the fixed fast boot.
@RhysSullivan RhysSullivan force-pushed the rs/desktop-boot-fixes branch from 4121d9a to 12e7d75 Compare July 4, 2026 05:34
@RhysSullivan RhysSullivan merged commit a968cc5 into main Jul 4, 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.

1 participant