Skip to content

T-317 - Criar no codegen a etapa de explicação do resultado #391

Open

Description

@pedro-fs-garcia

T-317 - Criar no codegen a etapa de explicação do resultado

  • Componente: codegen.
  • Depende de: T-316 no develop e T-302, que acrescenta resultado_id ao evento no-concluido.
  • Data máxima: 16/11/2026
  • Estimativa: 8 pontos (Fibonacci)

Entregável

  • Modelo explanation registrado, com os metadados da chamada.
  • Prompt da explicação com o resultado, a regra e a lista de números que podem ser citados.
  • Conferência determinística dos números citados, reaproveitando a extração de números da extração da regra.
  • Nó explain_result ligado ao grafo depois da decisão, gravando a explicação e publicando a conclusão.
  • Contador e duração da etapa, e logs sem conteúdo.
  • Testes da conferência, do nó e do grafo.

Descrição

O grafo não tem etapa de explicação. A tabela explicacoes existe e o codegen tem permissão de inserir nela, mas nada a grava. Esta tarefa cria a etapa que escreve a narrativa de cada simulação com sucesso, confere cada número citado contra o apurado, grava o resultado da conferência e publica a conclusão para a API ligar a flag de baixa rastreabilidade (T-318).

Contexto e decisões tomadas

  • A narrativa cita os números da simulação e nunca os calcula (codegen/AGENTS.md, regras "Never invents an audited number" e "No narrative reaches the user unverified"). Um número citado que não corresponde a nada apurado reprova a narrativa. Ela é gravada com aderencia_conferida = false, para o auditor, e não é exibida ao profissional de RH.
  • O nó vem depois de decision e antes do roteamento por encaminhamento (engine.py). Ele só roda quando status_simulacao é sucesso. Erro de código e asserção violada seguem direto da decisão, porque não há número a narrar. As execuções candidatas da busca da meta não passam pela decisão e não recebem narrativa.
  • A etapa nunca falha o ciclo. Falha do provedor, timeout, resposta vazia ou reprovação terminam a etapa sem narrativa exibível, e o grafo segue para a sugestão, para a busca ou para o fim. A etapa não usa chamar_com_espera_do_provedor, que espera o provedor voltar e avisa o usuário. Ela faz uma chamada com o max_retries do modelo e um timeout de 30 segundos, para atrasar pouco a sugestão e a busca.
  • A narrativa inclui a interpretação do resultado, isto é, o que puxou a diferença em relação ao baseline. Não há etapa de interpretação separada.
  • A extração de números em português já existe em app/extracao/lastro.py (_NUMERO, _decimal, a detecção de moeda e de percentual e os multiplicadores "mil" e "milhão"). A conferência usa essas funções, promovidas a um módulo compartilhado, sem cópia.
  • diferenca_pct dos totais é uma fração. Um "2,45%" citado corresponde a 0,0245.
  • A quebra matricula da decomposição identifica pessoas e não vai ao prompt nem à lista de números citáveis.
  • As respostas da T-315 podem mudar quais simulações recebem narrativa e quais números podem ser citados.

Escopo

Dentro do escopo

  • app/graph/core/llm/registry.py, um prompt novo em app/prompts/, o nó app/graph/nodes/explain_result.py, app/graph/core/engine.py, o módulo compartilhado de números, app/extracao/lastro.py (passa a importar do módulo), app/repositorio/ e app/core/metrics/global_metrics.py.
  • Testes unitários, do nó e do grafo.

Fora do escopo

  • Narrativa das candidatas da busca e da meta aceita.
  • Etapa de interpretação separada.
  • Flag, resposta HTTP e stream, que são da T-318.

Requisitos

Modelo e prompt

  1. Registrar explanation em _MODELS e _METADATA de registry.py, com o mesmo modelo dos demais, temperatura 0, timeout de 30 segundos e o max_retries dos demais. O comentário do registro diz por que o timeout é menor.
  2. Criar o prompt em app/prompts/ com o veredito, os totais, a decomposição sem matricula, a regra (núcleo e especificações) e a lista de números citáveis já formatados em português. O prompt manda citar os números exatamente como aparecem na lista, não fazer conta, não citar outro número e escrever um texto curto para o profissional de RH.

