feat: Thread-safety, hover-expand pill UI, and centralized date formatting#3
Merged
Merged
Conversation
…ormatting ## Thread Safety - Add NSLock wrapper for `lastBufferTime` in Audio.swift and SystemAudioCapture.swift - Fix race condition in audio file closure by using queue.sync before closing files - Prevents potential crashes during device changes while recording ## New Hover-Expand Idle Pill UX - Redesign idle pill from tap-to-record to hover-to-expand pattern - Collapsed state: 40x20px with minimal 3-bar waveform icon - Expanded state: 120x28px revealing Record and Files buttons side-by-side - Add subtle breathing animation to MinimalWaveformIcon - Add ExpandedPillButton component with hover highlights - Respects accessibilityReduceMotion preference ## Centralized Date Formatting - Add DateFormattingHelper.swift with cached DateFormatter instances - Migrate Audio.swift and TranscriptSaver.swift to use centralized formatters - Eliminates duplicate DateFormatter initialization across codebase - Methods: formatFilenamePrecise(), formatFilename(), formatDisplay(), formatDuration() ## Cleanup - Remove unused requestPermissions() from AppDelegate (now in onboarding) - Remove unused readProcessBundleID() and readProcessIsRunning() from CoreAudioUtils - Remove unused audioFile property and setAudioFile() from SystemAudioCapture - Remove ~180 lines of deprecated panel code from FloatingPanelView 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Owner
Author
Code ReviewNo issues found. Checked for bugs and CLAUDE.md compliance. Review SummaryReviewed by: 4 parallel agents (2 CLAUDE.md compliance, 2 bug detection) Potential issues investigated and validated as false positives:
Code quality observations:
🤖 Reviewed with Claude Code |
r3dbars
added a commit
that referenced
this pull request
Mar 18, 2026
…ormatting (#3) ## Thread Safety - Add NSLock wrapper for `lastBufferTime` in Audio.swift and SystemAudioCapture.swift - Fix race condition in audio file closure by using queue.sync before closing files - Prevents potential crashes during device changes while recording ## New Hover-Expand Idle Pill UX - Redesign idle pill from tap-to-record to hover-to-expand pattern - Collapsed state: 40x20px with minimal 3-bar waveform icon - Expanded state: 120x28px revealing Record and Files buttons side-by-side - Add subtle breathing animation to MinimalWaveformIcon - Add ExpandedPillButton component with hover highlights - Respects accessibilityReduceMotion preference ## Centralized Date Formatting - Add DateFormattingHelper.swift with cached DateFormatter instances - Migrate Audio.swift and TranscriptSaver.swift to use centralized formatters - Eliminates duplicate DateFormatter initialization across codebase - Methods: formatFilenamePrecise(), formatFilename(), formatDisplay(), formatDuration() ## Cleanup - Remove unused requestPermissions() from AppDelegate (now in onboarding) - Remove unused readProcessBundleID() and readProcessIsRunning() from CoreAudioUtils - Remove unused audioFile property and setAudioFile() from SystemAudioCapture - Remove ~180 lines of deprecated panel code from FloatingPanelView 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: justinbetker <Justin.betker@jamf.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
r3dbars
added a commit
that referenced
this pull request
Apr 7, 2026
remove max_budget_usd cap from orchestrator
r3dbars
added a commit
that referenced
this pull request
Apr 7, 2026
remove max_budget_usd cap from orchestrator
r3dbars
added a commit
that referenced
this pull request
Apr 15, 2026
The dictation flow now waits on engine readiness instead of racing it.
Three stacked bugs fixed:
1. Retry budget too short for Bluetooth. Old logic retried 4× × 350ms
(1.4s total). CoreAudio settle time is 100-500ms wired but 2-3+s for
Bluetooth. Replaced with a 3.5s wait-for-ready loop that polls engine
readiness flags every 150ms.
2. Two uncoordinated retry systems racing. ParakeetEngine.handleAudioConfigChange
tore down the engine and waited 550ms before rebuilding, but
DictationSessionController had no signal to know recovery was in flight
and would call startRecording() on a stopped engine. ParakeetEngine now
publishes isRecovering and inputFormatReady; the controller waits.
3. AirPods 24kHz HFP mode. AirPods on macOS run input in Hands-Free
Profile (24kHz hw / 48kHz output bus) — never converges. Old code
rejected the mismatch as transient; now we accept it and use the
output bus rate (what installTap actually delivers) as nativeSampleRate
so downstream resampling is correct.
Plus: bounded prewarm retry (10 attempts max, was infinite Task chain),
generation guard for stale recovery tasks, format-validation retry inside
attemptDeviceRecovery, copy update ("Couldn't reach {device}" instead of
"Microphone unavailable" with no diagnostic).
Verified end-to-end on AirPods Pro #3: cold start, mid-session swap,
4× rapid switch — all recover within 1 attempt. 7 new tests for the
extracted ParakeetRecoveryState policy struct.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4 tasks
This was referenced Apr 25, 2026
Merged
6 tasks
This was referenced Jul 3, 2026
r3dbars
added a commit
that referenced
this pull request
Jul 7, 2026
…ansport The negative-exemplar veto (#1487) was "sound but regime-limited" (eval in #1493): after a correction it removed 46% of repeat wrong-matches in-room (AMI) but only 12% cross-condition (VoxCeleb). Root cause: a single rejected in-room sample and a later telephone/VoIP sample of the same rejected impostor sit too far apart in embedding space for the raw cosine to clear the 0.80 veto floor. The positive side already closed this gap with multi-exemplar voiceprints (#1488); the negative side — one rejected embedding — had no analog. Give the negative side the same multi-condition treatment (eval rec #3): compare the candidate against each rejected sample AND against that sample transported along the profile's own observed condition shifts (unit(exemplar) − average). Channel/condition shifts are largely speaker-independent, so a rejected sample shifted by a condition the profile has actually seen approximates the same rejected voice returning in that other condition. Owner-safe by construction: - transport only along +(exemplar − average) — real, forward, profile-observed conditions; bidirectional/synthetic directions were measured to leak owner-collateral and are not used. - a profile with no positive exemplars derives nothing → reduces exactly to the raw maxNegativeSimilarity → single-condition profiles unchanged. - the 0.80 floor and the ≥positiveSimilarity owner gate are untouched; transport only widens which impostor returns are caught, never lowers the floor. Real qmatrix eval (SpeakerExemplarDeltaEvalTests): AMI cross-condition vetoed-among-re-match 0.350 → 0.374 (+7.0% rel) with owner-collateral flat (2.17% → 2.32%, +9 of 5773 checks). VoxCeleb (single-utterance corpus, no condition structure) byte-identical, incl. owner-collateral — no regression. Pushing VoxCeleb's 12% further was investigated and rejected: every mechanism that moves it trades owner-collateral ~1:1, violating the #1493 guardrail. See docs/speaker-eval-negative-veto-cross-condition-2026-07.md. Refs #1493. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
DateFormattingHelperwith cached formatters, eliminating duplicate initializationChanges
Thread Safety
lastBufferTimeinAudio.swiftandSystemAudioCapture.swiftqueue.syncbefore closing filesNew Hover-Expand Idle Pill
accessibilityReduceMotionpreferenceMinimalWaveformIconandExpandedPillButtoncomponentsDateFormattingHelper
Cached formatters for consistent date handling:
formatFilenamePrecise()— with milliseconds for audio filesformatFilename()— for transcript filenamesformatDisplay()— user-facing formatformatDuration()— TimeInterval → "MM:SS"Cleanup
requestPermissions()from AppDelegate (now in onboarding)Test plan
🤖 Generated with Claude Code