Harden the VoiceBridge pipeline by introducing seven new components (PipelineOrchestrator, AudioRoutingStateMachine, PlatformAdapters, AudioBridge, DegradationManager, DemoBootstrap, CleanupSequencer), extending existing modules (AudioOutputModule, MessageBus, types), and rewriting the offscreen document and content script to use sequence-tracked utterance lifecycle, strict playback ordering, backpressure management, failure isolation, track replacement coordination, network resilience, graceful degradation, and deterministic cleanup.
-
1. Add new types and message bus extensions
-
1.1 Add new types to
src/lib/types.ts- Add
AudioRoutingState,AudioRoutingEvent,DegradationLevel,DegradationTransition,AudioBridgeMessage,CleanupTarget, andCleanupResulttypes as defined in the design document - Requirements: 8.1, 5.1, 10.5, 7.1
- Add
-
1.2 Add new message types to
src/lib/message-bus.ts- Add
AUDIO_ROUTING_STATE_CHANGED,DEGRADATION_LEVEL_CHANGED,UTTERANCE_STATE_CHANGED,TRACK_INJECT,TRACK_RESTORE,TRACK_STATUS,AUDIO_BRIDGE_READY,AUDIO_BRIDGE_DISCONNECTED,DEMO_KEYS_POPULATED,EMBEDDED_KEY_EXHAUSTED, andCLEANUP_COMPLETEtoMessageTypeunion andMessagePayloadMap - Requirements: 1.10, 5.7, 10.5, 6.6
- Add
-
-
2. Implement AudioRoutingStateMachine (
src/lib/audio-routing.ts)-
2.1 Implement the pure state transition function
transitionRoutingState()- Implement the state machine with four states: PASSTHROUGH, MUTED, TTS_PLAYING, BARGE_IN
- Implement
getAudioSource()mapping each state to its audio source - Implement
getEchoCancellationMode()mapping routing states to echo cancellation modes - Follow the state diagram from the design: PASSTHROUGH→MUTED on session_start, MUTED→TTS_PLAYING on tts_start, TTS_PLAYING→BARGE_IN on barge_in, etc.
- Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.8
-
[ ]* 2.2 Write property test for audio routing state machine (Property 7)
- Property 7: Audio routing state machine produces only valid transitions
- Test that for any sequence of AudioRoutingEvents starting from PASSTHROUGH, the state is always valid and deterministic
- Test that
getAudioSource()maps correctly: PASSTHROUGH→mic, MUTED→silence, TTS_PLAYING→tts, BARGE_IN→mic-fade-tts - Validates: Requirements 8.1, 8.2, 8.3, 8.4, 8.5, 2.3, 2.4, 2.10
-
[ ]* 2.3 Write property test for routing-to-echo-cancellation mapping (Property 8)
- Property 8: Routing state correctly maps to echo cancellation mode
- Test that
getEchoCancellationMode()returns 'speaking' for MUTED and TTS_PLAYING, 'listening' for PASSTHROUGH and BARGE_IN - Validates: Requirements 8.8
-
-
3. Implement DegradationManager (
src/lib/degradation-manager.ts)-
3.1 Implement
computeDegradationLevel(),isValidDegradation(), andgetNextDegradationLevel()computeDegradationLevel(): full when all connected, text-only when STT+LLM connected but TTS not, transcription-only when only STT connected, passthrough when STT not connectedisValidDegradation(): degradation must follow cascade order (full→text-only→transcription-only→passthrough), upgrade can skip levelsgetNextDegradationLevel(): returns the next level down in the cascade, or null for passthrough- Requirements: 5.1, 5.2, 5.3, 5.4, 5.10
-
[ ]* 3.2 Write property test for degradation level computation (Property 9)
- Property 9: Degradation level is correctly computed from service health
- Test all combinations of service connection states produce the correct degradation level
- Validates: Requirements 5.1, 5.2, 5.3, 5.4
-
[ ]* 3.3 Write property test for degradation cascade ordering (Property 10)
- Property 10: Degradation cascade never skips levels
- Test that for any sequence of service failures, degradation only steps down one level at a time
- Validates: Requirements 5.10
-
-
4. Implement CleanupSequencer (
src/lib/cleanup-sequencer.ts)-
4.1 Implement
executeCleanupSequence()andbuildPipelineCleanupTargets()executeCleanupSequence(): iterate through targets in order, try/catch each, collect errors, return CleanupResult with durationbuildPipelineCleanupTargets(): build ordered list (AudioCapture → STT → Translation → TTS → AudioOutput → EchoCancellation → LatencyMonitor), skip null modules- Requirements: 7.1, 7.2, 7.8, 7.10
-
[ ]* 4.2 Write property test for cleanup resilience (Property 14)
- Property 14: Cleanup resilience — all steps execute regardless of failures
- Test that for any list of CleanupTargets where an arbitrary subset throw errors, all targets are attempted and errors are collected
- Validates: Requirements 7.8, 7.10
-
[ ]* 4.3 Write property test for cleanup ordering (Property 15)
- Property 15: Cleanup executes in deterministic order
- Test that
buildPipelineCleanupTargets()always returns targets in the correct order, skipping null modules - Validates: Requirements 7.1
-
-
5. Checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
-
6. Implement DemoBootstrap (
src/lib/demo-bootstrap.ts)-
6.1 Implement
bootstrapDemoKeys(),checkEmbeddedKeyExhaustion(), andisDemoMode()bootstrapDemoKeys(): read Vite env vars (VITE_DEMO_ELEVENLABS_KEY,VITE_DEMO_LLM_KEY,VITE_DEMO_LLM_PROVIDER,VITE_DEMO_OPENROUTER_MODEL), check if user keys exist in chrome.storage, write embedded keys using Settings_Store encryption if no user keyscheckEmbeddedKeyExhaustion(): checkembeddedKeyExhaustedflag in chrome.storage.local, cache result for 6 hoursisDemoMode(): return true if demo keys are active and no user-provided keys exist- Requirements: 6.1, 6.2, 6.5, 6.6, 6.7, 6.8
-
[ ]* 6.2 Write unit tests for DemoBootstrap
- Test demo key population with mocked chrome.storage
- Test that user-provided keys are not overwritten
- Test embedded key exhaustion caching (6-hour TTL)
- Test
isDemoMode()returns correct state - Requirements: 6.1, 6.2, 6.6, 6.7
-
-
7. Implement AudioBridge (
src/lib/audio-bridge.ts)-
7.1 Implement
AudioBridgeSenderclass (offscreen side)attachPort(): attach MessagePort from service workersendAudioChunk(): send PCM as Transferable ArrayBuffer (zero-copy)sendTrackCommand(): send inject/restore/status commands, return Promise for acknowledgmentsyncState(): send routing and echo state to content scriptisConnected()andclose()methods- Requirements: 10.1, 10.2, 10.5, 10.6, 10.7
-
7.2 Implement
AudioBridgeReceiverclass (content script side)attachPort(): attach MessagePort from service worker- Set up message handler dispatching to
onAudioChunk,onTrackCommand,onStateSynccallbacks sendTrackResponse(): send acknowledgment back to offscreenisConnected()andclose()methods- Requirements: 10.3, 10.5, 10.6, 10.7
-
[ ]* 7.3 Write unit tests for AudioBridge
- Test Transferable ArrayBuffer transfer (zero-copy verification)
- Test track command acknowledgment protocol
- Test port disconnection detection
- Requirements: 10.2, 10.6, 10.4
-
-
8. Implement PlatformAdapter interface and concrete adapters (
src/lib/platform-adapters.ts)-
8.1 Implement PlatformAdapter interface and
createPlatformAdapter()factory- Define the interface with
initialize(),injectVirtualTrack(),restoreOriginalTrack(),isInjected(),destroy() - Implement factory function mapping MeetingPlatform to adapter instances, returning null for 'none'
- Requirements: 3.1, 3.7
- Define the interface with
-
8.2 Implement GoogleMeetAdapter
- Inject main-world script at document_start that intercepts
navigator.mediaDevices.getUserMedia - Store original audio track reference, replace on session start via
RTCRtpSender.replaceTrack() - Use
window.postMessagewithvoicebridgesource marker for communication - Requirements: 3.2, 3.10
- Inject main-world script at document_start that intercepts
-
8.3 Implement TeamsAdapter and DiscordAdapter
- Inject main-world script monitoring
RTCPeerConnectionconstructor - Capture peer connections, use
replaceTrack()on audio sender - Use
window.postMessagewithvoicebridgesource marker for communication - Requirements: 3.3, 3.4, 3.10
- Inject main-world script monitoring
-
8.4 Implement ZoomAdapter
- Use
chrome.tabCapture.capture()to obtain tab audio stream - Create AudioContext mixing node combining TTS audio with tab output
- Route mixed audio back to the tab
- Requirements: 3.5
- Use
-
8.5 Implement GenericAdapter
- Monitor
RTCPeerConnectionconstructor in main world - Attempt
replaceTrack()on any detected audio sender - Requirements: 3.6
- Monitor
-
[ ]* 8.6 Write property test for platform adapter factory (Property 13)
- Property 13: Platform adapter factory returns correct adapter type
- Test that for any MeetingPlatform value,
createPlatformAdapter()returns the correct adapter type or null for 'none' - Validates: Requirements 3.7
-
-
9. Extend AudioOutputModule with
getMixedTrack()method- Add
getMixedTrack()to existingAudioOutputModuleinsrc/lib/audio-output.ts - Return a MediaStreamTrack from a mixing node that dynamically switches between silence and TTS audio based on routing state
- Ensure zero gaps in the audio stream sent to the meeting
- Requirements: 2.9, 2.3, 2.4
- Add
-
10. Checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
-
11. Implement PipelineOrchestrator (
src/lib/pipeline-orchestrator.ts)-
11.1 Implement utterance lifecycle tracking and sequence ID management
- Create
PipelineOrchestratorclass with#utterancesMap,#currentSequenceIdcounter,#playbackHead - Implement
handleSpeechEnd()to assign monotonically increasing sequence IDs and create PipelineUtterance records with state CAPTURED - Implement state transitions: CAPTURED→TRANSCRIBED→TRANSLATED→SYNTHESIZED→PLAYED, or to DROPPED from any state
- Reset sequence counter and clear state on new session
- Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.12
- Create
-
11.2 Implement strict playback ordering and backpressure management
- Implement
#canPlay(): utterance N+1 cannot play until N is PLAYED or DROPPED - Implement
#advancePlayback(): try to advance the playback head after each state transition - Implement
#enforceBackpressure(): drop oldest unprocessed utterances when queue > 3 - Implement bounded active utterance map (max 10 entries), evict completed utterances older than 30 seconds
- Requirements: 1.7, 1.8, 1.11
- Implement
-
11.3 Implement failure isolation and per-stage timeouts
- Implement
#setStageTimeout()for STT (5s), Translation (3s), TTS (3s) - On timeout or failure, transition utterance to DROPPED with reason, continue processing subsequent utterances
- Implement
#dropUtterance()with reason logging - Requirements: 1.9, 9.2, 9.3
- Implement
-
11.4 Implement latency enforcement and consecutive high-latency alerting
- Measure end-to-end latency per utterance using LatencyMonitor
- Track consecutive high-latency utterances (>3000ms), send ERROR after 5 consecutive
- Implement translation flush on backpressure (queue ≥ 2 pending utterances)
- Requirements: 9.1, 9.2, 9.3, 9.4, 9.5, 9.6
-
11.5 Integrate AudioRoutingStateMachine into PipelineOrchestrator
- Use
transitionRoutingState()for routing state transitions on session start/stop, TTS start/end, barge-in, degradation - Emit
AUDIO_ROUTING_STATE_CHANGEDmessages on state changes - Coordinate with EchoCancellationModule based on routing state
- Ensure state transitions complete within 50ms
- Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8
- Use
-
11.6 Integrate DegradationManager into PipelineOrchestrator
- Implement
handleServiceStateChange()to update service health and compute degradation level - Implement
#evaluateDegradation()and#attemptUpgrade()for cascade transitions - Restore original mic track when degrading below
full - Auto-upgrade within 5 seconds when services recover
- Log every degradation transition with trigger, previous level, and new level
- Emit
DEGRADATION_LEVEL_CHANGEDmessages - Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.8, 5.9, 5.10
- Implement
-
11.7 Integrate CleanupSequencer into PipelineOrchestrator
- Implement
stopSession()usingbuildPipelineCleanupTargets()andexecuteCleanupSequence() - Set all module references to null after cleanup
- Complete cleanup within 1 second
- Emit
CLEANUP_COMPLETEmessage with any errors - Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.8, 7.10
- Implement
-
11.8 Implement network resilience — reconnection and second-chance logic
- Detect WebSocket disconnection within 2 seconds via heartbeat timeout
- Implement exponential backoff reconnection (500ms base, 2x multiplier, 10s max, 5 attempts)
- Implement second-chance reconnection after 30 seconds if first cycle fails
- Pause session and send ERROR if second cycle also fails
- Send CONNECTION_STATE_CHANGED messages for connecting/connected/error states
- Requirements: 4.3, 4.4, 4.7, 4.8, 4.9, 4.10
-
11.9 Emit SESSION_STATE_CHANGED messages with utterance counts
- Send updated totalUtterances, droppedUtterances, and currentSequenceId after each state transition
- Requirements: 1.10
-
[ ]* 11.10 Write property test for utterance lifecycle transitions (Property 1)
- Property 1: Utterance lifecycle follows valid state transitions
- Test that for any utterance, state transitions only follow valid paths
- Validates: Requirements 1.1, 1.3, 1.4, 1.5, 1.6
-
[ ]* 11.11 Write property test for monotonic sequence IDs (Property 2)
- Property 2: Sequence IDs are monotonically increasing
- Test that for N speech-end events, IDs are exactly 1..N with no gaps or duplicates
- Validates: Requirements 1.2, 1.12
-
[ ]* 11.12 Write property test for strict playback ordering (Property 3)
- Property 3: Strict playback ordering
- Test that utterance N+1 never begins playback before N reaches PLAYED or DROPPED
- Validates: Requirements 1.7
-
[ ]* 11.13 Write property test for backpressure bounds (Property 4)
- Property 4: Backpressure bounds the unprocessed queue
- Test that unprocessed utterance count never exceeds 3
- Validates: Requirements 1.8
-
[ ]* 11.14 Write property test for failure isolation (Property 5)
- Property 5: Failure isolation — failed utterances do not block the pipeline
- Test that failed utterances transition to DROPPED and subsequent utterances continue
- Validates: Requirements 1.9, 9.3
-
[ ]* 11.15 Write property test for bounded active utterance map (Property 6)
- Property 6: Active utterance map is bounded
- Test that the active utterance map never exceeds 10 entries
- Validates: Requirements 1.11
-
-
12. Checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
-
13. Rewrite offscreen document (
src/offscreen/offscreen.ts)- Replace ad-hoc wiring with PipelineOrchestrator instantiation and delegation
- Wire SESSION_START to
orchestrator.startSession(), SESSION_STOP toorchestrator.stopSession() - Initialize AudioBridgeSender and attach MessagePort from service worker
- Forward audio chunks from PipelineOrchestrator through AudioBridgeSender
- Handle
beforeunloadto trigger cleanup via PipelineOrchestrator - Preserve existing voice time tracking and demo limit logic
- Requirements: 1.1–1.12, 7.11, 10.1, 10.2
-
14. Rewrite content script (
src/content/content-script.ts)-
14.1 Add PlatformAdapter lifecycle management
- On MEETING_DETECTED, instantiate the corresponding PlatformAdapter via
createPlatformAdapter()and callinitialize() - Handle initialization failure: send ERROR with domain "meeting" and code "injection-failed", display
[INJECTION FAILED]in widget - On session end, call
restoreOriginalTrack()anddestroy()on the active adapter - Requirements: 3.7, 3.8, 3.9
- On MEETING_DETECTED, instantiate the corresponding PlatformAdapter via
-
14.2 Add AudioBridgeReceiver for MessageChannel audio
- Attach MessagePort from service worker
- Route received audio chunks to PlatformAdapter for injection
- Handle track commands (inject/restore/status) and send acknowledgment responses
- Handle state-sync messages for routing and echo state
- Requirements: 10.3, 10.5, 10.6
-
14.3 Add RTCPeerConnection monitoring for renegotiation detection
- Monitor
trackevents andconnectionstatechangeevents on the RTCPeerConnection - Re-apply virtual track replacement within 500ms when renegotiation or new peer connection detected
- Requirements: 2.6, 2.7
- Monitor
-
14.4 Add
beforeunloadhandler and widget degradation status- On
beforeunload, send SESSION_STOP with reason "tab-closed" to trigger cleanup - Call
restoreOriginalTrack()on the active PlatformAdapter before tab unloads - Update floating widget with degradation level status text:
[TEXT ONLY],[TRANSCRIPT ONLY],[PASSTHROUGH] - Update widget status icon based on routing state (microphone, muted, speaker, microphone-pulse)
- Requirements: 7.7, 7.9, 5.7, 8.7
- On
-
-
15. Update service worker (
src/background/service-worker.ts)-
15.1 Add MessageChannel broker
- Create MessageChannel port pairs on session start
- Send one port to offscreen document, one to content script
- Detect port disconnection and re-establish within 1 second
- Close both ports on session end
- Requirements: 10.1, 10.4, 10.7
-
15.2 Add DemoBootstrap on install
- Call
bootstrapDemoKeys()inruntime.onInstalledhandler - Send
DEMO_KEYS_POPULATEDmessage if demo keys were populated - Requirements: 6.1, 6.2
- Call
-
-
16. Checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
-
17. Wire onboarding and settings for demo mode
-
17.1 Update onboarding wizard to skip API Keys step when demo keys are active
- Check
isDemoMode()on onboarding load - Skip Step 2 (API Keys) and proceed from Welcome (Step 1) to Voice Recording (Step 3)
- Display demo mode notice during Welcome step: "Demo mode active — 5 minutes of voice translation included. Enter your own API key in Settings for unlimited usage."
- Requirements: 6.3, 6.4
- Check
-
17.2 Update settings page for demo key override and exhaustion handling
- When user enters their own API key, overwrite demo key and switch to unlimited mode
- Handle embedded key exhaustion (HTTP 402): set
embeddedKeyExhausted: true, disable demo mode, prompt for personal API key - Requirements: 6.5, 6.6
-
-
18. Final checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
- Tasks marked with
*are optional and can be skipped for faster MVP - Each task references specific requirements for traceability
- Checkpoints ensure incremental validation
- Property tests validate universal correctness properties from the design document
- Unit tests validate specific examples and edge cases
- The design uses TypeScript throughout — all implementations use TypeScript
- All new files follow kebab-case naming and colocate tests with source