You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace SessionController's five hand-coordinated Handler threads (bg, capture, speech, plus main, plus the accessibility service's own thread) and manual @Volatile/turn-id state with structured concurrency (Kotlin coroutines + StateFlow/Mutex), without changing the frozen OverlayCommand/planner contracts or any of the five core pieces.
Rationale
Flagged by the repo audit as the highest-maintainability-risk code in the project. The turn-invalidation logic (newTurn(), isCurrent(), recordingTurn) is correct today because it was carefully hand-verified this session, but every new feature added to this class (app-choice state, chosenPackage, currentChoices, the newer open_ended/AppLauncher path) grows the same unstructured state space. This is not a bug report - nothing is currently broken - it's a bet against future regressions being introduced silently.
Acceptance criteria
No Handler/HandlerThread remains in SessionController - replaced by coroutines on appropriately-scoped dispatchers
Turn invalidation (a mic-tap during "Thinking..." must not let a stale plan repaint the pill) is expressed via Job cancellation, not manual turn-id comparison
Every existing behavior verified in this session's manual device testing still holds: stop-mid-recording, stop-and-resume preserving step position, cursor/speech running in parallel with bounds resolution, debug panel not clobbering itself
All existing unit tests pass unmodified or are updated to test the same behavior through the new concurrency model
No change to contracts/*.schema.json, OverlayCommand, or PlannerResult
Implementation steps
Introduce a viewModelScope-equivalent CoroutineScope owned by SessionController, cancelled in dispose()
Model a "turn" as a cancellable coroutine Job rather than an AtomicInteger comparison
Move WavRecorder start/stop behind a Mutex instead of a dedicated Handler thread
Move TTS synthesis + playback onto its own dispatcher via withContext(Dispatchers.IO), preserving the "speech never blocks the visual path" property
Re-run every manual verification scenario from this session's transcript (mic-tap-during-thinking, Stop mid-utterance, taxi app-choice flow) on a physical device before merging
Estimated effort
High (3-5 days for one engineer familiar with the codebase, including manual device re-verification of every documented scenario)
Risks
This is the single riskiest change achievable in this codebase - it touches the class every other feature depends on
Objective
Replace
SessionController's five hand-coordinatedHandlerthreads (bg,capture,speech, plus main, plus the accessibility service's own thread) and manual@Volatile/turn-id state with structured concurrency (Kotlin coroutines +StateFlow/Mutex), without changing the frozenOverlayCommand/planner contracts or any of the five core pieces.Rationale
Flagged by the repo audit as the highest-maintainability-risk code in the project. The turn-invalidation logic (
newTurn(),isCurrent(),recordingTurn) is correct today because it was carefully hand-verified this session, but every new feature added to this class (app-choice state,chosenPackage,currentChoices, the neweropen_ended/AppLauncherpath) grows the same unstructured state space. This is not a bug report - nothing is currently broken - it's a bet against future regressions being introduced silently.Acceptance criteria
Handler/HandlerThreadremains inSessionController- replaced by coroutines on appropriately-scoped dispatchersJobcancellation, not manual turn-id comparisoncontracts/*.schema.json,OverlayCommand, orPlannerResultImplementation steps
viewModelScope-equivalentCoroutineScopeowned bySessionController, cancelled indispose()Jobrather than anAtomicIntegercomparisonWavRecorderstart/stop behind aMutexinstead of a dedicatedHandlerthreadwithContext(Dispatchers.IO), preserving the "speech never blocks the visual path" propertyEstimated effort
High (3-5 days for one engineer familiar with the codebase, including manual device re-verification of every documented scenario)
Risks
Testing checklist