Files
agent_contas/tests/docs/VALIDACAO_MIGRACAO.md
2026-08-31 21:11:57 -03:00

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, messageId e Authorization.
  • Contract Information: clientId (não client_id) e Basic Auth.
  • Profile/Line Info: header ClientID conforme contrato original.
  • Cancelamento VAS: messageId sempre não vazio, além de channel=AIAGENTCR e interactionProtocol.

Gates estruturais mantidos:

  • zero imports de agente_contas_tim em app/, mcp/ e no código-fonte do framework;
  • zero imports diretos de langgraph.graph no domínio Contas;
  • workflows do domínio executados por agent_framework.workflows.WorkflowRuntime;
  • FrameworkStateGraph usado para composição do grafo principal;
  • .env preservado 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: requer jellyfish, dependência declarada no projeto e instalada por uv sync.
  • test_original_workflow_cases.py: requer langgraph, dependência declarada no projeto e instalada por uv sync.

Novas coberturas e correções comprovadas nesta rodada:

  • cenário real cy0001 voltou a integrar a regressão de vas_variation; o skip causado por caminho incorreto do harness foi removido;
  • replay pós-finalização preserva terminal_status e possui fallback seguro quando a sessão é restaurada sem a última fala;
  • transformação de transcrição Fim/Mim -> Sim foi validada contra a matriz original de fronteira de fala inteira;
  • processing_interruption interrompí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_id antes de session_id;
  • o compositor determinístico de mensagem de cancelamento VAS foi portado e os 19 testes originais passam;
  • cancelar_vas_avulso encadeia cancelamento_vas_avulso -> contestacao_tool usando dois WorkflowRuntime do framework;
  • o MCP inicializa WorkflowRuntime/checkpointer/idempotência de forma lazy, evitando abrir Oracle durante import/health/tools-list;
  • o IdempotencyStore selecionado 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_cancelados e itens_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égico e VAS Avulso foram 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_detail corrige deterministicamente a linha do item antes do side effect;
  • CVAL encerra contestacao_tool imediatamente 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_explanation cria 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_protocol força um RT-15 novo quando solicitado;
  • suppress_cvn_protocol_ic preserva a semântica de VAS estratégico deferido;
  • WorkflowRuntime preserva 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 msisdn duplicado em preparar_invoice_explanation;
  • corrigido bug de inicialização de AgentWorkflow: router/agentes/grafo estavam em código inalcançável após return;
  • InvoiceContextService foi reconstruído sobre agent_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:

  • jellyfish para regressão fonética completa;
  • langgraph para os 18 casos reais de WorkflowRuntime.

Baseline 435 testes — continuação de paridade

Nesta baseline foram adicionadas as seguintes garantias:

  • InvoiceContextService com single-flight por sessão/fatura, cache incompleto sensível a include_detail, CVN.002/CVN.006/CVN.007 como business_events deduplicados por sessão e sem republicação em cache hit.
  • Metadados de prefetch: fetch_elapsed_ms, task_timings, cache_age_ms e erros por subconsulta.
  • Latch genérico business_workflows_executed no AgentRuntimeMixin; workflows em PAUSED já 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_details preserva 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 socialSecNo via LineInfo da própria linha.
  • Registro de protocolo aceita aliases de resposta interactionProtocol, protocolNumber, protocol e protocolo.
  • 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 xfail são limitações históricas documentadas do ranking fonético (gueimiloft, tim miusic, apou, agebeo max), não testes ignorados por dependência.
  • jellyfish deixou 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 do WorkflowRuntime; em produção o backend padrão continua sendo LangGraph e a ausência de langgraph continua 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_emitted impede 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 como socialSecNo no 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, messageId e agentSpecificData.
  • 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, apiResponsePayload e latencyMs.
  • SMS e Service Request Status carregam metadata de transporte e contexto de protocolo.
  • tim_payload_mapper aceita o formato histórico agentSpecificData JSON-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.* e SAD.* passam a carregar metadata conversacional TIM via _event_context: customerMessage, llmResponse, messageId, sessionId, channelId, uraCallId, billingId e sessionEndAt quando aplicável.
  • SAD.001 normaliza session_end_at ISO-8601 para epoch milliseconds.
  • VAS Estratégico recuperou a semântica histórica: NAO estratégico -> VEB.004 -> VEB.006 -> VEB.007; Bundle + NAO -> VEB.004 -> VEB.005 -> VEB.007 e protocolo deferido para finalização; SIM -> VEB.003 e 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.toml limita o gate padrão a tests/, evitando coleta acidental dos scripts de teste duplicados existentes dentro dos templates do framework.
  • cancelar_vas_avulso redireciona automaticamente para vas_estrategico quando o InvoiceResolver classifica a cobrança como estratégico/bundle.
  • invoice_explanation recuperou recomenda_finalizacao/status_finalizacao_sugerido por branch do WorkflowRuntime.
  • pro_rata recuperou recomendação de finalização nos branches registrar_aceitou e registrar_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 o AgentRuntimeMixin executa RagService do framework.

Baseline 578 - wrapper cancelamento + LLM composition

  • 593 testes passando; zero skipped/xfail.
  • Cancelamento preserva auto_finalize_on_failure em falha técnica de contestação.
  • Item já contestado não mascara cancelamento concluído como falha sistêmica.
  • cancelamento_vas_protocol e 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_composition do framework em vez de gateway LLM de domínio.

Continuação — paridade explícita dos wrappers (baseline 593)

  • contestacao_tool volta a garantir tipo_atendimento=contestacao e 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_candidates quanto o alias histórico itens_para_contestacao.
  • Resultado agregado em cancelados/nao_cancelados é aceito mesmo quando results[] não repete a flag success.
  • cpf volta a ser alias de social_sec_no e é 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_queries dos 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_contestados preservados desde a action de contestação até o compositor de resposta;
  • classificação de contested_items, not_contested_items e 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,00 retornado 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_subject não interfere na composição determinística de cancelamento;
  • falha de serviço em invoice_explanation preserva 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[] sem success=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_closed da contestação é preservado;
  • flags internas sms_sent não vazam no contrato externo e falha de SMS é propagada por sms_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_msisdn nã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