Verificar Finite
O Finite tem duas superfícies, e a maioria dos recursos precisa de ambas. Agentes editam designs através de ferramentas MCP em /mcp (as seis ferramentas doc6; call aciona as ferramentas clássicas em /mcp/classic). Pessoas observam no navegador: a lista de designs em / e o canvas em /design/?id=<designId>. Uma prova aciona o lado do agente com call e verifica o lado da pessoa na página, ou vice-versa para comentários.
A estrutura de teste é e2e/headless.mjs. .agents/skills/finite-headless/SKILL.md é a referência de comandos dela (seletores que alcançam shadow roots, iframes com sandbox, --agent, Python). Leia-a uma vez antes da sua primeira execução. Este skill adiciona isolamento, um médico, uma pasta de evidências, execuções de antes e depois e o mapa de recursos.
Cada comando abaixo é executado a partir da raiz do checkout:
V=.agents/skills/verify-finite/scripts/verify.sh
Variáveis de shell não sobrevivem entre chamadas de ferramenta. Repita V=... e RUN=... no início de cada chamada.
Passos
- Escolha os recursos. Encontre os recursos que sua alteração afeta na tabela em "Quais recursos uma alteração afeta" em
features/README.md. - Inicie uma execução do seu código. Para uma correção de bug, inicie também uma segunda execução do código antes da correção (veja "Antes e depois").
- Examine cada execução até que ela imprima apenas linhas
ok. - Execute cada ponto de entrada de cada arquivo de recurso escolhido, salvando evidências enquanto avança.
- Limpe todas as execuções que você iniciou, incluindo as com falha.
- Relate no formato abaixo em "Relatório".
Você terminou quando cada ponto de entrada de cada recurso escolhido for comprovado, ignorado com um motivo, ou falhou com sua evidência, e $V list não mostra nada em execução.
Iniciar
$V launch # compila o servidor, finite.wasm e o aplicativo web, depois os inicia
$V launch --no-build # reutiliza as últimas compilações; recusado se o código mudou desde que foram feitas
$V launch --width 390 --height 844 # uma página do tamanho de um telefone (o padrão é 1440 × 900)
$V launch --at main # uma execução de outro commit, em um checkout temporário (veja "Antes e depois")
Isso imprime RUN=<run>. Guarde esse id: todos os outros comandos o usam. Uma compilação a frio leva cerca de 2 minutos, e uma compilação sem nada para fazer leva alguns segundos. Defina o timeout do Bash para 600000. --no-build só economiza os poucos segundos de uma compilação sem nada para fazer, então, quando estiver em dúvida, não o use.
O lançamento está pronto quando imprime Finite at http://127.0.0.1:<port>. A estrutura de teste espera por /api/health e carrega a lista de designs antes de imprimir essa linha. A pasta de dados começa vazia, e não há dados de semente, migrações ou login. Uma pessoa posta comentários como "Guest", e agentes postam como "Agent" a menos que você passe --agent <name>.
Cada execução é uma sessão separada (verify-<run>) com sua própria porta livre, pasta de dados temporária e perfil do Chrome, para que as execuções possam ocorrer lado a lado. Nunca dirija um Finite que você não iniciou. vp run dev serve os designs reais do usuário de crates/server/data, e o aplicativo de desktop também serve os dados do próprio usuário. O médico falha em uma sessão que se conectou ao servidor de outra pessoa.
Uma execução é interrompida após 30 minutos ociosos. Depois disso, o doctor falha: limpe e inicie novamente.
Médico
$V doctor $RUN
Ele apenas lê o estado, e toda linha diz ok ou FAIL. Ele verifica cinco coisas:
- A sessão está ativa e possui uma pasta privada
finite-headless-data-*. /api/healthrespondeokcom a versão empackage.json.- A compilação em execução corresponde ao código. Ele compara um hash das entradas de compilação (
crates/,apps/web/, a estrutura de teste, os lockfiles, arquivos não rastreados incluídos) com o hash do código a partir do qual a execução foi compilada. Edições em docs, skills ou testes não contam. - Um Chrome, Chromium ou Edge está presente para
get_screenshot. - A página responde.
Em seguida, ele imprime o console da página desde a última chamada. Execute-o primeiro, após qualquer surpresa, e antes de capturar a prova final. Em caso de FAIL, limpe e inicie novamente em vez de continuar. Depois de alterar o código, a verificação de compilação falha por design: limpe e inicie novamente.
Executar
$V h $RUN <comando> ... executa qualquer comando de e2e/headless.mjs contra esta execução. Os comandos que você mais usará:
$V h $RUN call create_design '{"name":"Verificar"}' # lado do agente: imprime designId "<id>"
$V h $RUN call create_artboard @input.json # JSON inline, @arquivo, ou - para stdin
$V h $RUN design <designId> # lado da pessoa: abrir o canvas, esperar pelos artboards
$V h $RUN snapshot --selector main # árvore de acessibilidade, o que uma pessoa vê
$V h $RUN click 'button[title="Comentar (C)"]'
$V h $RUN click '[data-artboard] >>> h1' --shift # Shift-clique
$V h $RUN upload 'input[type=file]' card.html # escolher um arquivo, como o seletor do sistema faria
$V h $RUN api GET /api/designs/<designId> # o design armazenado, comentários incluídos
Use esses identificadores estáveis. Eles são os nomes e títulos acessíveis do aplicativo:
| Onde | Identificador |
|---|---|
| Lista de designs | heading Designs, botão New design, caixa de pesquisa Search designs by name, um link por cartão de design |
| Barra superior do canvas | link ← Designs, button[title="Variáveis CSS que todo artboard usa, em cada modo"] (Tokens), button[title="Todo comentário, aberto e resolvido"] (Comentários, com a contagem de abertos em seu nome), Import, Export, um chip por agente presente |
| Ferramentas do canvas | toolbar Tools: button[title="Pointer (V)"], button[title="Comment (C)"]; teclas v, c, Shift+1 (ajustar), =/- (zoom) |
| Caixa de comentário | textbox Add a comment, button[title="Change your name"], [data-selection-count], botão Send, pins nomeados Comment: <primeira mensagem> |
| Thread de comentário | [role=dialog] nomeado Comment thread: botões Delete, Resolve/Reopen, Close, Edit na sua mensagem mais recente, textbox Reply |
| Painéis | aside[aria-label=Comments] com abas Open N / Resolved N; section[aria-label=Tokens] com form[aria-label="Add a token"]; nav[aria-label=Pages]; [role=menu][aria-label=Export]; aside[aria-label=Import] com um status |
| Conteúdo do artboard | [data-artboard="<artboardId>"] >>> <css>; os atributos data-name dos agentes sobrevivem no DOM |
Prefira estes às coordenadas. Coordenadas são apenas para artboards com sandbox (script), que os seletores não conseguem alcançar. click aceita CSS, não texto, então botões sem título são selecionados por posição: [role=dialog] button --nth 1, com query listando a ordem.
A entrada de texto tem duas armadilhas. type anexa ao que um campo contém, e key Meta+a não seleciona texto através do CDP. Para substituir o texto de um campo, execute $V h $RUN eval "document.execCommand('selectAll')" com o campo focado, depois type.
Chamadas em segundo plano
wait_for_comments bloqueia até que uma pessoa comente, então deve ser executado enquanto você dirige a página:
$V bg $RUN 02-wait call wait_for_comments '{"designId":"<D>","timeoutSeconds":30}'
# ...dirija a página...
$V await $RUN 02-wait 30 # bloqueia até que a chamada retorne, então imprime .verify/<run>/02-wait.txt
Leia o resultado com await, nunca lendo o arquivo diretamente: o arquivo só aparece quando a chamada retorna. A chamada em segundo plano sobrevive entre chamadas de ferramenta.
Evidências
Tudo vai para .verify/<run>/ no checkout. .gitignore cobre isso, e a limpeza mantém.
$V save $RUN 01-comentario-postado snapshot --selector main # o comando, sua saída e código de saída
$V shot $RUN 02-canvas # .verify/<run>/02-canvas.png
$V shot $RUN 03-painel --selector 'aside[aria-label=Comments]'
save aceita qualquer comando headless, incluindo call, e escreve <nome>.txt contendo o comando, sua saída e [exit N]. Numere os nomes para que a execução seja lida em ordem. Leia cada PNG com a ferramenta Read antes de confiar nele. Imagens get_screenshot e qualquer captura de tela de página tirada sem um caminho vão para a pasta temporária da sessão. A limpeza as copia para .verify/<run>/tool-images/, e o log do servidor para .verify/<run>/server.log. Arquivos que você criar como entrada de teste, como um arquivo para importar, também vão para .verify/<run>/.
Uma prova atende a estes padrões:
- O caminho real. A ação de uma pessoa passa pela página (clique, tecla, digitação, upload), e a ação de um agente passa por uma chamada MCP
call. Use a API REST apenas para ler o estado armazenado. Escrever através dela ignora a UI que você está provando. - Ação e resultado. Salve a etapa que faz a coisa e o estado depois dela, não apenas uma captura de tela final.
- Efeitos colaterais. Mostre a alteração armazenada e também exibida.
api GET /api/designs/<id>retornameta,nodesecommentscomo o servidor os salvou, e a ferramenta de leitura de um agente (get_comments,get_tokens,get_tree_summary) mostra o que o próximo agente verá. - Ambas as direções para recursos ao vivo. A edição de um agente deve aparecer na página sem um recarregamento. O comentário de uma pessoa deve alcançar um agente em espera.
- Sem mocks. A execução usa o servidor real, o navegador real e sessões MCP reais.
- Console limpo. Termine com
$V save $RUN <n>-console console. Uma exceção ou requisição com falha ali estraga a prova.
Antes e depois
Uma correção de bug é comprovada quando a mesma jornada falha no código antigo e passa no novo. Execute ambos lado a lado:
$V launch --at main # RUN=<antes>: um checkout temporário do main, instalado e compilado (cerca de um minuto)
$V launch # RUN=<depois>: este checkout
Dirija as mesmas etapas em ambos, com os mesmos nomes de evidências. A execução "antes" deve mostrar o bug. Se não mostrar, sua jornada não atinge o bug, e a execução "depois" não prova nada sobre a correção. --at aceita qualquer ref git: um branch, uma tag, um commit, ou HEAD quando sua correção ainda não foi commitada. O médico nomeia o ref e o commit a partir dos quais uma execução foi compilada. A limpeza remove o checkout temporário e mantém suas evidências.
Limpeza
$V cleanup $RUN
Isso interrompe o daemon desta execução. O daemon interrompe o servidor que ele gerou (SIGTERM, para que os designs salvem primeiro) e o Chrome que ele iniciou, então exclui seus dados temporários e perfil. Em seguida, a limpeza copia o log do servidor e as imagens das ferramentas para a pasta de evidências, remove o checkout temporário de uma execução --at, e lista o que manteve. Não toca em mais nada, para que outras sessões, vp run dev e o aplicativo de desktop continuem em execução.
$V list imprime as execuções deste checkout que ainda estão em execução ou deixaram um checkout para trás. Limpe cada uma com $V cleanup <run>, nunca pkill. $V prune [dias] exclui as evidências de execuções limpas com mais de tantos dias (7 por padrão). Nunca remova uma execução cujas evidências você está prestes a relatar.
Relatório
Termine com um bloco por recurso que você executou:
<ID do recurso> via <ponto de entrada>: comprovado | ignorado | falhou
evidência: .verify/<run>/<arquivos>
motivo (ignorado ou falhou): <o comando que você executou e o que estava faltando ou errado>
Em seguida, forneça os ids das execuções, a saída do médico para cada uma e, para uma correção, a evidência da execução "antes" que mostra o bug. Relate um ponto de entrada ignorado como ignorado, mesmo quando outro ponto de entrada comprovou o mesmo comportamento.
Ajuda
scripts/verify.sh aceita estes comandos: launch, doctor, h, save, shot, bg, await, cleanup, list e prune. Execute-o sem argumentos para ver os argumentos deles. É uma camada fina sobre e2e/headless.mjs: a sessão é verify-<run>, e as evidências vão para .verify/<run>/.