Replace SSSpeechSynthesizer with testable MUDSpeechQueue skeleton#16
Open
powerje wants to merge 1 commit into
Open
Replace SSSpeechSynthesizer with testable MUDSpeechQueue skeleton#16powerje wants to merge 1 commit into
powerje wants to merge 1 commit into
Conversation
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
Phase 2 foundation for the VoiceOver speech-pipeline rebuild. Replaces the 2013
SSSpeechSynthesizerObj-C class fromVendored/SSAccessibilitywith three new Swift types undersrc/Mudrammer/Accessibility/:SpeechLine— struct carryingtext,priority(iOS 17+UIAccessibilityPriority), andorigin(.server/.prompt/.trigger/.system). Onlytextis load-bearing today; the other fields exist so follow-up work can populate them without reshaping the type.Announcer— protocol with a singleannounce(_:completion:)method that abstracts the "post to VoiceOver" step. Production implementationUIAccessibilityAnnouncerposts anNSAttributedStringwithaccessibilitySpeechAnnouncementPriorityandaccessibilitySpeechQueueAnnouncementattributes, observesUIAccessibility.announcementDidFinishNotificationfor completion, with a 16s timeout fallback matching the 2013 implementation's behavior.MUDSpeechQueue—@objc-exposed class that holds an internal FIFO buffer and drains one line at a time through the injectedAnnouncer. ExposesenqueueLineForSpeaking:andstopSpeakingfor one-line drop-in replacement at the SSMudView call site.SSMudView.mis updated to construct[MUDSpeechQueue new]instead of[SSSpeechSynthesizer new]and no longer importsSSAccessibility. The unusedcontinueSpeakingmethod (declared in SSMudView.h but only self-referentially called from SSMudView.m) is removed — a grep across the tree found no external callers.The 2013
Vendored/SSAccessibilitypackage is left in place for now; it has no remaining call sites in app code and will be deleted in a follow-up cleanup step once the migration settles.Why this matters
Research in the prior session surfaced that the #1 real-world complaint from blind MUDRammer users in the 2025 AppleVis thread is prompt-jumping — the 2013
SSSpeechSynthesizerposts at default priority, which interrupts current speech mid-sentence whenever a new line arrives. Posting at.lowpriority (queued behind existing speech, yielding to system announcements) is the direct fix, and iOS 17'sUIAccessibilityPriorityis the first-party primitive that makes it trivial. TheAnnouncerseam is what lets future work unit-test the queue without relying on a real VoiceOver subsystem that can't be observed from tests.Deliberately out of scope
This is a skeleton. Each item below is a separate follow-up PR:
Vendored/SSAccessibilitySSANSIEnginepreprocessing test coverageTest plan
xcodebuild test -workspace Wammer.xcworkspace -scheme MRTests -destination 'platform=iOS Simulator,name=iPhone 17 Pro' -only-testing:MRTests/SpeechQueueTests— expect 6 passing tests in ~0.2sxcodebuild build -workspace Wammer.xcworkspace -scheme Wammer -destination 'platform=iOS Simulator,name=iPhone 17 Pro'— expect clean build with no new warningsWammer.xcworkspacein Xcode, build theWammertarget, verify the audit navigator shows no regressionsstopSpeakingfires on disconnect/clear/user input/radial-movement (the four[self stopSpeaking]call sites in SSMudView.m)Known pre-existing issues not addressed here
The
MRTestsscheme has a pre-existing flake inGMCPHandlerTests.resetwhere an auto-layout call runs on a background thread and aborts the test process. Verified present on trunk independently of these changes — not introduced by this PR.Unit test coverage
src/MRTests/SpeechQueueTests.swiftuses aRecordingAnnouncertest double that captures everyannouncecall and exposes a manualcompleteOldestoperation, so each test drives the queue's drain loop deterministically:emptyTextIsDroppedAtEnqueuenonEmptyLineReachesAnnouncerobjcEnqueueUsesLowPriorityAndServerOriginlinesDrainInOrderAsCompletionsFirestopSpeakingClearsPendingLinesNotYetAnnouncedenqueueAfterStopSpeakingWorksNormally