O que frame-judge faz?
Você não pode avaliar seu próprio trabalho visual.
Você constrói e renderiza. Então um crítico separado julga o que realmente apareceu na tela contra o que o usuário realmente pediu. O crítico nunca vê seu código, seu raciocínio ou sua opinião sobre o resultado. Até que o trabalho passe, ou o limite de rodadas seja atingido, você não pode considerá-lo pronto, polido, suave ou bonito.
Por quê: o modelo que escreveu o código lê sua intenção na saída. Ele "vê" o ciclo de caminhada que pretendia escrever, não o que foi renderizado. Um crítico que só recebe pixels mais as palavras do usuário não pode fazer isso. Ele precisa olhar.
<skill> abaixo significa a pasta onde este arquivo está (no Claude Code: ${CLAUDE_SKILL_DIR}). Os scripts são Node 18+ puros, sem etapa de instalação. Eles mantêm estado em .frame-judge/ no seu diretório de trabalho.
O ciclo
| Passo | O quê | Quem |
|---|---|---|
| 0 | Travar a solicitação do usuário, verbatim | você |
| 0b | Perguntar "unsloppy?". Se sim, um batedor pesquisa os padrões de IA a evitar | você, o usuário, um batedor |
| 1 | Construir | você |
| 2 | Renderizar e capturar: screenshots, folhas de quadro, trilhas de movimento | scripts |
| 3 | Autoverificação mecânica: renderiza, nada em branco, sem erros de runtime | você |
| 4 | Empacotar um pacote de revisão sem código | script |
| 5 | Perguntar em qual modelo o crítico será executado, se a plataforma permitir (uma vez) | você, então o usuário |
| 6 | Crítico revisa o pacote | subagente novo |
| 7 | Portão valida a revisão e decide | script |
| 8 | Responder a cada achado must-fix, depois voltar ao passo 2 | você |
| 9 | Reportar o veredito do crítico, não sua opinião | você |
Limite padrão: 3 rodadas de crítico.
0. Travar o briefing
node <skill>/scripts/judge.mjs init --brief-file request.txt --kind frontend,motion
Use --brief "..." para texto inline, ou --brief-file - para ler da entrada padrão.
- Verbatim. Salve a mensagem do usuário como foi escrita: erros de digitação, maiúsculas, tudo. Nunca parafraseie, resuma ou "esclareça". O crítico julga com base nas palavras deles, não na sua leitura delas.
- Esclarecimentos posteriores do usuário entram com
judge.mjs brief --add "<as palavras exatas deles>". Suas próprias suposições nunca entram. - Imagens de referência que o usuário forneceu: adicione
--ref mock.png(repetível) para que o crítico possa comparar com elas. --kindseleciona as rubricas:frontendpara páginas e UI,motionpara qualquer animação,videopara clipes e edições. Deixe de fora para detecção automática a partir das capturas.--critic-modelse o usuário já nomeou um.
Isso cria .frame-judge/ (que se ignora no .git) com brief.md e ledger.json. O ledger sobrevive à compactação de contexto. Se perder o controle, execute judge.mjs status.
0b. Perguntar sobre o modo unslop (antes de construir)
Pergunte ao usuário uma vez, nestas palavras:
Quer que não seja sloppy? (experimental: pode diminuir a qualidade e gastará mais tokens)
No Claude Code, pergunte com AskUserQuestion, no mesmo prompt da pergunta sobre o modelo do crítico do passo 5. Em outras plataformas, pergunte no chat. Pule se o usuário já respondeu.
- Não: continue. Unslop está desligado por padrão.
- Sim:
- Execute
judge.mjs set unslop on, depoisjudge.mjs scout. Ele imprime uma mensagem para um batedor de slop: um novo subagente com pesquisa na web que descobre como as IAs geralmente erram esse tipo de solicitação. - Envie essa mensagem ao batedor e nada mais. As mesmas regras do crítico se aplicam: agente novo, sem fork, nada adicionado. Use o modelo do crítico se um estiver definido.
- Salve a resposta e execute
judge.mjs avoid --file <resposta>. Isso rejeita listas sem fontes reais.
- Execute
- Sem pesquisa na web disponível: avise o usuário que o unslop não pode ser executado aqui e continue sem ele.
A lista de evitação vai para .frame-judge/avoid.md e é incluída em todos os pacotes de revisão, para que o crítico também verifique o trabalho contra ela.
"Experimental" porque desviar dos padrões pode levar a escolhas estranhas na construção, e o batedor custa uma execução extra de agente com pesquisas na web.
1. Construir
Se o unslop estiver ativo, leia .frame-judge/avoid.md primeiro.
- Projete ao redor de cada padrão. Não apenas inverta: o objetivo é um trabalho que atenda ao briefing, não um trabalho que seja meramente diferente.
- Qualquer coisa que o usuário explicitamente pediu supera a lista.
Antes de construir, leia a seção de references/craft.md para seu meio, uma vez por sessão. Ela cobre o que os críticos mais sinalizam: espaçamento, tipo, marcas de template de IA, easing, ciclos de caminhada, ritmo de vídeo.
Para qualquer coisa animada, torne o tempo uma entrada explícita: uma linha do tempo que você pode percorrer, ou um hook window.frameJudgeSeek(ms). Isso torna a captura quadro-exata e transforma HTML em vídeo de graça.
2. Renderizar e capturar
Páginas e UI (precisa de Playwright; configuração em references/capture.md):
node <skill>/scripts/capture-page.mjs http://localhost:5173 --out .frame-judge/cap/page
Os padrões são desktop 1440×900, tablet 768×1024 e mobile 390×844, capturados tela por tela. Opções:
--actions states.jsonpara estados de hover, menu e erro--color-scheme dark--reduced-motion- arquivos locais funcionam também, além de URLs
Animação em uma página. Isso é quadro-exato (relógio falso com busca Web Animations) e codifica para MP4:
node <skill>/scripts/capture-page.mjs scene.html --out .frame-judge/cap/anim --animate 3000 --fps 30 --selector "#hero"
Qualquer vídeo, incluindo esse MP4:
node <skill>/scripts/video-frames.mjs .frame-judge/cap/anim/animation.mp4 --out .frame-judge/cap/anim-views --as motion
O que você obtém:
- Fatias de viewport em vez de uma imagem gigante de página inteira, que seria reduzida a uma pasta.
- Fotos de estado do seu arquivo de ações.
- Uma folha de contato com timestamp.
- Tiras de filme: quadros amostrados a 12 fps por padrão, mais tiras em taxa total em torno de qualquer salto ou parada repentina que o script detectar (
--motion-fps sourcedá todos os quadros em todos os lugares). Amostrado significa que uma falha de um quadro pode cair entre os tiles, e é por isso que a detecção de eventos existe. - Trilhas de movimento: o que deve ficar parado permanece nítido, e o que desliza borra.
- Números objetivos: duração, fps, segmentos pretos ou congelados, estouro horizontal, imagens quebradas.
Capture o que o usuário vai experimentar: cada viewport que ele usaria, os estados que importam, a animação inteira. O crítico não pode sinalizar o que você não mostrou a ele. Deixar de fora as partes feias é exatamente a trapaça que esta skill existe para impedir.
3. Autoverificação mecânica
Antes de gastar uma rodada de crítico, verifique e corrija as coisas binárias:
- renderiza
- sem quadros em branco ou pretos
- nada em
builder_onlyem cadacapture.json(erros de console, solicitações falhas) - a duração e o tamanho corretos
horizontal_overflow_pxebroken_imagessão zero
Essa é a lista completa. Você não pode decidir que parece bom e pular o crítico.
4. Empacotar
node <skill>/scripts/judge.mjs bundle .frame-judge/cap/page .frame-judge/cap/anim-views
Isso escreve .frame-judge/round-N/bundle/. Contém apenas arquivos visuais (png, jpg, webp, gif, mais vídeo se você passar --include-video) e estes arquivos de texto:
brief.md, com blocos de código removidos- as rubricas
CRITIC.md, as instruções do críticomanifest.json, com IDs de artefatos citáveisprior.json, a partir da rodada 2: achados em aberto sem suas alegações de "corrigido", para que o crítico verifique por si mesmo
O script não abrirá uma nova rodada enquanto achados must-fix estiverem sem resposta, ou após o limite de rodadas. Ele imprime a mensagem exata a ser enviada ao crítico.
Orçamento de imagens: mire em 20 imagens ou menos por rodada. O Claude aperta os limites por imagem além de 20 imagens em uma solicitação. Cada imagem custa cerca de ⌈w/28⌉×⌈h/28⌉ tokens; uma captura de 1440×900 custa cerca de 1,7k. Folhas de contato e tiras de filme empacotam 12 a 16 quadros em uma imagem, então use-as. --slices 3 reduz páginas longas.
5. Escolher o modelo do crítico (apenas onde a plataforma suportar)
Pergunte apenas se sua plataforma permite escolher o modelo de um subagente, e apenas uma vez, antes da rodada 1. Pule se o usuário já nomeou um. Salve a resposta com judge.mjs set critic-model <alias> e reutilize-a a cada rodada.
| Plataforma | Perguntar? | Como |
|---|---|---|
| Claude Code, apps Claude | Sim | AskUserQuestion, no mesmo prompt da pergunta sobre unslop: Sonnet (equilibrado, recomendado), Opus (olho mais afiado, mais cota), Haiku (mais barato, perde problemas sutis), Igual a mim |
| App Codex, Codex CLI | Sim | Pergunte no chat, depois passe a escolha ao criar o crítico |
| Antigravity | Não | Não há escolha de modelo por criação. O crítico executa na configuração do arquivo do agente; avise o usuário disso. |
| Qualquer outra | Não | A menos que suporte claramente modelos por subagente. Use o padrão e avise o usuário qual modelo revisou o trabalho. |
Ao perguntar, seja direto sobre a troca. Um crítico mais fraco é mais barato, mas alucina mais defeitos e perde os sutis. O portão pega evidências falsas; não pode pegar mau gosto.
Sintaxe exata por plataforma: references/platforms.md.
6. Executar o crítico
Use um crítico novo a cada rodada, para que ele não tenha memória além de prior.json e nenhum interesse em suas chamadas anteriores. Envie a mensagem que o bundle imprimiu, e nada mais:
Você é o crítico de quadros. Seu pacote é
<caminho abs>. Leia<caminho abs>/CRITIC.mde siga-o exatamente. Não abra nada fora dessa pasta. Responda apenas com o JSON da revisão.
- Não adicione nada. Nenhum resumo do que você construiu, nenhum "foco no cabeçalho", nenhum "eu corrigi as pernas". Sua opinião é a única entrada que o crítico nunca deve receber. Se o usuário quer que algo seja verificado, já está no briefing, nas palavras dele.
- Sem forks. Nunca execute o crítico como um fork ou qualquer outra coisa que herde contexto. Ele veria toda a sua conversa, código incluído.
- Prefira o agente instalado. Use
frame-criticse existir, porque é limitado a ler arquivos. Seu nome éframe-judge:frame-criticquando a skill veio como um plugin do Claude Code, eframe_criticno Codex. Caso contrário, use um subagente de uso geral com a mesma mensagem. - Claude Code: execute a sandbox se puder. Se o CLI
claudeestiver no PATH, executenode <skill>/scripts/critic-sandbox.mjsem vez de criar um subagente. Ele executa o crítico como um processo headless separado em uma cópia privada do pacote. Esse processo tem apenas a ferramenta Read, mais um hook que bloqueia qualquer leitura fora da cópia, e o script faz o gate da revisão ele mesmo (pule o passo 7). Este é o único caminho onde a cegueira de código é aplicada em vez de solicitada. - Em todos os outros lugares: use o subagente na sessão, e a cegueira de código depende das instruções do crítico. No Claude Code, a auditoria de transcrição no passo 7 ainda pega um crítico que espionou. No Codex, Antigravity e Cursor, nada verifica isso, então diga isso no seu relatório.
Salve a resposta, intocada, em .frame-judge/round-N/review.json.
7. Portão
node <skill>/scripts/judge.mjs gate --review .frame-judge/round-N/review.json --reviewer subagent --transcript auto
No Claude Code, --transcript auto encontra a transcrição do subagente crítico, para que o portão conte as imagens que ele realmente abriu (não as que ele alega) e anule a revisão se ele tocou em algo fora do pacote. Em outros lugares, deixe a flag de fora; a cobertura é então auto-relatada, e o relatório diz isso. (critic-sandbox.mjs passa sua própria transcrição automaticamente.)
O portão decide, não o humor do crítico e nem você. Ele:
- Rejeita achados que citam IDs de artefatos que não existem ou que o crítico nunca abriu, achados sem evidência, citações do briefing que não estão no briefing, e valores ruins de severidade ou confiança.
- Verifica a cobertura: uma aprovação só conta se o crítico abriu cada imagem, verificado a partir de sua transcrição onde uma existir, caso contrário a partir de sua própria lista
opened. - Verifica o isolamento: com uma transcrição, qualquer leitura fora do pacote anula a revisão (
RERUN_CRITIC). - Classifica o resto:
- must-fix: bloqueador ou grande, confiança 0,6 ou superior
- verify: bloqueador ou grande abaixo de 0,6. Recapture mais de perto; não corrija às cegas.
- polish: menor
- ignored: minúcias
- Verifica se
CRITIC.mde as rubricas não foram editados, para que ninguém tenha amolecido o juiz. - Atualiza o ledger e imprime uma decisão:
| Decisão | Significado | Você |
|---|---|---|
PASS | Nenhum must-fix restante, nada do briefing faltando | Relate (passo 9) |
SELF_PASS | Mesmo, mas de um fallback de auto-revisão | Relate, e diga que não foi independente |
REVISE | Itens must-fix existem | Passo 8, depois uma nova rodada |
RETHINK | Crítico diz que a abordagem está errada na raiz | Avise o usuário antes de reconstruir |
STOP_MAX_ROUNDS | Limite atingido, ainda falhando | Relate o que está aberto, pergunte se deve continuar |
STOP_PLATEAU | Esta rodada não resolveu nada | Pare de circular. Relate, pergunte |
RERUN_CRITIC | Revisão inutilizável (sem JSON, evidência principalmente falsa), uma aprovação de um crítico que pulou imagens, ou um crítico que leu fora de seu pacote | Execute um crítico novo no mesmo pacote |
STOP_CRITIC_UNRELIABLE | Segunda revisão inutilizável | Sugira um modelo de crítico mais forte ou um fallback |
8. Revisar
Trabalhe através dos itens must-fix por ID, bloqueadores primeiro. Responda a cada um antes da próxima rodada:
node <skill>/scripts/judge.mjs respond R1-F2 fixed "pé de contato plantado por 4 quadros"
node <skill>/scripts/judge.mjs respond R1-F4 disputed "calhas são iguais em ambos os lados" --evidence crop.png
node <skill>/scripts/judge.mjs respond R1-F6 wont-fix "usuário pediu este gradiente" --quote "gradiente roxo para azul"
disputedprecisa de evidência visual, como um recorte ou quadros extras. Isso vai para o próximo pacote e o próximo crítico decide sobre isso. "O CSS diz 16px" não é evidência; pixels são.wont-fixprecisa de uma citação verbatim do briefing que a correção violaria.- Corrija causas, não capturas. Nunca mude a captura para evitar um achado: sem cortar o rodapé quebrado, descartar o viewport mobile, ou cortar o clipe.
- Itens verify e
requestsdo crítico: capture esse ponto mais de perto (uma ação comclip, uma janela--motionmais densa) para que o próximo crítico possa confirmar ou descartá-los. - Não regrida o que o crítico listou sob
keep. - ...
[truncado para tradução]