Skip to content

fix(release): restart gateway after app replacement#106

Open
tcballard wants to merge 4 commits into
mainfrom
codex/restart-gateway-after-app-replacement
Open

fix(release): restart gateway after app replacement#106
tcballard wants to merge 4 commits into
mainfrom
codex/restart-gateway-after-app-replacement

Conversation

@tcballard

@tcballard tcballard commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements WF-ROADMAP-0015 desktop v0.1.0 app-replacement recovery.

Adds:

  • one-time bundled-gateway reconciliation after the containing app is replaced;
  • fixed bundle-relative path and installation-fingerprint checks before restart;
  • deterministic changed, unchanged, mismatch, stopped, uninstalled, and restart-failure coverage.

Scope

Included

  • Detect a changed installed app before the initial gateway health/readiness refresh.
  • Restart only a loaded LaunchAgent that points at the exact bundled Rust gateway path.
  • Persist the installation fingerprint only after a successful restart.

Excluded

  • Provider, credential, routing-policy, or default-destination changes.
  • Automatic update support or replacement of the existing manual update/rollback contract.
  • Repairing a LaunchAgent that points at an external or mismatched gateway.

Product / Architecture Decisions

  • A loaded launchd process can retain the executable image and signing context from the app it was launched under even after /Applications/Wayfinder.app is replaced at the same path.
  • The app fingerprint combines desktop version/build, verified signing-Team state, and bundled-helper file metadata. It is an optimization marker, not a trust decision.
  • The reconciler locates only the fixed bundle-relative helper and requires the exact LaunchAgent executable path; full bundled-helper authentication still occurs at each execution boundary.
  • Reconciliation runs before the initial setup and gateway status refresh so Apple Foundation Models readiness is not computed through a stale process.
  • Failure is fail-closed and retryable: no marker is stored after locator, status, path, or restart failure.

User-Facing Contract

CLI

No CLI changes.

Human Output

Replacing Wayfinder and reopening it automatically refreshes the persistent bundled gateway. Users should not need to run launchctl kickstart to restore Apple Foundation Models availability.

JSON Output

No JSON changes.

Exit Codes

No exit-code changes.

Verification

Ran

env CLANG_MODULE_CACHE_PATH=/private/tmp/wayfinder-replacement-module-cache SWIFTPM_MODULECACHE_OVERRIDE=/private/tmp/wayfinder-replacement-module-cache WAYFINDER_DISABLE_SWIFTPM_SANDBOX=1 swift test --disable-sandbox --scratch-path /private/tmp/wayfinder-replacement-build --package-path macos/WayfinderMac

git diff --check

Covered

  • All 171 Swift tests passed.
  • Changed matching installations restart once and persist the new marker.
  • Unchanged installations do not query or restart launchd.
  • External/mismatched, stopped, and uninstalled services defer without mutation.
  • Failed restarts remain retryable and never persist success.
  • A Developer ID-signed replacement changed the live gateway PID from 23749 to 48559 and persisted the new 0.1.0|1|R8HXTBY3NM|... fingerprint.
  • The restarted gateway reported {"status":"ok","models":["apple-local"],"offline":true} and returned OK. from a real non-streaming apple-local request.
  • The first signed acceptance build exposed a release-only Swift concurrency crash in async helper verification during launch. The final implementation removes async execution from replacement detection; the corrected signed build remained running and passed the same end-to-end check.

Review Path

  1. GatewayReplacementReconciler.swift for fingerprint, trust, and retry behavior.
  2. WayfinderMacApp.swift for startup ordering.
  3. GatewayReplacementReconcilerTests.swift for boundary coverage.

Notes For Reviewer

The bug was reproduced on a real signed/notarized RC: the live Foundation Models harness reported available, while the stale pre-replacement gateway returned wayfinder_router_not_ready. A manual launchd restart immediately restored a successful apple-local reply. The corrected branch was then Developer ID-signed and installed over the stale process; automatic reconciliation restarted the gateway and restored the same successful Apple reply without manual launchctl work.

@tcballard
tcballard marked this pull request as ready for review July 19, 2026 21:55
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