Prueba visual en video para PRs
Graba un video corto y reproducible en navegador que demuestre una corrección de UI, adjúntalo a la descripción del PR y verifica el cuerpo en vivo. No modifiques el código de la aplicación para la grabación a menos que el usuario lo solicite explícitamente.
Ejecución de referencia: PR #723 (scroll largo expandido de /automations).
Prerrequisitos
ghautenticado con acceso push al repositorio destino- Bun + dependencias del repositorio instaladas en el árbol de trabajo (
bun install) - Google Chrome (o Chromium) en el equipo
ffmpegen PATH (para convertir webm a H.264 MP4)- Playwright en un directorio aislado bajo
/tmp(no lo agregues al repositorio):
mkdir -p /tmp/<ejecución>/playwright
cd /tmp/<ejecución>/playwright
npm i playwright
npx playwright install ffmpeg
Proceso
1. Aislar con un worktree de git
Mantén limpio el checkout principal.
cd "$(git rev-parse --show-toplevel)"
git fetch origin main
git worktree add -b <rama> .worktrees/<slug> origin/main # o conéctate a la rama de la corrección
cd .worktrees/<slug>
Trabaja solo dentro de ese worktree para servidores y grabación.
2. Inspeccionar fixtures y UI primero
Antes de inventar datos:
- Lee la página bajo prueba (etiquetas, controles de expansión, contenedores de scroll).
- Revisa los fixtures / factories de prueba existentes para la misma funcionalidad.
- Prefiere sembrar datos a través de la API HTTP pública. Recurre a una inserción SQLite única en un
NAKAMA_CONFIG_DIRaislado solo cuando ninguna API pueda crear la fila necesaria (por ejemplo, una ejecución de automatización completada con unoutputenorme).
3. Sembrar contenido alto determinista
Para pruebas de scroll / desbordamiento, el fixture debe ser más alto que el panel.
- Coloca un marcador superior único cerca del inicio:
SCROLL_PROOF_MARKER_TOP - Coloca un marcador inferior único al final:
SCROLL_PROOF_MARKER_BOTTOM - Usa suficiente texto para que
scrollHeight - clientHeightsea grande (miles de px)
Ejemplo de forma para el output de una ejecución:
# SCROLL_PROOF_MARKER_TOP — salida larga de ejecución de automatización
## Sección 1
...
## Sección 80
...
# SCROLL_PROOF_MARKER_BOTTOM — fin del contenido alto
Nunca siembres datos en los datos reales ~/.nakama del operador. Usa siempre un NAKAMA_CONFIG_DIR nuevo bajo /tmp/<ejecución>/.
4. Iniciar servidores locales aislados
Elige puertos libres. No tomes la pila por defecto si algo ya está escuchando en 4310 / 3000 / 3003.
RUN=/tmp/<ejecución>
API_PORT=4330
WEB_PORT=3014
mkdir -p "$RUN/nakama-data" "$RUN/logs"
# Mantener procesos vivos después de que el shell termine (plain nohup ... & no funciona aquí)
setsid nohup env NAKAMA_CONFIG_DIR="$RUN/nakama-data" NAKAMA_PORT=$API_PORT \
bun run apps/server/src/index.ts \
>"$RUN/logs/server.log" 2>&1 < /dev/null &
setsid nohup env VITE_API_URL="http://127.0.0.1:${API_PORT}" \
bun run --cwd apps/web dev -- --host 127.0.0.1 --port $WEB_PORT \
>"$RUN/logs/web.log" 2>&1 < /dev/null &
Espera hasta que curl -sf http://127.0.0.1:$API_PORT/health tenga éxito y el origen web responda. Configuración inicial: POST /v1/auth/setup, luego crea proveedor / perfil / automatización (o reutiliza fixtures) con Cookie + X-CSRF-Token + X-Org-Id.
5. Grabar con Playwright (H.264 MP4)
Prepara el grabador bajo /tmp/<ejecución>/ solamente. Nunca lo confirmes en el repositorio.
const browser = await chromium.launch({
channel: "chrome", // si Chrome está instalado
headless: false,
args: ["--disable-gpu"],
});
const context = await browser.newContext({
viewport: { width: 1440, height: 900 },
recordVideo: { dir: rawDir, size: { width: 1440, height: 900 } },
});
Reglas:
- Conduce la ruta real de la UI bajo prueba (localizadores por rol/texto).
- Haz visible el movimiento — rueda del ratón o scroll escalonado, no solo un salto invisible único.
- Afirma que el scroll se movió (delta de
scrollTop) y que el marcador inferior se vuelve alcanzable. - Captura
page.video()?.path()antes decontext.close(). - Convierte:
ffmpeg -y -i in.webm -c:v libx264 -pix_fmt yuv420p out.mp4 - Escribe
results.json+ capturas de pantalla antes/después bajoartifacts/e2e-<id>/.
Solo WebM no es suficiente para la reproducción en GitHub. Entrega H.264 + yuv420p.
6. Validar el video antes de afirmar nada
ffprobe -v error -show_entries stream=codec_name,width,height \
-show_entries format=duration -of json out.mp4
# Extraer fotogramas tempranos / tardíos y examinarlos
ffmpeg -y -ss 00:00:02 -i out.mp4 -vframes 1 frame-early.png
ffmpeg -y -ss 00:00:08 -i out.mp4 -vframes 1 frame-late.png
Pasa solo si:
- el codec es
h264 - la duración es suficiente para ver la interacción
- el fotograma temprano muestra el estado inicial (por ejemplo, marcador superior / panel expandido)
- el fotograma tardío muestra el progreso del scroll (marcador inferior o secciones avanzadas)
results.jsonreporta un delta real descrollTop(o métrica de prueba equivalente)
7. Subir a user-attachments de GitHub
Aunque no está documentado, la autenticación por token funciona para imágenes/video cuando tienes acceso push:
TOKEN=$(gh auth token)
REPO_ID=$(gh api repos/<propietario>/<repositorio> --jq .id)
MP4=artifacts/e2e-<id>/<nombre>.mp4
UPLOAD_JSON=$(curl -sS -X POST \
"https://uploads.github.com/user-attachments/assets?name=$(basename "$MP4")&repository_id=${REPO_ID}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: video/mp4" \
-H "Accept: application/vnd.github+json" \
--data-binary @"${MP4}")
VIDEO_URL=$(printf '%s' "$UPLOAD_JSON" | bun -e 'console.log(JSON.parse(await Bun.stdin.text()).url)')
echo "$VIDEO_URL" # https://github.com/user-attachments/assets/<uuid>
Guarda la URL. Confirma que una solicitud HEAD/GET al recurso devuelve un tipo de contenido de video.
8. Actualizar la descripción del PR
Agrega una sección corta Browser proof con los pasos mostrados y la URL https://github.com/user-attachments/assets/... en su propia línea (GitHub incrusta el reproductor). Prefiere escribir el cuerpo a través de un archivo:
gh api repos/<propietario>/<repositorio>/pulls/<n> --method PATCH --input body.json
# o: gh pr edit <n> --body-file /tmp/pr-body.md
Sigue .agents/skills/adhd-pr-description/SKILL.md para el resto del cuerpo.
9. Verificar el cuerpo en vivo del PR
gh api repos/<propietario>/<repositorio>/pulls/<n> --jq .body | rg 'user-attachments/assets/<uuid>|Browser proof'
No reportes éxito hasta que esta verificación pase.
Ejemplo: scroll de ejecución expandida de automations
- Worktree en la rama de la corrección (o rama solo de documentación para esta habilidad).
- API aislada
4330+ web3014,NAKAMA_CONFIG_DIRnuevo. POST /v1/auth/setup→ proveedor → crear automatización Long output digester.- Insertar/completar una ejecución cuyo
outputsea el markdown largo conSCROLL_PROOF_MARKER_TOP/SCROLL_PROOF_MARKER_BOTTOM. - Playwright: abrir
/automations→ seleccionar la automatización → Expand run → hacer scroll con la rueda en el panel de detalle hasta que el marcador inferior esté a la vista. - Convertir a H.264 MP4, inspeccionar fotogramas, subir, parchear el cuerpo del PR, verificar.
Limpieza
- Detén los listeners de API/web aislados en los puertos que elegiste.
- Deja
/tmp/<ejecución>/y el perfilartifacts/e2e-<id>/como evidencia local (no confirmes videos ni scripts del grabador). - Elimina el worktree cuando la rama esté fusionada o abandonada:
git worktree remove .worktrees/<slug>
Reglas de honestidad
- Nunca afirmes tener una prueba visual sin revisar los fotogramas o
ffprobe+ capturas de pantalla. - Nunca pegues una URL de
user-attachmentsque no hayas subido y recuperado del cuerpo en vivo del PR. - Nunca trates una prueba unitaria verde como sustituto del video cuando la solicitud fue una prueba visual.
- Si el scroll no se movió, los marcadores están mal o el MP4 está vacío/corrupto — di que falló. No suavices el mensaje.
- No modifiques el código de la aplicación “para hacer el video más fácil” a menos que el usuario haya solicitado una corrección del producto.
- No toques el directorio de configuración Nakama real del operador.