From f6d049127d0b2d0c8a1975f36a2fb43d02eb3c48 Mon Sep 17 00:00:00 2001 From: Enmanuel Date: Sun, 8 Mar 2026 13:57:29 +0000 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20a=C3=B1adir=20comando=20/create-iss?= =?UTF-8?q?ue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuevo comando slash que automatiza la creacion de issues en dev/issues/. Sigue estrictamente la regla create_issue.md, evalua el tamaño del issue para desglosar en sub-issues con feature flags si es necesario, y registra todo en el README automaticamente. Co-Authored-By: Claude Opus 4.6 --- .claude/commands/create-issue.md | 154 +++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 .claude/commands/create-issue.md diff --git a/.claude/commands/create-issue.md b/.claude/commands/create-issue.md new file mode 100644 index 0000000..5b390d5 --- /dev/null +++ b/.claude/commands/create-issue.md @@ -0,0 +1,154 @@ +# Command: create issue + +Crea un issue nuevo en `dev/issues/` siguiendo **estrictamente** la regla `create_issue.md`. Si el issue es grande, lo desglosa automaticamente en sub-issues con feature flags. + +## Inputs + +Se necesitan los datos del issue. Si no se proporcionan, preguntar. + +- `titulo`: titulo corto y descriptivo (ej: "Hot reload de configuracion") +- `descripcion`: objetivo/descripcion de lo que se quiere lograr +- `dependencias` (opcional): issues de los que depende (ej: "Requiere issue 0010") + +## Flujo obligatorio + +### 1. Determinar el numero del issue + +Buscar el numero mas alto en `dev/issues/` y `dev/issues/completed/` y usar el siguiente. +Formato: 4 digitos con ceros a la izquierda (`0023`, `0024`, etc.). + +```bash +ls dev/issues/ dev/issues/completed/ | grep -oP '^\d{4}' | sort -rn | head -1 +``` + +### 2. Generar slug + +A partir del titulo: +- Lowercase +- Palabras separadas por guiones +- Conciso (2-4 palabras) +- Ejemplo: "Hot reload de configuracion" → `hot-reload` + +### 3. Evaluar tamano del issue + +Antes de escribir el issue, analizar el alcance y determinar si cabe en **una sola rama corta (horas)**. + +**Criterios para desglosar en sub-issues:** +- Toca mas de 2 capas del patron (pkg/ + shell/ + agents/ + tools/) +- Requiere mas de ~3 fases de implementacion +- El usuario lo indica explicitamente +- La descripcion implica multiples componentes independientes + +**Si es un issue simple** (cabe en una rama): +- Crear un solo archivo `dev/issues/-.md` +- Seguir directo al paso 4 + +**Si es un issue grande** (necesita desglose): +- Crear el issue principal `dev/issues/-.md` con seccion `## Desglose multi-issue` +- Crear cada sub-issue como `dev/issues/-.md` (ej: `0023a-types`, `0023b-client`) +- Cada sub-issue es autocontenido: debe compilar, pasar tests, no romper master +- Agregar feature flag en la descripcion del issue principal +- Registrar todos los sub-issues en `dev/issues/README.md` + +### 4. Crear el issue desde el template + +Copiar `.claude/templates/issue.md` y rellenar **todas** las secciones: + +- **Objetivo**: 1-3 frases claras +- **Contexto**: que existe, que falta, dependencias +- **Arquitectura**: archivos afectados (marcar `NEW` los nuevos). Explicar que va en `pkg/` (puro) vs `shell/` (impuro) +- **Tareas**: fases con tareas numeradas (`1.1`, `1.2`, etc.). Cada tarea concreta y verificable. Siempre incluir fase de tests y fase de cleanup/docs +- **Ejemplo de uso**: flujo concreto +- **Decisiones de diseno**: justificaciones clave +- **Prerequisitos**: que debe existir antes +- **Riesgos**: problemas potenciales y mitigacion + +### 5. Para issues multi-issue — contenido adicional + +En el issue principal, agregar despues de las tareas: + +```markdown +## Desglose multi-issue + +Este issue se implementa en sub-issues independientes, cada uno en su propia rama. + +| Sub-issue | Rama | Alcance | Estado | +|-----------|------|---------|--------| +| a- | issue/a- | | pendiente | +| b- | issue/b- | | pendiente | +| ... + +### Feature flag + +Nombre: `` +Se activa en el ultimo sub-issue cuando todo esta integrado. + +### Progreso por tarea + +- [ ] **1.1** — sub-issue a +- [ ] **1.2** — sub-issue a +- [ ] **2.1** — sub-issue b +... +``` + +Cada sub-issue individual debe tener su propio archivo con: +- Objetivo especifico del sub-issue +- Tareas que le corresponden del issue principal +- Nota de que es parte de un issue mayor + +### 6. Registrar feature flag (solo multi-issue) + +Actualizar `dev/feature_flags.json`: + +```json +{ + "": { + "enabled": false, + "issue": "", + "description": "", + "added": "" + } +} +``` + +### 7. Actualizar el indice + +En `dev/issues/README.md`, agregar filas al final de la tabla. + +**Issue simple:** +```markdown +| | | [-.md](-.md) | pendiente | +``` + +**Issue multi-issue (agregar fila por cada sub-issue tambien):** +```markdown +| | | [-.md](-.md) | pendiente | +| a | (parte a) | [a-.md](a-.md) | pendiente | +| b | (parte b) | [b-.md](b-.md) | pendiente | +``` + +### 8. Verificar + +- [ ] Archivo(s) creado(s) en `dev/issues/` +- [ ] Todas las secciones del template rellenadas +- [ ] Fila(s) agregada(s) en `dev/issues/README.md` +- [ ] Numero de issue es consecutivo (sin saltos ni duplicados) +- [ ] Si es multi-issue: sub-issues creados, feature flag en `dev/feature_flags.json`, seccion de desglose en issue principal + +### 9. Reportar al usuario + +Mostrar resumen: +- Numero y titulo del issue +- Si fue desglosado: listar sub-issues con su alcance +- Recordar: usar `/fix-issue ` (o `/fix-issue a`, `b`, etc.) para implementar + +## Reglas criticas + +- Seguir `create_issue.md` de forma estricta +- **Patron pure core / impure shell**: toda feature debe explicar que va en `pkg/` vs `shell/` +- **Tareas atomicas**: cada tarea debe ser implementable de forma independiente +- **Numeracion continua**: nunca reusar numeros +- **Estado**: issues nuevos siempre `pendiente` +- **Issues grandes**: desglosar en sub-issues con feature flags, nunca dejar una rama abierta por dias +- **Feature flag != WIP**: un flag protege codigo terminado y testeado, no codigo a medias +- **No commitear**: este comando solo crea archivos en `dev/issues/`. No hace commits ni crea ramas From 4ab4efd245db692351be53b6fec6f324e48a402c Mon Sep 17 00:00:00 2001 From: Enmanuel Date: Sun, 8 Mar 2026 13:57:36 +0000 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20crear=20issue=200022=20=E2=80=94=20?= =?UTF-8?q?tests=20E2E=20con=20Playwright?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue multi-issue desglosado en 3 sub-issues: - 0022a: infraestructura base (Docker, Playwright config, CI) - 0022b: auth fixtures y helpers (login, E2EE, utilidades Matrix) - 0022c: tests de agentes + documentacion Incluye actualizacion del README con issue 21 (completado) y todos los sub-issues de 0022 registrados como pendientes. Co-Authored-By: Claude Opus 4.6 --- dev/issues/0022-e2e-tests-playwright.md | 147 +++++++++++++++++++++++ dev/issues/0022a-e2e-infra.md | 119 +++++++++++++++++++ dev/issues/0022b-e2e-auth-helpers.md | 125 ++++++++++++++++++++ dev/issues/0022c-e2e-agent-tests.md | 148 ++++++++++++++++++++++++ dev/issues/README.md | 5 + 5 files changed, 544 insertions(+) create mode 100644 dev/issues/0022-e2e-tests-playwright.md create mode 100644 dev/issues/0022a-e2e-infra.md create mode 100644 dev/issues/0022b-e2e-auth-helpers.md create mode 100644 dev/issues/0022c-e2e-agent-tests.md diff --git a/dev/issues/0022-e2e-tests-playwright.md b/dev/issues/0022-e2e-tests-playwright.md new file mode 100644 index 0000000..6f2bbd4 --- /dev/null +++ b/dev/issues/0022-e2e-tests-playwright.md @@ -0,0 +1,147 @@ +# 0022 — Tests E2E con Playwright contra Element Web + +## Objetivo + +Crear una suite de tests E2E que use Playwright para controlar Element Web (headless) y verificar que los agentes Matrix responden correctamente. Los tests simulan un usuario real: login, verificacion E2EE, enviar mensajes a los bots y validar respuestas. + +## Contexto + +- Los agentes corren en una VPS sin entorno grafico — Playwright debe operar en modo headless +- Element Web se levanta como servicio estatico (o Docker) apuntando al homeserver `matrix-af2f3d.organic-machine.com` +- El login requiere usuario, contraseña y recovery key (cross-signing) — todo desde `.env` +- Actualmente no hay tests que verifiquen el flujo completo usuario→bot→respuesta por Matrix +- Playwright descarga sus propios browsers y necesita deps del sistema (`npx playwright install-deps`) + +## Arquitectura + +``` +e2e/ NEW — proyecto Node.js independiente +├── package.json NEW — playwright + dependencias +├── playwright.config.ts NEW — config headless, timeouts, base URL +├── .env.example NEW — template de variables E2E +├── fixtures/ +│ ├── element-auth.ts NEW — login + verificacion cross-signing +│ └── matrix-room.ts NEW — helpers para navegar a rooms, enviar mensajes, esperar respuestas +├── tests/ +│ ├── login.spec.ts NEW — test basico: login + E2EE verification funciona +│ ├── assistant-bot.spec.ts NEW — tests del assistant-bot +│ └── asistente-2.spec.ts NEW — tests del asistente-2 (con tools) +└── scripts/ + └── setup-element.sh NEW — descargar/levantar Element Web local +``` + +``` +dev-scripts/ +└── e2e/ + ├── run.sh NEW — levantar Element + ejecutar tests + teardown + └── install.sh NEW — instalar Node, Playwright, deps del sistema +``` + +### Patron pure core / impure shell + +Este issue es 100% infraestructura de testing, no modifica codigo Go. +- `pkg/` — sin cambios +- `shell/` — sin cambios +- `agents/` — sin cambios +- `e2e/` — proyecto Node.js aislado, no forma parte del modulo Go + +## Desglose multi-issue + +Este issue se implementa en 3 sub-issues independientes, cada uno en su propia rama. + +| Sub-issue | Rama | Alcance | Estado | +|-----------|------|---------|--------| +| 0022a-e2e-infra | issue/0022a-e2e-infra | Proyecto Node.js, Playwright config, scripts install/setup Element | pendiente | +| 0022b-e2e-auth-helpers | issue/0022b-e2e-auth-helpers | Fixtures de login E2EE, storageState, helpers de rooms | pendiente | +| 0022c-e2e-agent-tests | issue/0022c-e2e-agent-tests | Specs de agentes, run.sh, verificacion, docs | pendiente | + +### Nota sobre feature flags + +Este issue no requiere feature flag porque es infraestructura de testing externa (proyecto Node.js aislado). No hay codigo de produccion que activar/desactivar — cada sub-issue produce artefactos funcionales e independientes que no afectan al runtime Go. + +### Progreso por tarea + +**Fase 1: Infraestructura base** — sub-issue 0022a +- [ ] **1.1** Crear `e2e/` con `package.json` (playwright, @playwright/test, dotenv) +- [ ] **1.2** Crear `playwright.config.ts` configurado para headless, timeouts 30s, screenshot on failure +- [ ] **1.3** Crear `e2e/.env.example` con variables necesarias +- [ ] **1.4** Crear `e2e/scripts/setup-element.sh` — descarga Element Web, config.json, servidor estatico +- [ ] **1.5** Crear `dev-scripts/e2e/install.sh` — instala Node.js, npm ci, Playwright chromium + deps + +**Fase 2: Fixtures de autenticacion** — sub-issue 0022b +- [ ] **2.1** Crear fixture `element-auth.ts` — flujo login completo + cross-signing +- [ ] **2.2** Implementar `storageState` para cachear sesion autenticada +- [ ] **2.3** Crear `global-setup.ts` que ejecute login una vez + +**Fase 3: Helpers de interaccion** — sub-issue 0022b +- [ ] **3.1** Crear fixture `matrix-room.ts` con helpers (goToRoom, sendMessage, waitForBotReply, getLastMessage) +- [ ] **3.2** Manejar mensajes encriptados — validar que no aparece "Unable to decrypt" + +**Fase 4: Tests de los agentes** — sub-issue 0022c +- [ ] **4.1** `login.spec.ts` — smoke test: login, rooms visibles, E2EE verificado +- [ ] **4.2** `assistant-bot.spec.ts` — saludo, pregunta, !help, !ping +- [ ] **4.3** `asistente-2.spec.ts` — saludo, !tools, pregunta con tool use, !help + +**Fase 5: Script de ejecucion** — sub-issue 0022c +- [ ] **5.1** Crear `dev-scripts/e2e/run.sh` — verificar agentes, levantar Element, ejecutar tests, teardown +- [ ] **5.2** Agregar opcion `--headed` para debug local + +**Fase 6: Verificacion** — sub-issue 0022c +- [ ] **6.1** Verificar que `npx playwright test` pasa en headless +- [ ] **6.2** Verificar screenshots on failure +- [ ] **6.3** Verificar login cacheado funciona + +**Fase 7: Cleanup y docs** — sub-issue 0022c +- [ ] **7.1** Documentar en `e2e/README.md` +- [ ] **7.2** Agregar `e2e/node_modules/` y `e2e/test-results/` a `.gitignore` +- [ ] **7.3** Actualizar `CLAUDE.md` con seccion de E2E tests + +## Ejemplo de uso + +```bash +# Primera vez: instalar todo +./dev-scripts/e2e/install.sh + +# Configurar credenciales +cp e2e/.env.example e2e/.env +# editar e2e/.env con usuario, password, recovery key + +# Asegurar que los agentes estan corriendo +./dev-scripts/server/start.sh + +# Ejecutar tests +./dev-scripts/e2e/run.sh + +# Output esperado: +# ✓ login.spec.ts — login y verificacion E2EE (12s) +# ✓ assistant-bot.spec.ts — responde a saludo (8s) +# ✓ assistant-bot.spec.ts — responde a pregunta (15s) +# ✓ assistant-bot.spec.ts — comando !help (3s) +# ✓ asistente-2.spec.ts — responde con tool use (20s) +# 5 passed (58s) +``` + +## Decisiones de diseno + +- **Proyecto Node.js separado**: Playwright es ecosistema Node. Mantenerlo en `e2e/` aislado del modulo Go evita contaminar el proyecto principal. +- **Element Web local**: servir Element localmente en vez de usar app.element.io para tener control total del config.json y no depender de servicios externos. +- **storageState para cachear login**: el login + cross-signing es lento (~10s). Cachearlo evita repetirlo en cada test y hace la suite mas rapida. +- **Solo Chromium**: en headless server no necesitamos multi-browser. Chromium es suficiente y reduce el tamaño de la instalacion. +- **Recovery key via .env**: las palabras de seguridad (recovery key) son necesarias para verificar cross-signing y poder desencriptar mensajes E2EE. Sin esto los tests verian "Unable to decrypt". +- **Timeouts generosos**: los bots dependen de LLMs externos (OpenAI), que pueden tardar 5-20s en responder. Timeout de 30s por defecto. +- **Sin feature flag**: al ser infra de testing aislada (no modifica codigo Go), no hay codigo de produccion que proteger con un flag. + +## Prerequisitos + +- Node.js v18+ instalado en la VPS (o el install.sh lo instala) +- Los agentes deben estar corriendo contra el homeserver +- Un usuario de test registrado en el homeserver con cross-signing configurado +- El usuario de test debe estar en los rooms de los bots (o los bots aceptan DMs) + +## Riesgos + +- **Selectores de Element Web inestables**: Element cambia su UI entre versiones. Mitigacion: fijar una version de Element en `setup-element.sh`, usar selectores por role/testid cuando sea posible. +- **Timeouts por LLM lento**: si OpenAI esta lento, los tests fallan por timeout. Mitigacion: timeouts generosos (30s), retry con `test.retry(1)` en la config. +- **Cross-signing verification UI**: el flujo de verificacion en Element puede variar. Mitigacion: documentar la version exacta de Element, usar screenshots on failure para debug. +- **Deps del sistema en VPS**: `npx playwright install-deps` necesita sudo. Mitigacion: documentar en install.sh, ejecutar con permisos adecuados. +- **Mensajes E2EE**: si el cross-signing no se completa correctamente, los mensajes aparecen como "Unable to decrypt". Mitigacion: el smoke test (login.spec.ts) verifica E2EE antes de los tests de agentes. diff --git a/dev/issues/0022a-e2e-infra.md b/dev/issues/0022a-e2e-infra.md new file mode 100644 index 0000000..7feaf46 --- /dev/null +++ b/dev/issues/0022a-e2e-infra.md @@ -0,0 +1,119 @@ +# 0022a — E2E Tests: Infraestructura base + +> Parte de [0022 — Tests E2E con Playwright](0022-e2e-tests-playwright.md) + +## Objetivo + +Crear el proyecto Node.js base para tests E2E con Playwright: estructura de directorios, configuracion, scripts de instalacion y setup de Element Web local. + +## Contexto + +- Primer sub-issue del desglose de 0022. Establece la base sobre la que 0022b y 0022c construyen. +- Playwright necesita un proyecto Node.js independiente con sus propias dependencias +- Element Web se sirve localmente para control total del entorno +- La VPS no tiene entorno grafico — todo headless + +## Arquitectura + +``` +e2e/ NEW — proyecto Node.js independiente +├── package.json NEW — playwright, @playwright/test, dotenv +├── playwright.config.ts NEW — config headless, timeouts, base URL +├── .env.example NEW — template de variables E2E +├── fixtures/ NEW — directorio vacio (se llena en 0022b) +├── tests/ NEW — directorio vacio (se llena en 0022c) +└── scripts/ + └── setup-element.sh NEW — descargar/levantar Element Web local + +dev-scripts/e2e/ +├── install.sh NEW — instalar Node, Playwright, deps +└── run.sh NEW — placeholder (se completa en 0022c) +``` + +### Patron pure core / impure shell + +100% infra de testing, sin cambios al codigo Go. + +## Tareas + +### Fase 1: Proyecto Node.js + +- [ ] **1.1** Crear `e2e/package.json` con dependencias: `@playwright/test`, `dotenv` +- [ ] **1.2** Crear `e2e/playwright.config.ts`: + - Headless por defecto + - Timeout de 30s para acciones (LLMs son lentos) + - Screenshot on failure + - Base URL desde env (`ELEMENT_URL`) + - Solo proyecto Chromium + - `globalSetup` apuntando a `global-setup.ts` (se creara en 0022b) +- [ ] **1.3** Crear `e2e/.env.example`: + ``` + ELEMENT_URL=http://localhost:8080 + MATRIX_HOMESERVER=https://matrix-af2f3d.organic-machine.com + MATRIX_USER=@test-user:matrix-af2f3d.organic-machine.com + MATRIX_PASSWORD= + MATRIX_RECOVERY_KEY= + ``` + +### Fase 2: Scripts + +- [ ] **2.1** Crear `e2e/scripts/setup-element.sh`: + - Descargar Element Web release (version fijada) + - Generar `config.json` apuntando al homeserver + - Servir con `python3 -m http.server` o `npx serve` en puerto 8080 + - Opcion para detener el servidor +- [ ] **2.2** Crear `dev-scripts/e2e/install.sh`: + - Verificar/instalar Node.js v18+ + - `npm ci` en `e2e/` + - `npx playwright install chromium` + - `npx playwright install-deps` (necesita sudo) +- [ ] **2.3** Crear `dev-scripts/e2e/run.sh` como placeholder: + - Verificar que `e2e/node_modules/` existe + - Verificar que `e2e/.env` existe + - Mensaje indicando que los tests se agregan en 0022c + +### Fase 3: Gitignore y verificacion + +- [ ] **3.1** Agregar a `.gitignore`: `e2e/node_modules/`, `e2e/test-results/`, `e2e/.auth/`, `e2e/.env` +- [ ] **3.2** Verificar que `npm ci` y `npx playwright install chromium` funcionan en la VPS +- [ ] **3.3** Verificar que Element Web se levanta y es accesible en `localhost:8080` + +--- + +## Ejemplo de uso + +```bash +# Instalar todo +./dev-scripts/e2e/install.sh + +# Configurar credenciales +cp e2e/.env.example e2e/.env +vim e2e/.env + +# Levantar Element Web +./e2e/scripts/setup-element.sh start +# → Element Web serving at http://localhost:8080 + +# Verificar que carga +curl -s http://localhost:8080 | head -5 +# → ... + +# Detener +./e2e/scripts/setup-element.sh stop +``` + +## Decisiones de diseno + +- **Version fijada de Element**: evita que cambios de UI rompan selectores. Se actualiza manualmente. +- **python3 http.server como fallback**: disponible en cualquier VPS sin instalar nada extra. `npx serve` como alternativa si esta disponible. +- **Directorios vacios con .gitkeep**: `fixtures/` y `tests/` se crean vacios para que la estructura exista desde el primer sub-issue. + +## Prerequisitos + +- Acceso a la VPS con sudo (para `playwright install-deps`) +- Conectividad al homeserver Matrix + +## Riesgos + +- **Node.js no instalado**: `install.sh` debe manejarlo con instrucciones claras o instalacion automatica via nvm/nodesource. +- **Playwright deps del sistema**: varian por distro. `playwright install-deps` lo maneja pero necesita sudo. diff --git a/dev/issues/0022b-e2e-auth-helpers.md b/dev/issues/0022b-e2e-auth-helpers.md new file mode 100644 index 0000000..eb889e6 --- /dev/null +++ b/dev/issues/0022b-e2e-auth-helpers.md @@ -0,0 +1,125 @@ +# 0022b — E2E Tests: Auth fixtures y helpers de interaccion + +> Parte de [0022 — Tests E2E con Playwright](0022-e2e-tests-playwright.md) +> Depende de: [0022a — Infraestructura base](0022a-e2e-infra.md) + +## Objetivo + +Implementar los fixtures de Playwright para autenticacion en Element Web (login + cross-signing E2EE) y los helpers de interaccion con rooms Matrix (enviar mensajes, esperar respuestas de bots). + +## Contexto + +- Element Web requiere login + verificacion de dispositivo con recovery key para desencriptar mensajes E2EE +- El flujo de login es lento (~10s) — se cachea con `storageState` de Playwright para reutilizar entre tests +- Los helpers de room abstraen la interaccion con la UI de Element para que los tests sean legibles +- Depende de 0022a: el proyecto Node.js y Element Web local ya deben estar configurados + +## Arquitectura + +``` +e2e/ +├── global-setup.ts NEW — ejecuta login una vez, guarda storageState +├── fixtures/ +│ ├── element-auth.ts NEW — flujo de login + cross-signing +│ └── matrix-room.ts NEW — goToRoom, sendMessage, waitForBotReply, getLastMessage +└── .auth/ + └── state.json NEW (generado) — sesion autenticada cacheada +``` + +### Patron pure core / impure shell + +100% infra de testing, sin cambios al codigo Go. + +## Tareas + +### Fase 1: Fixture de autenticacion + +- [ ] **1.1** Crear `e2e/fixtures/element-auth.ts` con el flujo completo: + 1. Navegar a Element Web + 2. Click "Sign in" + 3. Configurar homeserver URL si no esta preset + 4. Ingresar usuario y contraseña + 5. Manejar prompt de verificacion de dispositivo + 6. Ingresar recovery key para cross-signing + 7. Verificar login exitoso (lista de rooms visible) +- [ ] **1.2** Crear `e2e/global-setup.ts`: + - Lanzar browser + - Ejecutar flujo de login de `element-auth.ts` + - Guardar sesion con `page.context().storageState({ path: 'e2e/.auth/state.json' })` + - Cerrar browser +- [ ] **1.3** Actualizar `playwright.config.ts` para usar `globalSetup` y `storageState` + +### Fase 2: Helpers de interaccion + +- [ ] **2.1** Crear `e2e/fixtures/matrix-room.ts` con helpers: + - `goToRoom(page, roomName)` — buscar y navegar a un room por nombre + - `sendMessage(page, text)` — escribir mensaje en el composer y enviar + - `waitForBotReply(page, options?)` — esperar respuesta de un bot con timeout configurable, filtrar por sender si se especifica + - `getLastMessage(page)` — obtener texto del ultimo mensaje del timeline +- [ ] **2.2** Implementar deteccion de "Unable to decrypt" — si aparece, el test debe fallar con mensaje claro indicando problema de E2EE + +### Fase 3: Tests de validacion + +- [ ] **3.1** Crear `e2e/tests/login.spec.ts` — smoke test: + - Login funciona (usa storageState cacheado) + - Se ven rooms en el sidebar + - No aparece "Unable to decrypt" en mensajes recientes +- [ ] **3.2** Verificar que el segundo run reutiliza la sesion cacheada (no repite login) +- [ ] **3.3** Verificar que los helpers navegan correctamente a rooms de los bots + +--- + +## Ejemplo de uso + +```typescript +// global-setup.ts +import { chromium } from '@playwright/test'; +import { loginToElement } from './fixtures/element-auth'; + +async function globalSetup() { + const browser = await chromium.launch(); + const page = await browser.newPage(); + + await loginToElement(page, { + url: process.env.ELEMENT_URL!, + user: process.env.MATRIX_USER!, + password: process.env.MATRIX_PASSWORD!, + recoveryKey: process.env.MATRIX_RECOVERY_KEY!, + }); + + await page.context().storageState({ path: 'e2e/.auth/state.json' }); + await browser.close(); +} + +export default globalSetup; +``` + +```typescript +// Uso de helpers en un test (preview de 0022c) +import { goToRoom, sendMessage, waitForBotReply } from '../fixtures/matrix-room'; + +test('bot responde', async ({ page }) => { + await goToRoom(page, 'Assistant Bot'); + await sendMessage(page, 'Hola'); + const reply = await waitForBotReply(page, { timeout: 30_000 }); + expect(reply).toBeTruthy(); +}); +``` + +## Decisiones de diseno + +- **storageState global**: el login + cross-signing se hace una sola vez en `globalSetup`. Todos los tests arrancan ya autenticados. +- **Helpers como funciones puras de page**: reciben `page` como argumento en vez de extender fixtures de Playwright, para simplicidad y reusabilidad. +- **Deteccion explicita de E2EE fallido**: en vez de timeouts silenciosos, detectar "Unable to decrypt" y fallar con mensaje descriptivo. + +## Prerequisitos + +- 0022a completado (proyecto Node.js, Element Web local funcionando) +- Usuario de test con cross-signing configurado en el homeserver +- `.env` con credenciales validas + +## Riesgos + +- **UI de cross-signing cambia entre versiones de Element**: mitigacion con version fijada en 0022a y screenshots on failure. +- **Recovery key formato inconsistente**: las palabras pueden tener espacios. Asegurarse de que el input acepta el formato tal cual esta en `.env`. +- **Sesion expirada**: si el token caduca entre runs, `globalSetup` debe re-autenticar. Implementar deteccion de sesion invalida. diff --git a/dev/issues/0022c-e2e-agent-tests.md b/dev/issues/0022c-e2e-agent-tests.md new file mode 100644 index 0000000..6cafc61 --- /dev/null +++ b/dev/issues/0022c-e2e-agent-tests.md @@ -0,0 +1,148 @@ +# 0022c — E2E Tests: Tests de agentes, ejecucion y docs + +> Parte de [0022 — Tests E2E con Playwright](0022-e2e-tests-playwright.md) +> Depende de: [0022b — Auth fixtures y helpers](0022b-e2e-auth-helpers.md) + +## Objetivo + +Escribir los tests E2E para cada agente (assistant-bot, asistente-2), completar el script de ejecucion `run.sh`, y documentar todo el sistema E2E. + +## Contexto + +- Los fixtures de auth y helpers de room ya estan implementados (0022b) +- Cada agente tiene comportamiento distinto: assistant-bot es basico, asistente-2 tiene tools +- Los tests dependen de LLMs externos (OpenAI) que pueden tardar 5-20s en responder +- El script `run.sh` orquesta todo: verifica agentes, levanta Element, ejecuta tests, teardown + +## Arquitectura + +``` +e2e/tests/ +├── login.spec.ts EXISTENTE (de 0022b, se puede extender) +├── assistant-bot.spec.ts NEW — tests del assistant-bot +└── asistente-2.spec.ts NEW — tests del asistente-2 (con tools) + +e2e/README.md NEW — documentacion del sistema E2E + +dev-scripts/e2e/ +└── run.sh MODIFICAR — completar el placeholder de 0022a +``` + +### Patron pure core / impure shell + +100% infra de testing, sin cambios al codigo Go. + +## Tareas + +### Fase 1: Tests de agentes + +- [ ] **1.1** Crear `e2e/tests/assistant-bot.spec.ts`: + - Enviar saludo en DM → bot responde (no timeout, no error) + - Enviar pregunta → respuesta coherente (no vacia, longitud > 10 chars) + - Enviar `!help` → respuesta contiene lista de comandos + - Enviar `!ping` → respuesta contiene "pong" o similar +- [ ] **1.2** Crear `e2e/tests/asistente-2.spec.ts`: + - Enviar saludo → respuesta + - Enviar `!tools` → lista de herramientas disponibles + - Enviar pregunta que active una tool (ej: "que hora es?") → respuesta con resultado + - Enviar `!help` → comandos incluyendo los especificos del agente + +### Fase 2: Script de ejecucion + +- [ ] **2.1** Completar `dev-scripts/e2e/run.sh`: + 1. Verificar que los agentes estan corriendo (`dev-scripts/server/ps.sh`) + 2. Levantar Element Web si no esta corriendo (`e2e/scripts/setup-element.sh start`) + 3. Ejecutar `npx playwright test` con reporte en consola + 4. Generar reporte HTML en `e2e/test-results/` para debug + 5. Teardown de Element Web (`e2e/scripts/setup-element.sh stop`) + 6. Retornar exit code de playwright +- [ ] **2.2** Agregar opcion `--headed` para debug local (si hay DISPLAY disponible) + +### Fase 3: Verificacion completa + +- [ ] **3.1** Ejecutar `npx playwright test` en la VPS (headless) — todos los tests pasan +- [ ] **3.2** Verificar que screenshots on failure se generan en `e2e/test-results/` +- [ ] **3.3** Verificar que el login cacheado funciona (segundo run no repite login) +- [ ] **3.4** Verificar que `dev-scripts/e2e/run.sh` orquesta todo correctamente + +### Fase 4: Cleanup y docs + +- [ ] **4.1** Crear `e2e/README.md` con: + - Como instalar (`dev-scripts/e2e/install.sh`) + - Como configurar `.env` + - Como ejecutar tests (`dev-scripts/e2e/run.sh`) + - Como debuggear fallos (screenshots, `--headed`, reporte HTML) + - Estructura del proyecto +- [ ] **4.2** Actualizar `.gitignore` si faltan entradas de 0022a +- [ ] **4.3** Actualizar `CLAUDE.md` con seccion de E2E tests + +--- + +## Ejemplo de uso + +```typescript +// assistant-bot.spec.ts +import { test, expect } from '@playwright/test'; +import { goToRoom, sendMessage, waitForBotReply } from '../fixtures/matrix-room'; + +test.describe('assistant-bot', () => { + test('responde a un saludo', async ({ page }) => { + await goToRoom(page, 'Assistant Bot'); + await sendMessage(page, 'Hola, como estas?'); + + const reply = await waitForBotReply(page, { timeout: 30_000 }); + expect(reply).toBeTruthy(); + expect(reply!.length).toBeGreaterThan(10); + }); + + test('!help muestra comandos', async ({ page }) => { + await goToRoom(page, 'Assistant Bot'); + await sendMessage(page, '!help'); + + const reply = await waitForBotReply(page, { timeout: 5_000 }); + expect(reply).toContain('help'); + expect(reply).toContain('ping'); + }); + + test('!ping responde', async ({ page }) => { + await goToRoom(page, 'Assistant Bot'); + await sendMessage(page, '!ping'); + + const reply = await waitForBotReply(page, { timeout: 5_000 }); + expect(reply).toBeTruthy(); + }); +}); +``` + +```bash +# Ejecucion completa +./dev-scripts/e2e/run.sh +# ✓ login.spec.ts — login y verificacion E2EE (12s) +# ✓ assistant-bot.spec.ts — responde a saludo (8s) +# ✓ assistant-bot.spec.ts — !help muestra comandos (3s) +# ✓ assistant-bot.spec.ts — !ping responde (3s) +# ✓ asistente-2.spec.ts — responde con tool use (20s) +# 5 passed (46s) + +# Debug con browser visible +./dev-scripts/e2e/run.sh --headed +``` + +## Decisiones de diseno + +- **Assertions flexibles**: no validar contenido exacto de respuestas LLM (son no-deterministicas). Solo verificar que responde, que no esta vacio, y longitud razonable. +- **Commands con assertions estrictas**: los `!help` y `!ping` tienen respuestas deterministicas — se pueden validar con mayor precision. +- **Test retry**: `test.retry(1)` en la config para manejar timeouts ocasionales por LLM lento. +- **Tests secuenciales**: los tests de un mismo agente se ejecutan en serie (fullyParallel: false) para evitar race conditions en el timeline de Matrix. + +## Prerequisitos + +- 0022a y 0022b completados +- Agentes corriendo contra el homeserver +- `.env` configurado con credenciales validas + +## Riesgos + +- **LLM timeout**: respuestas de GPT-4o pueden tardar >30s bajo carga. Mitigacion: retry + timeout generoso. +- **Race conditions en timeline**: si dos tests envian mensajes al mismo bot simultaneamente, las respuestas pueden mezclarse. Mitigacion: tests secuenciales por agente. +- **Tool use no deterministico**: el LLM puede decidir no usar una tool. Mitigacion: prompt de test claro (ej: "que hora es?" para current_time), retry si falla. diff --git a/dev/issues/README.md b/dev/issues/README.md index 070f5fe..7991359 100644 --- a/dev/issues/README.md +++ b/dev/issues/README.md @@ -25,3 +25,8 @@ afectados y notas de implementacion. | 18 | Shared knowledge | [0018-shared-knowledge.md](0018-shared-knowledge.md) | pendiente | | 19 | Prompt injection hardening | [0019-prompt-injection-hardening.md](completed/0019-prompt-injection-hardening.md) | completado | | 20 | Aislar claude -p del repo | [0020-claude-code-sandbox.md](completed/0020-claude-code-sandbox.md) | completado | +| 21 | Threads default config | (completado via branch) | completado | +| 22 | Tests E2E con Playwright | [0022-e2e-tests-playwright.md](0022-e2e-tests-playwright.md) | pendiente | +| 22a | E2E: Infraestructura base | [0022a-e2e-infra.md](0022a-e2e-infra.md) | pendiente | +| 22b | E2E: Auth fixtures y helpers | [0022b-e2e-auth-helpers.md](0022b-e2e-auth-helpers.md) | pendiente | +| 22c | E2E: Tests de agentes + docs | [0022c-e2e-agent-tests.md](0022c-e2e-agent-tests.md) | pendiente |