Números citáveis e conferência

  1. Mover para um módulo compartilhado de app/ as funções de lastro.py que encontram números no texto e os convertem em Decimal, com moeda, percentual e multiplicadores. lastro.py passa a importar desse módulo, e os testes da extração continuam passando sem mudança.
  2. Montar a lista de números citáveis a partir dos totais, das quebras da decomposição (valores e chaves, exceto matricula), do orçamento, da meta de venda, dos números da regra e das competências, incluindo o ano e o mês.
  3. Conferir a narrativa extraindo cada número do texto e comparando o valor normalizado com a lista. Um percentual citado é comparado como fração. Qualquer número sem correspondência reprova a narrativa. Os números por extenso seguem a mesma regra.

Nó e gravação

  1. Criar explain_result, que lê os totais com buscar_totais (app/repositorio/resultados.py) e a decomposição com uma leitura nova no mesmo repositório, chama o modelo, grava o prompt e a resposta com gravar_prompt_e_resposta (no = "explicacao"), confere a narrativa e grava a linha de explicacoes com id derivado do resultado por uuid5.
  2. Na reexecução do nó, se já existe linha em explicacoes para o resultado, o nó republica a conclusão com ela, sem chamar o modelo.
  3. Publicar no-concluido com no = "explicacao", evento_id por id_do_evento_de_trilha com o resultado, regra_id, resultado_id, prompt_id quando houve resposta, explicacao_id quando há linha em explicacoes e desfecho_explicacao na conclusão.
  4. Em engine.py, a decisão segue para explain_result quando a simulação teve sucesso e direto para o roteamento atual nos demais casos. explain_result segue para o roteamento atual. Conferir com a skill graph (codegen/.agents/skills/graph/SKILL.md) a retomada depois de uma interrupção.

Observabilidade

  1. Contador explicacoes com o rótulo desfecho (conferida, reprovada, sem_resposta e provedor_indisponivel) e duração da etapa registrada em sucesso e em falha, carregados no registry exposto em /metrics.
  2. Logs de início e de conclusão com job_id, no e o desfecho. Nenhum log inclui prompt, resposta, narrativa ou número citado.

Contexto técnico

  • Entradas: estado do grafo depois da decisão (resultado_id, status_simulacao, veredito, regra_id) e o resultado no Postgres.
  • Saídas: prompts, respostas_modelo, explicacoes e o evento no-concluido da etapa.
  • Componentes afetados: os listados no escopo.
  • Restrições: o nó não altera encaminhamento nem outro campo que o roteamento lê; nenhum número da narrativa é exibido sem conferência; a quebra por matrícula não sai do Postgres.
  • Referências: graph (codegen/.agents/skills/graph/SKILL.md), observability (codegen/.agents/skills/observability/SKILL.md), metrics (codegen/.agents/skills/metrics/SKILL.md), testing (codegen/.agents/skills/testing/SKILL.md), codegen/app/extracao/lastro.py, codegen/app/graph/core/llm/registry.py, codegen/app/graph/core/engine.py, codegen/app/graph/nodes/decision.py, codegen/app/repositorio/artefatos.py, codegen/app/repositorio/resultados.py, contracts/domain/resultado-totais.schema.json, contracts/domain/resultado-decomposicao.schema.json.

Critérios de aceitação

  • Uma narrativa que cita o simulado em reais, a diferença em percentual, uma loja pelo código e a competência é conferida.
  • Uma narrativa que cita uma porcentagem calculada, como a participação de uma loja na diferença, é reprovada e gravada com aderencia_conferida = false.
  • Com o provedor fora do ar, a etapa termina como provedor_indisponivel, sem linha em explicacoes, e o ciclo segue para a sugestão de uma simulação inviável.
  • Uma simulação com erro de código não passa pela etapa.
  • A reexecução do nó depois da gravação republica o mesmo evento_id sem chamar o modelo.
  • O prompt gravado não contém a quebra por matrícula.

Definição de concluído (DoD)

  • make pre-commit no codegen sem falha.
  • Testes do grafo exercitando sucesso, reprovação, falha do provedor e reexecução, com o evento publicado validado contra o schema oficial.
  • Contador e duração conferidos no registry depois dos testes, e logs serializados sem conteúdo.
  • Uma simulação local com o modelo real produzindo narrativa conferida, consultada em explicacoes.

Metadata

Metadata

Labels

codegentarefa que diz respeito ao componente de orquestração de agentes, denominado `codegen`

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions