¿Qué hace frame-judge?
No te toca calificar tu propio trabajo visual.
Lo construyes y lo renderizas. Luego un crítico independiente juzga lo que realmente salió en pantalla contra lo que el usuario pidió realmente. El crítico nunca ve tu código, tu razonamiento ni tu opinión del resultado. Hasta que pase el trabajo, o se alcance el límite de rondas, no lo des por terminado, pulido, suave o hermoso.
Por qué: el modelo que escribió el código lee su intención en la salida. "Ve" el ciclo de marcha que quiso escribir, no el que se renderiza. Un crítico que solo recibe píxeles más las palabras del usuario no puede hacer eso. Tiene que mirar.
<skill> a continuación significa la carpeta donde está este archivo (en Claude Code: ${CLAUDE_SKILL_DIR}). Los scripts son Node 18+ simples sin paso de instalación. Mantienen el estado en .frame-judge/ bajo tu directorio de trabajo.
El ciclo
| Paso | Qué | Quién |
|---|---|---|
| 0 | Bloquear la solicitud del usuario, textual | tú |
| 0b | Preguntar "¿unsloppy?". Si es sí, un explorador investiga los valores predeterminados de IA que evitar | tú, el usuario, un explorador |
| 1 | Construir | tú |
| 2 | Renderizar y capturar: capturas de pantalla, hojas de fotogramas, estelas de movimiento | scripts |
| 3 | Autocomprobación mecánica: se renderiza, nada en blanco, sin errores de ejecución | tú |
| 4 | Empaquetar un paquete de revisión sin código | script |
| 5 | Preguntar en qué modelo se ejecutará el crítico, si la plataforma lo permite (una vez) | tú, luego el usuario |
| 6 | El crítico revisa el paquete | subagente fresco |
| 7 | La puerta valida la revisión y decide | script |
| 8 | Responder a cada hallazgo de corrección obligatoria, luego volver al paso 2 | tú |
| 9 | Reportar el veredicto del crítico, no tu opinión | tú |
Límite predeterminado: 3 rondas de críticas.
0. Bloquear la solicitud
node <skill>/scripts/judge.mjs init --brief-file request.txt --kind frontend,motion
Usa --brief "..." para texto en línea, o --brief-file - para leer desde stdin.
- Textual. Guarda el mensaje del usuario tal como está escrito: errores tipográficos, mayúsculas, todo. Nunca parafrasees, resumas o "aclarezcas". El crítico juzga contra sus palabras, no contra tu lectura de ellas.
- Aclaraciones posteriores del usuario van con
judge.mjs brief --add "<sus palabras exactas>". Tus propias suposiciones nunca entran. - Imágenes de referencia que el usuario te dio: añade
--ref mock.png(repetible) para que el crítico pueda comparar con ellas. --kindelige las rúbricas:frontendpara páginas e IU,motionpara cualquier animación,videopara clips y ediciones. Omítelo para que se detecte automáticamente desde las capturas.--critic-modelsi el usuario ya nombró uno.
Esto crea .frame-judge/ (se ignora a sí mismo en git) con brief.md y ledger.json. El libro mayor sobrevive a la compactación del contexto. Si pierdes el rastro, ejecuta judge.mjs status.
0b. Preguntar sobre el modo unslop (antes de construir)
Pregunta al usuario una vez, en estas palabras:
¿Lo quieres sin chapuzas? (experimental: puede disminuir la calidad y gastará más tokens)
En Claude Code, pregunta con AskUserQuestion, en el mismo prompt que la pregunta del modelo crítico del paso 5. En otros lugares, pregunta en el chat. Omítelo si el usuario ya lo dijo.
- No: continúa. Unslop está desactivado por defecto.
- Sí:
- Ejecuta
judge.mjs set unslop on, luegojudge.mjs scout. Imprime un mensaje para un explorador de chapuzas: un subagente fresco con búsqueda web que descubre cómo los LLM suelen equivocarse en este tipo de solicitud. - Envía ese mensaje al explorador y nada más. Las mismas reglas que para el crítico: agente fresco, sin bifurcación, sin añadidos. Usa el modelo del crítico si está configurado.
- Guarda su respuesta, luego ejecuta
judge.mjs avoid --file <respuesta>. Eso rechaza listas sin fuentes reales.
- Ejecuta
- No hay búsqueda web disponible: dile al usuario que unslop no puede ejecutarse aquí y continúa sin él.
La lista de evitar termina en .frame-judge/avoid.md, y se incluye en cada paquete de revisión, para que el crítico también verifique el trabajo contra ella.
"Experimental" porque alejarse de los valores predeterminados puede llevar a una construcción hacia elecciones extrañas, y el explorador cuesta una ejecución adicional de agente con búsquedas web.
1. Construir
Si unslop está activado, lee primero .frame-judge/avoid.md.
- Diseña evitando cada patrón. No lo inviertas simplemente: el objetivo es un trabajo que se ajuste a la solicitud, no un trabajo que sea meramente diferente.
- Cualquier cosa que el usuario haya pedido explícitamente prevalece sobre la lista.
Antes de construir, lee la sección de references/craft.md para tu medio, una vez por sesión. Cubre lo que los críticos señalan más: espaciado, tipo, marcas de plantilla de IA, easing, ciclos de marcha, ritmo de video.
Para cualquier cosa animada, haz que el tiempo sea una entrada explícita: una línea de tiempo que puedas buscar, o un hook window.frameJudgeSeek(ms). Eso hace que la captura sea precisa al fotograma, y convierte HTML en video gratis.
2. Renderizar y capturar
Páginas e IU (necesita Playwright; configuración en references/capture.md):
node <skill>/scripts/capture-page.mjs http://localhost:5173 --out .frame-judge/cap/page
Los valores predeterminados son escritorio 1440×900, tableta 768×1024 y móvil 390×844, capturados pantalla por pantalla. Opciones:
--actions states.jsonpara estados hover, menú y error--color-scheme dark--reduced-motion- los archivos locales funcionan también como URLs
Animación en una página. Esto es preciso al fotograma (reloj falso más búsqueda de Web Animations) y codifica a MP4:
node <skill>/scripts/capture-page.mjs scene.html --out .frame-judge/cap/anim --animate 3000 --fps 30 --selector "#hero"
Cualquier video, incluyendo ese MP4:
node <skill>/scripts/video-frames.mjs .frame-judge/cap/anim/animation.mp4 --out .frame-judge/cap/anim-views --as motion
Lo que obtienes:
- Rebanadas de viewport en lugar de una imagen gigante de página completa, que se reduciría a papilla.
- Tomas de estado de tu archivo de acciones.
- Una hoja de contactos con marca de tiempo.
- Tiras de película: fotogramas muestreados a 12 fps por defecto, más tiras a velocidad completa alrededor de cualquier salto repentino o parada que el script detecte (
--motion-fps sourceda cada fotograma en todas partes). Muestreado significa que un fallo de un fotograma puede caer entre losetas, por lo que existe la detección de eventos. - Estelas de movimiento: lo que debería permanecer quieto se mantiene nítido, y lo que se desliza se mancha.
- Números objetivos: duración, fps, segmentos negros o congelados, desbordamiento horizontal, imágenes rotas.
Captura lo que el usuario experimentará: cada viewport que usaría, los estados que importan, toda la animación. El crítico no puede señalar lo que no le mostraste. Omitir las partes feas es exactamente el engaño que este skill existe para detener.
3. Autocomprobación mecánica
Antes de gastar una ronda de críticas, verifica y corrige lo básico:
- se renderiza
- sin fotogramas en blanco o negros
- nada en
builder_onlyen cadacapture.json(errores de consola, solicitudes fallidas) - la duración y el tamaño correctos
horizontal_overflow_pxybroken_imagesson cero
Esa es toda la lista. No te corresponde decidir que se ve bien y saltarte el crítico.
4. Empaquetar
node <skill>/scripts/judge.mjs bundle .frame-judge/cap/page .frame-judge/cap/anim-views
Esto escribe .frame-judge/round-N/bundle/. Contiene solo archivos visuales (png, jpg, webp, gif, más video si pasas --include-video) y estos archivos de texto:
brief.md, con los bloques de código eliminados- las rúbricas
CRITIC.md, las instrucciones del críticomanifest.json, con IDs de artefactos citablesprior.json, desde la ronda 2 en adelante: hallazgos abiertos sin tus afirmaciones de "corregido", para que el crítico verifique por sí mismo
El script no abrirá una nueva ronda mientras haya hallazgos de corrección obligatoria sin responder, o más allá del límite de rondas. Imprime el mensaje exacto para enviar al crítico.
Presupuesto de imágenes: apunta a 20 imágenes o menos por ronda. Claude endurece los límites por imagen después de 20 imágenes en una sola solicitud. Cada imagen cuesta aproximadamente ⌈w/28⌉×⌈h/28⌉ tokens; una toma de 1440×900 es alrededor de 1.7k. Las hojas de contactos y las tiras de película empaquetan de 12 a 16 fotogramas en una imagen, así que apóyate en ellas. --slices 3 recorta páginas largas.
5. Elegir el modelo del crítico (solo donde la plataforma lo soporte)
Pregunta solo si tu plataforma te permite elegir el modelo de un subagente, y solo una vez, antes de la ronda 1. Omítelo si el usuario ya nombró uno. Guarda la respuesta con judge.mjs set critic-model <alias> y reutilízala cada ronda.
| Plataforma | ¿Preguntar? | Cómo |
|---|---|---|
| Claude Code, apps Claude | Sí | AskUserQuestion, en el mismo prompt que la pregunta de unslop: Sonnet (equilibrado, recomendado), Opus (ojo más agudo, más cuota), Haiku (más barato, pasa por alto problemas sutiles), Igual que yo |
| Codex app, Codex CLI | Sí | Pregunta en el chat, luego pasa la elección cuando generes al crítico |
| Antigravity | No | No hay opción de modelo por generación. El crítico se ejecuta en la configuración de su archivo de agente; díselo al usuario. |
| Cualquier otra cosa | No | A menos que soporte claramente modelos por subagente. Usa el predeterminado y dile al usuario qué modelo revisó el trabajo. |
Cuando preguntes, sé directo sobre el compromiso. Un crítico más débil es más barato, pero alucina más defectos y pasa por alto los sutiles. La puerta atrapa la evidencia falsa; no puede atrapar el mal gusto.
Sintaxis exacta por plataforma: references/platforms.md.
6. Ejecutar el crítico
Usa un crítico fresco cada ronda, para que no tenga memoria más allá de prior.json y ningún interés en sus llamadas anteriores. Envíale el mensaje que bundle imprimió, y nada más:
Eres el crítico de fotogramas. Tu paquete es
<ruta abs>. Lee<ruta abs>/CRITIC.mdy síguelo exactamente. No abras nada fuera de esa carpeta. Responde solo con el JSON de revisión.
- No añadas nada. Sin resumen de lo que construiste, sin "céntrate en el encabezado", sin "arreglé las piernas". Tu opinión es la única entrada que el crítico nunca debe recibir. Si el usuario quiere que se revise algo, ya está en la solicitud, en sus palabras.
- Sin bifurcaciones. Nunca ejecutes al crítico como una bifurcación o cualquier otra cosa que herede contexto. Vería toda tu conversación, código incluido.
- Prefiere el agente instalado. Usa
frame-criticsi existe, porque está limitado a leer archivos. Su nombre esframe-judge:frame-criticcuando el skill vino como un plugin de Claude Code, yframe_criticen Codex. De lo contrario, usa un subagente de propósito general con el mismo mensaje. - Claude Code: ejecuta el sandbox si puedes. Si el CLI de
claudeestá en PATH, ejecutanode <skill>/scripts/critic-sandbox.mjsen lugar de generar un subagente. Ejecuta al crítico como un proceso sin cabeza separado en una copia privada del paquete. Ese proceso tiene solo la herramienta Read, más un hook que bloquea cualquier lectura fuera de la copia, y el script controla la revisión en sí mismo (omitir el paso 7). Este es el único camino donde la ceguera al código se aplica en lugar de solicitarse. - En cualquier otro lugar: usa el subagente en sesión, y la ceguera al código descansa en las instrucciones del crítico. En Claude Code, la auditoría de transcripción en el paso 7 aún atrapa a un crítico que haya mirado. En Codex, Antigravity y Cursor, nada lo verifica, así que dilo en tu informe.
Guarda la respuesta, sin modificaciones, en .frame-judge/round-N/review.json.
7. Puerta
node <skill>/scripts/judge.mjs gate --review .frame-judge/round-N/review.json --reviewer subagent --transcript auto
En Claude Code, --transcript auto encuentra la transcripción del subagente crítico, para que la puerta cuente las imágenes que realmente abrió (no las que afirma) e invalide la revisión si tocó algo fuera del paquete. En otros lugares, omite la bandera; la cobertura entonces es autoinformada, y el informe lo dice. (critic-sandbox.mjs pasa su propia transcripción automáticamente.)
La puerta decide, no el estado de ánimo del crítico y no tú. Ella:
- Rechaza hallazgos que citan IDs de artefactos que no existen o que el crítico nunca abrió, hallazgos sin evidencia, citas de la solicitud que no están en la solicitud, y valores incorrectos de gravedad o confianza.
- Verifica la cobertura: una aprobación solo cuenta si el crítico abrió cada imagen, verificado desde su transcripción donde exista, de lo contrario desde su propia lista
opened. - Verifica el aislamiento: con una transcripción, cualquier lectura fuera del paquete invalida la revisión (
RERUN_CRITIC). - Ordena el resto:
- corrección obligatoria: bloqueante o mayor, confianza 0.6 o superior
- verificar: bloqueante o mayor por debajo de 0.6. Recapturar más de cerca; no corregir a ciegas.
- pulir: menor
- ignorado: nimiedades
- Verifica que
CRITIC.mdy las rúbricas no fueron editadas, para que nadie haya suavizado al juez. - Actualiza el libro mayor e imprime una decisión:
| Decisión | Significado | Tú |
|---|---|---|
PASS | No queda corrección obligatoria, nada de la solicitud falta | Reportar (paso 9) |
SELF_PASS | Lo mismo, pero de un fallback de autoevaluación | Reportar, y decir que no fue independiente |
REVISE | Existen elementos de corrección obligatoria | Paso 8, luego una nueva ronda |
RETHINK | El crítico dice que el enfoque es incorrecto desde la raíz | Decírselo al usuario antes de reconstruir |
STOP_MAX_ROUNDS | Límite alcanzado, aún fallando | Reportar lo que está abierto, preguntar si continuar |
STOP_PLATEAU | Esta ronda no resolvió nada | Dejar de dar vueltas. Reportar, preguntar |
RERUN_CRITIC | Revisión inutilizable (sin JSON, evidencia mayormente falsa), una aprobación de un crítico que se saltó imágenes, o un crítico que leyó fuera de su paquete | Ejecutar un crítico fresco en el mismo paquete |
STOP_CRITIC_UNRELIABLE | Segunda revisión inutilizable | Sugerir un modelo de crítico más fuerte o un fallback |
8. Revisar
Trabaja a través de los elementos de corrección obligatoria por ID, bloqueantes primero. Responde a cada uno antes de la siguiente ronda:
node <skill>/scripts/judge.mjs respond R1-F2 fixed "contact foot planted for 4 frames"
node <skill>/scripts/judge.mjs respond R1-F4 disputed "gutters are equal on both sides" --evidence crop.png
node <skill>/scripts/judge.mjs respond R1-F6 wont-fix "user asked for this gradient" --quote "purple to blue gradient"
disputednecesita evidencia visual, como un recorte o fotogramas adicionales. Va al siguiente paquete y el próximo crítico decide sobre ello. "El CSS dice 16px" no es evidencia; los píxeles lo son.wont-fixnecesita una cita textual de la solicitud que la corrección violaría.- Corrige causas, no capturas. Nunca cambies la captura para esquivar un hallazgo: nada de recortar el pie de página roto, eliminar el viewport móvil o recortar el clip.
- Elementos de verificar y solicitudes del crítico: captura ese punto más de cerca (una acción con
clip, una ventana--motionmás densa) para que el próximo crítico pueda confirmarlos o eliminarlos. - No retrocedas en lo que el crítico enumeró en
keep.