refactor: cut the Electron desktop app — remote always-on server is canonical (ADR-051) - #273
Conversation
…anonical (ADR-051) Delete packages/app/ (~9.5k LOC Electron tree), the server's --embedded flag + embedded-mode.ts, and the DMG/sign/notary/electron-updater half of the release pipeline. The canonical client is now the browser + PWA (#71) against an always-on server (launchd/systemd-user, ADR-050). Retains the pid-file mutual-exclusion lock (ADR-029 core), the launchd/systemd lifecycle (ADR-028 core), and auth.ts CONFIG_DIR token isolation (ADR-030 server-side). The dashboard-embedded-in-server-binary bundle (_embedded_dashboard, ADR-043) is unrelated to Electron's --embedded and is untouched. Mid-execution: helpers/embedded-server.ts was a shared real-spawn harness used by 4 integ suites (not Electron-specific); rewritten to parse the always-emitted "listening on" startup log instead of the removed --embedded/AUTONOMOS_READY signal, and renamed helpers/test-server.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZvsJYsGE8rAfD42TrX86i
2e16cb9 to
ee217d5
Compare
nox-0x
left a comment
There was a problem hiding this comment.
Approving — the surgical edits hold up: --embedded is gone everywhere it was checked, embedded-mode.ts and its consumers are cleanly removed from run.ts, the renamed helpers/test-server.ts reliably picks up the new "listening on" banner (newline-anchored regex, defensive (r.stdout ?? "") guard), the changeset fixed group is correctly trimmed, and version-source repointing (scripts/release-notes.ts, scripts/sync-changelog.ts, version.yml) lines up with packages/server/package.json. The retained cores (pid-file mutual-exclusion, launchd/systemd lifecycle, auth.ts CONFIG_DIR isolation) are all preserved as ADR-051 promises.
One follow-up (non-blocking) — scripts/test-1a1-isolated.sh (still wired into package.json as test:1a1) passes --embedded and waits for AUTONOMOS_READY; with this PR, parseCliArgs will throw Unknown argument: --embedded at spawn. It's a manual smoke script (not run by make check or CI), so the bleed is contained, but bun run test:1a1 is now broken. Either drop --embedded + switch the grep to match the new autonomOS server listening on http://…:<port> banner, or delete the script and its test:1a1 package.json entry alongside the desktop cut.
Summary
Cut the Electron desktop app entirely (ADR-051). The real user need behind "desktop app" was always "agents stay alive when my laptop is closed" — which is a remote always-on server, not a local GUI shell. The PWA (#71) already covers the installable-app / desktop-notifications / thin-client value at zero Electron cost, and the always-on server lifecycle (launchd/systemd-user, #271 / ADR-050) is the actual delivery mechanism.
Electron had become the single most expensive maintenance surface in the repo — signing/notary 85min+ stalls, electron-updater, universal2 lipo, the bun-compile/node-pty ABI wall — for a layer that wasn't getting used. This removes ~9,500 LOC of app source plus two CI jobs and five signing secrets.
The architectural shift
graph TB subgraph OLD["❌ OLD — Electron-bundle path (cut)"] direction TB U1[User] --> DMG[Download signed/notarized<br/>universal2 .dmg] DMG --> APP[autonomOS.app<br/>Electron shell] APP -->|spawns as child<br/>--embedded| SRV1[autonomos-server<br/>Built-in mode] APP -.electron-updater.-> DMG SRV1 --> AG1[agents die when<br/>laptop sleeps] end subgraph NEW["✅ NEW — always-on remote path"] direction TB U2[User] --> BROWSER[Browser / PWA #71] BROWSER -->|HTTP + token| SRV2[autonomos-server] SRV2 -.supervised by.-> LD[launchd / systemd-user<br/>ADR-050] LD --> SRV2 SRV2 --> AG2[agents stay alive<br/>across laptop sleep] INSTALL[curl install.sh] -->|fetches per-platform<br/>server tarball| SRV2 end OLD -.replaced by.-> NEWThe two "embedded"s — a naming-collision footgun, handled
The codebase has two unrelated things called "embedded". This PR removes one and leaves the other completely untouched:
--embeddedflag /embedded-mode.tsautonomos-serveras an in-process child ("Built-in mode")_embedded_dashboard/build:embed-dashboard(ADR-043)Future readers grepping for "embedded": we deleted Electron embedded-mode; we kept dashboard-embedded-in-server-bundle.
What's retained (the cores of the partially-superseded ADRs)
~/.autonomos/.auth.tsCONFIG_DIR token isolation (ADR-030 server-side) — serves worktree-dev + future profiles.ADR-051 adds append-only Update notes to ADR-005, 028, 029, 029-follow-up, and 030.
Changes
Deleted
packages/app/— entire Electron source tree (main/renderer/preload, electron-builder config, DMG/sign/notary/lipo scripts, build resources, 8 test files)packages/server/src/embedded-mode.ts+ the--embeddedflag (cli-args.ts,run.ts, CLI help).github/workflows/pr-artifact.yml;reusable-dmg-build.ymlgutted →reusable-server-build.yml(server tarballs only)desktop-as-thin-client.md,desktop-embedded-server.md,desktop-app-design-notes.md,phase-1b-sketch.md);desktop-shells/retained as ADR-005's foundational researchRepointed / rewired
packages/app/package.json→packages/server/package.json(release-notes.ts,sync-changelog.ts,version.yml)@autonomos/appremoved from the changesetfixedgroup;bun.lockregeneratedrelease.ymlkeeps the server-tarball assembly; drops DMG/zip/blockmap/latest-mac.yml/signing/attestationpackage.json,tsconfig.json,Makefile,.gitignore,.changeset/README.md, release skill — de-app'dMid-execution refinement (flagged + approved during the cut)
helpers/embedded-server.tsturned out to be a shared real-spawn harness used by 4 integration suites (not Electron-specific). Rather than delete it, it was rewritten to parse the server's always-emittedlistening on …:<port>startup log (instead of the going-away--embedded+AUTONOMOS_READYsignal) and renamedhelpers/test-server.ts(bootEmbedded→bootServer), preserving the 3 non-Electron suites (agent-spawn-prompt,usage-queue-integration,usage-queue-sim-integration).Five now-unused GitHub Actions secrets should be deleted (Settings → Secrets → Actions). Not deleted by this PR (flagging is safer than scripting secret deletion):
CSC_LINK,CSC_KEY_PASSWORD,APPLE_API_KEY,APPLE_API_KEY_ID,APPLE_API_ISSUERCoordination
cli/install-service.ts, is touched here only to reword an obsolete "quit the Desktop app" error string — the pid-file mutual-exclusion check it lives in is preserved.run.tsoverlap with ServerLifecycle'sinitFileLogging()was pre-resolved (different hunks; no conflict).Testing
make check(biome + tsc --build + node:test + vitest) greeninstall.sh: fetches only the server tarball + SHA256SUMS — no.dmg/.AppImage🤖 Generated with Claude Code