Meu harness de IA para frontend: do prompt ao pull request
O sistema que uso para transformar uma ideia em frontend verificável: specs, skills, escolha de modelo, Ralph Starter, worktrees, browser, screenshots, testes, GitHub e telemetria. O modelo escreve código. O harness decide em que acreditar.
O build do meu portfólio estava verde. Em 390px, o endereço de email saía do próprio card. Depois do primeiro fix, ele cabia, mas quebrava um único “m” para a linha seguinte. Foram três ciclos de screenshot até uma string ficar certa.
Esse é o detalhe que separa um agente que escreve frontend de um sistema que entrega frontend. O TypeScript não sabia que a página de contato tinha falhado na tarefa mais básica da página. O browser sabia. A imagem sabia. O harness precisava olhar para os três.
Uso Claude, Codex, Amp, Kimi e GLM conforme disponibilidade e tipo de trabalho. Nenhum deles é o harness. Modelos são workers dentro de um circuito maior, junto de specs, skills, git, browser, testes, críticos e condições de parada.
Este é o circuito completo que uso hoje, do pedido ao pull request.
Primeiro: o que chamo de harness
Harness é o ambiente de execução e medição de um agente.
O prompt diz o que fazer agora. O harness decide quais arquivos o agente lê, quais ferramentas pode usar, onde escreve, o que precisa medir, como recebe uma falha e qual evidência permite encerrar o trabalho.
No meu caso, o fluxo cabe neste mapa:
ideia, issue ou bug
→ pesquisa e spec
→ seleção de papel, modelo e skills
→ worktree isolada
→ implementação
→ test, lint e build
→ browser, screenshots e evals
→ crítico adversarial
→ pull request
→ telemetria e novas issues
Nem toda tarefa atravessa todas as etapas. Uma troca de copy não precisa de swarm. Uma nova experiência de navegação precisa do browser. Um experimento de shader precisa de screenshots e medição de GPU. O harness roteia pelo risco, não pelo entusiasmo.
1. A entrada precisa ser melhor que “faça uma tela”
O primeiro artefato é uma spec curta. Ela descreve comportamento, restrições e prova de conclusão.
Para uma feature de frontend, quero pelo menos:
- rota ou superfície afetada;
- estados normal, loading, vazio, erro e sucesso;
- breakpoints relevantes;
- origem e forma dos dados;
- interações de teclado e foco;
- orçamento de performance quando importa;
- comandos de validação;
- screenshots ou referências visuais;
- o que está explicitamente fora do escopo.
Uma spec não precisa prever cada classe Tailwind. Ela precisa impedir que o agente invente a definição de pronto.
O caso mais claro veio do Ralph Starter. Uma issue chamada “Improve performance” atravessou três loops sem progresso verificável. A cada rodada o agente escolhia uma otimização diferente, porque ninguém tinha escrito rota, dispositivo, métrica inicial ou meta. O circuit breaker encerrou o trabalho corretamente.
Depois disso, “melhorar performance” deixou de ser uma tarefa. “Reduzir o LCP da rota /catalog no mobile de 3,1s para menos de 2,5s no cenário de teste X” é uma tarefa.
2. Skills carregam método, a spec carrega intenção
Eu separo conhecimento reutilizável do pedido atual.
A spec diz: implemente este filtro no catálogo. Uma skill diz: ao trabalhar com frontend deste projeto, inspecione os componentes existentes, preserve tokens, verifique 390px e desktop, teste teclado, capture screenshots e rode os gates.
Sem essa separação, cada issue repete um manual de operação. Pior: duas issues acabam com versões diferentes do manual.
Skills úteis num projeto frontend incluem:
- padrões de React, Next.js ou Svelte usados no repo;
- sistema visual e convenções de Tailwind;
- acessibilidade e navegação por teclado;
- captura e comparação de screenshots;
- escrita e tradução de conteúdo;
- política de dependências;
- observabilidade e eventos de produto;
- release e rollback.
Neste portfólio, a voz editorial já era uma skill. Agora o fluxo bilíngue e o sistema visual das capas também são skills versionadas no repo. O próximo agente não precisa reconstruir essas decisões a partir de uma conversa antiga.
3. Eu não uso um router mágico entre modelos
Roteamento de modelo funciona melhor como uma tabela de papéis do que como uma eleição abstrata de “melhor IA”.
Minha tabela muda com o projeto e a disponibilidade, mas os critérios são estáveis:
| Papel | O que procuro |
|---|---|
| scout de pesquisa | contexto longo, busca, boa síntese e links verificáveis |
| spec writer | decomposição, restrições e casos de borda |
| builder | uso confiável de ferramentas e edição precisa do repo |
| crítico visual | leitura de screenshots e capacidade de apontar defeitos concretos |
| regression hunter | paciência para comparar antes e depois sem inventar achados |
| reviewer | análise de diff, risco e cobertura de testes |
Claude pode ocupar spec e build numa tarefa. Codex pode revisar e corrigir issues em sequência. Kimi pode pesquisar referências. GLM pode executar trabalho bem delimitado em volume. Isso não é uma lei sobre os modelos. É uma decisão operacional que posso trocar sem redesenhar o pipeline.
Em trabalhos caros, o roteamento também considera limite de contexto, rate limit, custo e disponibilidade. O harness que construí para o ECDSA.fail faz isso de forma explícita com tabelas de papel para modelo e adapters fail-closed. Para um frontend pequeno, uma tabela no arquivo de instruções já resolve.
4. Ralph Starter executa o loop mecânico
O Ralph Starter é a peça que transforma uma spec numa execução repetível.
Um comando mínimo é:
ralph-starter run "add an accessible search field to /catalog" --commit --pr
Ele pode buscar a tarefa no GitHub, Linear, Notion, arquivo local ou URL. Depois:
- cria uma branch;
- executa o agente escolhido;
- roda test, lint e build;
- injeta a saída bruta da falha na próxima iteração;
- repete até passar ou atingir uma condição de parada;
- faz commit, push e abre o PR quando autorizado.
Para várias issues, cada execução pode usar uma worktree própria:
ralph-starter auto \
--source github \
--project owner/repo \
--label auto-ready \
--parallel \
--concurrency 3
Ralph não substitui o harness inteiro. Ele é o executor do loop de implementação. Não decide se a feature merece existir, não sabe sozinho se o layout ficou bom e não deve promover uma mudança apenas porque o build passou.
A razão para citá-lo aqui é prática: muita gente tenta construir agentic engineering começando por um swarm. Um loop com uma spec, um agente e três gates já resolve uma grande parte do trabalho. Paralelismo vem depois que a execução individual é confiável.
5. Worktrees impedem que velocidade vire contaminação
Quando dois agentes editam o mesmo checkout, o resultado pode parecer colaboração. Na prática, um altera o chão enquanto o outro mede.
Uso uma git worktree por frente de trabalho. Cada agente recebe branch, diretório e diff próprios. Isso permite:
- atribuir cada resultado a uma tentativa;
- matar uma rota sem desfazer outra;
- comparar abordagens lado a lado;
- rodar validações sem arquivos não commitados de outro worker;
- escolher um vencedor antes do merge.
No modo swarm do Ralph Starter, as estratégias race, consensus e pipeline usam esse isolamento de formas diferentes. race aceita o primeiro loop bem-sucedido. consensus espera todos e compara execuções válidas. pipeline passa o mesmo trabalho por estágios sequenciais.
Para frontend, uso race com cuidado. O primeiro build verde não é necessariamente a melhor interface. Quando gosto visual importa, prefiro terminar os candidatos, capturar as mesmas rotas e comparar as imagens sob a mesma rubrica.
6. Framework muda o gate, não a arquitetura do loop
React, Next.js, Svelte e Tailwind pedem verificações diferentes.
Em React, olho para estado duplicado, efeitos que deveriam ser derivados e componentes que renderizam mais do que precisam. Em Next.js, entram limites entre server e client components, cache, serialização, rotas dinâmicas e o risco de colocar segredo no bundle. Em Svelte, verifico o modelo de reatividade usado pelo projeto e se o agente misturou convenções de versões diferentes. Em Tailwind, procuro duplicação de classes, valores mágicos e componentes que ignoram os tokens existentes.
O build encontra parte disso. Testes encontram outra parte. O browser encontra o restante.
Por isso uma skill de frontend deve começar lendo o repo. Pedir “use best practices de Next.js” pode fazer o agente aplicar a prática certa para uma versão, router ou arquitetura que o projeto não usa. Instrução genérica perde para evidência local.
7. O browser é uma ferramenta de teste
Depois de três versões do portfólio chegarem a produção sem ninguém renderizar todas as páginas, criei um gauntlet visual.
O comando captura cada rota em 1600x1000 e 390x844. Uma rubrica escrita dá de 0 a 2 pontos em 15 critérios, máximo de 30 por screenshot. O ciclo é:
build
→ abrir com browser real
→ capturar desktop e mobile
→ avaliar com rubrica
→ corrigir
→ capturar novamente
O próprio rig precisou ser corrigido. Chrome headless com renderização por software destruía WebGL e produzia falsos bugs. Animações do compositor eram capturadas com opacity: 0. A toolbar do Astro aparecia nas imagens. Antes de o gauntlet avaliar o site, eu precisei calibrar a câmera.
Os ciclos chegaram a médias de 29,4, 29,75 e 29,83 de 30. O último defeito real era o endereço de email. Build verde, página quebrada. É por isso que screenshot não é decoração de PR. É saída de teste.
8. Um crítico precisa ter permissão para reprovar
Builder e reviewer não deveriam compartilhar o mesmo objetivo.
O builder quer terminar a feature. O crítico quer encontrar a razão concreta pela qual ela ainda não deveria entrar. Dou ao crítico o diff, os screenshots, a spec e os logs de validação. Não dou a conclusão do builder como verdade.
Um relatório útil precisa responder:
DECISION:
WHY:
EVIDENCE:
MISSING:
NEXT COMMAND:
STOP RULE:
Também separo o que foi confirmado, inferido e não verificado. “O teste passou” e “o teste deveria passar” não podem ocupar a mesma categoria.
No frontend, o crítico procura regressão visual, foco perdido, overflow, estado ausente, console error, request duplicada, conteúdo que salta e caminhos que só funcionam com mouse. Se não encontrar nada, pode dizer que não encontrou. Crítico obrigado a descobrir um bug começa a fabricar bugs.
9. GitHub é a fila, não a memória inteira
Erros reportados por jogadores do CS Brasil já podem virar issues no GitHub automaticamente. O passo seguinte é classificar, reproduzir e preparar correções por agente. Essa automação só funciona se a issue carregar evidência suficiente: rota ou mapa, versão, mensagem, stack, estado relevante e passos conhecidos.
O GitHub organiza trabalho e revisão. A memória operacional continua no repo: instruções, skills, specs, decisões, invariantes e resultados de eval. Uma conversa privada com um modelo é um lugar ruim para guardar por que uma regra existe.
No caminho inverso, o agente pode buscar uma issue pronta e entregá-la ao Ralph Starter. Isso fecha um circuito útil:
telemetria ou erro
→ issue estruturada
→ triagem
→ spec aprovada
→ loop de implementação
→ PR
→ deploy
→ nova telemetria
Eu ainda mantenho aprovação humana entre triagem e execução para mudanças que afetam produto, segurança, custo ou arquitetura. Automação deve reduzir relay mecânico, não esconder decisões.
10. Telemetria fecha o loop que o PR não fecha
Testes dizem se a mudança respeita um contrato conhecido. Telemetria mostra o que aconteceu com pessoas reais.
Para um jogo, observo tempo por mapa, personagem, duração de round, score e abandono. Para um produto web, seriam eventos de funil, erros por rota, Core Web Vitals, uso por breakpoint e falhas de rede. Os sinais dependem do produto. A regra é a mesma: uma feature sem observação pós-deploy termina no merge, não no aprendizado.
Telemetria também cria novas specs. Se uma rota tem erro concentrado em mobile, a próxima issue já nasce com cenário e medida. O harness melhora porque o produto devolve casos reais.
A versão mínima que eu montaria hoje
Para alguém começando, eu não recomendaria cinco modelos nem um swarm.
Montaria isto:
AGENTS.mdcom arquitetura, comandos e limites.- Uma skill de frontend específica do repo.
- Issues com critérios de aceite observáveis.
- Um agente de código confiável.
- Ralph Starter ou um loop equivalente.
- Test, lint e build obrigatórios.
- Dois screenshots por rota crítica: desktop e mobile.
- Um reviewer separado olhando diff e imagens.
- Uma condição de parada e um limite de iterações.
Depois adicionaria worktrees paralelas, roteamento entre modelos, mutation testing, telemetria automática e bots de triagem conforme os modos de falha aparecessem.
O modelo mais novo pode melhorar a primeira tentativa. Ele não resolve uma spec vaga, uma câmera mentirosa ou uma régua que premia a coisa errada.
A lição é operacional: comece pelo feedback que consegue reprovar o agente. Depois escolha quem escreve o código.
Se os termos ainda parecem misturados, leia antes Do prompt ao produto: cinco formas de desenvolver com IA.