Communitygithub.com

genekogan/proof

Grava o clipe de prova que uma alteração T2+ precisa — um vídeo Playwright ininterrupto e em velocidade real da jornada do usuário alterada em um mundo local com mente falsa, com barra de progresso e timecode inseridos, desktop e (quando o layout mudar) telefone — e o anexa ao pull request sem fazer commit do vídeo no repositório. Use quando a alteração for de nível T2 ou superior, quando um PR ou issue pedir um clipe, quando a skill finish atingir a etapa de prova ou ao reproduzir um bug em vídeo para triagem.

O que é proof?

A skill **proof** automatiza a criação de evidências visuais inalteradas para alterações de código classificadas como T2 ou superiores. Ela grava um vídeo único, ininterrupto e em velocidade real da jornada do usuário modificada, usando Playwright em um mundo local com modo de mente falsa e dados isolados. O vídeo é gerado com barra de progresso e timecode (quando ffmpeg com drawtext está disponível) e pode incluir versões para desktop e telefone se o layout tiver sido alterado. A skill gerencia todo o ciclo: inicia um servidor de mundo local, executa os passos da jornada definidos em um arquivo `.steps.mjs`, faz a gravação, gera um preview em GIF animado e faz upload dos arquivos para uma release do GitHub associada ao PR, sem nunca commitar o vídeo no repositório. Ela também suporta um teste smoke local rápido para alterações T1, verificando a renderização sem erros de console. A ferramenta é compatível com ambientes locais e de nuvem, com fallbacks para quando `gh` ou ffmpeg não estão disponíveis, e inclui verificações de segurança para evitar vazamento de dados privados nos clipes.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/genekogan/souls/tree/HEAD/.claude/skills/proof

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Prévia

Do README da skill

desktop.mp4

Documentação

prova — um clipe ininterrupto da jornada alterada

Um revisor deve poder assistir ao que um usuário veria, em velocidade normal, do início ao fim. O clipe é a evidência; uma captura de tela, uma folha de contatos ou uma gravação acelerada não são.

Fonte da verdade para o que cada nível exige: docs/process/PROOF-POLICY.yml (T0 nada; T1 testes focados + typecheck; T2 adiciona um clipe da jornada alterada, desktop, mais telefone se o layout mudou, em um mundo com mente falsa; T3/T4 adicionam mais). Obtenha o nível do diff atual com node tools/proof/tier.mjs --base origin/main.

Regras

  • Ininterrupto e em velocidade real. Um contexto de navegador, uma tomada. Nunca corte, emende, acelere ou desacelere. Se a jornada for maior que max_seconds da política, grave uma jornada mais curta que ainda mostre a alteração, não uma mais rápida.
  • A tomada começa na chegada (o padrão): a gravação começa quando o mundo está na tela e o cartão de chegada desapareceu, então o clipe abre no mundo, não no carregamento. A partir daí é uma tomada ininterrupta e em velocidade real da jornada, que é o que a política pede. Quando o carregamento ou a chegada é o que a alteração trata (o cartão de chegada, uma tela de carregamento, primeiro paint), ou a jornada não está em uma página de mundo (a lista de mundos, login), passe --from-load: a tomada então começa na criação da página. O start do sidecar (arrival ou load) indica qual foi usado, e upload.mjs --proof o copia para proof.json media[].
  • Durante o dia. Em uma URL de mundo local, o gravador define o mundo para o meio-dia com seu relógio pausado antes de abrir a página (--time-of-day 12, o padrão; a rota god env como o desenvolvedor proprietário). Mundos de desenvolvimento iniciam às 06:00 e executam um dia de mundo por hora real, então sem isso um mundo ativo por 40 minutos estará à noite. Configurá-lo é uma entrada world no histórico god do mundo, e o relógio permanece pausado depois. Passe outra hora, ou --time-of-day keep quando o relógio, a luz ou o histórico god é o que a alteração trata. O worldTime do sidecar indica o que foi definido.
  • Entrada real. Dirija com page.mouse, page.keyboard, page.touchscreen ou cliques de localizador, como um usuário faria. Não chame internos do aplicativo de page.evaluate para fazer as coisas acontecerem na câmera.
  • Mentes falsas, dados isolados. Apenas mundos locais, BRAIN_MODE=fake, um diretório de dados novo. Nunca grave contra um mundo de produção a menos que o mantenedor peça, e nunca com um perfil de navegador pessoal conectado.
  • Nunca faça commit de vídeo (ou quadros) no repositório. Trabalhe em .e2e/ (ignorado pelo git).
  • O clipe deve mostrar a alteração. Assista-o (ou pelo menos extraia quadros, abaixo) antes de anexá-lo.

1. Inicie um mundo com mente falsa

Precisa de um cliente web compilado (pnpm install --frozen-lockfile && pnpm build; pule se apps/web/dist/index.html existir e estiver atualizado para sua alteração). Em um clone novo, a verificação pré-construção da build falha até que as mídias web estejam no lugar: node tools/assets/pull.mjs --only 'apps/web/**' (alguns arquivos) é suficiente para isso.

