Verificar Finite
Finite tiene dos superficies, y la mayoría de las funciones necesitan ambas. Los agentes editan diseños a través de herramientas MCP en /mcp (las seis herramientas doc6; call maneja las herramientas clásicas en /mcp/classic). Las personas observan en el navegador: la lista de diseños en / y el lienzo en /design/?id=<designId>. Una prueba maneja el lado del agente con call y verifica el lado de la persona en la página, o al revés para los comentarios.
El arnés es e2e/headless.mjs. .agents/skills/finite-headless/SKILL.md es su referencia de comandos (selectores que alcanzan shadow roots, iframes en sandbox, --agent, Python). Léelo una vez antes de tu primer manejo. Este skill añade aislamiento, un doctor, una carpeta de evidencia, ejecuciones de antes y después, y el mapa de funcionalidades.
Cada comando de abajo se ejecuta desde la raíz del repositorio:
V=.agents/skills/verify-finite/scripts/verify.sh
Las variables de shell no sobreviven entre llamadas de herramientas. Repite V=... y RUN=... al inicio de cada llamada.
Pasos
- Elige las funcionalidades. Encuentra las funcionalidades que tu cambio toca en la tabla bajo "Qué funcionalidades toca un cambio" en
features/README.md. - Lanza una ejecución de tu código. Para una corrección de errores, lanza también una segunda ejecución del código antes de la corrección (ver "Antes y después").
- Revisa cada ejecución hasta que solo imprima líneas
ok. - Maneja cada punto de entrada en cada archivo de funcionalidad elegido, guardando evidencia a medida que avanzas.
- Limpia cada ejecución que lanzaste, incluyendo las que fallaron.
- Informa en el formato bajo "Informe".
Has terminado cuando cada punto de entrada de cada funcionalidad elegida está probado, omitido con una razón, o fallido con su evidencia, y $V list muestra que no hay nada en ejecución.
Lanzar
$V launch # construye el servidor, finite.wasm y la aplicación web, luego los inicia
$V launch --no-build # reutiliza las últimas construcciones; se rechaza si el código cambió desde que se hicieron
$V launch --width 390 --height 844 # una página del tamaño de un teléfono (el valor predeterminado es 1440 × 900)
$V launch --at main # una ejecución de otro commit, en un repositorio temporal (ver "Antes y después")
Imprime RUN=<run>. Guarda ese id: todos los demás comandos lo requieren. Una construcción en frío toma unos 2 minutos, y una construcción sin nada que hacer unos segundos. Establece el tiempo de espera de Bash a 600000. --no-build solo ahorra los pocos segundos de una construcción sin nada que hacer, así que si tienes dudas, no lo uses.
El lanzamiento está listo cuando imprime Finite at http://127.0.0.1:<port>. El arnés espera a /api/health y carga la lista de diseños antes de imprimir esa línea. La carpeta de datos comienza vacía, y no hay datos semilla, migraciones ni inicio de sesión. Una persona publica comentarios como "Invitado", y los agentes publican como "Agente" a menos que pases --agent <name>.
Cada ejecución es una sesión separada (verify-<run>) con su propio puerto libre, carpeta de datos temporal y perfil de Chrome, por lo que las ejecuciones pueden ejecutarse en paralelo. Nunca manejes un Finite que no hayas lanzado. vp run dev sirve los diseños reales del usuario desde crates/server/data, y la aplicación de escritorio también sirve los datos del propio usuario. El doctor falla en una sesión que se conectó al servidor de otra persona.
Una ejecución se detiene sola después de 30 minutos de inactividad. Después de eso, doctor falla: limpia y lanza de nuevo.
Revisar
$V doctor $RUN
Solo lee el estado, y cada línea dice ok o FAIL. Verifica cinco cosas:
- La sesión está viva y posee una carpeta privada
finite-headless-data-*. /api/healthrespondeokcon la versión enpackage.json.- La construcción en ejecución coincide con el código. Compara un hash de las entradas de construcción (
crates/,apps/web/, el arnés, los archivos de bloqueo, incluidos archivos no rastreados) con el hash del código del que se construyó la ejecución. Las ediciones a documentos, skills o pruebas no cuentan. - Un Chrome, Chromium o Edge está disponible para
get_screenshot. - La página responde.
Luego imprime la consola de la página desde la última llamada. Ejecútalo primero, después de cualquier sorpresa, y antes de capturar la prueba final. En un FAIL, limpia y lanza de nuevo en lugar de continuar manejando. Después de cambiar el código, la verificación de construcción falla por diseño: limpia y lanza de nuevo.
Manejar
$V h $RUN <comando> ... ejecuta cualquier comando de e2e/headless.mjs contra esta ejecución. Los comandos que usarás más a menudo:
$V h $RUN call create_design '{"name":"Verificar"}' # lado del agente: imprime designId "<id>"
$V h $RUN call create_artboard @input.json # JSON en línea, @archivo, o - para stdin
$V h $RUN design <designId> # lado de la persona: abrir el lienzo, esperar mesas de trabajo
$V h $RUN snapshot --selector main # árbol de accesibilidad, lo que ve una persona
$V h $RUN click 'button[title="Comentario (C)"]'
$V h $RUN click '[data-artboard] >>> h1' --shift # Shift-clic
$V h $RUN upload 'input[type=file]' card.html # seleccionar un archivo, como lo haría el selector del sistema operativo
$V h $RUN api GET /api/designs/<designId> # el diseño almacenado, incluidos los comentarios
Usa estos identificadores estables. Son los nombres y títulos accesibles de la aplicación:
| Dónde | Identificador |
|---|---|
| Lista de diseños | encabezado Diseños, botón Nuevo diseño, cuadro de búsqueda Buscar diseños por nombre, un enlace por tarjeta de diseño |
| Barra superior del lienzo | enlace ← Diseños, button[title="Variables CSS que usa cada mesa de trabajo, en cada modo"] (Tokens), button[title="Cada comentario, abierto y resuelto"] (Comentarios, con el recuento de abiertos en su nombre), Importar, Exportar`, un chip por agente presente |
| Herramientas del lienzo | barra de herramientas Herramientas: button[title="Puntero (V)"], button[title="Comentario (C)"]; teclas v, c, Shift+1 (ajustar), =/- (zoom) |
| Caja de comentarios | cuadro de texto Añadir un comentario, button[title="Cambiar tu nombre"], [data-selection-count], botón Enviar, pines nombrados Comentario: <primer mensaje> |
| Hilo de comentarios | [role=dialog] nombrado Hilo de comentarios: botones Eliminar, Resolver/Reabrir, Cerrar, Editar en tu mensaje más reciente, cuadro de texto Responder |
| Paneles | aside[aria-label=Comentarios] con pestañas Abiertos N / Resueltos N; section[aria-label=Tokens] con form[aria-label="Añadir un token"]; nav[aria-label=Páginas]; [role=menu][aria-label=Exportar]; aside[aria-label=Importar] con un status |
| Contenido de mesa de trabajo | [data-artboard="<artboardId>"] >>> <css>; los atributos data-name de los agentes sobreviven en el DOM |
Prefiere estos a las coordenadas. Las coordenadas son solo para mesas de trabajo en sandbox (script), a las que los selectores no pueden acceder. click toma CSS, no texto, por lo que los botones sin título se seleccionan por posición: [role=dialog] button --nth 1, con query listando el orden.
La entrada de texto tiene dos trampas. type añade a lo que contiene un campo, y key Meta+a no selecciona texto a través de CDP. Para reemplazar el texto de un campo, ejecuta $V h $RUN eval "document.execCommand('selectAll')" con el campo enfocado, luego type.
Llamadas en segundo plano
wait_for_comments se bloquea hasta que una persona comenta, por lo que debe ejecutarse mientras manejas la página:
$V bg $RUN 02-esperar call wait_for_comments '{"designId":"<D>","timeoutSeconds":30}'
# ...maneja la página...
$V await $RUN 02-esperar 30 # se bloquea hasta que la llamada regresa, luego imprime .verify/<run>/02-esperar.txt
Lee el resultado con await, nunca leyendo el archivo directamente: el archivo solo aparece una vez que la llamada ha regresado. La llamada en segundo plano sobrevive entre llamadas de herramientas.
Evidencia
Todo va a .verify/<run>/ en el repositorio. .gitignore lo cubre, y la limpieza lo conserva.
$V save $RUN 01-comentario-publicado snapshot --selector main # el comando, su salida y código de salida
$V shot $RUN 02-lienzo # .verify/<run>/02-lienzo.png
$V shot $RUN 03-panel --selector 'aside[aria-label=Comentarios]'
save toma cualquier comando headless, incluido call, y escribe <nombre>.txt que contiene el comando, su salida y [salida N]. Numera los nombres para que la ejecución se lea en orden. Lee cada PNG con la herramienta Read antes de confiar en él. Las imágenes de get_screenshot y cualquier captura de pantalla de página tomada sin una ruta terminan en la carpeta temporal de la sesión. La limpieza las copia en .verify/<run>/tool-images/, y el registro del servidor en .verify/<run>/server.log. Los archivos que crees como entrada de prueba, como un archivo para importar, también van en .verify/<run>/.
Una prueba cumple con estos estándares:
- La ruta real. La acción de una persona pasa por la página (clic, tecla, escritura, carga), y la acción de un agente pasa por una
callde MCP. Usa la API REST solo para leer el estado almacenado. Escribir a través de ella omite la interfaz de usuario que estás probando. - Acción y resultado. Guarda el paso que hace la acción y el estado después de ella, no solo una captura de pantalla final.
- Efectos secundarios. Muestra el cambio almacenado además de mostrado.
api GET /api/designs/<id>devuelvemeta,nodesycommentstal como el servidor los guardó, y la herramienta de lectura de un agente (get_comments,get_tokens,get_tree_summary) muestra lo que verá el siguiente agente. - Ambas direcciones para funciones en vivo. La edición de un agente debe aparecer en la página sin una recarga. El comentario de una persona debe llegar a un agente en espera.
- Sin simulacros. La ejecución utiliza el servidor real, el navegador real y sesiones MCP reales.
- Una consola limpia. Termina con
$V save $RUN <n>-consola console. Una excepción o solicitud fallida allí estropea la prueba.
Antes y después
Una corrección de errores se demuestra cuando el mismo recorrido falla en el código antiguo y pasa en el nuevo. Ejecuta ambos en paralelo:
$V launch --at main # RUN=<antes>: un repositorio temporal de main, instalado y construido (aproximadamente un minuto)
$V launch # RUN=<después>: este repositorio
Maneja los mismos pasos en ambos, con los mismos nombres de evidencia. La ejecución anterior debe mostrar el error. Si no lo hace, tu recorrido no alcanza el error, y la ejecución posterior no prueba nada sobre la corrección. --at toma cualquier referencia de git: una rama, una etiqueta, un commit, o HEAD cuando tu corrección aún no está confirmada. El doctor nombra la referencia y el commit desde los que se construyó una ejecución. La limpieza elimina el repositorio temporal y conserva su evidencia.
Limpiar
$V cleanup $RUN
Detiene el daemon de esta ejecución. El daemon detiene el servidor que generó (SIGTERM, para que los diseños se guarden primero) y el Chrome que lanzó, luego elimina sus datos temporales y su perfil. Luego, la limpieza copia el registro del servidor y las imágenes de herramientas en la carpeta de evidencia, elimina el repositorio temporal de una ejecución --at, y enumera lo que conservó. No toca nada más, por lo que otras sesiones, vp run dev y la aplicación de escritorio siguen ejecutándose.
$V list imprime las ejecuciones de este repositorio que aún se están ejecutando o dejaron un repositorio atrás. Limpia cada una con $V cleanup <run>, nunca con pkill. $V prune [días] elimina la evidencia de ejecuciones limpiadas que tengan más de esa cantidad de días (7 por defecto). Nunca limpie una ejecución cuya evidencia estés a punto de informar.
Informe
Termina con un bloque por funcionalidad que manejaste:
<ID de funcionalidad> vía <punto de entrada>: probado | omitido | fallado
evidencia: .verify/<run>/<archivos>
por qué (omitido o fallado): <el comando que ejecutaste y lo que faltaba o estaba mal>
Luego proporciona los ids de las ejecuciones, la salida del doctor para cada una, y, para una corrección, la evidencia de la ejecución anterior que muestra el error. Informa un punto de entrada omitido como omitido, incluso cuando otro punto de entrada probó el mismo comportamiento.
Ayudante
scripts/verify.sh acepta estos comandos: launch, doctor, h, save, shot, bg, await, cleanup, list y prune. Ejecútalo sin argumentos para ver sus argumentos. Es una capa delgada sobre e2e/headless.mjs: la sesión es verify-<run>, y la evidencia va a .verify/<run>/.