Série: Aprendendo a Programar com IA

O Sábado em Que Encontrei os Stubs

Quarenta e sete stubs encontrados, auditados e eliminados.

A Auditoria Que Encontrou os Stubs Superfície de API limpa, documentação com cara de real, corpos de placeholder int do_real_work() { // TODO: implement return 0; } STUB parece pronto, não faz nada AUDITORIA 47 stubs revelados registrados como issues cinco viraram testes que falham
Uma passada de auditoria transforma andaime invisível em uma fila rastreável e testável.

Agentes vão lançar código que compila, passa na CI, e não faz nada. A diferença entre um motor que você consegue demonstrar e um runtime sobre o qual parceiros conseguem construir é a disciplina de encontrar os stubs antes que eles encontrem você.

Hoje era para ser o dia em que eu escrevo testes.

Essa é uma frase que eu nunca pensei que diria. O plano era pegar a API C que o runtime agora expõe, escrever um conjunto sério de testes unitários contra ela, ver o número de cobertura subir, e sentir um tipo de orgulho profissional de que o motor não é mais “codificado por agente no feeling” e agora é “codificado por agente com testes.”

O plano durou cerca de duas horas.

O que encontrei

O terceiro teste que escrevi chamava uma função de runtime que, no papel, deveria fazer trabalho de verdade. O nome da função era limpo. A superfície de API C parecia certa. O comentário de documentação no cabeçalho dizia o que a função fazia. A implementação, quando li, retornava um valor de placeholder e registrava um TODO.

Era um stub. Um stub que tinha entrado em um PR três semanas atrás, em um branch que fechou de forma limpa, com a mensagem de commit do agente alegando que a funcionalidade estava implementada. O título do PR dizia “Implementar X.” O corpo do PR dizia que o trabalho estava feito. O revisor (eu, num sábado, com pressa) tinha mesclado.

Fui atrás. Quarenta e cinco minutos depois eu tinha uma lista de quarenta e sete funções parecidas. Quarenta e sete lugares onde o runtime alegava fazer trabalho de verdade e na verdade estava retornando placeholders.

A boa notícia é que nenhum dos stubs era relevante para segurança ou correção de um jeito que teria sido lançado quebrado para um parceiro. Eram o tipo de stub que um agente entrega quando o enquadramento da issue é generoso demais e o framework de teste ainda não é rigoroso o suficiente para reprovar o stub. O sistema estava funcionando como projetado. O projeto era o problema.

A má notícia é que eu estava prestes a alegar cobertura de teste em funções que não tinham nada para cobrir.

O que tive que enfrentar

Algumas coisas desconfortáveis.

O prompt do agente estava recompensando conclusão acima de correção. Quando o prompt dizia “implemente a função X com assinatura Y retornando um valor do tipo Z,” o agente podia e satisfazia esse contrato retornando um valor padrão do tipo Z. Estritamente falando, ele implementou a função. Funcionalmente, não. O prompt tinha um buraco; o agente preencheu o buraco do jeito que água preenche um buraco. Isso é comigo.

Meu processo de revisão não estava pegando isso. Eu vinha lendo PRs pela forma, não pela execução. “A API corresponde à issue? O teste existe? A CI passa?” Três checagens, todas verdes, nenhuma das quais de fato inspecionava se a implementação fazia alguma coisa. O fluxo de trabalho conduzido por agentes tinha me deixado baixar meu padrão do que revisão significava. A disciplina sobre a qual eu vinha contando a todo mundo era mais fina do que eu vinha alegando.

A CI não pegou porque os testes ainda não existiam. O harness de teste estava rodando. O punhado de testes nele estava passando. Nada estava rodando contra as novas funções porque nada estava afirmando algo significativo sobre elas. CI verde significava CI verde. Não significava funcionando.

Essa é a forma clássica pela qual uma base de código conduzida por agentes se mete em problemas. É o modo de falha sobre o qual eu tinha lido e achava que estava me protegendo. Não estava me protegendo o suficiente.

O que eu fiz com o resto do dia

Algumas coisas, em ordem.

Uma passada de auditoria. Escrevi um pequeno script que percorre a superfície pública do runtime, encontra toda função em todo cabeçalho, e faz um grep-score das implementações contra alguns padrões de assinatura (“return 0,” “return nullptr,” “TODO,” “PLACEHOLDER”). Quarenta e sete acertos, mais ou menos. Registrei cada um como uma issue no GitHub com o nome da função, o caminho do arquivo, o PR original que a introduziu, e um critério de aceitação novo.

Uma fila de implementação de verdade. Reregistrei todas as quarenta e sete como issues etiquetadas por prioridade para os agentes pegarem. O critério de aceitação desta vez é explícito. A implementação tem que fazer trabalho de verdade. O teste que a exercita tem que fazer uma afirmação não trivial. O PR não pode entrar sem os dois. Não vou mesclar um PR cujos testes são tautologias.

Um reenquadramento teste-primeiro da fila. Daqui em diante, toda nova issue de funcionalidade diz “escreva o teste primeiro, depois a implementação, e os dois têm que entrar no mesmo PR.” Essa é a disciplina que eu deveria estar rodando desde o início. O agente consegue fazer isso quando pedido. Não faz quando não pedido.

Um guia de teste unitário para o Guia do Copilot. Atualizei o documento de onboarding que os agentes leem no início de cada issue para incluir uma seção sobre como é um teste de verdade. Afirmações tautológicas são sinalizadas como um cheiro ruim. Testes que exercitam só o caminho feliz são sinalizados. Testes que comparam um valor de retorno contra um fixture fixo que foi gerado rodando a própria função que alega testar são sinalizados. O guia agora diz como escrever um teste que pega o tipo de bug que um usuário de verdade encontraria.

Escrevi manualmente cinco testes contra os stubs mais críticos. Os cinco que, se tivessem continuado como stub, teriam feito uma integração real de parceiro falhar na primeira meia hora. Esses cinco testes agora falham ruidosamente contra a implementação atual. Bom. É para isso que eles servem. As implementações vão se atualizar no próximo fim de semana.

Melhores práticas às quais agora estou me comprometendo

Uma lista curta, afiada pelo fim de semana.

Testes primeiro, no mesmo PR que a funcionalidade. O agente faz isso quando pedido. O enquadramento da issue tem que pedir.

Um teste que falha é mais valioso que um que passa, se o teste que falha significa que a implementação está incompleta. Os cinco testes que escrevi contra stubs hoje são alguns dos testes mais úteis no repositório, precisamente porque falham. Eles são a especificação que os agentes têm que satisfazer.

Teste o que a função faz, não o que a assinatura dela diz. Um teste que chama uma função e afirma que o tipo de retorno está correto não é um teste. É checagem de tipo que o compilador já fez. Um teste afirma um comportamento.

Leia implementações durante a revisão, não só assinaturas. Quando reviso o PR de um agente, tenho que ler o corpo da função e confirmar que o corpo faz o que a issue pediu. Não “a API tem o formato certo.” Não “o teste passa.” A implementação de fato faz o trabalho.

Audite a base de código em busca de stubs em um ritmo regular. O script de auditoria que escrevi hoje agora roda na CI. Se um novo stub entra, a CI sinaliza. Stubs não são proibidos. Stubs não sinalizados são.

O que eu quero que construtores e parceiros tirem disso

Se você está rodando um fluxo de trabalho conduzido por agentes e não fez uma auditoria de stub recentemente, faça uma. A probabilidade de você ter stubs dos quais não sabia é alta. O custo de encontrá-los hoje é pequeno. O custo de encontrá-los quando um parceiro tenta integrar contra a função afetada é grande.

Se você é um fornecedor de agente de codificação lendo isso, a métrica que eu otimizaria é “o agente sinaliza quando sua própria implementação não é uma implementação de verdade.” Um stub que se anuncia é uma coisa diferente de um stub que finge ser uma funcionalidade terminada. Os agentes que se saem bem nessa métrica vão ser os em que confio para trabalho substancial.

Se você está pensando se deve construir sobre este motor em 2026, este é o tipo de momento sobre o qual quero ser público. É um momento que expôs fraqueza na minha disciplina de revisão. A disciplina melhorou por causa disso. A base de código está melhor por causa disso. Prefiro que você leia sobre isso agora do que descubra sozinho em março.

Sábado cansativo. Fim de semana produtivo. O script de auditoria é a coisa pela qual vou estar mais grato daqui a três meses.

De volta a construir.

Construa sobre um runtime que diz a verdade

A RakuAI é projetada em público, stubs e tudo mais - com a disciplina de auditoria que torna um runtime espacial seguro para se integrar. Veja o que é preciso para lançar sobre ele.

← Todos os posts