5fe8f228c1
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>
2.3 KiB
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_vectorstable 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.MemoryStorefor speaker vector storage (samememory_vectorstable, differentsourceprefix) - Reuses
internal/audiofor PCM preprocessing - Integration point:
cmd/mavend/voice.go:HandlePushToTalk— speaker ID extracted before STT, passed through context
Steps:
- Research speaker embedding approaches — simplest floor: MFCC + cosine similarity via
github.com/mjibson/go-dspor a pre-trained ONNX model (SpeechBrain ECAPA) - Create
internal/speaker/recognizer.go—Recognizerinterface:Identify(pcm []float32) (SpeakerID, confidence),Enroll(id, pcm) - Create
internal/speaker/store.go— speaker profile CRUD viastore.MemoryStore:Insert("speaker:<id>", embedding, meta),Search(embedding, k) - Create
internal/speaker/enroll.go— enrollment flow: capture N seconds of audio, extract embedding, prompt for name via TTS + STT round-trip - Wire into
cmd/mavend/voice.go:HandlePushToTalk— run speaker ID on the PCM before STT; pass speaker ID throughcontext.ContexttoapplyAction - Tag all voice-written facts/notes with speaker ID —
Sourcebecomestap:voice:speaker:<id>or metadata field - Add IPC methods
MethodEnrollSpeaker,MethodListSpeakers,MethodRemoveSpeaker - Add speaker config block to
voiceinconfig.Config—{speaker_recognition: true, model_path} - Test with 2+ recorded voice samples — verify correct identification and rejection of unknown speakers