Standard app instead of menu-bar-only: removed LSUIElement from Info.plist.
Dock icon, Cmd+Tab, and the standard app menu (Cmd+Q) are back. The
accessory-app design was making the app hard to quit reliably -- no Dock
icon and no accessible app menu meant the only way to quit was finding the
menu bar dropdown's "Quit BusyMirror" item, which was blocking updates
(old process holds the bundle open, "app in use" on replace). Menu bar
extra stays as a secondary quick-access point.
Verified via `lsappinfo` (type="Foreground", was "UIElement") since this is
an app-type change a screenshot wouldn't show either way.
All unit tests pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Sync reminders: new "Sync reminders when mirroring" option (global and
per-route) copies source event alarms into mirrored placeholders. CLI flag
--sync-reminders.
- CLI polish: --help, --list-calendars, --status (all support --json).
Scheduled/headless runs record last-run time/result/summary. Failure paths
now exit with distinct nonzero codes (2 = no calendar access, 3 = no saved
routes) instead of always exiting 0.
- Fix settings silently wiped on upgrade: SettingsPayload's auto-synthesized
Codable threw on any settings blob missing a field added since (e.g. the
new syncReminders key), failing the whole decode and letting the next
autosave persist an empty state over real routes/filters. Custom decode
now falls back per-field like Route already did, and loadSettingsFromDefaults
recovers routes from the legacy routes.v1 key if settings.v2 comes back
empty, repairing installs already hit by this.
- Roadmap: event-driven background sync (SMAppService + EKEventStoreChanged +
wake notification) and an external MCP wrapper around the CLI queued next;
decided against direct Google/CalDAV API integration since EventKit already
covers it via System Settings accounts.
All 47 unit tests pass (45 existing + 2 new SettingsPayloadTests).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>