19 KiB
Validação da reconstrução
Resultado
- Sintaxe Python (
compileall): PASS - YAML de
config/: PASS - Testes de domínio mock: 4 PASS
- Smoke MCP: PASS para faturas, invoice explanation, VAS, histórico, cancelamento e contestação
- Diretório do pacote anterior presente: NÃO
- Imports do namespace anterior em
app/,mcp/,config/: 0 .env: preservado byte a byte
Limitação do ambiente de construção
O runtime usado para montar o pacote não possui langgraph instalado globalmente. Por isso o teste de import/execução do StateGraph completo não foi executado aqui. O projeto declara langgraph em pyproject.toml; rode uv sync antes de subir o backend.
Aceite recomendado em ambiente do projeto
uv sync
pytest -q tests/migration
uv run uvicorn contas_mcp.servers.contas_mcp_server.main:app --port 8400
uv run uvicorn app.main:app --port 8000
Depois execute os cenários descritos em MANUAL_AGENT_CONTAS_MIGRADO.md.
Atualização de paridade - 2026-08-18
Gate local atual: 338 passed / 3 skipped em tests/migration.
Os skips dependem de bibliotecas não instaladas no runtime de construção (principalmente LangGraph/jellyfish) e permanecem habilitados para execução após uv sync.
Contratos adicionais corrigidos nesta rodada:
- VAS History:
GET ?msisdn=...,clientId,messageIdeAuthorization. - Contract Information:
clientId(nãoclient_id) e Basic Auth. - Profile/Line Info: header
ClientIDconforme contrato original. - Cancelamento VAS:
messageIdsempre não vazio, além dechannel=AIAGENTCReinteractionProtocol.
Gates estruturais mantidos:
- zero imports de
agente_contas_timemapp/,mcp/e no código-fonte do framework; - zero imports diretos de
langgraph.graphno domínio Contas; - workflows do domínio executados por
agent_framework.workflows.WorkflowRuntime; FrameworkStateGraphusado para composição do grafo principal;.envpreservado como arquivo principal de configuração.
Atualização de paridade - continuação 2026-08-18
Gate local atual: 400 passed / 2 skipped em tests/migration.
Skips restantes:
test_original_item_matcher_transcription.py: requerjellyfish, dependência declarada no projeto e instalada poruv sync.test_original_workflow_cases.py: requerlanggraph, dependência declarada no projeto e instalada poruv sync.
Novas coberturas e correções comprovadas nesta rodada:
- cenário real
cy0001voltou a integrar a regressão devas_variation; o skip causado por caminho incorreto do harness foi removido; - replay pós-finalização preserva
terminal_statuse possui fallback seguro quando a sessão é restaurada sem a última fala; - transformação de transcrição
Fim/Mim -> Simfoi validada contra a matriz original de fronteira de fala inteira; processing_interruptioninterrompível voltou a usar classificador LLM leve do framework; sem classificador/erro/resultado negativo o comportamento é replay fail-safe;- os dois templates oficiais do framework receberam o mesmo fluxo de classificação de interrupção;
- SMS recuperou o default canônico
senderName=TIM Brasil; - Service Request Status prioriza
messageId/ura_call_idantes desession_id; - o compositor determinístico de mensagem de cancelamento VAS foi portado e os 19 testes originais passam;
cancelar_vas_avulsoencadeiacancelamento_vas_avulso -> contestacao_toolusando dois WorkflowRuntime do framework;- o MCP inicializa WorkflowRuntime/checkpointer/idempotência de forma lazy, evitando abrir Oracle durante import/health/tools-list;
- o
IdempotencyStoreselecionado pelo framework é agora realmente injetado nos actions do Contas, eliminando o fallback local involuntário para memória; - cancelamento usa VAS History como fallback e bloqueia recancelamento quando
canCancel=false; - resultado em lote expõe
cancelados,nao_encontrados,nao_canceladoseitens_para_contestacao, preservando sucesso parcial; - finalização normaliza status/aliases e summary conforme o original;
- finalização informacional cria protocolo fechado somente quando necessário e evita duplicidade quando já existe protocolo;
- combinações canônicas de notas
VAS Bundle,VAS EstratégicoeVAS Avulsoforam portadas e testadas.
Gates estruturais desta versão
agente_contas_tim em app/ 0
agente_contas_tim em mcp/ 0
agente_contas_tim em agent_framework/src 0
langgraph.graph em app/ 0
langgraph.graph em mcp/ 0
O LangGraph continua interno ao agent_framework_oci por FrameworkStateGraph e WorkflowRuntime.
Atualização de paridade - continuação 2026-08-18 (baseline 420)
Gate local atual: 420 passed / 2 skipped em tests/migration.
Novas correções comprovadas desde a baseline 400:
- plano família mantém o MSISDN do titular na contestação e o MSISDN real do dependente no cancelamento;
invoice_detailcorrige deterministicamente a linha do item antes do side effect;CVALencerracontestacao_toolimediatamente quando bloqueia a operação, sem seguir para SMS/contrato/SR;- o MCP propaga
success=false, mensagem e estado sistêmico quando a contestação é bloqueada; - finalização de
invoice_explanationcria protocolo informacional apenas quando o workflow realmente executou, não por mero prefetch; - protocolo VEB já fechado é reutilizado sem nova abertura/fechamento;
force_rt15_finalization_protocolforça um RT-15 novo quando solicitado; suppress_cvn_protocol_icpreserva a semântica de VAS estratégico deferido;WorkflowRuntimepreserva snapshot parcial, nodes e trace quando uma action posterior falha;- Billing Analysis agora carrega metadata de tentativas e gera RCT.079-084 por tentativa;
- corrigido bug de
msisdnduplicado empreparar_invoice_explanation; - corrigido bug de inicialização de
AgentWorkflow: router/agentes/grafo estavam em código inalcançável apósreturn; InvoiceContextServicefoi reconstruído sobreagent_framework.cache.Cache, com isolamento por sessão, TTL, prefetch e reaproveitamento de CompleteInvoices/Billing Analysis/detalhe.
Os dois skips continuam sendo exclusivamente dependências deste runtime de construção:
jellyfishpara regressão fonética completa;langgraphpara os 18 casos reais de WorkflowRuntime.
Baseline 435 testes — continuação de paridade
Nesta baseline foram adicionadas as seguintes garantias:
InvoiceContextServicecom single-flight por sessão/fatura, cache incompleto sensível ainclude_detail, CVN.002/CVN.006/CVN.007 comobusiness_eventsdeduplicados por sessão e sem republicação em cache hit.- Metadados de prefetch:
fetch_elapsed_ms,task_timings,cache_age_mse erros por subconsulta. - Latch genérico
business_workflows_executednoAgentRuntimeMixin; workflows emPAUSEDjá contam como executados e o latch é persistido no patch transacional. - Cancelamento em lote com concorrência máxima 5 (configurável por
TIM_CANCELAMENTO_BATCH_CONCURRENCY) e protocolo por linha antes do side effect; falha de protocolo bloqueia o cancelamento daquela linha. WorkflowRunResult.error_detailspreserva fatos estruturados de exceções externas sem acoplamento do framework a TIM.- Contestação FAILED mapeia mensagem do provider/protocolo parcial quando disponíveis e diferencia erro de negócio de falha sistêmica.
Resultado local: 435 passed / 2 skipped em tests/migration.
Os dois skips continuam dependentes de langgraph/jellyfish indisponíveis neste runtime de construção.
Baseline 440 testes - continuação
- 440 testes de migração passando; 2 skipped por dependências indisponíveis neste runtime (
langgraph/jellyfish). - Cancelamento VAS: falha de bloqueio/cancelamento pode permanecer candidata à contestação sem mascarar sucesso.
- Resposta composta preserva protocolos de cancelamento por linha + protocolo de contestação e sinaliza finalização sugerida.
- Plano família: protocolo de cancelamento em dependente resolve
socialSecNovia LineInfo da própria linha. - Registro de protocolo aceita aliases de resposta
interactionProtocol,protocolNumber,protocoleprotocolo. - Finalização informacional recalcula Bundle/Estratégico/Avulso pela evidência de
invoice_detail/Billing Analysis quando disponível.
Baseline 533 - dependências de regressão e finalização
tests/migration: 533 passed / 4 xfailed / 0 skipped.- Os quatro
xfailsão limitações históricas documentadas do ranking fonético (gueimiloft,tim miusic,apou,agebeo max), não testes ignorados por dependência. jellyfishdeixou de ser requisito obrigatório: o domínio possui fallback puro-Python para Jaro-Winkler, Levenshtein e chave fonética. A biblioteca externa pode ser usada como aceleração, mas o projeto e a regressão não dependem dela.- Os 18 casos históricos de workflow não usam mais
importorskip(langgraph). Em builders offline executam pelo backend determinístico explicitamente opt-in doWorkflowRuntime; em produção o backend padrão continua sendo LangGraph e a ausência delanggraphcontinua sendo erro de configuração. - Finalização validada adicionalmente para: CVN.008/CVN.009, MPI.006/MPI.005, RCT.085/RCT.086, CVN.010/CVN.011, SAD.001 e árvore SAD opcional; protocolo informacional canônico de invoice explanation; supressão em handoff; ausência de aceite informacional após workflows transacionais; classificação de VAS estratégico/avulso sem invoice detail.
Lockfile
O uv.lock herdado de snapshots anteriores foi removido porque ainda descrevia o pacote legado (agente-contas-tim) e dependências que já não pertencem ao projeto (jellyfish obrigatório, NeMoGuardrails/LangChain extras, entre outras). O primeiro uv sync deve regenerar o lock a partir do pyproject.toml atual.
Baseline 550 - finalização e matcher sem skips/xfails
Validação consolidada desta etapa:
550 passed
0 skipped
0 xfailed
Coberturas adicionadas nesta etapa:
- finalização conversacional diferencia encerramento genérico de contexto real de fatura;
- prefetch/invoice context pode garantir CVN.002/CVN.006 e RT-15 conforme semântica histórica;
conversation_unresolved_transition_emittedimpede reemissão indevida de CVN/MPI positivos;- VEB terminal com protocolo fechado não cria RT-15 duplicado nem reemite CVN/MPI;
- evidência da fatura prevalece sobre tipo informacional salvo em match total;
- match parcial mescla inferência da fatura com tipo salvo ainda não representado;
- sem match na fatura, tipos salvos conflitantes são descartados;
- protocolo já existente impede RT-15 duplicado;
- alias
cpfé propagado comosocialSecNono protocolo informacional; - matcher de transcrição resolveu os quatro casos históricos antes marcados como xfail.
Matcher sem dívida conhecida no catálogo de regressão
O SimilarityItemMatcher passou a combinar:
- similaridade de frase;
- similaridade fonética;
- alinhamento token-a-token;
- dupla evidência grafia + fonética por token.
Isso corrigiu explicitamente:
gueimiloft->Gameloft;tim miusic->TIM Music;apou->Apple Music;agebeo max->HBO Max.
Baseline 556 — paridade VAA (2026-08-18)
A regressão de migração passou a executar 556 testes sem skip/xfail.
Nesta etapa os testes históricos do projeto original foram usados diretamente como catálogo para restaurar a família VAA sem trazer o publisher legado:
- cancelamento VAS: VAA.001/VAA.002/VAA.003 no caminho feliz e VAA.004 em falha operacional;
- contestação: VAA.005 + VAA.006/VAA.007 e VAA.008/VAA.009 conforme sucesso e elegibilidade do código de barras;
- SMS: VAA.012/VAA.014 em sucesso e VAA.013/VAA.015 em falha, mantendo o workflow ativo;
- atualização/fechamento de SR: VAA.016/VAA.017.
Os events são retornados como business_events; transporte, sequence e fan-out permanecem responsabilidade exclusiva do AgentObserver/analytics do agent_framework_oci.
Baseline 560 testes - metadata corporativa TIM
- 560 testes de migração passando, sem skips/xfails.
- Business events preservam contexto corporativo:
agentProtocolId,adjustedProtocol,billingId,uraCallId,channelId,sessionId,messageIdeagentSpecificData. - Contestação VAA.005-009 preserva itens/valores ajustados e protocolo.
- Finalização CVN.010/011 preserva protocolo TIM/URA e billing context.
- RCTs derivados de retry HTTP carregam
apiUrl,apiStatusCode,apiResponsePayloadelatencyMs. - SMS e Service Request Status carregam metadata de transporte e contexto de protocolo.
tim_payload_mapperaceita o formato históricoagentSpecificDataJSON-string e o converte para o objeto canônico TIM no payload final.
Baseline 565 — metadata MPI/VEB/SAD e VAS estratégico
- Regressão: 565 passed / 0 skipped / 0 xfailed.
VEB.*,MPI.*,CVN.*eSAD.*passam a carregar metadata conversacional TIM via_event_context:customerMessage,llmResponse,messageId,sessionId,channelId,uraCallId,billingIdesessionEndAtquando aplicável.SAD.001normalizasession_end_atISO-8601 para epoch milliseconds.- VAS Estratégico recuperou a semântica histórica:
NAOestratégico ->VEB.004 -> VEB.006 -> VEB.007; Bundle +NAO->VEB.004 -> VEB.005 -> VEB.007e protocolo deferido para finalização;SIM->VEB.003e registro de atendimento. - Invoice Explanation (
MPI.005/006), Pró-Rata (MPI.010) e cancelamento (MPI.011) usam o mesmo enriquecimento de contexto.
Baseline 570 testes
pytest -q: 570 passed, 0 skipped, 0 xfailed.pyproject.tomllimita o gate padrão atests/, evitando coleta acidental dos scripts de teste duplicados existentes dentro dos templates do framework.cancelar_vas_avulsoredireciona automaticamente paravas_estrategicoquando oInvoiceResolverclassifica a cobrança como estratégico/bundle.invoice_explanationrecuperourecomenda_finalizacao/status_finalizacao_sugeridopor branch doWorkflowRuntime.pro_ratarecuperou recomendação de finalização nos branchesregistrar_aceitoueregistrar_nao_controle.- VAS Estratégico recuperou a busca de orientação do parceiro sem RAG próprio: a action declara
requires_rag/rag_queries, e oAgentRuntimeMixinexecutaRagServicedo framework.
Baseline 578 - wrapper cancelamento + LLM composition
- 593 testes passando; zero skipped/xfail.
- Cancelamento preserva
auto_finalize_on_failureem falha técnica de contestação. - Item já contestado não mascara cancelamento concluído como falha sistêmica.
cancelamento_vas_protocole todos os protocolos de resposta são preservados.- Plano família contesta titular + dependentes em uma única
contestacao_tool. - Lote com muitos no-match continua contestando exatamente os candidatos elegíveis.
- Pró-rata usa
requires_llm_compositiondo framework em vez de gateway LLM de domínio.
Continuação — paridade explícita dos wrappers (baseline 593)
contestacao_toolvolta a garantirtipo_atendimento=contestacaoe preserva o contexto do turno (message_id,customer_message,ura_call_id,channel_id,ani,invoice_id).- Falhas de contestação são diferenciadas entre erro técnico (
erro_falha_sistema) e conflito/item já contestado com mensagem/protocolo do provider. - Cancelamento composto aceita tanto
contestation_candidatesquanto o alias históricoitens_para_contestacao. - Resultado agregado em
cancelados/nao_canceladosé aceito mesmo quandoresults[]não repete a flagsuccess. cpfvolta a ser alias desocial_sec_noe é normalizado para dígitos antes de protocolo/contestação.- Em fluxo misto Bundle + Estratégico no branch NÃO, o protocolo segue deferido para finalização, porém as
rag_queriesdos serviços estratégicos são preservadas. - Falha parcial com candidato continua encadeando
cancelamento_vas_avulso -> contestacao_tool; falha de SMS não transforma o cancelamento em falha. pytest -q: 593 passed, 0 skipped, 0 xfailed.
Baseline 599 testes — paridade explícita de wrappers
Validação consolidada: 599 passed, 0 skipped, 0 xfailed.
A rodada adicionou regressões 1:1 baseadas nos wrappers históricos para:
itens_ja_contestadospreservados desde a action de contestação até o compositor de resposta;- classificação de
contested_items,not_contested_itemse itens já contestados feita no domínio, não reconstruída no MCP; - totais de contestação calculados somente sobre itens efetivamente aceitos;
- valor
0/0,00retornado pela contestação tratado como ausência de valor útil para composição, usando o total cancelado; - valores monetários normalizados em pt-BR na borda do MCP (
14,99); next_subjectnão interfere na composição determinística de cancelamento;- falha de serviço em
invoice_explanationpreserva a fraseologia canônica e não ativa auto-finalização.
Gates: compileall PASS, zero imports do namespace legado e zero imports diretos de LangGraph em app//mcp/.
Baseline 615 — contratos 1:1 dos wrappers históricos
A regressão foi ampliada para 615 testes executados, sem skips e sem xfails.
Nesta etapa foram portados como contratos explícitos do MCP novo os seguintes
outcomes do backend_cancelar_vas_single e finalize_support históricos:
- sucesso implícito quando o workflow reporta
cancelados[]semsuccess=true; - lista explícita vazia de candidatos não cria fallback indevido para contestação;
- no-match não chama contestação nem vocaliza valor como se houvesse ajuste;
protocol_closedda contestação é preservado;- flags internas
sms_sentnão vazam no contrato externo e falha de SMS é propagada porsms_not_send_error; - cancelamento com protocolo e sem item efetivamente contestado continua resolvido;
- candidato explícito pode seguir para RT-02 mesmo após falha/no-match em RT-01;
- falha parcial de bloqueio/cancelamento continua elegível à contestação quando marcada pelo domínio;
holder_msisdnnão pode ser sobrescrito por linha dependente;- item do titular não é marcado como dependente;
- titular + múltiplos dependentes são agregados em uma única contestação do titular;
- VAS estratégico após invoice explanation prioriza nota estratégica na finalização;
- Bundle + Estratégico deferidos geram RT-15 combinado na finalização;
- invoice explanation não abre protocolo informacional antes da finalização.
Gate executado:
pytest -q: 615 passed
compileall app/mcp/framework: PASS
agente_contas_tim em app/mcp/framework runtime: 0
import direto langgraph.graph em app/mcp: 0