* refactor(server): extract voice mode subsystem into VoiceSession
session.ts was a 10.5k-line god object and the most-churned file in the
repo. ~1,100 of those lines were an entire voice/audio subsystem — the
STT/TTS/dictation managers, the barge-in audio-buffering state machine,
voice-turn orchestration, and the MCP voice bridge — interleaved field by
field and method by method with workspace/git/agent/provider concerns.
Move the whole subsystem into a new VoiceSession deep module. Session now
holds one `voiceSession` field, constructs it once, and delegates the
voice/dictation/abort message types, the permission auto-allow gate, and
cleanup to it. VoiceSession owns all 18 voice fields and ~25 methods and
reaches back into the agent run only through a narrow VoiceSessionHost
seam (emit, loadAgent, reloadAgentSession, sendSpokenInput,
interruptAgentIfRunning, hasActiveAgentRun).
Behavior is preserved (verbatim method moves); deleting voice-session.ts
now removes the feature mechanically. The voice unit tests drive the
VoiceSession boundary instead of reaching into Session internals, so
future voice tests can construct a VoiceSession with a fake host.
session.ts: 10,468 -> 9,272 lines.
* refactor(server): move VoiceSession into voice/ and test it at the boundary
Address Greptile review on #1640:
- Move voice-session.ts into the existing voice/ subdirectory, alongside
voice-turn-controller.ts, instead of adding another peer to the 30+ file
server/ directory. The directory now carries the domain.
- Add voice/voice-session.test.ts beside the module: it constructs a
VoiceSession with a fake VoiceSessionHost and drives it through the public
API (handleSetVoiceMode, then turn-detection/STT events), asserting on the
host seam (sendSpokenInput) and emitted messages. No Session, no private
field/method access.
- Remove the voice tests from session.test.ts that reached through Session's
private voiceSession field into VoiceSession internals.
Same three behaviors are covered (streaming final -> agent, finalization
timeout empty path, low-confidence filtering); driving handleSetVoiceMode
additionally exercises the enable path the old tests bypassed.