Files
Maven/docs/plans/10-speaker-recognition.md
kami 5fe8f228c1 feat(mavweb): /ecosystem page consuming Nexus/Praxis/Hexis + shell fixes
Add a read-only /ecosystem page that consumes the sibling services'
JSON APIs (Nexus entities, Praxis attention, Hexis capabilities),
fetched concurrently with honest per-panel error states. Siblings stay
headless — mavweb is their human surface (arch §16). Wired via mavweb
-nexus/-praxis/-hexis flags; mavweb joins the ecosystem compose network.

Fix mobile horizontal overflow across all pages: .content is a flex
child with default min-width:auto, so it refused to shrink below the
tables' intrinsic width. min-width:0 lets wide tables pan inside .scroll
instead of dragging the page sideways. Verified via CDP geometry check
(scrollWidth === clientWidth at 430px).

Also includes in-progress Ethos UI redesign, ecosystem deploy compose,
and planning docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:04:23 +04:00

2.3 KiB

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:<id> 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.goRecognizer interface: Identify(pcm []float32) (SpeakerID, confidence), Enroll(id, pcm)
  3. Create internal/speaker/store.go — speaker profile CRUD via store.MemoryStore: Insert("speaker:<id>", 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:<id> 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