Communitygithub.com

genekogan/proof

Graba el clip de prueba que necesita un cambio T2+ — un video sin cortes, a velocidad real, de Playwright, del recorrido del usuario modificado en un mundo local con mente falsa, con barra de progreso y código de tiempo incrustados, para escritorio y (cuando el diseño cambió) teléfono — luego lo adjunta a la solicitud de extracción sin comprometer el video en el repositorio. Úsalo cuando un cambio es de nivel T2 o superior, cuando una PR o issue solicita un clip, cuando la habilidad de finalización llega a su paso de prueba, o al reproducir un error en cámara para triaje.

¿Qué es proof?

Esta habilidad para agentes de IA permite generar evidencia visual de cambios en aplicaciones web mediante la grabación de videos de prueba sin cortes, a velocidad real, usando Playwright. Está diseñada específicamente para cambios de nivel T2+ según la política de prueba definida en el proyecto. La herramienta inicia un mundo local con cerebro falso, ejecuta los pasos del recorrido del usuario modificado, y graba un video MP4 con barra de progreso y código de tiempo incrustados. Soporta grabaciones de escritorio y teléfono cuando el diseño cambia, y adjunta automáticamente los clips a la solicitud de extracción a través de GitHub Releases, generando también miniaturas GIF animadas para vista previa en la PR. Es útil para desarrolladores y evaluadores que necesitan demostrar cambios visuales de manera clara y reproducible, asegurando que nunca se comprometan archivos de video en el repositorio.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Vista previa

Del README del skill

desktop.mp4

Documentación

prueba — un clip sin cortes del recorrido modificado

Un revisor debería poder ver lo que un usuario vería, a velocidad normal, de principio a fin. El clip es la evidencia; una captura de pantalla, una hoja de contactos o una grabación acelerada no lo es.

Fuente de verdad para lo que necesita un nivel: docs/process/PROOF-POLICY.yml (T0 nada; T1 pruebas enfocadas + verificación de tipos; T2 agrega un clip del recorrido modificado, escritorio, más teléfono si el diseño cambió, en un mundo con mente falsa; T3/T4 agregan más). Obtén el nivel del diff actual con node tools/proof/tier.mjs --base origin/main.

Reglas

  • Sin cortes y a velocidad real. Un contexto de navegador, una toma. Nunca recortes, empalmes, aceleres o disminuyas la velocidad. Si el recorrido es más largo que el max_seconds de la política, graba un recorrido más corto que aún muestre el cambio, no uno más rápido.
  • La toma comienza en la llegada (el valor predeterminado): la grabación comienza una vez que el mundo está en pantalla y la tarjeta de llegada ha desaparecido, por lo que el clip se abre en el mundo, no en la carga. A partir de ahí es una toma sin cortes, a velocidad real del recorrido, que es lo que pide la política. Cuando la carga o la llegada es en sí misma el tema del cambio (la tarjeta de llegada, una pantalla de carga, el primer pintado), o el recorrido no está en una página de mundo (la lista de mundos, inicio de sesión), pasa --from-load: la toma entonces comienza en la creación de la página. El start del archivo sidecar (arrival o load) indica cuál se usó, y upload.mjs --proof lo copia en proof.json media[].
  • De día. En una URL de mundo local, el grabador establece el mundo al mediodía con su reloj pausado antes de abrir la página (--time-of-day 12, el valor predeterminado; la ruta god env como el propietario del desarrollo). Los mundos de desarrollo arrancan a las 06:00 y ejecutan un día de mundo por hora real, por lo que sin esto, un mundo activo durante 40 minutos está de noche. Establecerlo es una entrada world en el historial god del mundo, y el reloj permanece pausado después. Pasa otra hora, o --time-of-day keep cuando el reloj, la luz o el historial god es el tema del cambio. El worldTime del sidecar indica lo que se estableció.
  • Entrada real. Conduce con page.mouse, page.keyboard, page.touchscreen o clics de localizador, como lo haría un usuario. No llames a partes internas de la aplicación desde page.evaluate para hacer que las cosas sucedan en cámara.
  • Mentes falsas, datos aislados. Solo mundos locales, BRAIN_MODE=fake, un directorio de datos nuevo. Nunca grabes contra un mundo de producción a menos que el mantenedor lo solicite, y nunca con un perfil de navegador personal con sesión iniciada.
  • Nunca comprometas el video (o fotogramas) en el repositorio. Trabaja bajo .e2e/ (ignorado por git).
  • El clip debe mostrar el cambio. Míralo (o al menos extrae fotogramas, a continuación) antes de adjuntarlo.

