Implement partial and final transcription streaming
epic-speech-to-text-input-speech-engine-task-005 — Wire the raw speech_to_text package callbacks (onResult with isFinal flag) into the domain event stream. Map partial results to PartialTranscriptionEvent and final results to FinalTranscriptionEvent, preserving confidence scores where available. Ensure back-pressure is handled safely and that no events are emitted after the stream is closed.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
The speech_to_text package's onResult provides a SpeechRecognitionResult with recognizedWords (String) and finalResult (bool) and alternates (List with confidence). Extract confidence as result.alternates?.firstOrNull?.confidence — it may be null on some platforms. Map in a private _mapToEvent(SpeechRecognitionResult result) method to keep the callback wiring clean. Always check !_controller.isClosed before sink.add() — the platform can fire callbacks after stopListening() returns on some Android versions.
Consider using StreamController with an onCancel callback to call stopListening() if the consumer cancels the stream, preventing orphaned sessions. For Norwegian (nb-NO), confidence scores from on-device models are often low (0.4–0.7) — do not filter by confidence threshold in this service layer; leave that to consumers.
Testing Requirements
Unit tests (flutter_test): emit sequences for partial-only, final-only, mixed partial+final; verify confidence null handling when platform omits it; verify post-close guard prevents late emissions; verify empty transcript string passes through; test burst of 20 partial events in sequence and verify all emitted in order. Use a FakeNativeSpeechApiBridge that calls back synchronously in tests. Assert event types and field values with matcher library.
The speech_to_text Flutter package delegates accuracy entirely to the OS-native engine. Norwegian accuracy for domain-specific vocabulary (medical terms, organisation names, accessibility terminology) may fall below the 85% acceptance threshold on older devices or in noisy environments, causing user frustration and manual correction overhead that negates the time saving.
Mitigation & Contingency
Mitigation: Configure the SpeechRecognitionService with Norwegian as the explicit locale and test against a representative corpus of peer mentoring vocabulary on target devices. Expose locale switching so users can fallback to Bokmål vs Nynorsk. Clearly set user expectations in the UI that transcription is a starting point for editing, not a finished product.
Contingency: If accuracy is consistently below threshold on specific device/OS combinations, add a device-capability check that hides the dictation button with an explanatory message rather than offering a degraded experience. Document affected device models for QA and org contacts.
The speech_to_text Flutter package is a third-party dependency that may introduce breaking API changes or deprecations on major version upgrades, requiring rework of SpeechRecognitionService when Flutter or platform OS versions are updated.
Mitigation & Contingency
Mitigation: Wrap all speech_to_text API calls behind the SpeechRecognitionService interface so that package changes are isolated to one file. Pin the package version in pubspec.yaml and review changelogs before any upgrade. Write integration tests that exercise the package contract so regressions are caught immediately.
Contingency: If the package is abandoned or has unresolvable issues, NativeSpeechApiBridge already provides the platform-channel abstraction needed to implement a direct plugin replacement with minimal changes to SpeechRecognitionService.