githubnext/ace2Public

Ace: a collaborative coding environment on the team's own machines

fix(desktop): isolate checkout development runs from installed helpers #112

Mergediamnbutlermerged 7 commits intomainfromrefs/pull/112/head
  1. IA

    Makes the ordinary `bun run dev` path safe for branch testing. A checkout's desktop build now runs that checkout's own host and UI under an isolated identity. It never registers or attaches to the installed Ace-dev helper. Part of #97, under #5.

    **Why.** Every development build, whether installed or in any lane's `dist/`, shared `dev.ace.desktop.dev`: bundle ID, launchd label (with a bundle-relative `BundleProgram`), BTM item/launch constraint, port 4141, `ace-dev` data, Keychain service and WebKit store. That produced Nate's recurring dialogs: - A lane client attached to the installed 0.0.8 helper ("incompatible protocol"). With matching protocols it would have silently used stale backend and UI code. - After that helper stopped, the lane's ad-hoc copy kickstarted the shared label. launchd rejected it with `OS_REASON_CODESIGNING | Launch Constraint Violation` (vc 10) → "Ace Helper did not start". - The reused BTM item then rejected the Apple Development install in /Applications (vc 3). Startup only recovered after the 17 other same-ID LaunchServices copies were removed and the agent re-registered. - Canary is unaffected. It has 9 same-ID copies, all Developer ID signed, so the constraint always matches.

    **Change** - `electrobun.config.ts`: dev builds get `dev.ace.desktop.dev.<sha256(checkout)[:8]>`, which is stable per checkout. Only `ACE_DEV_INSTALL=1` builds the shared installed identity, and that build refuses ad-hoc signing. - `desktop()` derives the profile from the bundle identifier. A checkout build gets `~/.local/state/ace-dev-<hash>`, `Ace-dev-<hash>` preferences, an `ace-dev-<hash>` Keychain service and a port in 4200–4999. It ignores ambient `ACE_HOME`/`ACE_CONFIG_HOME`/`ACE_KEYCHAIN_SERVICE`. Stable, canary and installed dev derive exactly as before. - Checkout builds never register, unregister or kickstart Ace Helper. Startup without their host fails with "This development build has no Ace host on port N. Start it with bun run dev from its checkout." Helper menu and Settings actions are refused. - `bun run dev` builds the checkout, refuses any listener already on its port, and starts the checkout's source host with the isolated profile. That host serves the freshly built `apps/app/dist`. Other `ACE_*` settings are stripped, except `ACE_PORT` and `ACE_*_API_KEY`. The command then launches the app and stops the host when the app exits, and the app when the host exits or the command gets SIGINT/SIGTERM. - Runner lifecycle: signal handlers are installed before the build. A run stopped during the build or before the host is healthy launches nothing and stops any host it has already started. Ports 4140–4142 are refused. Collision errors say "Leave it running and set ACE_PORT"; they no longer say "restart it". - Local signing: dev builds sign with `ACE_CODESIGN_IDENTITY`, else the repository's untracked Git setting `ace.codesignIdentity`, else ad hoc. The `.git/config` setting is shared by every worktree and lane, so agents' and background builds pick it up. No identity is in source, and release/CI signing is unchanged. With an Apple Development identity, codesign's default designated requirement covers the bundle identifier and certificate. Privacy and Keychain grants then persist across a checkout's rebuilds while staying separate per checkout, and native inspection of lane builds works. - Docs: desktop UI testing and signing, the installed Ace-dev procedure, architecture, data locations, desktop tools and updates.

    Deferred: health reporting a managed helper's bundle path and naming the conflicting install (#97 follow-up), loopback-only test hosts, and a reload menu.

    **Validation** (real runtimes on Nate's Mac, with Canary 0.0.12 on 4142 and installed Ace-dev on 4141 running throughout) - `bun types`, `bun run ci`. - Four `bun run dev` runs of `dev.ace.desktop.dev.4b23eec1` on port 4681, protocol 8, `helper:false`. The served `index.html` SHA-1 matched the lane's `apps/app/dist`. Each WebKit networking process connected only to its own host (4141, 4142, 4681). - With `ACE_HOME=~/.local/state/ace-dev ACE_KEYCHAIN_SERVICE=ace-dev ACE_DIRECTORY=…` exported, the lane host's environment still contained only lane values and no directory setting. - A channel created in one run appeared in the next run's dashboard. - Shutdown left no app, host or worker processes in each case: SIGTERM to the command, SIGTERM to the host (the window closed), and SIGINT to the command (within 2 s). - Opening the lane bundle with no host showed the error above and quit. `launchctl print gui/501/dev.ace.desktop.dev.4b23eec1.helper` reports no such service. - Startup-window stop: SIGTERM during the build let the build finish, then nothing was launched and no processes remained. `ACE_PORT=4141 bun run dev` was refused with "Port 4141 belongs to an installed Ace". - Signing with `ace.codesignIdentity` set locally: - The app, `Ace Helper` and `…desktop-client` are signed "Apple Development", TeamIdentifier 8S43JJMN6B. The DR is `identifier "dev.ace.desktop.dev.4b23eec1" and anchor apple generic and certificate leaf[subject.CN] = "Apple Development: …"`, identical across two signed builds. - `codesign --verify --deep --strict` passes. - `ACE_CODESIGN_IDENTITY=-` still builds ad hoc, with the warning. - An obsolete pre-fix image-paste-91 build re-registered `dev.ace.desktop.dev` with LaunchServices on its own. It was unregistered and moved, inert, to `~/.local/state/ace-quarantine/helper-recovery-2026-10-05/image-paste-91/Ace-dev.app.disabled`. LaunchServices now lists `dev.ace.desktop.dev` only at /Applications. - Before and after (final check at 00f203f, after all runs): identical `launchctl print` state, PID, BTM UUID and bundle version for `dev.ace.desktop.dev.helper` (55171, F59D93B3, 0.0.10) and `dev.ace.desktop.canary.helper` (9041, 74FE912C, 0.0.12). `/health` on 4141 and 4142 was identical, and `~/.local/state/ace-dev` mtimes were unchanged. - Read-only reviews by the dev-ui-validation channel at e968869, 8fc4184 and 00f203f found no blockers.

    ### Built in Ace

    Built entirely in Ace. The helper-recovery channel's agent made every edit, build, runtime check and GitHub operation from Ace Canary. Native UI checks used Ace's desktop tools. Codex supervised by driving the Canary UI only; it made no edits or runtime changes. One gap: a background Cmd+Q to the test app can't be verified by Ace's desktop tools (tracked with the computer-use work in #8), so these runs were quit by signalling the command.

  2. iamnbutlerreferenced this in Finish development-run isolation: helper conflict diagnostics, loopback test hosts, and reload #97last month on GitHub

  3. iamnbutlermerged 6ec1747bc4eelast month on GitHub

  4. iamnbutlerclosedlast month on GitHub

  5. iamnbutlerreferenced this in chore(desktop): release canary 0.0.13 #115last month on GitHub