mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
* feat(onboarding): state-aware macOS notification permission step The Set up notifications step showed a one-size-fits-all 'Open Mac Settings' button that simultaneously fired the macOS permission prompt and opened System Settings — two competing system UIs, with System Settings unnecessary for the common fresh-install case. Electron exposes no API to read macOS notification authorization, but scheduling outcomes do reveal it: a silent probe notification's 'show' event means permission is granted, 'failed' means delivery is blocked. A new notifications:probeDelivery IPC runs that probe (cached via passive delivery evidence and a persisted confirmation flag), and the onboarding card now renders the real state: - fresh install: the probe itself pops the native Allow dialog the moment the step opens; the card flips to 'Notifications are enabled' automatically when the user clicks Allow (silent 2.5s re-probes) - blocked: amber card with an Open System Settings deep-link, which also self-heals once the user flips the toggle - granted: green confirmation card The test-notification button now feeds the same card instead of the ambiguous 'if no banner appeared…' toast during onboarding. Co-authored-by: Orca <help@stably.ai> * fix: don't log expected probe rejections while polling for permission Co-authored-by: Orca <help@stably.ai> * fix: amber warning styling + single stable dev bundle id for notifications - Blocked card now uses the app's shipped amber idiom (tinted surface with amber title/body) instead of white-on-amber-wash, which read muddy in dark mode; macOS permission card split into its own module to stay under the max-lines budget. - Dev instances previously minted a unique macOS bundle id per branch x Electron version, registering a new Notification Settings entry every time ('Orca: <branch>' rows piling up forever) and pointing the settings deep-link at ids System Settings can't resolve. All dev instances now share com.stablyai.orca.dev: one Notification Center entry, one permission grant covering every dev build. Co-authored-by: Orca <help@stably.ai> * fix: tighten macOS permission card copy Body copy was one long sentence; now a single short instruction with 'Updates automatically.' as a separate dimmer line. Also repairs locale catalog parity for keys introduced by commits rebased into this branch. Co-authored-by: Orca <help@stably.ai> * fix: drop 'Updates automatically.' line; ad-hoc sign dev app copies The extra line read as confusing filler — the cards now carry one short instruction each. Dev Electron copies had broken code signatures (the Info.plist identity edits invalidate the ad-hoc seal), which macOS punishes by refusing Notification Center registration outright: every dev notification failed with UNErrorDomain error 1, the app never appeared in System Settings > Notifications, and the settings deep-link had nothing to land on. The dev runner now ad-hoc re-signs the copied bundle after the plist edits (bundleLayoutVersion bumped so stale unsigned copies are recreated). Verified end-to-end: runner-built copy passes codesign --verify --deep, probe delivery returns delivered, the onboarding card flips green in dev, and the deep link opens the dev app's own notifications pane. Co-authored-by: Orca <help@stably.ai> * fix: drop confusing copy line; session-only permission evidence Removes the 'Updates automatically.' line from both permission cards. Also drops the persisted notificationDeliveryConfirmed flag: OS-level permission changes between sessions, and a stale positive rendered a false green card. Delivery evidence is now session-scoped only. Documented detection ceiling (verified empirically on macOS 26): while the permission dialog is unanswered — and when notifications are toggled off in System Settings after being authorized — macOS accepts requests and silently swallows them, with no public API (Notification Center delivered-history and legacy ncprefs both included) able to distinguish that from real delivery. 'failed' remains definitive for unsigned builds and dialog-level denials. Co-authored-by: Orca <help@stably.ai> * feat: real macOS notification permission readout via native helper Electron has no API for UNUserNotificationCenter authorization, and every observable fallback lies: scheduling succeeds (and getHistory lists the notification) even while macOS silently swallows display because the permission dialog is unanswered or notifications were toggled off in System Settings. The onboarding card therefore showed 'enabled' after the user disabled notifications. Adds native/notification-status-macos: a tiny Swift binary that prints the app's real authorization status. It runs from inside the app bundle (NSBundle resolves the bundle by walking up from the executable) and embeds the app's CFBundleIdentifier in a __TEXT,__info_plist section so every codesign --force pass — electron-builder's signing or the dev runner's ad-hoc deep sign — derives the identifier macOS keys notification records to. Spawning it from the app returns authorized / denied / not-determined exactly matching System Settings. notifications:probeDelivery now prefers this readout (authoritative, silent), firing at most one dialog-trigger probe per session while the decision is pending, and falls back to the previous delivery-probe heuristics when the helper is unavailable. The card polls the readout silently in every state, so toggling Allow notifications in System Settings flips the card within a poll — both directions, verified live. Test notifications also consult the readout so 'delivered' is no longer claimed for swallowed notifications. Packaged builds ship the helper via extraResources and sign it in afterPack like the computer-use helper; dev copies compile it on demand (swiftc, non-fatal when missing) with the shared dev bundle id. Co-authored-by: Orca <help@stably.ai> * feat: in-app fallback for swallowed notifications + permission card in Settings - Dispatch now consults the authorization readout before creating a native notification: when macOS would silently swallow it (denied or prompt unanswered) it returns reason 'blocked-by-system' instead of piling invisible notifications into Notification Center. The terminal notification path surfaces that as a once-per-session in-app toast with an Open System Settings action. Mobile fan-out is unaffected. - Settings > Notifications now shows the same live permission card as onboarding (moved to components/notifications/), polling the readout so System Settings changes reflect within seconds, and the test button updates it inline. - Test sends that are blocked at the OS level now show the settings-pointing failure toast instead of a generic error. Co-authored-by: Orca <help@stably.ai> * fix: hide macOS permission card while Orca notifications are disabled A green 'Notifications are enabled' card next to a disabled Enable Notifications toggle read as a contradiction — the card now renders (and the readout polls) only while Orca's own notifications setting is on. Also single-flights the authorization helper so simultaneous agent completions share one readout process. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>