Decision: harden and retain the shipped asynchronous, review-before-send voice lane. Live duplex: declined.
The microphone/TTS path was not rebuilt. The decision closes concrete depth gaps in the existing customer-web lane: mic-start barge-in, truthful capture and transcription privacy states, teardown cancellation, browser-locale recognition, low-confidence review guidance, and no-store transcript responses.
Requirement disposition#
| Clause | Result | Direct evidence |
|---|---|---|
| vad | pass | apps/oshun/web/src/lib/assistant/voice.ts#startVoiceRecordingapps/oshun/web/src/lib/assistant/__tests__/voice.spec.ts |
| captions | pass | apps/oshun/web/src/components/assistant/AssistantPanel.tsxapps/oshun/web/src/components/assistant/__tests__/AssistantPanelCaptions.spec.tsx |
| playback-controls | pass | apps/oshun/web/src/components/assistant/AssistantPanel.tsx#stopSpeakingapps/oshun/web/e2e/assistant-voice.spec.ts |
| barge-in | pass | apps/oshun/web/src/components/assistant/AssistantPanel.tsx#startListeningapps/oshun/web/src/components/assistant/__tests__/AssistantPanelCaptions.spec.tsxapps/oshun/web/e2e/assistant-voice.spec.ts |
| privacy-indicators | pass | apps/oshun/web/src/components/assistant/AssistantPanel.tsx#data-assistant-voice-privacyapps/oshun/bff/src/routes/assistant.ts#cache-control-no-storedocs/audits/eve-sota-voice-depth-decision/operator-review-2026-09-12.json |
| accent-noise-empty-errors | pass | docs/audits/eve-sota-voice-depth-decision/live-measurement-2026-09-12.jsonapps/oshun/web/e2e/assistant-voice.spec.ts |
| text-fallback | pass | apps/oshun/web/src/components/assistant/AssistantPanel.tsx#noteVoiceUnavailableapps/oshun/web/src/components/assistant/__tests__/AssistantPanel.test.tsx |
| existing-path-reuse | pass | apps/oshun/web/src/lib/assistant/voice.tsapps/oshun/bff/src/assistant/voice-config.ts |
Live STT measurement#
The probe used the shipped OpenRouter microsoft/mai-transcribe-2 binding. Each
speech and silence cell ran three times.
| Fixture | Samples | Worst WER | Budget | Result |
|---|---|---|---|---|
| us-clean | 3 | 0.200 | 0.200 | pass |
| british-clean | 3 | 0.000 | 0.300 | pass |
| caribbean-clean | 3 | 0.000 | 0.300 | pass |
| us-background-noise | 3 | 0.222 | 0.350 | pass |
All three empty-audio transcripts were empty. Nearest-rank p95 was 776.294 ms across 15 calls, against a 5000 ms budget.
Privacy boundary#
- Classification: Microphone bytes are ephemeral sensitive input; the transcript is derived member content.
- Minimization: Capture is member-initiated, VAD-bounded, capped at 60 seconds, and sent only after the member stops.
- Processor disclosure: The UI distinguishes on-device capture, provider transcription, and browser recognition before words reach the composer.
- Retention: The client holds the recording only for the active request; the transcript response is no-store and audio/provider bodies are not logged.
- Deletion: Cancel and panel teardown stop recorder or recognizer state; server normalization removes private temporary files on every exit.
- Member control: Recognized words remain editable text until explicit Send; voice output is opt-in and stoppable, with text always present.
Operator rubric#
| Criterion | Result | Observation |
|---|---|---|
| mic-state-discoverable | pass | The active microphone changes to a red Stop control and the composer reads Listening with both pause and one-minute auto-stop expectations. |
| capture-boundary-clear | pass | A compact status immediately above the composer says Microphone on and that the recording stays on the device until Stop. |
| transcription-boundary-clear | pass | The next state says Microphone off, names Eve's speech provider, and tells the member to review before Send. |
| review-before-send-clear | pass | Recognized words appear in the normal editable text composer with an enabled Send control; no user turn is created by transcription alone. |
| uncertainty-recovery-clear | pass | A low-confidence result visibly states that words may have been missed and directs review while preserving the transcript for correction. |
| synthetic-voice-label-clear | pass | Enabling output reveals a visible Synthetic voice chip and explanation that voice replies are synthetic alongside the AI assistant identity. |
| stop-and-barge-in-clear | pass | The rendered Stop-speaking control and microphone affordance are backed by the Chromium journey, which observes playback pause before the second capture begins. |
| text-fallback-preserved | pass | Every retained state keeps the standard composer visible and editable; the muted-output Chromium cell proves the written reply remains complete without speech. |
This is operator outcome evidence, not an external participant study.
Honest boundary#
- Synthetic voices make accent/noise checks reproducible but do not establish demographic accent fairness or replace consented-human-speech evaluation.
- The operator rubric is a repository implementation review, not an independent participant preference or usability study.
- Server TTS has a plain exact-text caption because the provider does not supply playback timings; word synchronization is not fabricated.
- The live quality probe covers the pinned OpenRouter STT model, not every optional Deepgram, Whisper, ElevenLabs, or Cartesia deployment.
- Manual assistive-technology interoperability remains Task 8.8.
- Mobile voice parity remains Task 8.9; this decision closes only customer-web voice depth.
- Phase 8 and G9 remain open for the remaining interaction, accessibility, mobile, and final reclassification tasks.
Record digest:
fe99b0b197fd1c8a507dbb44786098f07b284e5aeeb09cb45cb7a05c0c9ea1ef.