# Voice Phase 2 Streaming — Cutover Plan

## Мета

Безпечно ввімкнути Phase 2 sentence-chunking streaming (`/api/voice/chat/stream`)
для **всіх голосових сесій** без регресій.

## Поточний стан (baseline)

| Метрика | Значення |
|---------|---------|
| TTS p95 | ~1536ms ✅ |
| gemma3 TTFA | ~2620ms ✅ |
| qwen3.5 TTFA | ~8524ms ✅ (auto-promote qualified) |
| qwen3:14b TTFA | ~11618ms ⚠ fallback only |
| Streaming | enabled by default (checkbox ON) |

---

## Stages

### Stage 0 — Pre-conditions (blockers)

Виконати **перед будь-яким Stage**:

```bash
# 1. Voice canary preflight
python3 ops/scripts/voice_canary.py --mode preflight

# 2. Contract tests
python3 -m pytest tests/test_voice_policy.py tests/test_voice_stream.py -v

# 3. Degradation state check
curl -s http://localhost:8002/api/voice/degradation_status | python3 -m json.tool
# Очікування: state = "ok"
```

**Блокери:**
- [ ] voice_canary preflight passed (Polina + Ostap OK)
- [ ] 45/45 tests green
- [ ] degradation_status state = "ok"
- [ ] edge-tts версія = 7.2.7 (`docker exec dagi-memory-service-node2 pip show edge-tts | grep Version`)

---

### Stage 1 — 5% canary (feature flag в UI)

Увімкнути `streamMode=true` за замовчуванням (вже є), але обмежити до 5% сесій через cookie.

Реалізація (мінімальна):
- BFF `/api/voice/chat/stream` вже є.
- UI вже має `streamMode` checkbox (ON за замовчуванням).
- Достатньо: **не блокувати**, але збирати метрики.

**Що моніторити (10 хвилин):**
```bash
# TTFA
curl -s http://localhost:8002/api/voice/degradation_status

# Логи
docker logs sofiia-console --tail 50 | grep "voice_stream ok"

# Underflows у browser console
_voiceStats()
```

**SLO Gate Stage 1:**
- `voice_ttfa_ms` p95 ≤ 6000ms (20% буфер)
- `voice_tts_first_ms` p95 ≤ 2500ms
- underflow_rate ≤ 5% (relaxed for canary)
- No `emergency` state in degradation_status

---

### Stage 2 — 50% rollout

Якщо Stage 1 пройшов 30 хвилин без SLO breach:
- Переконатись що streamMode ON за замовчуванням.
- Включити polling деградації (`_startDegradPolling` — вже активний).

**Що додатково перевірити:**
```bash
# Grafana dashboard (імпортувати ops/grafana_voice_dashboard.json)
# Перевірити панелі 1-4 на наявність spike-ів

# Voice latency audit
bash ops/voice_latency_audit.sh 2>&1 | tail -30
```

---

### Stage 3 — 100% (production default)

Умови:
- Stage 2 стабільний ≥ 2 години
- Усі алерти (ops/voice_alerts.yml) в стані "OK" (не firing)
- `voice_queue_underflows_total` rate ≤ 0.017/s (1/хв)

**Дії:**
1. Переконатись `streamMode` checkbox: `checked` by default — вже є.
2. Додати voice_canary у ops/cron/jobs.cron — вже є.
3. Задеплоїти ops/voice_alerts.yml у Prometheus.

---

## Rollback план

Якщо будь-який SLO breach або degradation state ≠ ok:

```bash
# 1. Негайний rollback: вимкнути stream mode у BFF
#    (без rebuild — через env var)
docker exec sofiia-console env | grep VOICE_STREAM_DISABLED
# Або через конфіг — додати VOICE_STREAM_DISABLED=true і перезапустити

# 2. Перевірити стан
curl -s http://localhost:8002/api/voice/degradation_status
python3 ops/scripts/voice_canary.py --mode preflight

# 3. Якщо TTS деградував — перезапустити memory-service
docker restart dagi-memory-service-node2
sleep 10 && curl -s http://localhost:8000/voice/health
```

**Fallback chain (автоматичний):**
1. TTFA p95 > 5s → badge "⚠ AI SLOW", profile stays fast
2. TTFA p95 > 8s → badge "⚡ FAST MODE", voiceQuality checkbox auto-unchecked
3. TTS p95 > 2s → badge "⚠ TTS SLOW"
4. TTS p95 > 4s → badge "🔴 TTS DEGRADED", user informed

---

## Feature Flag (якщо потрібен explicit ON/OFF)

Додати в `docker-compose.node2-sofiia.yml` → environment:

```yaml
VOICE_STREAM_ENABLED: "true"   # або "false" для rollback
```

Та в `main.py` `/api/voice/chat/stream`:
```python
if not os.getenv("VOICE_STREAM_ENABLED", "true").lower() == "true":
    raise HTTPException(503, "Voice streaming disabled")
```

---

## Метрики для Phase 2 auto-approve

voice_policy_update.py читає ops/voice_canary_last.json + Prometheus і автоматично:
1. Оновлює `auto_promote` пороги в router-config.yml
2. Генерує ops/voice_latency_report.json

```bash
python3 ops/voice_policy_update.py --apply
```