1. Inicia un mundo con mente falsa

Necesita un cliente web compilado (pnpm install --frozen-lockfile && pnpm build; omítelo si apps/web/dist/index.html existe y está actualizado para tu cambio). En un clon nuevo, la verificación previa a la compilación falla hasta que los recursos web estén en su lugar: node tools/assets/pull.mjs --only 'apps/web/**' (unos pocos archivos) es suficiente para ello.

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); el servidor sigue ejecutándose en segundo plano

La página de inicio (lista de mundos, Nuevo mundo) es servida por el lanzador de mundos, no por un solo mundo. Para un recorrido que comienza allí, ejecuta un lanzador (sus mundos siempre obtienen mentes falsas) y crea un mundo para la lista a través de su 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
# graba contra http://127.0.0.1:4720/ ; detén el lanzador por su pid (detiene sus mundos)

Elige la plantilla que contiene la superficie modificada (worlds/templates/: hello-hamlet es pequeño y rápido; eden-2026, mars-two y otros son más grandes). Usa un puerto libre; e2e/config.mjs enumera puertos reservados para otros arneses. Detén el servidor con kill <pid> cuando termines.

Prueba rápida de que la aplicación funciona: la prueba de humo local

Antes de grabar, o como la prueba completa de un cambio T1 que toca el servidor o la aplicación web, ejecuta la prueba de humo local. Inicia su propio lanzador aislado (mentes falsas, inicio de sesión de desarrollo, datos bajo el directorio de ejecución) en un puerto libre, abre la lista de mundos y un mundo, verifica que se dibuja una persona sin errores de consola y sin solicitudes fallidas, y detiene lo que inició:

node e2e/local-smoke.mjs --port 9950 --clip      # --build primero en un clon nuevo; omite --port para cualquier puerto libre
# → .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" en summary.json es la evidencia; su clip es una toma sin cortes, a velocidad real del recorrido de humo. No es un clip de tu cambio: un cambio T2 aún graba su propio recorrido a continuación. Detalles: docs/testing/e2e.md#local-smoke.

2. Escribe los pasos

Copia .claude/skills/proof/steps.example.mjs a .e2e/proof/<slug>/steps.mjs y programa el recorrido modificado: haz la acción, muestra el resultado. Con el inicio de llegada predeterminado, los pasos comienzan en el mundo ya llegado (la marca arrived es 0:00); con --from-load comienzan justo después de la navegación. mark('label') sella un tiempo de capítulo en el sidecar para que la PR pueda decir "el panel se abre a las 0:07". Limítalo al recorrido que afecta el cambio.

3. Graba

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
# ¿El diseño o el tacto también cambiaron? también:
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, de lo contrario /opt/pw-browsers cuando está presente. Si falta Chromium: PLAYWRIGHT_BROWSERS_PATH="$PWD/.e2e/browsers" pnpm --filter mars-campus-viewer exec playwright install chromium.
  • Playwright se resuelve de la misma manera que el arnés de prueba de juego (tools/playtest/lib/platform.mjs: un playwright global, o @playwright/test desde mars/viewer). No se necesita GPU; WebGL se ejecuta en SwiftShader.
  • --max-seconds por defecto es el max_seconds de la política. El código de salida 3 significa que el recorrido lo superó: acórtalo.
  • Con ffmpeg: un mp4 con una barra de progreso en la parte inferior y un código de tiempo hh:mm:ss / total (el código de tiempo necesita un ffmpeg compilado con drawtext; el timecode del sidecar indica si está presente). Sin ffmpeg: el .webm sin procesar; dilo en la PR (los reproductores aún muestran su propia barra de desplazamiento).
  • Cada clip obtiene un sidecar <clip>.json: url, viewport, duración, start, startedAt, marcas (arrived entre ellas), worldTime, errores de consola, commit y bandera de suciedad. Un Playwright sin page.screencast graba desde la creación de la página incluso sin --from-load; el sidecar lo indica en startFallback.
  • La página tiene --arrival-seconds (120 por defecto) para llegar antes de que comience la toma; una página que nunca muestra un mundo falla (código de salida 1) con una sugerencia para usar --from-load, una imagen fija de dónde se atascó (<clip>.open-failed.png) y un sidecar. Los errores de consola en el sidecar son hallazgos: explícalos o corrígelos.

La ejecución toma mucho menos del límite de 10 minutos en primer plano. Para varios clips de una sola vez, ejecútalos en segundo plano (nohup setsid node ... > .e2e/proof/<slug>/rec.log 2>&1 &) y consulta el registro.

