Skip to content

feat(voice): F010 push-to-talk on-device STT to chat - #11

Merged
nimat-dev merged 1 commit into
mainfrom
feat/F010
Oct 8, 2026
Merged

nimat-dev merged 1 commit into
mainfrom
feat/F010

Conversation

@nimat-dev

Copy link
Copy Markdown
Owner

Summary

This PR implements F010: Push-to-talk, on-device STT → chat, the first feature in Phase 04 (Voice — thin).

Changes Included:

  1. On-Device STT Provider Architecture (@shellmind/mobile/src/voice):
    • types.ts: Defines ISpeechToTextProvider interface with contract:
      • isAvailable(): Promise<boolean>
      • requestPermission(): Promise<"granted" | "denied" | "undetermined">
      • startRecording(onInterimResult?: (text: string) => void): Promise<void>
      • stopRecording(): Promise<string>
      • cancelRecording(): Promise<void>
      • isRecording(): boolean
    • mock.ts: MockSpeechToTextProvider providing deterministic audio simulation, configurable fixture text, interim transcript streaming (word-by-word with delay), cancellation, and error/permission testing support.
    • native.ts: NativeSpeechToTextProvider integrating with native speech recognition (@react-native-voice/voice / Web Speech API) and falling back gracefully if native recognition is unavailable.
    • registry.ts: Provider registration with getSpeechToTextProvider(), setSpeechToTextProvider(), and resetSpeechToTextProvider().
    • Exported through packages/mobile/src/voice/index.ts and packages/mobile/src/index.ts.
  2. Push-to-Talk Chat UI Integration (@shellmind/mobile/src/components/ChatScreen.tsx):
    • Push-to-talk microphone button (testID="mic-button").
    • Active recording state banner & indicator (testID="recording-indicator") with pulse label and interim transcript preview.
    • Cancel recording button (testID="voice-cancel-button").
    • Injects recognized transcript directly into testID="chat-input-field" so text is clearly visible and user-editable before sending.
    • Permission denial handling with informative banner (testID="voice-error-banner") and dismissal button (testID="voice-error-dismiss"), falling back safely to keyboard typing.
  3. Tests & Evidence:
    • 7 new comprehensive mobile tests in packages/mobile/src/mobile.test.ts covering STT lifecycle, interim streaming, recording cancellation, permission denial, native fallback, registry overrides, and ChatScreen voice props.
    • 120/120 tests passing monorepo-wide (29 protocol, 52 agent, 39 mobile).
    • Clean architecture verified with dependency-cruiser (75 modules, 220 dependencies cruised, 0 violations).
    • Maestro E2E flow in .maestro/voice_stt_flow.yaml.
    • Architecture summary, test summary, and E2E trace stored in .harness/evidence/F010/.

@nimat-dev

Copy link
Copy Markdown
Owner Author

Maker-Checker Review: F010 (Push-to-talk, on-device STT → chat)

1. Acceptance Criteria Verification

  • On-device STT provider abstraction ISpeechToTextProvider defined in packages/mobile/src/voice/types.ts.
  • Mock provider MockSpeechToTextProvider supports deterministic test fixtures, interim streaming, permission overrides, and cancellation.
  • Native provider NativeSpeechToTextProvider bridges native speech recognizers with graceful fallback.
  • Provider registry in packages/mobile/src/voice/registry.ts supports runtime swapping.
  • Push-to-talk mic button (testID="mic-button"), recording indicator (testID="recording-indicator"), cancel button (testID="voice-cancel-button"), and error banner (testID="voice-error-banner") implemented in ChatScreen.tsx.
  • Speech output populates testID="chat-input-field" allowing review and editing before dispatch.
  • Permission denial falls back cleanly to typing without application crashes.
  • 120/120 tests pass across all packages (39 mobile tests).
  • Dependency cruiser reports 0 violations across 75 modules.
  • Pure core invariant preserved: voice STT is mobile-only; protocol and agent remain audio-agnostic.
  • Maestro E2E specification in .maestro/voice_stt_flow.yaml.
  • Harness docs and evidence logged in .harness/evidence/F010/.

2. Evaluation Scores

  • Acceptance: 5/5
  • Correctness: 5/5
  • Boundaries: 5/5
  • Modularity: 5/5
  • Evidence: 5/5
  • Average: 5.0 (PASS)

3. Decision

APPROVE. Ready for squash merge to main.

@nimat-dev
nimat-dev merged commit d6a40c8 into main Oct 8, 2026
2 checks passed
@nimat-dev
nimat-dev deleted the feat/F010 branch October 8, 2026 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant