Fix macOS 15+ permission caching causing stale Not Granted UI and generic transcript names#28
Merged
Merged
Conversation
…eric transcript names Two separate macOS 15+ TCC caching bugs: 1. AXIsProcessTrusted() returns a stale false even when Accessibility is granted, causing extractMeetingTitle and RosterReader to short-circuit and return nil/[]. This makes every recording get an empty title, which produces generic date-only transcript filenames. Fix: remove the AXIsProcessTrusted() pre-checks; the underlying AXUIElementCopyAttributeValue calls already return .apiDisabled when access is genuinely denied. 2. CGPreflightScreenCaptureAccess() and the CGWindowListCopyWindowInfo window-name probe both return stale false values on macOS 15+ for a fresh process whose screen recording was granted in a prior session. screenCaptureGrantedLive resets to false on every launch, so the UI shows "Not Granted" after a restart even though the grant is still in TCC. Fix: persist the confirmed-granted state to UserDefaults (same pattern already used for audioCaptureTCCGranted) and initialize from it at launch. Also update isAccessibilityGranted to use the same live AX API fallback already used by accessibilityState(). https://claude.ai/code/session_0141TjDnmekRsDDGoBu4jQyT
… bundle reset TextInjector.inject(): AXIsProcessTrusted() stale-false caused all dictation text injection to silently fail on macOS 15+. Added live AX API fallback (same pattern as PermissionCenter.isAccessibilityGranted) — only returns false when AXUIElementCopyAttributeValue returns .apiDisabled. TextInjector.ensureAccessibility(): same stale-false could trigger a redundant Accessibility permission prompt when the permission was already granted. Added the live fallback before showing the dialog. bundle.sh --reset: now also clears the screenCaptureTCCGranted and audioCaptureTCCGranted UserDefaults keys. Without this, --reset wiped TCC but left the cached-granted flags intact, causing the app to show permissions as Granted immediately after a full reset. setupAppAudioRecording: removed the CGPreflightScreenCaptureAccess() log warning — it fires on every meeting start on macOS 15+ even with the permission fully granted, producing false-positive noise that trains developers to ignore real errors. The actual tap failure error at AudioHardwareCreateProcessTap is the right signal. https://claude.ai/code/session_0141TjDnmekRsDDGoBu4jQyT
All four CardRows were using isLast: index == perms.count - 1, which draws a 0.5pt separator after every non-last row. Due to varying row heights (rows with the Required badge and Grant button are taller than those without), only the separator at the audioCapture→screenCapture boundary landed on a crisp pixel, making it the only visible line. Switch all permission CardRows to isLast: true so no separators are drawn, matching the consistent no-divider appearance the user sees for the other rows. https://claude.ai/code/session_0141TjDnmekRsDDGoBu4jQyT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two separate macOS 15+ TCC caching bugs:
AXIsProcessTrusted() returns a stale false even when Accessibility is
granted, causing extractMeetingTitle and RosterReader to short-circuit
and return nil/[]. This makes every recording get an empty title, which
produces generic date-only transcript filenames. Fix: remove the
AXIsProcessTrusted() pre-checks; the underlying AXUIElementCopyAttributeValue
calls already return .apiDisabled when access is genuinely denied.
CGPreflightScreenCaptureAccess() and the CGWindowListCopyWindowInfo
window-name probe both return stale false values on macOS 15+ for a
fresh process whose screen recording was granted in a prior session.
screenCaptureGrantedLive resets to false on every launch, so the UI
shows "Not Granted" after a restart even though the grant is still in
TCC. Fix: persist the confirmed-granted state to UserDefaults (same
pattern already used for audioCaptureTCCGranted) and initialize from it
at launch. Also update isAccessibilityGranted to use the same live AX
API fallback already used by accessibilityState().
https://claude.ai/code/session_0141TjDnmekRsDDGoBu4jQyT