0:00 — um build termina. O agente diz que está concluído, o que é uma afirmação sobre ter escrito código, não sobre o código funcionar. Todos os utilizadores de um construtor com IA já sentiram, pelo menos uma vez, a distância entre essas duas afirmações: a pré-visualização abre-se, clica-se no terceiro botão, não acontece nada. Já vi uma sala de demonstração ficar em silêncio exatamente nesse momento. Por isso, antes de qualquer humano ver um build, este passa por cerca de seis minutos de uma cadeia a discutir consigo mesma. Eis como isso é na prática, seguido através de um build que vimos correr mal e depois ser corrigido.
0:02 — começa a revisão de código. Não é o agente que escreveu o código a reler os seus próprios trabalhos de casa — é um agente separado, com um prompt diferente, sem interesse em que o build passe. Essa separação importa mais do que parece. Um agente que decidiu às 14h14 que uma chamada fetch sem tratamento de erros estava bem continuará a pensar o mesmo às 14h15 se lhe pedirem para verificar o seu próprio trabalho. Um revisor novo, a quem se diz "encontra o que está partido, cita o ficheiro", comporta-se como o engenheiro sénior rabugento que realmente se quer nesta função. Num build anterior, detetou um total de carrinho que nunca se atualizava silenciosamente — a função `updateTotal` estava definida em `Cart.jsx`, mas nunca ligada ao handler de alteração de quantidade, pelo que a função existia e simplesmente nunca corria. É esse tipo de categoria de problema que a revisão de código serve para apanhar — coisas perante as quais um compilador se encolhe de ombros.
0:04 — auditoria de segurança. Mais restrita do que soa, deliberadamente — não é um teste de intrusão, é uma caça a padrões de um punhado de erros que realmente aparecem em código gerado por IA. SQL construído por concatenação de strings. Validação apenas do lado do cliente, tratada como se fosse a história toda. E a especialidade da casa: uma chave de API codificada diretamente no código, porque o agente que escreveu a funcionalidade não tinha uma convenção de variáveis de ambiente à sua frente e recorreu ao que resultava. Vemos isto com frequência suficiente para já quase não surpreender.
0:07 — ligações e SEO. Pouco glamoroso, mas apanha o que ninguém repara até um cliente reparar: um link de navegação a apontar para /pricing quando a página foi realmente gerada em /price, uma entrada do sitemap para uma página que dá 404, uma meta descrição ainda com o texto do modelo por preencher. Nada disso quebra a build. Mas tudo isso prejudica silenciosamente aquilo para que a maioria dos nossos utilizadores construiu o site — ser encontrado, ser clicado.
0:09 — acessibilidade. É uma passagem automatizada com axe-core, não uma auditoria manual completa, e vale a pena ser honesto sobre o que essa opção implica. O axe-core deteta rácios de contraste, texto alternativo em falta, campos de formulário sem rótulo, armadilhas na ordem de tabulação — a camada mecânica, algo como 30-40% do que uma revisão WCAG completa assinalaria. Não deteta uma experiência de leitor de ecrã que é tecnicamente conforme mas genuinamente confusa de usar. Optámos apenas por automatização porque corre em segundos, e a maior parte do que passa por aqui são sites de marketing e pequenas ferramentas, não o tipo de aplicação em que uma auditoria parcial representa um risco real para alguém.
0:11 — conformidade. Esta camada não pergunta "isto é bom", pergunta "isto corresponde ao que foi prometido". O plano previa quatro páginas, o build entregou três — a conformidade é quem repara nisso. O plano prometia um formulário de contacto funcional, o que foi entregue é um formulário sem ação de envio — mesma camada, mesma deteção. É a verificação mais diretamente responsável perante o utilizador, porque mede em relação à intenção declarada pelo utilizador, não a uma noção abstrata de qualidade.
0:13 — a verificação no navegador, e foi aqui que o nosso build realmente falhou. Esta camada é a mais difícil de enganar porque não lê código, conduz um navegador real — clica, escreve, espera, verifica que a DOM mudou como devia. O build em questão era um jogo idle, e os jogos recebem uma passagem extra aqui porque um jogo pode renderizar de forma impecável e continuar injogável — o marcador de pontuação pode parecer perfeito e estar totalmente desligado da lógica de pontuação. O verificador jogou. A pontuação atualizava-se bem. O áudio não emitia qualquer som.
Três rondas, depois uma escalada
A descoberta não nos chegou como um relatório de bug — foi diretamente para uma passagem de correção, e a cadeia voltou a verificar, até três rondas dentro do build. Ronda um: a correção mexeu na inicialização do mixer, que já estava bem, pelo que o áudio continuou silencioso. Ronda dois: uma correção diferente abordou um caso limite do estado de carregamento que parecia relacionado e — isto acontece mais do que seria de esperar — introduziu um pequeno problema novo sem resolver o original. Ronda três: ainda em silêncio, e a este ponto está normalmente perante algo genuinamente difícil ou um alarme falso, e este era do tipo difícil.
Por isso, a plataforma escalou por conta própria. Colocou em fila uma execução de correção de acompanhamento, focada inteiramente na descoberta sobrevivente, a trabalhar sobre um clone do build em vez do build em si — o que significava que a execução de escalada podia falhar sem nos custar a versão funcional que já tínhamos. Essa execução encontrou a causa real: uma flag de silenciamento definida numa passagem de depuração anterior que nunca tinha sido revertida, num ficheiro completamente diferente dos dois tocados pelas correções anteriores. Limpou a flag, voltou a verificar, passou. Ninguém viu este build até já estar a funcionar.
| Encomenda | Camada | Deteções |
|---|---|---|
| 1 | Revisão de código | Lógica quebrada, handlers inativos, bugs de estado |
| 2 | Auditoria de segurança | Superfícies de injeção, segredos expostos, padrões inseguros |
| 3 | Ligações e SEO | Links quebrados, metadados em falta, correção do sitemap/robots.txt |
| 4 | Acessibilidade | Axe-core automatizado: contraste, rótulos, navegação por teclado |
| 5 | Conformidade | Se o build contém o que o plano prometia |
| 6 | Verificação no navegador | Executa o build de verdade — clica, escreve, observa a resposta |
O que evitaria da próxima vez
Alguns meses antes de esse jogo idle correr, experimentámos uma versão mais branda de todo o sistema — verificadores autorizados a levantar qualquer preocupação, seja como for que a formulassem. Produzia descobertas do tipo "considerar extrair isto para uma função auxiliar" e "este nome de variável podia ser mais claro", que passavam por diligência e não corrigiam nada. As passagens de correção gastavam rondas inteiras a polir texto em vez de corrigir o que estava realmente partido. Apertámos a regra para: nomear um ficheiro, descrever uma falha, ou não dizer nada. A produção dos verificadores caiu para cerca de metade e quase tudo o que sobrou era acionável. Se estivesse a reconstruir isto do zero, saltaria por completo a versão branda e iria direto para a regra da evidência — não precisávamos de aprender essa lição pela via cara, mas foi o que aconteceu.
A regra tem um custo real, e não vou fingir que não tem: uma preocupação vaga mas verdadeira, como "este design de API vai causar problemas a alguém daqui a seis meses", agora é descartada, porque um verificador não a consegue associar a uma falha concreta. Fizemos as pazes com essa contrapartida. Uma cadeia que também fizesse revisão de arquitetura não seria rápida o suficiente para correr em todos os builds, e a velocidade é precisamente o objetivo de fazer isto automaticamente em vez de pedir a um humano.
Também não acrescentaria uma quarta ronda, se alguém perguntar. Afinámos o número de rondas com base em builds reais, e o valor marginal para lá da terceira ronda cai a pique — a primeira ronda resolve a maioria das descobertas corrigíveis, a segunda sobretudo limpa problemas introduzidos pela primeira, e à terceira ronda o que resta ou é genuinamente difícil ou nunca esteve realmente partido. Uma quarta ronda serve sobretudo para comprar tempos de espera mais longos para o mesmo resultado.
Nada disto é gratuito, nem infalível. Seis camadas mais o número de rondas de correção que forem necessárias acrescentam tempo real a cada build — a diferença entre terminar em menos de um minuto e terminar em vários. Achamos que é a contrapartida certa para tudo o que esteja prestes a mostrar aos seus próprios clientes, mas "rápido" e "verificado" puxam em direções opostas, e escolhemos verificado. Os verificadores também são LLMs, pelo que ocasionalmente assinalam algo que não está realmente partido, ou deixam passar algo que está. A regra da evidência e o ciclo de múltiplas rondas são salvaguardas contra isso, não garantias.
O que se obtém no final é um registo: que camadas correram, o que encontraram, o que foi corrigido e o que ficou para o seu próprio critério. Esse registo está mais próximo do produto real do que o código está — é a diferença entre confiar numa build porque parece acabada e confiar nela porque algo hostil tentou quebrá-la primeiro e falhou.



