Skip to content

Health fixes: no freeze on Email Support, cheaper idle call detection, lighter Speakers page - #1860

Merged
r3dbars merged 5 commits into
mainfrom
claude/app-health-check-w19eqh
Sep 25, 2026
Merged

r3dbars merged 5 commits into
mainfrom
claude/app-health-check-w19eqh

Conversation

@r3dbars

@r3dbars r3dbars commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Requested by Justin · project thread

Why

Before: clicking Email Support or Send Diagnostic walked the whole model cache folder (lots of CoreML files) and read the full reliability log (up to ~10 MB) on the main thread, so the app could stall right when someone is reporting a problem. While the app sat idle, call detection's 5 s backstop read the bundle ID of every audio process on the Mac (30-60 of them), even ones doing no audio. And the Speakers page re-read up to 256 KB of every saved transcript after every rename, merge, discard, or meeting save (~250 MB per rename at 1,000 meetings).

After: the support disk reads run off the main thread. The idle scan only fetches a bundle ID for processes actually using the mic or speakers, and the mic and camera backstop timers get 500 ms leeway so macOS can batch their wakes. The Speakers scan skips transcripts it already knows have no unnamed voices until the file changes.

Three commits, one problem each, from an app health audit (thread linked above).

Product Impact

  • Affects: meetings (call detection, speaker review), settings support actions
  • Lane: meeting reliability
  • Why this matters: the app idles for hours on ~150 Macs; fewer wakes and disk reads mean less battery, and support/settings flows shouldn't beachball.

What changed

  • TranscriptedSupportActions: diagnosticsSnapshot is now async. The model-cache walk and reliability log read run in a Task.detached; everything else stays on the main actor. sendFeedback / sendDiagnosticEvent / feedbackEmailURL / diagnosticsText became async. An in-flight flag stops a double click from opening two drafts.
  • TranscriptedSettingsActions.sendDiagnosticEvent is now () async -> String?. The settings view awaits it in a Task and has its own in-flight guard.
  • MicActivityMonitor.currentProcessAudioState: reads isRunningInput/isRunningOutput first and the bundle ID only when one is true. All three consumers already ignore bundle IDs of processes with the relevant flag false, so detection results are unchanged. Mic and camera backstop timers: 500 ms leeway.
  • SpeakerReviewQueueScanner: new NoPendingSpeakersCache (path → modification date + size, lock-guarded, capped at 20k entries). A transcript with no db_pending speaker can never produce a review row regardless of profiles, so it is skipped until its fingerprint changes. Files with pending speakers are still read every scan. New hasPendingSpeakers(in:) helper. Two new fast-test suites.

How I checked it

  • bash scripts/dev/linux-checks.sh (48 passed)
  • python3 scripts/dev/check-source-pins.py --changed-only (pass)
  • bash build.sh --no-open / bash run-tests.sh / bash run-integration-smoke.sh: via CI

Checks I could not run, and why:

  • No Swift toolchain in this session, so build and tests rely on CI.

Mac or hardware test still needed? If yes:

  • Optional: start a Zoom/Meet call and check the "record this meeting?" prompt still shows (unchanged behavior). Click Email Support and check the draft opens once with diagnostics. Name a pending voice on the Speakers page and check it leaves the queue.

Risk Review

  • Privacy / local-first behavior reviewed (no new data leaves the device)
  • No new analytics properties or Sentry tags
  • Checked the text-pin tests for every file I edited
  • No storage path changes
  • Agent PRs got an independent deep review of the full diff

Notes

Audio real-time code untouched. No new AVAudioEngine/inputNode touches.

🤖 Generated with Claude Code

https://claude.ai/code/session_0126tPTsXGHmWx6EmsR32sjX

Email Support and Send Diagnostic walked the whole model cache folder
(many CoreML files) and read the full reliability log (up to ~10 MB) on
the main thread, so the app could stall right when someone is reporting
a problem. Those two disk reads now run in a detached task; the rest of
the snapshot is cheap in-memory state and stays on the main actor.

A double click can't open two drafts or send two events while the
first one is still gathering.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126tPTsXGHmWx6EmsR32sjX
The mic-activity backstop scans every audio process every 5 s while the
app idles. It read each process's bundle ID even when the process was
doing no audio, which every consumer then ignored. Now it reads the two
running flags first and fetches the bundle ID only for processes that
are actually using the mic or speakers. Both 5 s backstop timers (mic
and camera) also get 500 ms leeway so macOS can batch their wakes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126tPTsXGHmWx6EmsR32sjX
@r3dbars r3dbars self-assigned this Sep 25, 2026
The Speakers review queue rescans the meetings folder after every
rename, merge, discard, and meeting save while Settings is open, and
each rescan read up to 256 KB of every saved transcript. With 1,000
meetings that is ~250 MB per rename.

Transcripts with no db_pending speaker can never produce a review row,
whatever the current profiles are. The scanner now remembers those by
path plus modification date and size, and skips reading them until the
file changes (naming a speaker rewrites the file, so it is read again).
Transcripts that do have pending speakers are still read every time.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126tPTsXGHmWx6EmsR32sjX
@r3dbars r3dbars changed the title Health fixes: no freeze on Email Support, cheaper idle call detection Health fixes: no freeze on Email Support, cheaper idle call detection, lighter Speakers page Sep 25, 2026
@r3dbars
r3dbars marked this pull request as ready for review September 25, 2026 17:23
@r3dbars
r3dbars merged commit 5b61b0e into main Sep 25, 2026
8 checks passed
@r3dbars
r3dbars deleted the claude/app-health-check-w19eqh branch September 25, 2026 17:23
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.

2 participants