4. Compruébalo tú mismo

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

Mira los fotogramas (Lee los PNG). El estado modificado debe ser visible, el mundo debe haberse cargado (no un lienzo en blanco o de carga), y nada en el fotograma debe ser privado. Si no muestra el cambio, corrige los pasos y graba una nueva toma; no adjuntes un clip que no pruebe la afirmación.

5. Adjúntalo a la PR (nunca lo comprometas)

Verifica cada carga útil de texto/JSON saliente con node tools/proof/publication.mjs <payload files> antes de la publicación. Inspecciona los píxeles de los medios, el audio, los nombres de archivo y los metadatos binarios por separado. Las rutas de dispositivos, nombres de host, IPs de dispositivos/privadas, URLs locales e identificadores operativos pertenecen solo a registros privados. Usa rutas relativas y etiquetas de captura neutrales. El cargador bloquea las fugas de texto detectadas antes de cargar el lote; esto no puede certificar la privacidad de los medios.

node tools/proof/upload.mjs --pr $N --proof .e2e/journal/$ISSUE/proof.json .e2e/proof/$SLUG/desktop.mp4 .e2e/proof/$SLUG/phone.mp4
  • El destino predeterminado es el lanzamiento previo de la propia PR proofs-<n> (etiqueta en la rama predeterminada, creada en el primer uso); un lanzamiento por PR mantiene cada uno por debajo del límite de 1000 activos de GitHub, que el antiguo lanzamiento compartido proofs alcanzó. --release <tag> (o SIM_PROOF_RELEASE) nombra otro lanzamiento. Los activos se nombran pr-<n>.<file>, y una retoma obtiene -2, -3, por lo que las tomas anteriores, incluidas las fallidas, permanecen enlazables. SIM_PROOF_UPLOAD_URL (+ SIM_PROOF_UPLOAD_TOKEN) cambia a otro punto final, como un CDN.
  • Con --proof, los enlaces de clips e imágenes se escriben en proof.json media[], otros archivos (registros, JSON) en files[], y proof.json se carga al final. Pega su enlace y los enlaces de los clips en la sección de Prueba de la PR. La habilidad journal cubre proof.json.
  • Vista previa en línea. GitHub sirve los activos de lanzamiento como descargas, por lo que un enlace mp4 nunca se reproduce en la PR. Para cada video, upload.mjs crea un pequeño GIF animado con ffmpeg (<clip>.preview.gif: 6 s a velocidad real desde la marca arrived del clip, o desde 0 para una toma --from-load; como máximo 5 MB), lo carga junto al clip, lo registra como media[].preview e imprime una línea como [![desktop.mp4](…pr-412.desktop.preview.gif)](…pr-412.desktop.mp4). Pega esa línea: la vista previa se reproduce en la PR y al hacer clic se abre el clip completo. Cuando el cambio se muestra más tarde en el clip, elige la ventana con --preview-start <s> (y --preview-seconds <s>). La vista previa es un puntero, no la prueba: el mp4 sin cortes lo es. Siempre coloca un enlace explícito de Video sin cortes de resolución completa antes de cada vista previa, indicando las dimensiones codificadas reales y la duración. Preserva la resolución de captura y enmarca la acción para que el contacto pueda ser revisado. No aumentes la escala de una captura ni uses el GIF reducido para afirmar la prueba de movimiento.
  • Salida 3: la carga está bloqueada (no hay gh, no has iniciado sesión, no tienes permiso o no hay red, como en muchas sesiones en la nube). Informa al usuario qué clips están esperando y dónde. Publica un comentario en la PR con la duración de cada clip, viewport, resumen del sidecar sanitizado (marcas, errores de consola, commit) y un comando record.mjs relativo al repositorio y archivo de pasos, para que cualquiera pueda volver a grabarlo. Marca la prueba como "pendiente de carga" en el cuerpo de la PR. Nunca pegues video como base64, nunca lo comprometas y nunca lo subas a otra rama.

gh pr puede no funcionar en sesiones en la nube; comenta con gh api repos/$REPO/issues/$N/comments -F [email protected]/proof/$SLUG/comment.md.

Qué escribir junto al clip

Una línea por clip: qué recorrido, qué plantilla de mundo, viewport, duración, commit y el momento en que el cambio es visible ("0:07 los asientos se resaltan y el Alma se sienta"). Además, cualquier error de consola y por qué son aceptables.

Individual skills in this repo

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

Skills relacionados