Files
tia_regional_xai_tts_pool/docs/refactor-log.md
2026-08-21 08:37:51 -03:00

613 lines
30 KiB
Markdown

# Refactor Log
Este arquivo registra o que mudou a cada etapa do refactor incremental.
Nota:
- as entradas `000` a `010` foram escritas antes da consolidacao da estrutura atual do repositorio
- por isso, varias delas ainda referenciam caminhos antigos sem o prefixo `src/`
- a partir da entrada `011`, os caminhos refletem o layout atual da raiz + `src/`
## Como preencher
Para cada mudanca relevante, registrar:
- data
- objetivo
- arquivos alterados
- comportamento preservado
- comportamento alterado
- risco conhecido
- validacao executada
- proximo passo
## Entrada 000 - Baseline documental
- Data: 2026-03-27
- Objetivo: criar uma base de documentacao viva para acompanhar o refactor incremental
- Arquivos alterados:
- `README.md`
- `docs/README.md`
- `docs/refactor-plan.md`
- `docs/refactor-log.md`
- `docs/api-overview.md`
- Comportamento preservado: nenhum codigo de execucao foi alterado
- Comportamento alterado: nenhum
- Risco conhecido: a documentacao precisa ser mantida junto das mudancas, senao perde valor
- Validacao executada: revisao manual do conteudo criado
- Proximo passo: iniciar Fase 1 com extracao dos adapters de pipeline, speech, bridge e export
## Entrada 001 - Fase 1 / adapters extraidos
- Data: 2026-03-27
- Objetivo: extrair boundaries de pipeline, speech, bridge e export sem mudar o comportamento publico da API
- Arquivos alterados:
- `app/livekit/main.py`
- `app/livekit/adapters/pipeline_adapter.py`
- `app/livekit/adapters/speech_service.py`
- `app/livekit/adapters/bridge_gateway.py`
- `app/livekit/adapters/export_service.py`
- `docs/refactor-log.md`
- Comportamento preservado:
- contrato do websocket do bridge
- fluxo STT -> pipeline -> TTS
- notificacao `DONE` para o bridge
- exportacao final de sessao
- Comportamento alterado:
- nenhum comportamento publico planejado
- `app/livekit/main.py` passa a delegar responsabilidades para adapters
- Risco conhecido:
- como a extracao preserva a logica inline, ainda existe acoplamento forte no runtime
- faltam testes automatizados de regressao para interrupcao, idle nudge e finalizacao
- Validacao executada:
- revisao manual do diff
- validacao sintatica prevista apos a extracao
- Proximo passo:
- reduzir `nonlocal` no runtime com um `CallRuntime` explicito
- preparar o terreno para policies e scheduler unificados
## Entrada 002 - Fase 2 / runtime explicito
- Data: 2026-03-27
- Objetivo: encapsular o fluxo da chamada em um `CallRuntime` com `CallState` explicito, reduzindo estado implícito e `nonlocal` em `app/livekit/main.py`
- Arquivos alterados:
- `app/livekit/main.py`
- `app/livekit/runtime/state.py`
- `app/livekit/runtime/call_runtime.py`
- `docs/refactor-log.md`
- `docs/api-overview.md`
- Comportamento preservado:
- contrato do websocket do bridge
- fluxo STT -> pipeline -> TTS
- idle nudge, interrupcao e finalizacao continuam com a mesma logica operacional
- exportacao e notificacao `DONE` continuam sendo disparadas pelo agent
- Comportamento alterado:
- `app/livekit/main.py` passa a ser majoritariamente wiring do session e construcao do runtime
- o estado mutavel da chamada fica concentrado em `CallState`
- Risco conhecido:
- as regras ainda nao foram transformadas em policies puras; a logica segue acoplada ao runtime, apenas mais organizada
- ainda faltam testes automatizados para cenarios concorrentes de fala, interrupcao e fechamento
- Validacao executada:
- revisao manual do diff
- `PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile app/livekit/main.py app/livekit/adapters/bridge_gateway.py app/livekit/adapters/export_service.py app/livekit/adapters/pipeline_adapter.py app/livekit/adapters/speech_service.py app/livekit/runtime/state.py app/livekit/runtime/call_runtime.py`
- Proximo passo:
- introduzir command/execution boundaries no runtime
- preparar a migracao de interrupcao, idle e finalize para policies + scheduler
## Entrada 003 - Fase 3 / commands e executor
- Data: 2026-03-29
- Objetivo: separar efeitos colaterais do `CallRuntime` por meio de comandos tipados e um executor dedicado
- Arquivos alterados:
- `app/livekit/main.py`
- `app/livekit/runtime/commands.py`
- `app/livekit/runtime/command_executor.py`
- `app/livekit/runtime/call_runtime.py`
- `docs/refactor-log.md`
- `docs/api-overview.md`
- Comportamento preservado:
- contrato do websocket do bridge
- fluxo STT -> pipeline -> TTS
- sequencia de idle nudge, interrupcao e finalizacao
- integracao com LiveKit, pipeline e export sem troca de contrato
- Comportamento alterado:
- `CallRuntime` deixa de chamar diretamente bridge/export/speech/pipeline para os principais side effects
- side effects passam a trafegar por comandos (`commands.py`) executados por `RuntimeCommandExecutor`
- Risco conhecido:
- ainda existe conhecimento de regras dentro de `CallRuntime`; a extracao atual isola efeitos, mas nao transforma as regras em policies puras
- `agent._ready`, `agent._run_lock` e coordenacao de fila ainda pertencem ao runtime
- Validacao executada:
- revisao manual do diff
- validacao sintatica com `python3 -c 'from pathlib import Path; paths = [...]; [compile(Path(p).read_text(), p, "exec") for p in paths]'`
- Proximo passo:
- extrair policies de interrupcao, idle e finalizacao
- introduzir scheduler unico para timers e reduzir logica condicional no runtime
## Entrada 004 - Fase 4 / policies e scheduler
- Data: 2026-03-29
- Objetivo: mover regras de interrupcao, idle e finalize-once para policies dedicadas e centralizar timers em um scheduler unico
- Arquivos alterados:
- `app/livekit/main.py`
- `app/livekit/policies/interrupt_policy.py`
- `app/livekit/policies/idle_policy.py`
- `app/livekit/policies/finalization_policy.py`
- `app/livekit/runtime/scheduler.py`
- `app/livekit/runtime/state.py`
- `app/livekit/runtime/call_runtime.py`
- `docs/refactor-log.md`
- `docs/api-overview.md`
- Comportamento preservado:
- contrato do websocket do bridge
- fluxo STT -> pipeline -> TTS
- timers de idle nudge e idle close continuam ativos
- finalizacao por `DONE`, `room_empty`, `shutdown_callback` e `no_user_response` continua existindo
- Comportamento alterado:
- `InterruptPolicy` passa a decidir interrupcao por stage e filtro de backchannel
- `IdlePolicy` passa a concentrar regras de nudge/close
- `FinalizationPolicy` passa a concentrar regras de finalize-once e room-empty
- `TimerScheduler` passa a concentrar arm/cancel/token dos timers
- `CallState` deixa de carregar estado interno de timers
- Risco conhecido:
- o `CallRuntime` ainda conhece a ordem operacional completa da chamada; as policies reduzem acoplamento, mas ainda nao existe reducer/event engine
- `RuntimeConfig` ainda carrega campos hoje parcialmente sobrepostos pelas policies; isso pode ser simplificado em um corte futuro
- Validacao executada:
- revisao manual do diff
- validacao sintatica com `python3 -c 'from pathlib import Path; paths = [...]; [compile(Path(p).read_text(), p, "exec") for p in paths]'`
- Proximo passo:
- avaliar se vale introduzir eventos/comandos mais declarativos no runtime ou parar aqui e estabilizar
- se seguir, o proximo salto natural e um reducer/event engine ou a evolucao da integracao de IA (`llm_node` ou agente remoto)
## Entrada 005 - Estabilizacao / testes unitarios do runtime
- Data: 2026-03-29
- Objetivo: adicionar cobertura automatizada para os cenarios mais criticos do runtime sem depender de LiveKit real
- Arquivos alterados:
- `tests/__init__.py`
- `tests/livekit/__init__.py`
- `tests/livekit/test_runtime.py`
- `docs/refactor-log.md`
- Comportamento preservado:
- nenhum contrato publico da API foi alterado
- nenhum fluxo de audio ou websocket foi modificado
- Comportamento alterado:
- o repositorio passa a ter uma suite unitária para policies, scheduler, command executor e cenarios críticos do `CallRuntime`
- Risco conhecido:
- os testes ainda usam doubles/fakes e nao substituem validacao integrada com LiveKit real
- ainda faltam cenarios mais completos de timer real, callback de room e speech handle real
- Validacao executada:
- `python3 -m unittest tests.livekit.test_runtime -v`
- `python3 -m unittest discover -s tests -v`
- Proximo passo:
- ampliar cobertura para speech handle real e integracao de callbacks com objetos LiveKit reais, se isso passar a ser area de regressao
- ou encerrar a fase de estabilizacao e voltar a discutir a evolucao da camada de IA
## Entrada 006 - Backend remoto via websocket
- Data: 2026-03-29
- Objetivo: permitir trocar a pipeline local por um agent remoto via websocket, preservando o fluxo STT -> IA -> TTS e o runtime atual
- Arquivos alterados:
- `app/livekit/main.py`
- `app/livekit/adapters/agent_backend.py`
- `app/livekit/adapters/backend_factory.py`
- `app/livekit/adapters/pipeline_adapter.py`
- `app/livekit/adapters/remote_agent_ws_adapter.py`
- `app/livekit/runtime/command_executor.py`
- `requirements.txt`
- `tests/livekit/test_remote_agent_ws_adapter.py`
- `docs/refactor-log.md`
- `docs/api-overview.md`
- Comportamento preservado:
- contrato do websocket do bridge
- fluxo de audio com LiveKit e TTS no agent local
- runtime de interrupcao, idle nudge e finalizacao
- backend `langgraph` segue como default
- Comportamento alterado:
- o backend da camada de IA passa a ser selecionavel por `AGENT_BACKEND`
- quando `AGENT_BACKEND=remote_ws`, o agent envia cada turno transcrito para um websocket remoto e vocaliza a resposta retornada
- a finalizacao pode opcionalmente buscar um `result` remoto via mensagem `type=end`
- o bridge agora repassa `agent`, `RouterCallKeyDay`, `RouterCallKey`, `ANI`, `GSM` e `ID_FATURA` para o agent quando esses campos vierem no metadata do cliente
- o adapter remoto roteia a chamada para endpoints diferentes de acordo com `agent` (`conta`, `oferta`, `cobranca`)
- o agent `conta` passou a usar contrato proprio em websocket com `action/payload` na entrada e `result.content` na resposta
- Risco conhecido:
- o contrato do websocket remoto ainda e interno e precisa ser homologado com o agent externo real
- o adapter atual usa conexao websocket por turno, nao uma sessao persistente
- se o agent remoto nao devolver `stage`, a politica local dependera do ultimo stage conhecido ou do default configurado
- o campo `timestamp` e gerado localmente no momento de cada turno; se o integrador exigir outro formato, isso ainda precisa ser alinhado
- Validacao executada:
- testes unitarios do adapter remoto e factory
- execucao da suite `unittest`
- Proximo passo:
- homologar o contrato do websocket remoto com payload/resposta reais
- decidir se a conexao remota deve continuar por turno ou evoluir para sessao persistente
## Entrada 007 - Cliente web de voz e call_config por chamada
- Data: 2026-03-30
- Objetivo: disponibilizar um cliente web para testar o fluxo de voz pelo navegador e permitir overrides de `STT`, `TTS` e `AGENT` por chamada
- Arquivos alterados:
- `app/ws_gateway/main.py`
- `app/ws_gateway/voice_client.html`
- `app/ws_gateway/call_config.py`
- `app/livekit/main.py`
- `app/livekit/call_config.py`
- `app/livekit/adapters/backend_factory.py`
- `tests/config/test_call_config.py`
- `docs/api-overview.md`
- `docs/refactor-log.md`
- Comportamento preservado:
- fluxo principal de audio via `/ws/agent`
- bridge continua recebendo `start`, audio binario e encerrando com `stop`
- defaults de `STT`, `TTS` e backend continuam vindo de env quando nao houver override
- Comportamento alterado:
- `/voice-client` agora serve um cliente web para capturar microfone e ouvir o audio retornado
- o `start` pode carregar `call_config` com overrides por chamada
- o agent agora aplica overrides de backend, STT e TTS para a sessao corrente
- Risco conhecido:
- o cliente web usa `ScriptProcessorNode`, que e suficiente para homologacao mas nao e a opcao mais moderna da Web Audio API
- os providers dinamicos suportados ainda sao os que ja existem no projeto (`internal_http` e `elevenlabs`)
- Validacao executada:
- testes puros de `call_config`
- execucao da suite `unittest`
- Proximo passo:
- se o cliente web passar a ser usado em rotina de homologacao, vale migrar a captura/playback para `AudioWorklet`
- se surgirem novos providers de STT/TTS, plugar nas factories por chamada
## Entrada 008 - Timeline estruturada por chamada
- Data: 2026-03-30
- Objetivo: criar observabilidade ponta a ponta para entender o caminho `bridge -> livekit -> stt -> backend -> tts -> stop` por chamada
- Arquivos alterados:
- `app/utils/call_timeline.py`
- `app/ws_gateway/main.py`
- `app/livekit/main.py`
- `app/livekit/runtime/call_runtime.py`
- `app/livekit/adapters/backend_factory.py`
- `app/livekit/adapters/pipeline_adapter.py`
- `app/livekit/adapters/remote_agent_ws_adapter.py`
- `app/livekit/adapters/bridge_gateway.py`
- `app/providers/stt_internal_livekit.py`
- `tests/utils/test_call_timeline.py`
- `docs/api-overview.md`
- `docs/refactor-log.md`
- Comportamento preservado:
- contrato publico de `WS /ws/agent`
- fluxo de audio ja existente entre cliente, bridge, LiveKit e agent
- backends de IA, STT e TTS seguem com a mesma responsabilidade funcional
- Comportamento alterado:
- bridge e agent agora escrevem uma timeline estruturada em `jsonl` compartilhada por chamada
- a timeline usa o mesmo `timeline_id` e o mesmo `origin_unix_ms` entre os dois processos para manter a ordem relativa dos eventos
- o bridge passou a registrar eventos como `ready_sent`, `dispatch_started`, `agent_join`, `client_audio_enabled`, `done_packet_received` e `call_end`
- o agent passou a registrar eventos como `user_transcript_final`, `pipeline_run_started`, `pipeline_run_completed`, `tts_stage_started`, `interrupt_marked`, `finalize_started` e `finalize_completed`
- o provider de STT agora registra etapas de reconhecimento (`stt_recognize_started`, `stt_vosk_completed`, `stt_http_completed`)
- o backend remoto por websocket agora registra `remote_agent_request` e `remote_agent_response`
- Risco conhecido:
- a timeline registra payloads de request do backend remoto, o que aumenta a verbosidade e pode expor dados sensiveis em ambiente de debug
- o arquivo `jsonl` e compartilhado entre dois processos locais; o uso atual com `flock` e suficiente para dev/homologacao, mas nao substitui observabilidade centralizada
- Validacao executada:
- `py_compile` dos arquivos alterados
- teste unitario novo de timeline
- execucao completa da suite `unittest`
- Proximo passo:
- decidir se a timeline deve continuar sempre habilitada em dev ou ficar atras de flag por ambiente
- se a homologacao exigir, adicionar visualizador simples da timeline no cliente web
## Entrada 009 - Fake remoto para homologacao via UI
- Data: 2026-03-30
- Objetivo: permitir testar o fluxo `STT -> remote_ws -> TTS` pela UI mesmo sem o agent remoto real estar de pe
- Arquivos alterados:
- `app/ws_gateway/fake_remote_agent.py`
- `app/ws_gateway/main.py`
- `app/ws_gateway/voice_client.html`
- `app/livekit/adapters/backend_factory.py`
- `tests/ws_gateway/test_fake_remote_agent.py`
- `tests/livekit/test_remote_agent_ws_adapter.py`
- `docs/api-overview.md`
- `docs/refactor-log.md`
- Comportamento preservado:
- backend `remote_ws` continua exigindo URL real quando selecionado
- o contrato do adapter remoto segue o mesmo
- Comportamento alterado:
- o `bridge` agora expoe `WS /fake-agent/ws`
- a UI ganhou a opcao `remote_ws_fake`
- quando `remote_ws_fake` e selecionado, o agent local aponta para `REMOTE_AGENT_WS_FAKE_URL` ou usa por padrao `ws://127.0.0.1:8000/fake-agent/ws`
- o fake responde nos contratos `conta` e generico, com progressao simples de stages e encerramento por palavras-chave como `encerrar`, `obrigado` e `tchau`
- Risco conhecido:
- o fake nao simula comportamento de negocio real; ele serve apenas para homologacao tecnica do fluxo de voz
- o fake e stateless por conexao, entao a progressao depende do `stage` enviado pelo agent local
- Validacao executada:
- testes unitarios do fake remoto
- testes do backend fake no adapter remoto
- execucao completa da suite `unittest`
- Proximo passo:
- se a homologacao pedir cenarios mais realistas, adicionar scripts por agent (`conta`, `oferta`, `cobranca`) com respostas configuraveis
## Template de nova entrada
- Data:
- Objetivo:
- Arquivos alterados:
- Comportamento preservado:
- Comportamento alterado:
- Risco conhecido:
- Validacao executada:
- Proximo passo:
## Entrada 010 - Correcao do roteamento `remote_ws_fake`
- Data: 2026-03-30
- Objetivo: garantir que a selecao `remote_ws_fake` na UI nao seja sobrescrita pela URL real configurada em `REMOTE_AGENT_WS_URL`
- Arquivos alterados:
- `app/livekit/adapters/backend_factory.py`
- `app/livekit/adapters/remote_agent_ws_adapter.py`
- `tests/livekit/test_remote_agent_ws_adapter.py`
- `docs/api-overview.md`
- `docs/refactor-log.md`
- Comportamento preservado:
- `remote_ws` continua usando `REMOTE_AGENT_WS_URL`
- o adapter remoto continua sendo o mesmo para backend real e fake
- Comportamento alterado:
- `remote_ws_fake` agora prioriza sempre `REMOTE_AGENT_WS_FAKE_URL`, mesmo quando `REMOTE_AGENT_WS_URL` existe no ambiente
- a timeline do adapter remoto agora diferencia `backend=remote_ws_fake` de `backend=remote_ws`
- Risco conhecido:
- aliases como `fake_remote_ws` e `ws_fake` continuam sendo tratados como `remote_ws_fake`, mas o label emitido na timeline fica canonico como `remote_ws_fake`
- Validacao executada:
- `python3 -m unittest tests.livekit.test_remote_agent_ws_adapter -v`
- `python3 -m py_compile app/livekit/adapters/backend_factory.py app/livekit/adapters/remote_agent_ws_adapter.py tests/livekit/test_remote_agent_ws_adapter.py`
- Proximo passo:
- validar na chamada real da UI que o timeline e o request usam `ws://127.0.0.1:8000/fake-agent/ws`
## Entrada 011 - Reorganizacao da raiz e remocao de boilerplate
- Data: 2026-04-06
- Objetivo: consolidar a estrutura real do projeto na raiz do repositorio, mantendo `src/app` e `src/agent` como codigo-fonte canonico
- Arquivos alterados:
- `README.md`
- `makefile`
- `Dockerfile`
- `pytest.ini`
- `.env.example`
- `.gitignore`
- `.dockerignore`
- `requirements.txt`
- `livekit.yaml`
- `docs/*`
- `tests/*`
- `k8s/deployment.yaml`
- remocao de `pyproject.toml`, `uv.lock`, `README copy.md`, `configs/config.example.yaml` e scripts herdados do boilerplate
- Comportamento preservado:
- `src/app` e `src/agent` permanecem como raiz do codigo de execucao
- o bridge FastAPI continua em `src/app/ws_gateway/main.py`
- o projeto continua usando `PYTHONPATH=src`
- Comportamento alterado:
- a raiz do repositorio passa a refletir o projeto real, e nao mais o boilerplate original
- `requirements.txt` passa a ser a fonte principal de dependencias
- artefatos de runtime (`logs`, `timeline`, `__pycache__`) deixam de ser versionados
- Risco conhecido:
- arquivos de infra legados fora do fluxo principal ainda poderiam carregar suposicoes antigas do boilerplate
- a migracao para `requirements.txt` simplifica a operacao, mas remove o lockfile anterior
- Validacao executada:
- `python3 -m compileall src tests`
- `python3 -m pytest tests/utils/test_call_timeline.py -q`
- Proximo passo:
- revisar a infra auxiliar restante e reduzir ruido operacional na raiz
## Entrada 012 - Simplificacao do compose local de observabilidade
- Data: 2026-04-06
- Objetivo: transformar o `docker-compose.yml` em uma stack minima e coerente para Langfuse local
- Arquivos alterados:
- `docker-compose.yml`
- Comportamento preservado:
- a stack opcional de Langfuse continua disponivel para uso local
- a aplicacao principal segue fora do compose, operada via `make`
- Comportamento alterado:
- remocao do servico `mongo`
- consolidacao apenas de `langfuse-web`, `langfuse-worker`, `postgres`, `redis`, `clickhouse` e `minio`
- reducao de duplicacao com anchors para configuracoes compartilhadas
- Risco conhecido:
- o compose continua sendo opcional e depende de configuracao explicita do projeto para apontar para Langfuse self-hosted
- Validacao executada:
- validacao sintatica do YAML com parser local
- Proximo passo:
- se a equipe mantiver uso frequente, considerar alvos dedicados no `makefile` para subir e derrubar a stack
## Entrada 013 - Provider TTS opcional desacoplado do import global
- Data: 2026-04-06
- Objetivo: impedir que a falta do SDK do ElevenLabs quebrasse o import do modulo inteiro de TTS
- Arquivos alterados:
- `src/app/providers/tts.py`
- `tests/providers/test_tts.py`
- Comportamento preservado:
- selecao de provider TTS por configuracao
- suporte aos providers ja existentes
- Comportamento alterado:
- o SDK do ElevenLabs deixa de ser carregado no topo do modulo e passa a ser resolvido sob demanda
- ausencia do SDK passa a gerar `missing_elevenlabs_sdk`, em vez de falha de import que derruba testes e providers nao relacionados
- Risco conhecido:
- o provider continua opcional, mas a disciplina de dependencias ainda segue concentrada em `requirements.txt`
- Validacao executada:
- `python3 -m pytest tests/providers/test_tts.py -q`
- `python3 -m pytest tests/adapters/test_azure_tts.py -q`
- Proximo passo:
- continuar removendo acoplamentos desnecessarios entre providers e entrypoints
## Entrada 014 - Remocao de mocks e hardcodes dos pipelines de texto
- Data: 2026-04-06
- Objetivo: tirar codigo de demonstracao do caminho produtivo dos endpoints de texto
- Arquivos alterados:
- `src/app/services/session_context.py`
- `src/app/services/text_pipeline.py`
- `src/app/services/text_pipeline_stream.py`
- `src/app/ws_gateway/main.py`
- `tests/services/test_session_context.py`
- Comportamento preservado:
- os endpoints `/ws/text` e `/ws/text_stream` continuam aceitando a mesma sessao de entrada
- os pipelines continuam recebendo `mailing` e `intro`
- Comportamento alterado:
- remocao do uso de `app.models.mock`
- remocao de protocolo e dados fixos hardcoded nos pipelines
- introducao de extracao explicita de protocolo via `session_context`
- Risco conhecido:
- se existiam fluxos de dev que dependiam dos mocks antigos, eles passam a precisar de payloads reais
- Validacao executada:
- `python3 -m pytest -q`
- resultado observado na etapa: `36 passed`
- Proximo passo:
- consolidar contratos duplicados entre gateway e runtime
## Entrada 015 - Unificacao de `call_config`
- Data: 2026-04-06
- Objetivo: eliminar duplicacao entre as implementacoes de `call_config` do gateway e do runtime LiveKit
- Arquivos alterados:
- `src/app/common/call_config.py`
- `src/app/ws_gateway/call_config.py`
- `src/app/livekit/call_config.py`
- `tests/config/test_call_config.py`
- Comportamento preservado:
- API publica de `build_call_config(...)`
- API publica de `normalize_call_config(...)` e resolucao dos campos auxiliares
- Comportamento alterado:
- a normalizacao passa a ter um nucleo compartilhado em `src/app/common/call_config.py`
- `ws_gateway` e `livekit` viram wrappers leves para o mesmo contrato
- Risco conhecido:
- qualquer evolucao futura de `call_config` passa a ter impacto compartilhado entre bridge e agent, o que e desejado, mas exige disciplina de compatibilidade
- Validacao executada:
- `python3 -m pytest tests/config/test_call_config.py -q`
- `python3 -m pytest -q`
- resultado observado na etapa: `36 passed`
- Proximo passo:
- iniciar a quebra incremental do monolito em `src/app/ws_gateway/main.py`
## Entrada 016 - Extracao do parsing inicial da sessao no bridge
- Data: 2026-04-06
- Objetivo: remover do `ws_gateway/main.py` a logica de parsing da mensagem `start`, resolucao de mailing e montagem de `intro`/`nudge`
- Arquivos alterados:
- `src/app/ws_gateway/session_start.py`
- `src/app/ws_gateway/main.py`
- `tests/ws_gateway/test_session_start.py`
- Comportamento preservado:
- contrato de primeira mensagem `type=start`
- geracao de `mailing`, `intro` e `nudge`
- construcao do contexto do agente remoto a partir de metadata + mailing
- Comportamento alterado:
- criacao da dataclass `StartSessionContext`
- centralizacao de `parse_start_payload`, `recv_start_message` e `build_remote_agent_context` em modulo proprio
- `/ws/agent`, `/ws/text` e `/ws/text_stream` passam a consumir um contexto estruturado, e nao uma tuple solta
- Risco conhecido:
- o contrato de entrada continua dependente do payload do cliente; a extracao melhora testabilidade, mas nao redefine o protocolo
- Validacao executada:
- `python3 -m compileall src/app/ws_gateway src/app/services tests/ws_gateway`
- `python3 -m pytest tests/ws_gateway/test_session_start.py -q`
- `python3 -m pytest -q`
- resultado observado na etapa: `39 passed`
- Proximo passo:
- extrair o bootstrap da chamada para reduzir ainda mais a responsabilidade do endpoint
## Entrada 017 - Extracao do bootstrap da chamada do bridge
- Data: 2026-04-06
- Objetivo: separar a preparacao da chamada do runtime do endpoint `/ws/agent`
- Arquivos alterados:
- `src/app/ws_gateway/session_bootstrap.py`
- `src/app/ws_gateway/main.py`
- `tests/ws_gateway/test_session_bootstrap.py`
- Comportamento preservado:
- geracao de token de acesso ao LiveKit
- montagem de `call_config`, `remote_agent_context`, `timeline` e `dispatch_metadata`
- fallbacks de protocolo e telefone
- Comportamento alterado:
- introducao da dataclass `BridgeSessionBootstrap`
- centralizacao de `room_name`, `identity`, `token`, `protocol`, `phone_number` e `dispatch_metadata` em um builder dedicado
- `main.py` passa a consumir um pacote pronto de bootstrap
- Risco conhecido:
- o bootstrap ainda depende de envs e factories externas; a extracao organiza responsabilidade, mas nao muda a politica de configuracao
- Validacao executada:
- `python3 -m compileall src/app/ws_gateway tests/ws_gateway`
- `python3 -m pytest tests/ws_gateway/test_session_bootstrap.py -q`
- `python3 -m pytest -q`
- resultado observado na etapa: `41 passed`
- Proximo passo:
- extrair o ciclo de vida da sessao LiveKit do endpoint
## Entrada 018 - Extracao do lifecycle da sessao LiveKit no bridge
- Data: 2026-04-06
- Objetivo: remover do endpoint os handlers de participante, o processamento do pacote `DONE` e o watcher de encerramento
- Arquivos alterados:
- `src/app/ws_gateway/session_lifecycle.py`
- `src/app/ws_gateway/main.py`
- `tests/ws_gateway/test_session_lifecycle.py`
- Comportamento preservado:
- deteccao de entrada e saida do agente remoto
- processamento do pacote `agent.stage` com `DONE`
- envio de `stop` para o cliente ao final da chamada
- Comportamento alterado:
- criacao de `RoomLifecycleState` para concentrar `agent_participant` e `done_payload`
- extracao de `register_room_lifecycle_handlers(...)`
- extracao de `watch_call_done(...)`
- Risco conhecido:
- o fluxo ainda depende de coordenacao concorrente entre tasks do bridge; a extracao reduz tamanho do endpoint, mas nao muda o modelo de concorrencia
- Validacao executada:
- `python3 -m compileall src/app/ws_gateway tests/ws_gateway`
- `python3 -m pytest tests/ws_gateway/test_session_lifecycle.py -q`
- `python3 -m pytest -q`
- resultado observado na etapa: `43 passed`
- Proximo passo:
- extrair a camada de intro/sinalizacao do bridge
## Entrada 019 - Extracao da intro TTS e da sinalizacao de audio no bridge
- Data: 2026-04-07
- Objetivo: isolar do endpoint o trecho responsavel por intro TTS, liberacao do audio do cliente, sinalizacao `client_audio_enabled` e bootstrap do streaming do agente
- Arquivos alterados:
- `src/app/ws_gateway/session_audio.py`
- `src/app/ws_gateway/main.py`
- `tests/ws_gateway/test_session_audio.py`
- Comportamento preservado:
- intro sintetizada antes da liberacao do audio do cliente
- emissao do controle `client_audio_enabled` para o agente
- inicializacao do worker que consome audio do agente quando ele fica pronto
- Comportamento alterado:
- extracao de `play_intro_to_client(...)`
- extracao de `notify_client_audio_enabled(...)`
- extracao de `stream_agent_audio_when_ready(...)`
- `main.py` passa a gerenciar explicitamente a task `t_control`, em vez de disparar a notificacao como fire-and-forget
- ajuste de typing para evitar import-time acidental de `audioop` em testes unitarios do modulo novo
- Risco conhecido:
- o caminho quente de audio continua centralizado em `main.py`; ainda faltam as primitivas de transporte para o arquivo deixar de ser monolitico
- Validacao executada:
- `python3 -m compileall src/app/ws_gateway tests/ws_gateway`
- `python3 -m pytest tests/ws_gateway/test_session_audio.py -q`
- `python3 -m pytest -q`
- resultado observado na etapa: `46 passed`
- Proximo passo:
- extrair as primitivas de transporte de audio e LiveKit (`ws_audio_receiver`, `publish_queue_to_livekit`, `connect_publish_livekit`, `stream_agent_audio_to_queue`)
## Entrada 020 - Validacao do Dockerfile para CI/CD
- Data: 2026-04-07
- Objetivo: revisar o `Dockerfile` frente ao layout atual do projeto e corrigir o principal risco de compatibilidade para pipeline
- Arquivos alterados:
- `Dockerfile`
- Comportamento preservado:
- execucao do bridge via `uvicorn app.ws_gateway.main:app`
- exposicao da porta `8000`
- `PYTHONPATH=/app/src`
- healthcheck em `/health`
- Comportamento alterado:
- troca da base de `python:3.13-slim` para `python:3.12-slim`
- o ajuste foi necessario porque o projeto ainda depende de `audioop` em `src/app/ws_gateway/main.py` e `src/app/utils/background.py`
- Risco conhecido:
- o build real da imagem nao conseguiu ser concluido nesta maquina porque nem o daemon Docker nem a conexao efetiva do Podman estavam operacionais no momento da validacao
- portanto, a validacao foi estrutural e de coerencia do arquivo, nao um smoke test completo de container
- Validacao executada:
- revisao manual de `Dockerfile`, `.dockerignore`, `requirements.txt`, `makefile` e `k8s/deployment.yaml`
- tentativa de `docker build`, bloqueada por daemon indisponivel
- tentativa de `podman build`, bloqueada por conexao local com a VM do Podman
- Proximo passo:
- executar um build real da imagem assim que houver runtime de containers disponivel no host ou direto no pipeline