# Контекст проекта

Следуй [AGENTS.md](</experiments/voice-ai/archive/w/AGENTS.md>), `.knowledge/` и [deployment runbook](</experiments/voice-ai/archive/w/DOCS/DEPLOYMENT.md>).

Текущая датированная приёмка: [C3 · 06.10.2026](</experiments/voice-ai/archive/w/DOCS/CHAT_AGENT_ACCEPTANCE_C3.md>).
Стэк chat-agent содержит 13 сервисов; Core без media, два ingress и один Ruby + AsyncGraph runtime.
Обычный новый разговор — dialog_step; active/pending workflows используют прежние графы.
Live ASR streaming находится в неизменённом voice. Старый PRODUCTION_STATE — история.

<!-- OPENWIKI:START -->

## OpenWiki

See [AGENTS.md](</experiments/voice-ai/archive/w/AGENTS.md>) for OpenWiki agent instructions.

<!-- OPENWIKI:END -->

При приёмке busy file upload проверяй ordinary и staged UI: обе должны быстро получить HTTP 409; после освобождения lock повторная загрузка получает 202 и DONE. Перед отказом сервер дочитывает multipart body, чтобы ingress не оставлял запрос на 100%. HTTP-регрессии — `tests/test_webui_upload_lock.py` в voice repository.

Для browser-проверки WebRTC используй отдельную тестовую сессию и дождись connected ICE/DTLS перед речью. Синтетический источник должен продолжать отправку silent PCM после WAV; остановка пакетов не является паузой и закономерно вызывает stream_disconnected. Проверяй partial → final и ответ ассистента по совпадающим session/stream ID. Во время ответа agent_busy отклоняет новую речь. После теста выключи голос и восстанови getUserMedia/RTCPeerConnection; не запускай direct workflow probes одновременно с голосовым тестом.

## WebRTC Trickle ICE

[Сигнализация](</experiments/voice-ai/archive/w/DOCS/WEBRTC_SIGNALING.md>): двусторонний Trickle ICE opt-in, один audio media, точные aiortc 1.14.0 / aioice 0.10.2. Внутренние API изолированы в `src_webrtc_ingress/ice/trickle.py`; legacy peer неизменён. Сохраняй DATA indication и STUN cleanup. Capability 404 — единственный legacy fallback. HTTP/WS защищены OAuth и токеном подключения (только память, не URL/логи). Сигнализация 10 с, media 20 с после answer, WS auth 3 с; предел 128 кандидатов / 16 КиБ. Потеря ICE WS после connected предупреждает без разрыва media. Проверять реальные DTLS/RTP/PCM до завершения STUN на обеих сторонах и late/cleanup tests, затем пять Chrome connects, speech partial/final/assistant и историю. Поставка через exact SHA CI, backend ingress/Core → Frontend/Ruby с проверкой OCI/digest; ASR payload и соседние владельцы не меняются.

Приёмка 05.10.2026: [отчёт](</experiments/voice-ai/archive/w/DOCS/WEBRTC_TRICKLE_ACCEPTANCE_2026-10-05.md>), Core a925c28 / Frontend 95595f2, CI 4899/4900; пять подключений, медиана 1245 мс, реальный TURN/DTLS/RTP и speech partial/final/assistant. TCP host-кандидаты Chrome пропускаются без отмены UDP-пар. Сохраняй STUN/TURN; полное отключение клиентского STUN не подтверждено как рабочая конфигурация. Снимок не заменяет свежую проверку при следующем rollout.

Текущие boundaries C3: Core без media; два ingress; единственный Ruby + AsyncGraph runtime.
Исполнение/отмена: DOCS/CHAT_AGENT_EXECUTION.md. Migration/storage/rollback:
DOCS/DEPLOYMENT.md. C0/C1/C2/C3 измерения — датированные, runtime проверять отдельно.
