# Plan: Speaker Recognition **Goal:** Maven can distinguish between different speakers on the voice channel — recognize known voices (the user, family members) and tag facts/notes/transcripts with a speaker identity. **Done when:** - Speaker embedding extractor (e.g., ECAPA-TDNN or a simple MFCC + GMM) runs on incoming voice PCM before STT - Embedding is compared against enrolled speaker profiles (stored as vectors in the `memory_vectors` table alongside semantic memory) - Unknown speakers are enrolled on first interaction (prompt: "кто это?") - All voice fact/note writes are tagged with `speaker:` in the value/source metadata - Speaker identity is available as context to the router, phraser, and replier ("ok, ") **Scope:** - New `internal/speaker/` package — enrollment, recognition, embedding extraction - Reuses `internal/store.MemoryStore` for speaker vector storage (same `memory_vectors` table, different `source` prefix) - Reuses `internal/audio` for PCM preprocessing - Integration point: `cmd/mavend/voice.go:HandlePushToTalk` — speaker ID extracted before STT, passed through context **Steps:** 1. Research speaker embedding approaches — simplest floor: MFCC + cosine similarity via `github.com/mjibson/go-dsp` or a pre-trained ONNX model (SpeechBrain ECAPA) 2. Create `internal/speaker/recognizer.go` — `Recognizer` interface: `Identify(pcm []float32) (SpeakerID, confidence)`, `Enroll(id, pcm)` 3. Create `internal/speaker/store.go` — speaker profile CRUD via `store.MemoryStore`: `Insert("speaker:", embedding, meta)`, `Search(embedding, k)` 4. Create `internal/speaker/enroll.go` — enrollment flow: capture N seconds of audio, extract embedding, prompt for name via TTS + STT round-trip 5. Wire into `cmd/mavend/voice.go:HandlePushToTalk` — run speaker ID on the PCM before STT; pass speaker ID through `context.Context` to `applyAction` 6. Tag all voice-written facts/notes with speaker ID — `Source` becomes `tap:voice:speaker:` or metadata field 7. Add IPC methods `MethodEnrollSpeaker`, `MethodListSpeakers`, `MethodRemoveSpeaker` 8. Add speaker config block to `voice` in `config.Config` — `{speaker_recognition: true, model_path}` 9. Test with 2+ recorded voice samples — verify correct identification and rejection of unknown speakers