# MiniMax Voice — Agent Runbook

## Before you start

1. Read `00-index.md`. Inject only the documents you need.
2. Check git status and the last commits.

```bash
cd /home/sam/paseo/projects/minimax_voice_tts_stt
git status
git log -n 5 --oneline
```

## Run the offline tests

The tests never speak. They use a stub MiniMax endpoint and a file sink.

```bash
cd tts_router && python3 -m unittest -v test_tts_router
cd ../voice_stt_shim && python3 -m unittest -v test_contract
```

Expected: 74 TTS tests pass. 7 STT tests pass. 13 bridge tests pass.
7 benchmark tests pass. Raw logs: `benchmark/results/aud32/`.

## Check the live services

```bash
curl -s http://127.0.0.1:5001/health
curl -s http://127.0.0.1:5002/health
curl -s -X POST http://127.0.0.1:8501/voice \
  -H 'Content-Type: application/json' -d '{"text":"what time is it"}'
```

## Test the STT shim

```bash
python3 voice_stt_shim/test_contract.py \
  --wav benchmark/corpus/feed_the_fish.wav \
  --endpoint http://127.0.0.1:5001/transcribe --expect "feed the fish"
```

## Test the TTS router without sound

Use a file sink. The house stays silent.

```bash
TTS_SINK=file:/tmp/out.raw \
  /home/sam/speech_piper/speak_direct.sh "Testing the router" en_US-hal_6409-medium.onnx 1.0
```

## Restart the services

`voice-agent` is a system unit.

```bash
docker restart voice_stt_shim
docker restart voice_whisper_fallback
sudo systemctl restart voice-agent
journalctl -u voice-agent -f
```

Agents have no sudo rule for `voice-agent`. An operator must restart it.

## STT primary (already MiniMax)

The live STT primary is MiniMax `asr-1.0` (AUD-31). The setting is
`STT_PROVIDER=minimax` in `voice_stt_shim/docker-compose.yml`.

To confirm a live clip:

```bash
cd voice_stt_shim
./run_shim.sh --status
curl -s -m 30 http://127.0.0.1:5001/transcribe \
  -F audio=@../benchmark/corpus/what_time_is_it.wav
```

To roll back to OpenRouter, set `STT_PROVIDER=openai` and rebuild.

## Test the Home Assistant announce path without sound

The HA announcement path is `script.jervis_say` -> MQTT
`homeassistant/voice/announce` -> the agent's announce mode. Announce mode uses
one LLM call and **no tools**.

Offline check:

```bash
python3 benchmark/aud23_test_announce_mode.py
```

Live intake check: use a spare agent with `TTS_SINK=null` and a test topic.
Do **not** publish to the live `homeassistant/voice/announce` topic in a test;
the live agent speaks it.

## Old-piper status

AUD-33 found **no HA to piper hang**. Two `shell_command` services stay
registered on `.30`: `tts_direct_piper` and `tts_doorbell_piper`.
`script.piper_doorbell` still calls `tts_doorbell_piper` ->
`doorbell_tts_to_wav.sh`, which is **broken, not hanging** (dead native piper +
missing `sox`, exits `127`). See `notes/aud32-ha-piper-hang-investigation.md`.

## Roll back

| Change | Rollback |
| :--- | :--- |
| STT primary | Set `STT_PROVIDER=openai`. Rebuild the shim. |
| STT shim itself | Point `WHISPER_URL` at `http://127.0.0.1:5000/transcribe`. Run `docker start voice_whisper`. |
| TTS router | `cp -p speak_direct.sh.bak-phase3.<ts> /home/sam/speech_piper/speak_direct.sh`. |
| Personality | Add `VOICE_PERSONALITY=0` to `/home/sam/voice-agent/.env`. Restart the agent. |

## Rebuild the documentation

```bash
cd docs
mmdc -i minimax-voice-flow.mmd -o diagrams/minimax-voice-flow.png --scale 2 -b white
cd ~/.agents/skills/archify
node bin/archify.mjs validate architecture <repo>/docs/archify/minimax-voice.architecture.json --quality showcase --json
node bin/archify.mjs deliver  architecture <repo>/docs/archify/minimax-voice.architecture.json <repo>/docs/minimax-voice-map.html --quality showcase --json
```

## Publish the map

```bash
~/.agents/skills/project-docs/scripts/publish-maps.sh /home/sam/paseo/projects/minimax_voice_tts_stt
```

Result: `https://maps.lab.audasmedia.com.au/minimax_voice_tts_stt/docs/`.

## Safety rules

- Never send listening audio to the cloud. Wake-word detection stays local.
- Never commit a secret.
- Test the TTS pipeline with a file sink. Do not make the house speak in a test.
- Keep `piper_tts` running. It is the fallback.
- Change one phase at a time. Keep every phase independently revertible.
