Repository navigation
Audit fixes: app hang, Write for Me crash, stuck hotkey tap, dead code and stale docs - #2336
Merged
Merged
Conversation
A whole-repo audit pass: 30 read-only lanes, then fix groups that re-checked each item before editing. This is the part that was safe to fix without an owner decision. Bug fixes - App hang: the only main-queue observer of UserDefaults changes (LiveMeetingTranscriptService) made every background defaults write wait for main. A writer holding a lock main was waiting on then hung the app for good. It now hops to main asynchronously, the way AnalyticsReporter already does. - Write for Me: an error reply with no message read stderr with queue.sync on the queue it was already running on. The buffer is guarded by the existing lock now. - Hotkey tap recovery dropped a disable that landed during the OS re-enable call, leaving the tap dead. `pending` is cleared before the call, so one more attempt queues behind it. - Speaker merge logs wrote display names under keys the log sanitizer doesn't redact. They log profile ids now. - FileLogger escapes every control character, SQLiteHandle closes the handle after a failed open, and a saved-audio "request was cancelled" status now clears like its sibling failures. - "Listening..." could sit over finished dictation text, a paused failed-meeting player said Pause, and F13-F20, Home, End and the Page keys showed as "Key105" in Settings. - The speaker eval harness and the Lab speaker sweep wrote to the real app log. They set TRANSCRIPTED_DISABLE_FILE_LOGGER like the other wrappers. - The QA bench release-health step still pinned the 1.1.75 fixtures after 1.1.76 shipped, so it failed under --strict. Cleanup, no behavior change - Dead code left by finished migrations, write-only state and unused parameters removed; stale comments and docs corrected against the code; trivial compiler warnings fixed (89 unique warnings down to 67). - The call-detection spec and a few comments describe behavior without naming other products. Tests and guardrails - A fast-test suite that was never called is wired in. - 100 assertionFailure calls that crashed the whole run now record a failure, and seven silent early returns now fail. - The banned-calls FileHandle rule scans the files that do file I/O. - The test matrix selects the banned-calls check and the speaker smoke for more files; linux-checks runs two more offline self-tests. - Preflight reports a hooks path that is unset or points elsewhere. Checked: check.sh full 18/18 before and after, the quick tier, both Speakers smokes, the Live tests, the CLI build modes, the harness and Lab builds, and the slow paste-back smoke. Two independent reviews of the full diff found no blockers. Not checked on hardware: no AirPods take and no live meeting.
This was referenced Nov 10, 2026
This was referenced Nov 10, 2026
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.
Why
A whole-repo audit: find what's broken, inconsistent, inefficient or no longer needed, fix what's certain, and list the rest for the owner. 30 read-only lanes covered the tree, fix groups re-checked every item before editing, and the more serious claims got a second adversarial read. This PR is the part that was safe to fix without an owner decision.
Product Impact
dictation/meetings/agent artifactsdictation reliability/meeting reliability/agent workflowWhat changed
Bug fixes (read these diffs):
LiveMeetingTranscriptServicewas the only main-queue observer ofUserDefaults.didChangeNotification. That makes every background defaults write wait for main, and a writer holding a lock main was waiting on then hung the app for good. It now hops to main asynchronously, the wayAnalyticsReporteralready does. The Live transcript toggle applies one run-loop turn later.queue.syncon the queue it was already on. The buffer is guarded by the existing lock. New test spawns a real child process.PhysicalShortcutTapRecoverydropped a disable that landed during the OS re-enable call.pendingis cleared before the call. New test.FileLoggerescapes every control character;SQLiteHandlecloses the handle after a failed open; a saved-audio "request was cancelled" status now clears like its sibling failures.TRANSCRIPTED_DISABLE_FILE_LOGGERlike the other wrappers.--strict. Ran both: 1.1.75 exits 1, 1.1.76 scores 100/100.transcripted-qatreated a sibling folder as the legacy library (prefix match with no/boundary). New test.Cleanup, no behavior change:
Sources,Tests,Tools, scripts and string references.SECURITY.mdstorage table,docs/agent-merge-policy.md(a dangling reference and a stale appcast sentence) and the "most-pinned" list in rootAGENTS.md. Owner-level docs: please read those three diffs.Tests and guardrails:
testDictationStoppedAudioRecoveryRetryRegistry) is wired in and passes.assertionFailurecalls that crashed the whole run now record a failure; seven silent early returns now fail; two fixture-setupXCTSkips became failures. A reviewer checked every swapped site for code that would now run on into a crash.linux-checks.shruns two more offline release self-tests.core.hooksPaththat is unset or points somewhere else.Nothing changed under
scripts/release/,Casks/,docs/appcast.xml,Info.plist,release-candidate.yml,auto-merge-lanes.jsonor any*-baseline.json.How I checked it
scripts/dev/agent-preflight.shbash scripts/dev/linux-checks.sh(98 checks pass; 96 on main, two self-tests added).agents/test-matrix.ymlfor the files changed (ran the wholecheck.sh fulltier instead)bash build.sh --no-openbash run-tests.sh(52,643 assertions, 0 failed; 52,636 on main)build.sh)bash run-integration-smoke.shswift testbash run-e2e-smoke.sh/swift test --package-path Tools/<Package>(CaptureKit, CLI, MCP, QA, Live, Lab; CLI audio, meeting, retrieval and diarization builds; SpeakerEvalHarness build)bash check.sh fullpassed 18/18 on untouchedmainfirst and 18/18 after;run-slow-pasteback-smoke.sh(6 scenarios);test-speaker-settings-model.sh;test-speakers-directory-scroll.shscripts/dev/verify-change.sh:Checks I could not run, and why:
bash check.sh hardwareand any live dictation or meeting: needs a person, a mic and AirPods..agent-review/visuals/.Mac or hardware test still needed? Yes:
main.Sources/Speechchanges are comments, dead-code removal and one unwrapped always-true#available.maina grey "Listening…" can sit over the text; here it shouldn't.mainthe button still says "Pause audio"; here it says "Play audio".Risk Review
check-telemetry-keys.pypasses)check-source-pins.py --changed-onlypasses; one planned deletion was dropped because a contract test pins text inside it)SECURITY.mdstorage table corrected to real paths; its privacy claims were left for the owner)Sources/(131 files) and one for everything else. Verdict: no blockers, no should-fix. One nit fixed (a doc typo). The app-hang fix landed after theSources/reviewer started; it was designed by a separate adversarial reader and re-read by the coordinator..agent-review/visuals/evidence (not done; see the hardware steps)Notes
Sources/Support/ClipboardRestoringTextPaster.swiftloses its paste-retry state. Atmainthat state was declared but never set: the parameter that would set it defaulted to false and no caller passed true. Traced three times, and the slow paste-back smoke passes.Agent handoff
COORD_DONE: GREEN | this PR | audit safe-fix pass: hang, crash and hotkey fixes, dead code, stale docs, test and guardrail repairs | none | owner reads SECURITY.md, agent-merge-policy.md and AGENTS.md diffs; open findings list delivered privately | check.sh full 18/18 before and after, quick tier, both Speakers smokes, Tools Live/Lab/harness/CLI modes, slow paste-back smoke, verify-change (paste PASS, native checks SKIP) | lanes used: Codex=0; Claude=30 auditors, 10 fixers, 5 skeptics, 2 reviewers; Local=all checks on the owner's Mac; Windows=0 | owner does the four hardware steps above, then marks ready🤖 Generated with Claude Code