high priority medium complexity testing pending testing specialist Tier 5

Acceptance Criteria

All 6 test scenario groups have at least one passing test each with no skipped tests
Happy-path test verifies exact state sequence: idle → requestingPermission → recording → processing → complete using state.history or sequential expect() calls
Scope guard rejection test verifies that calling startDictation() when DictationScopeGuard.isAvailable returns false transitions directly to error state with a ScopeGuardRejected error type
Recognition error test verifies that a stream error emitted by mock SpeechRecognitionService transitions state to error with the original exception wrapped in a RecognitionError
Session interruption test verifies that calling interrupt() with a non-empty partial transcript invokes PartialTranscriptionRepository.persist() exactly once before transitioning to interrupted state
Recovery test verifies that re-initializing after interrupted state restores the previously persisted partial transcript into the new session
Concurrent field instances test creates two ProviderContainer instances (or uses a single container with distinct family keys) and confirms mutations to one do not affect the other
Disposal test verifies that SpeechRecognitionService.cancel() is called exactly once and PartialTranscriptionRepository.persist() is called with the correct transcript on dispose
Overall test suite achieves 100% branch coverage of the TranscriptionStateManager state machine
No test uses real async timers — all use fake async / microtask flushing to remain deterministic

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
mocktail
apis
SpeechRecognitionService
DictationScopeGuard
PartialTranscriptionRepository
data models
TranscriptionState
TranscriptionStatus (enum)
PartialTranscript
RecognitionError
performance requirements
Full test suite must complete in under 10 seconds
No real network or file-system calls — all external dependencies mocked
Use fakeAsync/pumpEventQueue to avoid real timer delays
security requirements
Test fixtures must not contain real PII — use placeholder strings like 'test-partial-transcript'
Mock repository must not write to disk

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Prefer `ProviderContainer` over full widget tests for state machine logic — it is faster and avoids widget tree overhead. Pattern for collecting state history: `final states = []; container.listen(transcriptionProvider('field-1'), (_, next) => states.add(next), fireImmediately: true);`. For mocktail setup: create `MockSpeechRecognitionService extends Mock implements SpeechRecognitionService`, etc. Use `when(() => mockGuard.isAvailable).thenReturn(false)` for scope guard rejection.

For stream-based errors: expose a `StreamController` from the mock and `addError()` to it during the recognition error test. Ensure tearDown() calls `container.dispose()` to prevent test pollution.

Testing Requirements

This task IS the testing task. Organize tests into a single file `transcription_state_manager_test.dart` with clearly named group() blocks for each scenario. Use ProviderContainer (not WidgetTester) for pure state unit tests to keep them fast. Use mocktail: `registerFallbackValue` for all custom types passed to mocked methods.

Assert state transitions by collecting a list of emitted states via container.listen() into a local list and then checking the list against expected sequence. For the concurrent test, use two separate ProviderContainers with the same family key but assert they hold different state objects after diverging mutations.

Component
Transcription State Manager
service medium
Epic Risks (2)
medium impact low prob technical

If a peer mentor rapidly switches between dictation-enabled fields while a session is still processing, the Riverpod family provider may share state or the SpeechRecognitionService may receive conflicting start/stop commands, causing orphaned recording sessions or state corruption.

Mitigation & Contingency

Mitigation: Design the state manager to enforce a single active dictation session globally via a shared active-field-key notifier. When a new field requests dictation while another session is active, automatically issue a stop command to the existing session and await completion before starting the new one. Test this concurrency scenario explicitly.

Contingency: If concurrency issues persist in integration testing, add a global dictation mutex at the SpeechRecognitionService level that serialises all start requests, with a short debounce to handle rapid field switching.

medium impact medium prob scope

The recovery flow for interrupted dictation sessions (app restart with persisted partials) has ambiguous UX requirements. If recovery is automatic and the user has already typed different content into the field, the merge logic may overwrite or duplicate user input, causing data loss.

Mitigation & Contingency

Mitigation: Define the recovery behaviour explicitly: recovery should surface as an opt-in prompt ('You have unsaved dictation — insert or discard?') rather than an automatic merge. The state manager emits a dedicated recoverable-partial state that the UI layer renders as a non-blocking action sheet.

Contingency: If the recovery UI adds too much complexity for the initial release, scope recovery to display only the partial text in the preview field on re-open without auto-insertion, letting the user manually copy if needed, and defer the automatic recovery prompt to a subsequent iteration.