node tools/god-skill/dev-world.mjs proof 4710 --genesis worlds/templates/hello-hamlet.json --fresh --data .local/proof
# imprime http://127.0.0.1:4710/w/proof?dev=1 (pid N, log .lane/proof.log); o servidor continua executando em segundo plano

A página inicial (lista de mundos, Novo mundo) é servida pelo lançador de mundos, não por um único mundo. Para uma jornada que começa lá, execute um lançador (seus mundos sempre recebem mentes falsas) e crie um mundo para a lista através de sua API:

node tools/world-launcher/launcher.mjs --port 4720 --range 4721-4723 --data "$PWD/.local/proof-launcher" --eager 0 &
curl -s -X POST -H 'content-type: application/json' -H 'authorization: Bearer dev:proof' \
  -d '{"name":"Proof Garden","template":"hello-hamlet"}' http://127.0.0.1:4720/__sim/worlds
# grave contra http://127.0.0.1:4720/ ; pare o lançador pelo seu pid (ele para seus mundos)

Escolha o template que contém a superfície alterada (worlds/templates/: hello-hamlet é pequeno e rápido; eden-2026, mars-two e outros são maiores). Use uma porta livre; e2e/config.mjs lista portas reservadas para outros harnesses. Pare o servidor com kill <pid> quando terminar.

Prova rápida de que o aplicativo funciona: o smoke local

Antes de gravar, ou como prova completa de uma alteração T1 que toca o servidor ou aplicativo web, execute o smoke local. Ele inicia seu próprio lançador isolado (mentes falsas, login de desenvolvimento, dados sob o diretório de execução) em uma porta livre, abre a lista de mundos e um mundo, verifica se uma pessoa é desenhada sem erros de console e sem requisições falhas, e para o que iniciou:

