Phase 2 маршрутизации звонков (после MR!4). Закрывает AC-08 (retry при неответе оператора), AC-16/17 (RINGING/TALKING/AFTER_CALL_WORK), AC-19 (timeline по каждому переходу) + каталог событий §25. Без правок дайлплана — AMI-слушатель начал читать нативные DialEnd/Hangup вместо фильтрации только по UserEvent. Миграция 0033 (postgres+sqlite). Юнит-тесты: tests/test_escalation_retry.py + расширен tests/test_routing_engine.py.
Phase 2 маршрутизации звонков (после MR!4). Закрывает AC-08 (retry при неответе оператора), AC-16/17 (RINGING/TALKING/AFTER_CALL_WORK), AC-19 (timeline по каждому переходу) + каталог событий §25. Без правок дайлплана — AMI-слушатель начал читать нативные DialEnd/Hangup вместо фильтрации только по UserEvent. Миграция 0033 (postgres+sqlite). Юнит-тесты: tests/test_escalation_retry.py + расширен tests/test_routing_engine.py.
Phase 2 of the L1->L2 routing engine (Phase 1: MR!4).
- ami_loop() now also captures native AMI DialEnd/Hangup frames (not
only UserEvent), needed to detect that an escalated agent did not
answer. No dialplan change required - Redirect already routes the
client channel into an existing Dial()-based transfer context, so
Asterisk emits these events on its own; the listener just wasn't
reading them before.
- retry_escalation_no_answer(): on NOANSWER/BUSY/CANCEL/CHANUNAVAIL/
CONGESTION, releases the non-answering agent, excludes it, and
reserves+redirects to the next available agent via the routing
engine's existing exclude_agent_ids support. Exhausted pool marks
the escalation failed and leaves the call with the AI instead of
dropping the client (ТЗ §32).
- Agent status now actually moves through
RESERVED -> RINGING -> TALKING -> AFTER_CALL_WORK -> AVAILABLE
instead of staying stuck on RESERVED for the whole call; a new
acw_sweep_loop background thread (same pattern as the existing
failed_retry_loop) times out AFTER_CALL_WORK back to AVAILABLE.
- escalations gains attempt_count/real_agent_id/attempted_agent_ids_json
(migration 0033); fixes a latent bug where assigned_agent_id stored
the SIP extension instead of the real agent_id despite routing-service
already returning it in RoutingAgentReserveOut.
- Every transition now records an interaction timeline entry and
publishes the ТЗ §25 event catalog (AgentReserved/AgentRinging/
AgentNoAnswer/AgentConnected/TransferCompleted/TransferFailed)
through the existing emit_voice_event/EventOutboxRow idempotent path.
Not in this MR (see plan): SLA config, Callback, L3 (needs real
technical agents from the business), metrics.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Phase 2 маршрутизации звонков (после MR!4). Закрывает AC-08 (retry при неответе оператора), AC-16/17 (RINGING/TALKING/AFTER_CALL_WORK), AC-19 (timeline по каждому переходу) + каталог событий §25. Без правок дайлплана — AMI-слушатель начал читать нативные DialEnd/Hangup вместо фильтрации только по UserEvent. Миграция 0033 (postgres+sqlite). Юнит-тесты: tests/test_escalation_retry.py + расширен tests/test_routing_engine.py.