Phase 14 - Lesson 38
Portões de Verificação
O agente não define o próprio trabalho como concluído. Um portão de verificação lê o contrato de escopo, o log de feedback, o relatório de regras e o diff, e responde a uma única pergunta: esta tarefa está realmente concluída? Se o portão disser não, a tarefa não está concluída, não importa o que o chat diga.
Tipo: Build Idiomas: Python (stdlib) Pré-requisitos: Phase 14 · 33 (Rules), Phase 14 · 36 (Scope), Phase 14 · 37 (Feedback) Tempo: ~55 minutos
Objetivos de Aprendizagem
- Definir um portão de verificação como uma função determinística sobre os artefatos do workbench.
- Combinar relatório de regras, relatório de escopo, registros de feedback e diff em um único veredicto.
- Emitir um
verification_report.jsonque tanto o agente revisor quanto a CI possam ler. - Recusar o avanço de uma tarefa em qualquer falha de severidade de bloqueio (block-severity), sem exceções.
O Problema
Agentes declaram sucesso com facilidade excessiva. Três formatos de falha dominam:
- "Parece bom." O modelo leu seu próprio diff e decidiu que estava correto.
- "Testes passaram." Dito com confiança. Nenhum registro do teste realmente sendo executado.
- "Critérios de aceitação atendidos." Critérios de aceitação interpretados de forma tão flexível a ponto de significar "qualquer coisa parecida com concluído".
A solução do workbench é um único portão de verificação que lê os artefatos que o agente já produziu e toma a decisão. O portão é determinístico. O portão está sob controle de versão. O portão está conectado à CI. O agente não pode suborná-lo.
O Conceito
flowchart TD
Diff[Diff] --> Gate[verify_agent.py]
Scope[scope_report.json] --> Gate
Rules[rule_report.json] --> Gate
Feedback[feedback_record.jsonl] --> Gate
Gate --> Verdict[verification_report.json]
Verdict --> Pass{passou?}
Pass -- yes --> Review[Agente Revisor]
Pass -- no --> Refuse[recusar concluído + expor ao humano]
O que o portão verifica
| Check | Source artifact | Severity |
|---|---|---|
| Todos os comandos de aceitação foram executados | feedback_record.jsonl |
block |
| Todos os comandos de aceitação retornaram código zero | feedback_record.jsonl |
block |
| A verificação de escopo não tem gravações proibidas | scope_report.json |
block |
| A verificação de escopo não tem gravações fora do escopo | scope_report.json |
block or warn |
| Todas as regras de severidade de bloqueio passam | rule_report.json |
block |
Nenhum código de saída null no feedback |
feedback_record.jsonl |
block |
Arquivos modificados correspondem a scope.allowed_files |
both | warn |
Um achado warn anota o veredicto; um achado block impede passed: true.
Determinístico, não probabilístico
O portão deve produzir o mesmo veredicto para o mesmo conjunto de artefatos todas as vezes. Sem juízes LLM. Juízes LLM pertencem ao lado do revisor (Phase 14 · 39), onde o objetivo é a avaliação qualitativa, não o status.
Um relatório, um caminho
O portão emite um único verification_report.json por encerramento de tarefa, gravado em outputs/verification/<task_id>.json. A CI consome o mesmo caminho. Múltiplos portões com caminhos diferentes dividem a fonte da verdade.
Recusar sem exceções
Achados de severidade de bloqueio (block-severity) não podem ser contornados pelo agente. Eles só podem ser contornados por um humano, com um override_reason registrado e um ID de usuário overridden_by. O contorno (override) é uma alteração assinada, não uma decisão do agente.
Construa
code/main.py implementa:
- Um carregador para cada artefato de entrada, todos com stubs locais para que a lição seja autônoma.
- Uma função pura
verify(task_id, artifacts) -> VerdictReport. - Um formatador de saída (printer) que mostra os resultados por verificação e o resultado final de aprovação/falha.
- Uma demonstração com três cenários de tarefas: aprovação limpa (clean pass), desvio de escopo (scope creep) e aceitação ausente (missing acceptance).
Execute:
python3 code/main.py
Saída: três relatórios de veredicto, cada um salvo ao lado do script.
Padrões de produção na prática
Quatro padrões elevam o portão de "mais um trabalho de lint" para "o diferencial decisivo."
Defesa em profundidade, não um único portão. Gancho de pre-commit → verificação de status de CI → gancho de autorização pré-ferramenta → portão pré-merge. Cada camada é determinística, de modo que uma falha em uma camada é capturada pela próxima. O manual de março de 2026 de microservices.io é explícito: o gancho de pre-commit é não ignorável porque, ao contrário de uma habilidade do lado do modelo, não depende do agente seguir instruções. O portão de verificação fica na camada de CI / pré-merge.
Defesa por verificação determinística, juiz de modelo apenas para nuances. O emparelhamento Hybrid Norm de 2026 da Anthropic: recompensas verificáveis (testes unitários, verificações de esquema, códigos de saída) respondem a "o código resolveu o problema?" — rubricas de LLM respondem a "o código é legível, seguro, segue o estilo?". O portão executa a primeira classe; o revisor (Phase 14 · 39) executa a segunda. Misturá-los colapsa o sinal.
Log de contorno (override) assinado, não threads no Slack. Cada contorno emite uma linha em outputs/verification/overrides.jsonl com: carimbo de data/hora (timestamp), código do achado, motivo, usuário assinante, commit HEAD atual. O tempo de execução recusa qualquer contorno que careça de assinatura; a trilha de auditoria é rastreada pelo git. Esta é a linha entre uma política de contorno e um teatro de contorno.
Piso de cobertura de testes (coverage floor) como uma verificação de primeira classe. Um coverage_report.json alimenta uma verificação de coverage_floor (padrão 80%). O portão falha se a cobertura medida cair abaixo do piso ou abaixo do piso do merge anterior por mais de 1 ponto percentual. Sem essa verificação, os agentes silenciosamente excluem os testes que falham e os relatórios de verificação permanecem verdes.
Modo --strict promove alertas (warns) para bloqueios (blocks). Para ramificações de lançamento (release branches), PRs que bloqueiam o envio ou triagem pós-incidente, o modo --strict torna cada aviso uma falha grave. A flag é opcional por branch; não é o padrão global, porque strict-on-everything corrói o fluxo do dia a dia.
Use
Padrões de produção:
- Etapa de CI. Um job
verify_agentexecuta o portão contra os artefatos finais do agente. A proteção de merge recusa sempassed: true. - Gancho pré-entrega (pre-handoff hook). O tempo de execução do agente chama o portão antes de gerar o documento de entrega. Sem veredicto verde, sem entrega.
- Triagem manual. Os operadores leem o relatório quando um agente alega sucesso e um humano suspeita dele.
O portão é o diferencial decisivo no fluxo do workbench. Todas as outras superfícies estão a montante (upstream) dele.
Envie
outputs/skill-verification-gate.md conecta o portão a um projeto específico: quais comandos de aceitação o alimentam, quais regras são de severidade de bloqueio (block-severity), quais gravações fora do escopo são toleradas, como o log de auditoria de contorno (override) é armazenado.
Exercícios
- Adicione uma verificação de
coverage_floor: o comando de teste deve produzir um relatório de cobertura com pelo menos 80%. Decida qual artefato carrega o piso. - Dê suporte a um modo
--strictque promove cadawarnparablock. Documente os casos em que o modo strict é o padrão correto. - Faça com que o portão produza um resumo em Markdown além do JSON. Defenda quais campos pertencem ao resumo.
- Adicione uma verificação de
time_since_last_human_touch: qualquer arquivo editado dentro de 60 segundos após um toque de tecla humano é isento de sinalizações de fora do escopo (off-scope). - Execute o portão em um diff real de agente do seu produto. Quantos achados são reais e quantos são ruído? Onde o portão precisa crescer?
Termos-Chave
| Term | What people say | What it actually means |
|---|---|---|
| Portão de verificação | "A verificação que impede o avanço" | Função determinística sobre os artefatos do workbench que produz um veredicto de aprovação/falha |
| Severidade de bloqueio | "Falha crítica/grave" | Um achado que impede passed: true e exige um contorno (override) assinado |
| Log de contorno (override) | "Por que deixamos passar" | Entradas assinadas com o motivo e ID de usuário, auditadas por revisão |
| Comando de aceitação | "A prova" | Um comando de shell cuja saída zero é o significado de concluído |
| Caminho único de relatório | "Fonte da verdade" | outputs/verification/<task_id>.json, consumido tanto pela CI quanto por humanos |