Deploy: mavwaked and mavenclient run nowhere, so the wake path is untestable #159
@@ -77,8 +77,8 @@ Pure-Go packages (`router`, `memory`, `mavweb`, …) run under a plain `go test
|
||||
| `mavweb` | HTTP UI + PWA (`/dash`, `/history`, `/trace`, `/notifications`, `/tools`); WebAuthn auth. Connects to mavend's socket. |
|
||||
| `mavsttd` | Speech-to-text (whisper.cpp, CGO). |
|
||||
| `mavttsd` | Text-to-speech (piper subprocess). |
|
||||
| `mavwaked` | Wake-word / VAD gate. |
|
||||
| `mavenclient` | Voice loop client (mic → stt → core → tts). |
|
||||
| `mavwaked` | Wake-word / VAD gate. **Not on homesrv** — see below. |
|
||||
| `mavenclient` | Voice loop client (mic → stt → core → tts). **Not on homesrv** — see below. |
|
||||
| `mavpoll` | Telegram long-poll reach. |
|
||||
| `mavcaldav` | CalDAV calendar sync. |
|
||||
| `mavmaild` | Mail reader (IMAP, read-only). Holds the IMAP password; core never sees it. |
|
||||
@@ -87,6 +87,15 @@ Daemons are wired socket-to-socket, not linked. `internal/ipc` is the client/ser
|
||||
protocol; the config in `deploy/mavend.json` (with `${VAR}` env expansion from gitignored
|
||||
`deploy/telegram.env`) sets socket paths, model paths, and the phraser/embedder blocks.
|
||||
|
||||
**Seven of the nine run on homesrv. `mavwaked` and `mavenclient` do not, and that is the
|
||||
decision, not an oversight** (Vikunja #463, `docs/plans/17-where-the-voice-loop-runs.md`).
|
||||
homesrv has a microphone — it is a laptop — but it is in the wrong room, so a wake-word
|
||||
daemon there listens to nobody. They belong on a client machine where he is standing.
|
||||
`ipc.Dial` already takes `tcp://host:port?token=...` through the netaddr seam, so nothing
|
||||
needs building to allow it, but no such machine exists yet. **The consequence: the wake
|
||||
word and the VAD gate are covered by unit tests and by nothing else, and no amount of
|
||||
sitting at the box changes that.** Push-to-talk through `/dash` is what QA actually covers.
|
||||
|
||||
## The ecosystem: Nexus, Praxis, Hexis
|
||||
|
||||
Maven is one of four services. It owns conversation and personal memory. It does not
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Plan: Where mavwaked and mavenclient run
|
||||
|
||||
**The decision Vikunja #463 asked for. Written 04-08-2026.**
|
||||
|
||||
**Verdict: not in compose on homesrv. They run on a client machine in the room he is in.**
|
||||
The transport for that already exists and nothing needs building to allow it. What needs
|
||||
building is a way to check the wake path at all, which is a separate task.
|
||||
|
||||
## The state that prompted this
|
||||
|
||||
`docker-compose.yml` runs mavend, mavsttd, mavttsd, mavweb and mavpoll. `mavwaked` and
|
||||
`mavenclient` appear in no compose file and run as no host process. Both build under
|
||||
`make build`. So the wake word and the voice-activity gate are untested by construction:
|
||||
QA session 1 step 2 covers push-to-talk from `/dash` only, and #287 (voice session
|
||||
quality) can never be more than half-answered while this holds.
|
||||
|
||||
## The reason is not hardware
|
||||
|
||||
homesrv has a microphone. It is a Lenovo IdeaPad 5 Pro, and `/proc/asound/cards` lists
|
||||
the ACP digital mic array with capture devices at `/dev/snd/pcmC1D0c` and
|
||||
`/dev/snd/pcmC2D0c`. Adding `/dev/snd` to compose and joining the `audio` group would
|
||||
work.
|
||||
|
||||
It would also be pointless. A wake-word daemon is worth having in the room he is standing
|
||||
in. homesrv is a server, so its microphone hears the room the server is in, which is not
|
||||
where anybody talks to Maven. Wiring audio into a container to listen to an empty room is
|
||||
work spent on a capability nobody can use.
|
||||
|
||||
## The reason it belongs off-box
|
||||
|
||||
`mavenclient` is a client by name and by design: microphone, then STT, then core, then
|
||||
TTS. It is the one binary in the tree meant to run somewhere else. `mavwaked` is the gate
|
||||
in front of it, so it goes wherever the microphone goes.
|
||||
|
||||
Maven already has components that are not containers on homesrv. `mavupdate` is a
|
||||
host-side tool. The resident model, STT and TTS prefer the workstation and fall back to
|
||||
homesrv (`docs/offload.md`). Off-box is a shape this system already has.
|
||||
|
||||
**And the wire already supports it.** `ipc.Dial` takes a netaddr seam address:
|
||||
a bare path is the unix socket, and `tcp://host:port?token=...` reaches a core on another
|
||||
host, with the token checked in `internal/netaddr` before `internal/ipc` sees the
|
||||
connection. So a client machine reaching mavend over wg or the LAN needs no new protocol
|
||||
work. It needs mavend to listen on TCP, which `deploy/mavend.json` does not currently ask
|
||||
for.
|
||||
|
||||
## What this means for the QA plan
|
||||
|
||||
QA session 1 step 2 should say what it actually covers, which is push-to-talk through
|
||||
`/dash`. It should not read as though it covers the voice loop. The wake path is checked
|
||||
on the client machine or it is not checked, and today there is no client machine.
|
||||
|
||||
That is the honest state, and it is worse than the task suggests: this is not a
|
||||
configuration gap that a compose entry closes. Until a machine with a microphone runs
|
||||
`mavwaked` and `mavenclient` against a TCP-listening mavend, `internal/wake` and
|
||||
`cmd/mavwaked`'s VAD are covered by their unit tests and by nothing else.
|
||||
|
||||
## What was wrong in CLAUDE.md
|
||||
|
||||
The daemon table lists all nine binaries with no column for where they run, which is how
|
||||
this went unnoticed for as long as it did. It now says which two are not on the box.
|
||||
+15
-8
@@ -105,9 +105,9 @@ turns look misaligned when they are not.
|
||||
**Passes** (02-08-2026, five turns): `я рада`, `поняла`, `помогла`,
|
||||
`проверила`, `записала`, `грустна`, `ты` throughout, no pet names.
|
||||
2. Press push-to-talk on `/dash`. Say `привет`. Confirm a spoken reply comes
|
||||
back. This is the only check that covers mic to STT to core to TTS to
|
||||
speaker as one path. It is also the path the eleven-day outage most likely
|
||||
broke.
|
||||
back. This covers browser mic to STT to core to TTS as one path. It does
|
||||
**not** cover the wake word or the voice-activity gate, and no step here
|
||||
does — see below.
|
||||
3. Say `тихий режим`. Expect `тихий режим включён. буду реже напоминать.` **Passes.**
|
||||
4. Say `выключи тихий режим`. Expect `тихий режим выключен.` Negation must win. **Passes.**
|
||||
5. Say `в комнате тихо`. Quiet mode must NOT flip. Confirm on `/history` that no
|
||||
@@ -129,11 +129,18 @@ turns look misaligned when they are not.
|
||||
and stitch unrelated topics. Asked whether he should move flats, she opened
|
||||
with the weather. That is 287, and it is a phrasing problem, not a loop problem.
|
||||
|
||||
**The wake path cannot be checked as deployed.** `mavwaked` and `mavenclient`
|
||||
appear in no compose file and run as no host process. Step 2 covers only
|
||||
push-to-talk, from `/dash` through mavsttd and mavttsd. Wake word and VAD
|
||||
are untested by construction. Decide whether they belong in compose or on a
|
||||
client machine, and say which in the deploy docs. Tracked as **463**.
|
||||
**The wake path cannot be checked here, and that is now the decision rather
|
||||
than a gap.** `mavwaked` and `mavenclient` appear in no compose file and run as
|
||||
no host process. They are not going to. They belong on a client machine in the
|
||||
room he is standing in, because homesrv's microphone is real and in the wrong
|
||||
room — **463**, written up in `docs/plans/17-where-the-voice-loop-runs.md`.
|
||||
|
||||
So the wake word and the VAD gate are covered by their unit tests and by
|
||||
nothing else, and no session at this box changes that. Checking them needs a
|
||||
machine with a microphone running both binaries against a TCP-listening mavend.
|
||||
`ipc.Dial` already speaks `tcp://host:port?token=...`, so the work is a machine
|
||||
and a config line, not protocol work. Until then, **287** can only be
|
||||
half-answered, and step 2 above is push-to-talk, not the voice loop.
|
||||
|
||||
**319's single-token bug is fixed** (01-08-2026). Single-word Russian utterances no longer come
|
||||
back as `не совсем поняла — можешь переформулировать?`. `привет` and `поужинал`
|
||||
|
||||
Reference in New Issue
Block a user