node e2e/local-smoke.mjs --port 9950 --clip      # --build primeiro em um clone novo; omita --port para qualquer porta livre
# → .local/e2e/<timestamp>/summary.json, shots/1-world-list.png 2-world.png 3-person.png, clip.mp4
node tools/proof/upload.mjs --pr $N .local/e2e/<timestamp>/summary.json .local/e2e/<timestamp>/shots/*.png

status: "pass" em summary.json é a evidência; seu clipe é uma tomada ininterrupta e em velocidade real da jornada smoke. Não é um clipe da sua alteração: uma alteração T2 ainda grava sua própria jornada abaixo. Detalhes: docs/testing/e2e.md#local-smoke.

2. Escreva os passos

Copie .claude/skills/proof/steps.example.mjs para .e2e/proof/<slug>/steps.mjs e programe a jornada alterada: faça a coisa, mostre o resultado. Com o início padrão de chegada os passos começam no mundo que chegou (a marca arrived é 0:00); com --from-load eles começam logo após a navegação. mark('label') carimba um tempo de capítulo no sidecar para que o PR possa dizer "o painel abre em 0:07". Mantenha-o na jornada que a alteração afeta.

3. Grave

node .claude/skills/proof/record.mjs --url 'http://127.0.0.1:4710/w/proof?dev=1' \
  --steps .e2e/proof/<slug>/steps.mjs --out .e2e/proof/<slug>/desktop.mp4 --viewport desktop
# layout ou toque mudou? também:
node .claude/skills/proof/record.mjs --url '...' --steps .e2e/proof/<slug>/steps.mjs \
  --out .e2e/proof/<slug>/phone.mp4 --viewport phone
  • Navegadores: usa PLAYWRIGHT_BROWSERS_PATH, senão /opt/pw-browsers quando presente. Se o Chromium estiver faltando: PLAYWRIGHT_BROWSERS_PATH="$PWD/.e2e/browsers" pnpm --filter mars-campus-viewer exec playwright install chromium.
  • Playwright é resolvido da mesma forma que o harness de playtest (tools/playtest/lib/platform.mjs: um global playwright, senão @playwright/test de mars/viewer). Nenhuma GPU é necessária; WebGL executa no SwiftShader.
  • --max-seconds assume o padrão da política max_seconds. Saída 3 significa que a jornada passou dele: encurte-a.
  • Com ffmpeg: um mp4 com uma barra de progresso na parte inferior e um timecode hh:mm:ss / total (o timecode precisa de um ffmpeg compilado com drawtext; o timecode do sidecar indica se está presente). Sem ffmpeg: o .webm bruto; diga isso no PR (players ainda mostram sua própria barra de avanço).
  • Cada clipe recebe um sidecar <clip>.json: url, viewport, duração, start, startedAt, marcas (arrived entre elas), worldTime, erros de console, commit e flag de sujeira. Um Playwright sem page.screencast grava desde a criação da página mesmo sem --from-load; o sidecar indica isso em startFallback.
  • A página tem --arrival-seconds (padrão 120) para chegar antes da tomada começar; uma página que nunca mostra um mundo falha (saída 1) com uma dica para usar --from-load, uma imagem de onde travou (<clip>.open-failed.png) e um sidecar. Erros de console no sidecar são descobertas: explique ou corrija-os.

A execução leva bem menos do que o limite de 10 minutos em primeiro plano. Para vários clipes de uma só vez, execute-os em segundo plano (nohup setsid node ... > .e2e/proof/<slug>/rec.log 2>&1 &) e monitore o log.

4. Verifique você mesmo

for t in 1 4 8; do ffmpeg -loglevel error -y -ss $t -i .e2e/proof/<slug>/desktop.mp4 -frames:v 1 .e2e/proof/<slug>/t$t.png; done

Observe os quadros (Leia os PNGs). O estado alterado deve estar visível, o mundo deve ter carregado (não uma tela em branco ou canvas carregando), e nada no quadro deve ser privado. Se não mostrar a alteração, corrija os passos e grave uma nova tomada; não anexe um clipe que não prove a alegação.

5. Anexe ao PR (nunca faça commit)

Verifique cada payload de texto/JSON de saída com node tools/proof/publication.mjs <arquivos de payload> antes da publicação. Inspecione pixels de mídia, áudio, nomes de arquivo e metadados binários separadamente. Caminhos de dispositivo, nomes de host, IPs de dispositivo/privados, URLs locais e identificadores operacionais pertencem apenas a registros privados. Use caminhos relativos e rótulos de captura neutros. O uploader bloqueia vazamentos de texto detectados antes de enviar o lote; isso não pode certificar a privacidade da mídia.

node tools/proof/upload.mjs --pr $N --proof .e2e/journal/$ISSUE/proof.json .e2e/proof/$SLUG/desktop.mp4 .e2e/proof/$SLUG/phone.mp4
  • O alvo padrão é a própria pré-release do PR proofs-<n> (tag no branch padrão, criada no primeiro uso); uma release por PR mantém cada uma abaixo do limite de 1000 ativos do GitHub, que a antiga release compartilhada proofs atingiu. --release <tag> (ou SIM_PROOF_RELEASE) nomeia outra release. Os ativos são nomeados pr-<n>.<file>, e uma regravação recebe -2, -3, para que tomadas anteriores, incluindo as falhas, permaneçam linkáveis. SIM_PROOF_UPLOAD_URL (+ SIM_PROOF_UPLOAD_TOKEN) muda para outro endpoint, como um CDN.
  • Com --proof, links de clipe e imagem são escritos em proof.json media[], outros arquivos (logs, JSON) em files[], e proof.json é enviado por último. Cole seu link e os links do clipe na seção de Prova do PR. A skill journal cobre proof.json.
  • Preview inline. O GitHub serve ativos de release como downloads, então um link mp4 nunca reproduz no PR. Para cada vídeo, upload.mjs cria um pequeno GIF animado com ffmpeg (<clip>.preview.gif: 6 s em velocidade real a partir da marca arrived do clipe, ou a partir de 0 para uma tomada --from-load; no máximo 5 MB), faz upload dele ao lado do clipe, registra-o como media[].preview e imprime uma linha como [![desktop.mp4](…pr-412.desktop.preview.gif)](…pr-412.desktop.mp4). Cole essa linha: o preview reproduz no PR e clicar nele abre o clipe completo. Quando a alteração aparece mais tarde no clipe, escolha a janela com --preview-start <s> (e --preview-seconds <s>). O preview é um ponteiro, não a prova: o mp4 ininterrupto é. Sempre coloque um link explícito Vídeo ininterrupto em resolução total antes de cada preview, informando as dimensões codificadas reais e a duração. Preserve a resolução da captura e enquadre a ação para que o contato possa ser revisado. Não aumente a escala de uma captura ou use o GIF reduzido para alegar prova de movimento.
  • Saída 3: o upload está bloqueado (sem gh, não conectado, sem permissão ou sem rede, como em muitas sessões em nuvem). Informe ao usuário quais clipes estão aguardando e onde. Poste um comentário no PR com a duração de cada clipe, viewport, resumo do sidecar sanitizado (marcas, erros de console, commit), e um comando record.mjs relativo ao repositório e arquivo de passos, para que qualquer um possa regravá-lo. Marque a prova como "upload pendente" no corpo do PR. Nunca cole vídeo como base64, nunca faça commit dele e nunca o envie para outro branch.

gh pr pode não funcionar em sessões em nuvem; comente com gh api repos/$REPO/issues/$N/comments -F [email protected]/proof/$SLUG/comment.md.

O que escrever ao lado do clipe

Uma linha por clipe: qual jornada, qual template de mundo, viewport, duração, commit e o momento em que a alteração está visível ("0:07 os assentos destacam e a Alma senta"). Além de quaisquer erros de console e por que são aceitáveis.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Habilidades Relacionadas