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_secondsde 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. Elstartdel archivo sidecar (arrivaloload) indica cuál se usó, yupload.mjs --prooflo copia en proof.jsonmedia[]. - 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 entradaworlden el historial god del mundo, y el reloj permanece pausado después. Pasa otra hora, o--time-of-day keepcuando el reloj, la luz o el historial god es el tema del cambio. ElworldTimedel sidecar indica lo que se estableció. - Entrada real. Conduce con
page.mouse,page.keyboard,page.touchscreeno clics de localizador, como lo haría un usuario. No llames a partes internas de la aplicación desdepage.evaluatepara 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-browserscuando 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: unplaywrightglobal, o@playwright/testdesdemars/viewer). No se necesita GPU; WebGL se ejecuta en SwiftShader. --max-secondspor defecto es elmax_secondsde 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; eltimecodedel sidecar indica si está presente). Sin ffmpeg: el.webmsin 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 (arrivedentre ellas),worldTime, errores de consola, commit y bandera de suciedad. Un Playwright sinpage.screencastgraba desde la creación de la página incluso sin--from-load; el sidecar lo indica enstartFallback. - 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 compartidoproofsalcanzó.--release <tag>(oSIM_PROOF_RELEASE) nombra otro lanzamiento. Los activos se nombranpr-<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.jsonmedia[], otros archivos (registros, JSON) enfiles[], 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 habilidadjournalcubre 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.mjscrea un pequeño GIF animado con ffmpeg (<clip>.preview.gif: 6 s a velocidad real desde la marcaarriveddel clip, o desde 0 para una toma--from-load; como máximo 5 MB), lo carga junto al clip, lo registra comomedia[].previewe imprime una línea como[](…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 comandorecord.mjsrelativo 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.
