Como funciona

natural-language task ──▶ planner (LLM, 1 call) ──▶ JSON action plan

       trajectory cache ◀── cheap verification ◀── deterministic executor

             └──▶ subsequent runs: zero LLM, ~1s, $0

A parte cara — descobrir as ações do navegador — acontece uma única vez e é transformada em dados verificáveis em cache.

  • Planos são dados, não código — JSON validado por schema; sem scripts gerados, sem condicionais.
  • Verificação barata — pós-condições de DOM/URL após cada ação. Uma verificação que falha invalida o plano em cache e dispara um replanejamento automático.
  • Mapa do site — cada execução alimenta um grafo de páginas e transições; windup scan popula esse grafo direto do seu código-fonte antes da primeira execução, para que o planejador use os seletores reais do seu app em vez de adivinhar.
  • Fragmentos — blocos de ações comprovados (ex.: login) que o planejador compõe via { "type": "use" } em vez de regerar.
  • Zero conhecimento do site embutido — o motor conhece frameworks e a web, nunca o seu site. Todo conhecimento do site chega como entrada (cenários, config, manifesto) ou é descoberto em tempo de execução.

Por que Windup

Scripts escritos à mão são baratos de rodar, mas caros de manter. Agentes de IA por execução são fáceis de escrever, mas lentos e não determinísticos. O Windup pega a metade boa de cada um.

Scripts à mãoAgente de IA por execuçãoWindup
Autoriacódigo + seletores à mãolinguagem simpleslinguagem simples
Custo por execução$0LLM em cada execuçãoLLM apenas na primeira execução
Velocidaderápidolento (modelo no loop)~1s replay
Determinismoaltobaixo — improvisa toda vezalto — mesmo plano em cada replay
App mudouvocê conserta o scriptpode fazer outra coisa em silêncioverificação falha → replanejamento automático

O que o cache compra é $0, não “instantâneo”. Um acerto de cache pula o planejamento do LLM (plan=0ms, llm_calls=0) — mas as ações de Playwright do plano ainda rodam, e qualquer cadeia depends_on ainda executa, então o tempo real é tempo de navegador real, não uma consulta. Cada execução reporta o detalhamento — total=… (plan=… deps=… exec=… setup=…) — onde deps é a cadeia de dependências, exec são as ações deste cenário e setup é o contexto do navegador. O relatório HTML divide a duração de cada cenário em uma barra que reconcilia (setup · deps · plan · nav · actions), onde nav é o goto + o carregamento/hidratação da página antes da primeira ação — normalmente o verdadeiro sorvedouro de tempo em uma SPA (então uma ação de 113 ms que aparece como “3.6 s” na verdade é setup + nav). O Windup prossegue assim que a página renderiza elementos interativos ou a rede fica ociosa, então uma página apenas de exibição não fica presa no timeout de readiness. O cabeçalho da suíte mostra o tempo de parede (wall-clock, tempo real decorrido), não a soma dos totais por cenário, que infla ~N× sob --concurrency N. Sob concorrência, o resíduo por cenário é rotulado como contention (o tempo que o cenário passou esperando por um slot de CPU/navegador enquanto os irmãos rodavam — ocioso, não trabalho), e é mostrada uma cifra de active ms (o próprio trabalho ativo dele, ~estável ao longo da concorrência) para que os cenários permaneçam comparáveis. A maior alavanca são os snapshots de sessão: o estado de autenticação de uma dependência (storageState) é capturado uma vez e restaurado em replays posteriores, de modo que o fluxo de login não é reexecutado para cada dependente (deps≈0).

Para os mecanismos mais profundos — fronteiras entre módulos, formatos de dados, postura de custo e segurança — veja Arquitetura e especificação.