critical priority medium complexity backend pending backend specialist Tier 4

Acceptance Criteria

Every onResult callback with isFinal==false maps to exactly one PartialTranscriptionEvent emitted on the stream
Every onResult callback with isFinal==true maps to exactly one FinalTranscriptionEvent emitted on the stream
FinalTranscriptionEvent.confidence contains the raw confidence value from the platform (0.0–1.0) when available, or null when not provided
PartialTranscriptionEvent.transcript contains the cumulative partial text, not just the latest word delta
No SpeechRecognitionEvent is emitted after the StreamController is closed (guarded by _isClosed check before every sink.add())
Rapid successive partial results (>10/sec) do not cause stream buffer overflow or dropped events
If the platform returns an empty transcript string, the event is still emitted (empty string is valid, not filtered)
Events are emitted in chronological order matching platform callback order — no reordering
Confidence score of 0.0 is treated as a valid score, not as 'unavailable'

Technical Requirements

frameworks
Flutter
speech_to_text (pub.dev package)
Dart async streams
apis
SpeechToText.listen() onResult callback
SpeechRecognitionResult (speech_to_text model)
StreamController<SpeechRecognitionEvent>.sink
data models
PartialTranscriptionEvent {transcript: String, timestamp: DateTime}
FinalTranscriptionEvent {transcript: String, confidence: double?, timestamp: DateTime}
SpeechRecognitionResult (platform DTO)
performance requirements
Callback-to-stream-emit latency under 5ms (pure Dart mapping, no I/O)
No memory allocation for intermediate DTOs — map directly from platform result to domain event
Handle burst rate of 20 partial results/second without dropping events
security requirements
Transcript text must not be logged at INFO level or above — only DEBUG/VERBOSE
No transcript content written to persistent storage during active session

Execution Context

Execution Tier
Tier 4

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.

Component
Speech Recognition Service
service high
Epic Risks (2)
medium impact medium prob technical

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.

medium impact low prob dependency

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.