chore: auto-commit (9 archivos)

- .claude/commands/autopilot.md
- dev/proposals_e2e_checks_0121/altsnap_jitter_test.yaml
- dev/proposals_e2e_checks_0121/app_hub_launcher.yaml
- dev/proposals_e2e_checks_0121/element_matrix_chat.yaml
- dev/proposals_e2e_checks_0121/footprint_geo_stack.yaml
- dev/proposals_e2e_checks_0121/metabase_registry.yaml
- dev/proposals_e2e_checks_0121/script_navegador.yaml
- dev/proposals_e2e_checks_0121/services_monitor.yaml
- dev/proposals_e2e_checks_0121/tables_qa.yaml

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-19 01:41:49 +02:00
parent bed8a802a0
commit 32bb2cbd25
9 changed files with 1106 additions and 7 deletions
@@ -0,0 +1,134 @@
# Propuesta e2e_checks para apps/altsnap_jitter_test
# Generado por fn-recopilador modo design-e2e
# Fecha: 2026-05-19
# Issue: 0121a wave 3
#
# Diagnostico:
# app_id: altsnap_jitter_test
# lang: cpp
# framework: imgui (fn::run_app)
# domain: tools
# entry_point: main.cpp
# version: 0.1.0
# tags: [imgui, test, regression, headless]
#
# Estructura del directorio:
# CMakeLists.txt — usa add_imgui_app(altsnap_jitter_test main.cpp); sin
# funciones del registry enlazadas (test puro de framework)
# main.cpp — harness 6 fases; #ifdef _WIN32 para p2-p6
# appicon.ico — presente
# .git/ — sub-repo propio
#
# Toolchain: mingw-w64 (cross-compile Windows desde WSL)
# Runner Windows: bash/functions/infra/e2e_run_cpp_windows.sh
# source + e2e_run_cpp_windows <target> => build + deploy Desktop + run .exe
#
# Fases del binario:
# p1.sync (cross-platform) — glfwSetWindowPos 60 frames, aserta max_sync=0px
# p2.altsnap (Windows-only) — WM_ENTERSIZEMOVE + burst SWP + WM_EXITSIZEMOVE
# sobre HWND principal; aserta renders_during=0
# p3.secondary(Windows-only) — mismo bracket sobre HWND de viewport flotante
# p4.minimize (Windows-only) — iconify+restore; aserta alive(during)=1 +
# renders_iconified>0
# p5.alt_rmb (Windows-only) — SendMessageW WM_RBUTTONDOWN+Alt; aserta
# alt_rmb_resize_count delta=1
# p6.alt_lmb (Windows-only) — SendMessageW WM_LBUTTONDOWN+Alt; aserta
# alt_lmb_move_count delta=1
#
# Exit del binario: 0 = ALL phases PASS (o SKIP en Linux), !=0 = alguna FAIL
#
# Tests/: NO tiene directorio de tests separado
# operations.db: NO usa (pure framework test harness, sin entities/relations)
# ops_audit: OMITIDO
# tag 'service': NO — no expone HTTP
# smoke con health: OMITIDO
# uses_functions: [] — no linkea funciones del registry
# drift uses_functions: OMITIDO
#
# Patron de checks:
# - WSL/Linux: build (cmake Linux) + binary_exists + run bajo xvfb (p1 solamente)
# - Windows: e2e_run_cpp_windows (build mingw + deploy + run nativo, p1-p6)
# - Los checks Windows se marcan severity: warning porque requieren WSL2 con
# interop habilitado, mingw-w64 instalado y /mnt/c/Users/lucas/Desktop
# accesible. En CI Linux puro estos checks se skipean de forma natural
# (cmd.exe / taskkill.exe no existen).
# - El check linux_run es severity: critical porque p1 (sync) es cross-platform
# y debe pasar siempre en WSL.
app_id: altsnap_jitter_test
e2e_checks:
# Configura el build de Linux si el directorio de build no existe.
# Requerido antes de build_linux la primera vez (cmake configure-only, rapido).
# Se salta si cpp/build/linux/build.ninja ya existe (cmake --build no necesita
# reconfiguracion).
- id: cmake_configure_linux
cmd: >
test -f /home/lucas/fn_registry/cpp/build/linux/build.ninja ||
cmake -S /home/lucas/fn_registry/cpp
-B /home/lucas/fn_registry/cpp/build/linux
-DFN_BUILD_TESTS=OFF
-DCMAKE_BUILD_TYPE=RelWithDebInfo
timeout_s: 60
severity: critical
# Compila el target para Linux (xvfb). Valida que main.cpp compila sin errores
# y el linkado con fn_framework (app_base.cpp, GLFW, OpenGL) tiene exito.
# Este es el check de compilacion base que corre en cualquier entorno.
- id: build_linux
cmd: "cmake --build /home/lucas/fn_registry/cpp/build/linux --target altsnap_jitter_test -j4"
timeout_s: 300
severity: critical
# Verifica que el binario Linux existe tras el build.
- id: binary_exists_linux
cmd: "test -f /home/lucas/fn_registry/cpp/build/linux/apps/altsnap_jitter_test/altsnap_jitter_test"
timeout_s: 5
severity: critical
# Ejecuta el harness bajo xvfb (p1.sync solamente; p2-p6 se autoskipean en Linux).
# Valida que la capa de sincronizacion GLFW pos callback no tiene regresiones.
# Usa llvmpipe (soft-render) para no depender de GPU real en CI.
# Exit 0 = p1 PASS. Cualquier otro exit = bad_sync > 0 o crash.
- id: linux_run
cmd: >
xvfb-run -a -s "-screen 0 1280x800x24"
env LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=llvmpipe
/home/lucas/fn_registry/cpp/build/linux/apps/altsnap_jitter_test/altsnap_jitter_test
timeout_s: 60
severity: critical
# Verifica que el .ico esta presente.
# add_imgui_app genera altsnap_jitter_test_appicon.rc; si el .ico falta el build
# mingw pasa pero el .exe Windows queda sin icono embebido.
- id: icon_exists
cmd: "test -f /home/lucas/fn_registry/apps/altsnap_jitter_test/appicon.ico"
timeout_s: 5
severity: warning
# Cross-compila para Windows via mingw-w64, despliega al Desktop de Windows
# (matando instancia previa con taskkill.exe), y lanza el .exe nativamente
# desde WSL con WSL interop. Corre las 6 fases completas (p1-p6).
# Exit 0 = p1 PASS + p2 PASS (renders_during=0) + p3 PASS + p4 PASS +
# p5 PASS (alt_rmb delta=1) + p6 PASS (alt_lmb delta=1).
# Exit != 0 = alguna fase FAIL o crash del harness.
#
# severity: warning porque requiere:
# - WSL2 con interop habilitado (cmd.exe / taskkill.exe en PATH)
# - mingw-w64 instalado (sudo apt install mingw-w64)
# - /mnt/c/Users/lucas/Desktop accesible
# - cpp/build/windows pre-configurado (build_cpp_windows.sh)
# En CI Linux puro este check no puede correr. En la maquina de desarrollo
# (home-wsl) es el check mas valioso: detecta regresiones del WndProc subclass
# real bajo Win32 que xvfb no puede cubrir.
- id: windows_run
cmd: >
FN_REGISTRY_ROOT=/home/lucas/fn_registry
bash -c '
source /home/lucas/fn_registry/bash/functions/infra/e2e_run_cpp_windows.sh
e2e_run_cpp_windows altsnap_jitter_test
'
timeout_s: 300
severity: warning
expect_stdout_contains: "overall=PASS"
@@ -0,0 +1,84 @@
# e2e_checks proposal — app_hub_launcher
# app_id: app_hub_launcher
# lang: cpp
# stack: imgui hub — lista y lanza apps C++ Windows desde Desktop/apps/
# date: 2026-05-19
# issue: 0121a wave 3
# author: fn-recopilador (design-e2e)
#
# Diagnostico:
# lang=cpp, framework=imgui, entry_point=main.cpp
# NO tiene tests/ propios, NO tiene operations.db
# Binario en: cpp/build/windows/apps/app_hub_launcher/app_hub_launcher.exe
# Target CMake: app_hub_launcher (registrado via add_subdirectory en cpp/CMakeLists.txt:497)
# Runtime deps en local_files/:
# - local_files/hub_manifest.tsv (regenerable con refresh_app_hub)
# - local_files/icons/*.png (regenerable con refresh_app_hub)
# Sin --self-test implementado en el binario (no aplica el check de smoke headless)
# Sin health endpoint HTTP (app GUI pura, no service)
# NO tag 'service' -> sin smoke check de puerto
# NO operations.db -> sin ops_audit
#
# Justificacion de cada check:
# build -> gate primario: garantiza que el target compila sin errores
# binary_exists -> verifica que el .exe existe en la ruta de deploy Windows esperada
# appicon_exists -> appicon.ico en la fuente es requerido por add_imgui_app para
# embeber el recurso RC en el .exe; si falta el icono no compila en WIN32
# manifest_present -> hub_manifest.tsv en local_files/ es la fuente de descripcion +
# accent de cada tarjeta; su ausencia degrada el hub (cards grises sin
# descripcion) pero NO crashea; severity: warning porque es regenerable
# icons_cache_present -> local_files/icons/ con al menos 1 PNG indica que refresh_app_hub
# se ha corrido; su ausencia es operacional, no de build; warning
e2e_checks:
# Check 1: compilacion del target CMake
# Por que: gate esencial — si el target no compila, nada mas tiene sentido.
# Corre sobre el build de Windows via mingw toolchain (cross-compile desde WSL).
- id: build
cmd: "cd /home/lucas/fn_registry/cpp && cmake --build build/windows --target app_hub_launcher -j"
timeout_s: 300
severity: critical
# Check 2: binario Windows presente en la ruta de deploy
# Por que: el pipeline redeploy_cpp_app_windows copia el .exe al Desktop.
# Este check verifica que el binario existe y es un archivo regular.
# Si el build cross no produjo el .exe o el cp falló, este check lo detecta.
- id: binary_exists
cmd: "test -f /home/lucas/fn_registry/cpp/build/windows/apps/app_hub_launcher/app_hub_launcher.exe"
timeout_s: 5
severity: critical
# Check 3: appicon.ico presente en el directorio fuente
# Por que: add_imgui_app auto-genera el .rc solo si appicon.ico existe en CMAKE_CURRENT_SOURCE_DIR.
# Si se borra el ico, el .exe no tiene icono embebido (no falla el build, pero rompe el
# contrato visual de la suite). El .ico es artefacto versionado en el sub-repo.
- id: appicon_exists
cmd: "test -f /home/lucas/fn_registry/apps/app_hub_launcher/appicon.ico"
timeout_s: 5
severity: critical
# Check 4: hub_manifest.tsv presente en la ruta de deploy Windows
# Por que: sin manifest, el hub arranca pero todas las tarjetas muestran nombre snake_case
# y sin descripcion ni accent correcto. Degradacion funcional significativa pero no crash.
# Regenerable con: ./fn run refresh_app_hub --no-restart
# Path esperado tras deploy: Desktop/apps/app_hub_launcher/local_files/hub_manifest.tsv
- id: manifest_present
cmd: "test -f /mnt/c/Users/lucas/Desktop/apps/app_hub_launcher/local_files/hub_manifest.tsv"
timeout_s: 5
severity: warning
# Check 5: cache de iconos PNG presente (al menos 1 archivo)
# Por que: sin iconos PNG en local_files/icons/, las tarjetas del hub no muestran imagen
# (degradacion visual). El directorio se crea/puebla con refresh_app_hub.
# Regenerable con: ./fn run refresh_app_hub --no-restart
# Se verifica que el directorio existe y tiene al menos 1 .png (no validamos cada app).
- id: icons_cache_present
cmd: "test -d /mnt/c/Users/lucas/Desktop/apps/app_hub_launcher/local_files/icons && ls /mnt/c/Users/lucas/Desktop/apps/app_hub_launcher/local_files/icons/*.png >/dev/null 2>&1"
timeout_s: 5
severity: warning
# Acciones sugeridas si los checks de warning fallan:
# manifest_present / icons_cache_present:
# ./fn run refresh_app_hub
# o si el hub está cerrado:
# ./fn run refresh_app_hub --no-restart
@@ -0,0 +1,184 @@
# e2e_checks proposal — element_matrix_chat
# app_id: element_matrix_chat
# lang: bash
# framework: docker-compose
# stack: 10+ contenedores Docker (Synapse, Element Web, MAS, LiveKit, PostgreSQL x2,
# Synapse Admin, Nginx, LiveKit JWT, element-call-web)
# date: 2026-05-19
# issue: 0121a wave 3
#
# NOTAS DE DISENO:
# - La app es infraestructura Docker Compose pura: no hay build de codigo,
# no hay binarios locales que compilar, no hay tests unitarios.
# - Los checks validan que los archivos de config esten bien formados,
# que docker/docker-compose esten disponibles, y que el stack levante
# correctamente (smoke via health de la API Matrix).
# - NINGUN check usa credenciales reales. El smoke usa MATRIX_SERVER_NAME=localhost
# y valida solo que la API responde con JSON valido (no autenticacion).
# - El health check de Synapse (/_matrix/client/versions) es publico y no
# requiere credenciales — responde 200 con lista de versiones soportadas.
# - El check de LiveKit usa el endpoint /healthz que tambien es publico.
# - Los checks marcados severity: warning son los que dependen de red externa
# o de que el VPS este vivo — no bloquean merge en local.
# - No existe operations.db en esta app (infra Docker pura, no usa bucle reactivo).
# Por tanto no se incluye ops_audit.
#
# JUSTIFICACION POR CHECK:
# | check | razon |
# |--------------------------|------------------------------------------------------------------------|
# | env_example_syntax | Valida que .env.example es parseable bash sin errores de sintaxis |
# | docker_compose_validate | docker-compose config --quiet detecta YAML/interpolacion rota |
# | docker_compose_livekit_v | Igual para el compose secundario de LiveKit |
# | config_templates_present | Asegura que configs/ tiene los templates obligatorios para setup.sh |
# | setup_sh_syntax | bash -n detecta errores de sintaxis en scripts sin ejecutarlos |
# | create_user_sh_syntax | Igual para el script de creacion de usuarios |
# | element_config_json | Valida que element-config.json es JSON valido (python3 -m json.tool) |
# | smoke_synapse_health | GET /_matrix/client/versions en VPS. severity: warning (red externa) |
# | smoke_element_web | GET http://VPS:8081 devuelve 200. severity: warning (red externa) |
# | smoke_mas_health | GET http://VPS:8083/health devuelve 200. severity: warning |
# | smoke_synapse_admin | GET http://VPS:8082 devuelve 200. severity: warning |
e2e_checks:
# -----------------------------------------------------------------------
# CHECKS LOCALES (critical — sin red externa, sin credenciales)
# -----------------------------------------------------------------------
- id: env_example_syntax
# por que: .env.example define todas las variables del stack.
# Un error de sintaxis bash impide hacer `source .env` en setup.sh.
cmd: "bash -n projects/element_agents/apps/element_matrix_chat/.env.example || (bash --posix -c 'set -a; source projects/element_agents/apps/element_matrix_chat/.env.example' 2>&1 | grep -v 'command not found' && true)"
timeout_s: 5
severity: warning
- id: docker_compose_validate
# por que: docker-compose config --quiet detecta YAML malformado,
# imagenes invalidas, y referencias a variables sin definir antes
# de intentar levantar el stack.
# Requiere docker-compose instalado localmente.
cmd: >
cd projects/element_agents/apps/element_matrix_chat &&
cp -n .env.example .env.e2e_tmp 2>/dev/null;
env $(grep -v '^#' .env.example | xargs) docker-compose -f docker-compose.yml config --quiet
timeout_s: 20
severity: critical
- id: docker_compose_livekit_validate
# por que: el compose de LiveKit es independiente pero obligatorio para
# videollamadas. Validarlo por separado asegura que no rompe al hacer
# `docker-compose -f docker-compose.livekit.yml up -d`.
cmd: >
cd projects/element_agents/apps/element_matrix_chat &&
env $(grep -v '^#' .env.example | xargs) docker-compose -f docker-compose.livekit.yml config --quiet
timeout_s: 20
severity: critical
- id: config_templates_present
# por que: setup.sh requiere configs/nginx/well-known.conf,
# configs/well-known/, y configs/livekit/livekit.example.yaml.
# Si alguno falta, setup.sh falla silenciosamente o con un error opaco.
cmd: >
test -f projects/element_agents/apps/element_matrix_chat/configs/nginx/well-known.conf &&
test -d projects/element_agents/apps/element_matrix_chat/configs/well-known &&
test -f projects/element_agents/apps/element_matrix_chat/configs/homeserver.yaml.template &&
echo "all config templates present"
expect_stdout_contains: "all config templates present"
timeout_s: 5
severity: critical
- id: setup_sh_syntax
# por que: bash -n detecta errores de sintaxis en el script principal
# de deploy sin ejecutarlo (sin efectos secundarios).
cmd: "bash -n projects/element_agents/apps/element_matrix_chat/scripts/setup.sh"
timeout_s: 5
severity: critical
- id: create_user_sh_syntax
# por que: create-user.sh es el script operativo para crear usuarios Matrix.
# Un error de sintaxis lo romperia silenciosamente en produccion.
cmd: "bash -n projects/element_agents/apps/element_matrix_chat/scripts/create-user.sh"
timeout_s: 5
severity: critical
- id: backup_sh_syntax
# por que: backup.sh gestiona backups de PostgreSQL. Un error de sintaxis
# podria dejar la app sin backup en produccion.
cmd: "bash -n projects/element_agents/apps/element_matrix_chat/scripts/backup.sh"
timeout_s: 5
severity: warning
- id: element_config_json
# por que: element-config.json configura el cliente web de Element.
# JSON invalido hace que Element Web no arranque (pantalla en blanco).
cmd: "python3 -m json.tool projects/element_agents/apps/element_matrix_chat/element-config.json > /dev/null"
timeout_s: 5
severity: critical
- id: element_config_template_json
# por que: el template en configs/ se usa en setup para generar la
# configuracion final. Debe ser JSON valido tambien.
cmd: "python3 -m json.tool projects/element_agents/apps/element_matrix_chat/configs/element-config.json.template > /dev/null 2>&1 || echo 'template_not_json_skip'"
timeout_s: 5
severity: warning
# -----------------------------------------------------------------------
# CHECKS REMOTOS (warning — dependen del VPS organic-machine.com)
# Estos checks validan el estado del stack en produccion.
# severity: warning porque red externa puede fallar por razones ajenas al codigo.
# Se ejecutan en fn-analizador con MATRIX_HOST env var si esta configurado.
# -----------------------------------------------------------------------
- id: smoke_synapse_health
# por que: /_matrix/client/versions es el endpoint publico de Synapse
# que confirma que el homeserver esta vivo y responde JSON valido.
# No requiere autenticacion. Fallo aqui = stack caido en produccion.
cmd: >
MATRIX_HOST=${MATRIX_E2E_HOST:-matrix-af2f3d.organic-machine.com} &&
curl -sf --max-time 10
"https://${MATRIX_HOST}/_matrix/client/versions"
| python3 -m json.tool > /dev/null
timeout_s: 15
severity: warning
- id: smoke_element_web
# por que: Element Web en :8081 (o via proxy) devuelve el SPA HTML.
# Fallo = usuarios no pueden acceder al cliente.
# Usa el proxy Coolify que expone HTTPS en 443.
cmd: >
MATRIX_HOST=${MATRIX_E2E_HOST:-matrix-af2f3d.organic-machine.com} &&
curl -sf --max-time 10 -o /dev/null -w "%{http_code}"
"https://${MATRIX_HOST}/"
| grep -E "^(200|301|302)$"
timeout_s: 15
severity: warning
- id: smoke_mas_health
# por que: MAS (Matrix Authentication Service) debe estar vivo para
# que el login OIDC funcione. /health es su endpoint publico.
cmd: >
MATRIX_HOST=${MATRIX_E2E_HOST:-matrix-af2f3d.organic-machine.com} &&
curl -sf --max-time 10
"https://${MATRIX_HOST}/_mas/health"
| python3 -c "import sys,json; d=json.load(sys.stdin); sys.exit(0 if d.get('status')=='ok' else 1)"
timeout_s: 15
severity: warning
- id: smoke_synapse_admin_accessible
# por que: Synapse Admin en :8082 debe estar accesible para operaciones
# de administracion. Solo verificamos que el proxy responde, no login.
cmd: >
MATRIX_HOST=${MATRIX_E2E_HOST:-matrix-af2f3d.organic-machine.com} &&
curl -sf --max-time 10 -o /dev/null -w "%{http_code}"
"https://${MATRIX_HOST}/synapse-admin/"
| grep -E "^(200|301|302)$"
timeout_s: 15
severity: warning
- id: smoke_livekit_health
# por que: LiveKit expone /healthz en :7882. Si cae, Element Call
# no puede establecer conexiones RTC (videollamadas rotas).
cmd: >
curl -sf --max-time 10
"https://matrix-rtc-320bd4.organic-machine.com/healthz"
| grep -i "ok\|healthy\|alive" || true
timeout_s: 15
severity: warning
@@ -0,0 +1,189 @@
# e2e_checks proposal — footprint_geo_stack
# app_id: footprint_geo_stack
# lang: bash
# stack: docker-compose (PostGIS 16-3.4 + Martin tile server + Valhalla routing)
# geo_deps: PostGIS/GEOS/PROJ (via postgis image), Martin MVT (maplibre), Valhalla (nilsnolde)
# date: 2026-05-19
# issue: 0121a wave 3
#
# NOTAS DE DISENO:
#
# 1. Esta app NO tiene codigo fuente propio (solo docker-compose.yml). No hay build step.
# Los checks validan que el compose file es valido y que el stack arranca y responde.
#
# 2. VALHALLA_DATA_DIR es obligatoria — apunta a datos locales de tiles de Espana.
# Sin el .env o la variable, el compose falla antes de arrancar.
# Los checks de smoke estan marcados severity: warning porque dependen de:
# - Docker running
# - Datos de tiles presentes en VALHALLA_DATA_DIR
# - ~60-90s de boot de Valhalla (carga tiles en memoria)
#
# 3. NO se usan tile servers externos ni APIs reales — todos los health checks
# van contra localhost con datos locales (sin red externa).
#
# 4. Puertos e2e = mismos que produccion (no hay conflicto tipico porque aurgi-pc
# es el unico pc_target y el stack se levanta/para explicitamente).
# Si en el futuro se corre en CI, escalar a puertos efimeros via env overrides.
#
# 5. El check compose_config es critico (valida syntax YAML + referencias de env).
# El resto son warning porque dependen de runtime externo (Docker daemon + datos).
e2e_checks_suggested:
# --- CHECK 1: compose config valido ---
# Valida que docker-compose.yml no tiene errores de sintaxis y que todas las
# variables de entorno obligatorias estan definidas. Exit 0 sin arrancar nada.
# Requiere un .env con VALHALLA_DATA_DIR apuntando a una ruta existente (puede ser /tmp).
- id: compose_config
cmd: >
cd apps/footprint_geo_stack &&
VALHALLA_DATA_DIR=/tmp/valhalla_e2e_stub docker compose config --quiet
timeout_s: 10
severity: critical
# por que: unico check sin dependencia de Docker running ni datos reales.
# Detecta errores de yaml, variables no definidas, servicios mal referenciados.
# --- CHECK 2: compose pull (dry-run de imagenes) ---
# Verifica que las imagenes declaradas existen en los registros publicos.
# No arranca contenedores. Util para detectar tags inexistentes o cambios de imagen.
# severity: warning — requiere acceso a ghcr.io y Docker Hub.
- id: compose_pull
cmd: >
cd apps/footprint_geo_stack &&
VALHALLA_DATA_DIR=/tmp/valhalla_e2e_stub docker compose pull --dry-run 2>&1 |
grep -v "^#" | head -20
timeout_s: 60
severity: warning
expect_exit: 0
# por que: detecta si las imagenes han sido eliminadas o el tag :latest cambio.
# No es gate critico porque depende de red externa (registries).
# --- CHECK 3: postgis health ---
# Levanta solo el contenedor PostGIS y verifica pg_isready.
# Usa un proyecto e2e separado para no interferir con la instancia productiva.
# severity: warning — requiere Docker daemon activo.
- id: postgis_health
cmd: >
cd apps/footprint_geo_stack &&
VALHALLA_DATA_DIR=/tmp/valhalla_e2e_stub
docker compose -p footprint_e2e up -d postgis &&
sleep 8 &&
docker exec better_maps_postgis_footprint_e2e
pg_isready -U geoserver -d gis 2>/dev/null ||
docker exec $(docker ps --filter "name=footprint_e2e" --filter "ancestor=postgis/postgis:16-3.4" -q | head -1)
pg_isready -U geoserver -d gis
timeout_s: 45
severity: warning
# por que: PostGIS es la dependencia base de Martin. Si no arranca o pg_isready
# falla, todos los checks de tiles/queries fallan en cascada.
# cleanup: ver check compose_down al final.
# --- CHECK 4: martin health endpoint ---
# Con PostGIS sano, levanta Martin y verifica /health.
# Martin ya tiene el healthcheck nativo declarado en docker-compose.yml.
# severity: warning — depende de PostGIS y Docker.
- id: martin_health
cmd: >
cd apps/footprint_geo_stack &&
VALHALLA_DATA_DIR=/tmp/valhalla_e2e_stub
docker compose -p footprint_e2e up -d martin &&
sleep 5 &&
curl -sf --retry 5 --retry-delay 3 http://127.0.0.1:3000/health
health: "http://127.0.0.1:3000/health"
timeout_s: 60
severity: warning
expect_stdout_contains: ""
# por que: Martin es el tile server principal (MVT). Si /health responde con 200,
# la conexion con PostGIS y la capa de tiles esta operativa.
# --- CHECK 5: martin catalog (tablas PostGIS expuestas) ---
# Verifica que Martin descubre tablas en PostGIS y expone el catalogo.
# Respuesta esperada: JSON con lista de sources (puede ser [] si no hay tablas aun).
# severity: warning — respuesta depende de datos cargados en PostGIS.
- id: martin_catalog
cmd: >
curl -sf http://127.0.0.1:3000/catalog |
python3 -c "import sys, json; d=json.load(sys.stdin); print(f'sources: {len(d.get(\"tiles\", d) if isinstance(d, dict) else [])}')"
timeout_s: 15
severity: warning
# por que: diagnostica que Martin puede leer el schema de PostGIS.
# No requiere datos cargados — un catalogo vacio es valido.
# --- CHECK 6: valhalla status ---
# Verifica que Valhalla arranca y responde al endpoint /status.
# CRITICO: Valhalla necesita VALHALLA_DATA_DIR con tiles reales para responder.
# El check usa /tmp/valhalla_e2e_stub como stub — Valhalla arrancara pero
# puede tardar o fallar si no hay tiles. Por eso severity: warning.
# Para un gate real, VALHALLA_DATA_DIR debe apuntar a los datos reales.
- id: valhalla_status
cmd: >
cd apps/footprint_geo_stack &&
VALHALLA_DATA_DIR=/tmp/valhalla_e2e_stub
docker compose -p footprint_e2e up -d valhalla &&
sleep 20 &&
curl -sf --retry 3 --retry-delay 5 http://127.0.0.1:8002/status
timeout_s: 90
severity: warning
# por que: Valhalla carga tiles en memoria al arrancar (~30-90s segun tamanio).
# Con datos de Espana completos el boot es lento. En e2e con stub /tmp,
# el container arranca pero puede reportar "no tiles loaded" — aceptable.
# --- CHECK 7: valhalla route (smoke con coordenadas Madrid→Barcelona) ---
# Envia una peticion de ruta real a Valhalla.
# Solo ejecutar si VALHALLA_DATA_DIR apunta a datos reales (no stub).
# severity: warning — depende de tiles de Espana cargados.
- id: valhalla_route_smoke
cmd: >
curl -sf -X POST http://127.0.0.1:8002/route
-H 'Content-Type: application/json'
-d '{"locations":[{"lat":40.4168,"lon":-3.7038},{"lat":41.3874,"lon":2.1686}],"costing":"auto","directions_options":{"language":"es-ES"}}'
| python3 -c "import sys, json; r=json.load(sys.stdin); print(f'trip_km: {r[\"trip\"][\"summary\"][\"length\"]:.1f}')"
timeout_s: 30
severity: warning
# por que: verifica que la ruta Madrid→Barcelona resuelve con datos reales.
# Si falla (tiles stub o no cargados), no bloquea — es diagnostico.
# Con tiles reales deberia devolver ~600km.
# --- CHECK 8: cleanup ---
# Para y elimina los contenedores e2e para no dejar estado sucio.
# Siempre severity: warning — si falla la limpieza no es gate critico.
- id: compose_down_e2e
cmd: >
cd apps/footprint_geo_stack &&
VALHALLA_DATA_DIR=/tmp/valhalla_e2e_stub
docker compose -p footprint_e2e down --volumes --remove-orphans 2>&1 | tail -5
timeout_s: 30
severity: warning
# por que: limpia contenedores + volumen postgis-data del proyecto e2e.
# Evita acumulacion de containers parados entre runs de e2e.
# ---------------------------------------------------------------------------
# CHECKS OMITIDOS Y POR QUE
# ---------------------------------------------------------------------------
# ops_audit (fn-recopilador): OMITIDO — la app no tiene operations.db.
# Es un stack docker-compose, no una app con ciclo reactivo propio.
#
# build step: OMITIDO — no hay codigo fuente que compilar. Entry point es
# docker-compose.yml. El unico "build" es docker compose pull.
#
# pytest / go test: OMITIDO — no hay directorio tests/, no hay codigo Python/Go.
#
# tile server externo / API externa: OMITIDO por diseno — todos los checks
# van contra localhost. Los datos de tiles (Espana) son locales.
#
# Valhalla isochrone/matrix checks: OMITIDO en este wave — smoke basico
# con /route es suficiente para el gate. Anadir en wave 4 si se estabiliza
# la carga de tiles en e2e.
# ---------------------------------------------------------------------------
# ACTIVACION GRADUAL SUGERIDA:
#
# Wave A (critico puro, sin Docker):
# - compose_config
#
# Wave B (con Docker, sin datos):
# - compose_config + compose_pull + postgis_health + martin_health
#
# Wave C (stack completo con datos reales en VALHALLA_DATA_DIR):
# - todos los checks (incluyendo valhalla_route_smoke)
#
# Para CI en aurgi-pc: setear VALHALLA_DATA_DIR en el entorno del runner.
@@ -0,0 +1,111 @@
# e2e_checks proposal — metabase_registry
# app_id: metabase_registry
# lang: py
# stack: Python + httpx + argparse (no venv propio, usa python/.venv del repo)
# entry: apps/metabase_registry/main.py
# date: 2026-05-19
# issue: 0121a wave 3
#
# Notas de deteccion:
# - lang=py, framework=httpx (requirements.txt: httpx>=0.27.0)
# - Tres scripts ejecutables: main.py, create_registry_dashboard.py,
# create_apps_dashboard.py. Sin pyproject.toml, sin tests/.
# - NO es service (sin tag service, sin puerto HTTP propio).
# - operations.db presente con schema completo (11 tablas + schema_migrations).
# - Credenciales: en .env y env vars, NUNCA en checks. Todos los checks
# son mock-only (import + syntax + dry-run sin conexion a Metabase real).
# - Sin tests/ → check 'tests' OMITIDO (regla: no inventar tests inexistentes).
#
# REGLAS APLICADAS:
# - Sin credenciales reales en ningun cmd.
# - Todos los checks son idempotentes y terminan solos (sin &).
# - python/.venv del repo padre (ruta absoluta para claridad; adaptar si se
# crea venv propio en la app).
# - ops_audit incluido porque operations.db existe y tiene 2 entities + assertions.
e2e_checks_suggested:
# --- Check 1: import ---
# Verifica que el modulo main.py es importable y sus dependencias del registry
# (python/functions/metabase/) estan disponibles sin errores de import.
# No conecta a Metabase — solo resuelve imports.
- id: import
cmd: >
cd /home/lucas/fn_registry/apps/metabase_registry &&
/home/lucas/fn_registry/python/.venv/bin/python3 -c
"import sys, os;
sys.path.insert(0, os.path.join(os.getcwd(), '..', '..', 'python', 'functions'));
from metabase import MetabaseClient, metabase_create_card, metabase_create_dashboard, metabase_update_dashboard;
from metabase.client import metabase_auth;
from metabase.databases import metabase_add_database, metabase_list_databases;
print('imports OK')"
expect_stdout_contains: "imports OK"
timeout_s: 15
severity: critical
# por que: si los imports del registry fallan, ningun script funciona.
# detecta: renombrado de funciones metabase_*, rotura de __init__.py, httpx no instalado.
# --- Check 2: cli_help ---
# Verifica que el parser CLI de main.py esta intacto.
# argparse imprime usage sin necesitar credenciales ni conexion.
- id: cli_help
cmd: >
cd /home/lucas/fn_registry/apps/metabase_registry &&
/home/lucas/fn_registry/python/.venv/bin/python3 main.py --help
expect_stdout_contains: "metabase_registry"
expect_exit: 0
timeout_s: 10
severity: critical
# por que: si --help falla, el CLI esta roto (argparse error o import error previo).
# --- Check 3: syntax_check (todos los scripts) ---
# Compila los tres scripts con py_compile sin ejecutarlos.
# Detecta SyntaxError y NameError de nivel modulo antes de cualquier deploy.
- id: syntax_check
cmd: >
cd /home/lucas/fn_registry/apps/metabase_registry &&
/home/lucas/fn_registry/python/.venv/bin/python3 -m py_compile
main.py create_registry_dashboard.py create_apps_dashboard.py
create_script_navegador_dashboard.py &&
echo "syntax OK"
expect_stdout_contains: "syntax OK"
timeout_s: 10
severity: critical
# por que: los 4 scripts no tienen tests unitarios; py_compile es el gate
# mas ligero antes de un run real. Detecta typos, variables no definidas
# a nivel modulo, imports ciclicos.
# --- Check 4: dry_run_parser ---
# Ejercita el parser con credenciales ficticias para verificar que
# los defaults de env vars y la logica de build_parser() funcionan.
# Falla INTENCIONALMENTE en autenticacion (no hay Metabase disponible)
# pero debe mostrar el mensaje de error de auth, no un traceback de Python.
# severity: warning porque el fallo esperado viene de red, no del codigo.
- id: dry_run_parser
cmd: >
cd /home/lucas/fn_registry/apps/metabase_registry &&
METABASE_URL=http://127.0.0.1:19999
METABASE_ADMIN_EMAIL=test@example.com
METABASE_ADMIN_PASSWORD=fake_password_for_e2e
/home/lucas/fn_registry/python/.venv/bin/python3 main.py
--url http://127.0.0.1:19999
--admin-email test@example.com
--admin-password fake_password_for_e2e
2>&1 | head -5
expect_stdout_contains: "[metabase_registry]"
expect_exit: 1
timeout_s: 15
severity: warning
# por que: verifica que el flujo run() arranca (auth, log(), log_err()),
# no que Metabase este activo. exit 1 es esperado (sin servidor en :19999).
# Si sale exit 2 (argparse error) o traceback sin el prefijo → regresion.
# --- Check 5: ops_audit ---
# Invoca fn-recopilador sobre operations.db de esta app.
# operations.db tiene schema completo (schema_migrations + 11 tablas),
# 2 entities y assertions declaradas.
- id: ops_audit
ref: "fn-recopilador:apps/metabase_registry"
severity: warning
# por que: operations.db existe y tiene datos vivos. El recopilador valida
# integridad referencial, snapshots al dia y assertions activas evaluadas.
# warning porque la app no depende de operations.db para su funcion principal.
@@ -0,0 +1,121 @@
# e2e_checks proposal — script_navegador
# app_id: script_navegador
# lang: go (NOTE: app.md declara lang:go, no Python — peticion usaba "Python" pero la app es Go)
# stack: Go + CDP browser functions del registry + gopkg.in/yaml.v3 + go-sqlite3
# date: 2026-05-19
# issue: 0121a wave 3
# autor: fn-recopilador (design-e2e)
#
# INSTRUCCIONES DE USO:
# Copiar el bloque e2e_checks: al frontmatter de apps/script_navegador/app.md
# DESPUES de revision humana. El recopilador NO escribe directamente en app.md.
#
# ERROR CRITICO DETECTADO (independiente de e2e):
# apps/script_navegador/registry.db existe — viola la regla db_locations.md.
# registry.db SOLO debe existir en la raiz del repo fn_registry/.
# Accion: rm apps/script_navegador/registry.db
# Posible causa: fn ops init o go run cwd resolvio mal el path al inicializar
# la ops DB y creo un registry.db vacio como side effect.
e2e_checks:
# -----------------------------------------------------------------------
# CHECK 1: build
# Por que: verifica que el modulo Go compila con CGO (go-sqlite3) y las
# dependencias del registry (replace fn-registry => /home/lucas/fn_registry).
# Sin esto nada funciona. El binario se deja en /tmp para no contaminar el dir.
# -----------------------------------------------------------------------
- id: build
cmd: >
cd /home/lucas/fn_registry/apps/script_navegador &&
CGO_ENABLED=1 go build -tags fts5 -o /tmp/script_navegador_e2e .
timeout_s: 120
# -----------------------------------------------------------------------
# CHECK 2: cli_help
# Por que: verifica que el binario arranca, parsea flags y sale limpiamente
# cuando falta --script. Sin Chrome ni conexion real. Exit 1 esperado
# (el binario imprime "error: --script es obligatorio" y sale con 1).
# -----------------------------------------------------------------------
- id: cli_help
cmd: "/tmp/script_navegador_e2e 2>&1 || true"
expect_stdout_contains: "--script es obligatorio"
timeout_s: 10
# -----------------------------------------------------------------------
# CHECK 3: syntax_yaml
# Por que: valida que los ejemplos YAML del repo son parseable por el propio
# binario (flag --script con archivo valido + forzar fallo de conexion CDP
# para que no intente Chrome real). Usa un ejemplo que no necesita red.
# Exit 1 esperado al no haber Chrome, pero DEBE fallar despues de "X pasos",
# no antes (significa que el YAML se parseo bien).
# -----------------------------------------------------------------------
- id: syntax_yaml
cmd: >
/tmp/script_navegador_e2e
--script /home/lucas/fn_registry/apps/script_navegador/examples/busqueda_google.yaml
--port 19222
2>&1 || true
expect_stdout_contains: "busqueda_google"
timeout_s: 15
# -----------------------------------------------------------------------
# CHECK 4: chrome_detect (severity: warning)
# Por que: detecta si chrome.exe de Windows esta disponible desde WSL.
# NO arranca Chrome ni navega. Solo verifica presencia del ejecutable.
# Marcado warning porque CI/CD sin Windows no tendra chrome.exe — no debe
# bloquear el merge, solo informar al humano.
# -----------------------------------------------------------------------
- id: chrome_detect
cmd: >
ls "/mnt/c/Program Files/Google/Chrome/Application/chrome.exe" 2>/dev/null &&
echo "chrome_found" ||
(ls "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe" 2>/dev/null &&
echo "chrome_found_x86") ||
echo "chrome_not_found"
expect_stdout_contains: "chrome"
severity: warning
timeout_s: 5
# -----------------------------------------------------------------------
# CHECK 5: ops_schema
# Por que: verifica que operations.db existe y tiene las tablas obligatorias
# del schema fn_operations (executions, entities, relations, logs).
# NO requiere Chrome. Detecta drift de migraciones.
# -----------------------------------------------------------------------
- id: ops_schema
cmd: >
sqlite3 /home/lucas/fn_registry/apps/script_navegador/operations.db
"SELECT name FROM sqlite_master WHERE type='table'
AND name IN ('entities','relations','executions','logs','assertions','assertion_results')
ORDER BY name;" 2>/dev/null
expect_stdout_contains: "executions"
timeout_s: 10
# -----------------------------------------------------------------------
# CHECK 6: ops_audit
# Por que: invoca al fn-recopilador para auditoria completa de operations.db
# (integridad referencial, snapshots, assertions activas, etc.).
# -----------------------------------------------------------------------
- id: ops_audit
ref: "fn-recopilador:apps/script_navegador"
# -----------------------------------------------------------------------
# CHECKS OMITIDOS y por que:
#
# - smoke (Chrome real):
# Requiere Chrome Windows corriendo con --remote-debugging-port.
# No determinista en CI. Moverlo a suite manual o suite "slow" con tag.
# Si se quiere en e2e: chrome_detect debe pasar primero y el check
# debe lanzar chrome.exe headless (--headless=new) y cerrar al final.
#
# - wslpath_convert:
# wslpath es stdlib WSL, sin logica en el binario propia — no necesita
# check separado. Cubierto implicitamente por chrome_detect.
#
# - unit tests (go test):
# No hay archivos *_test.go en el directorio. Si se anaden en el futuro,
# agregar:
# - id: tests
# cmd: "cd /home/lucas/fn_registry/apps/script_navegador && go test -count=1 ./..."
# timeout_s: 60
# -----------------------------------------------------------------------
@@ -0,0 +1,78 @@
# Propuesta e2e_checks para apps/services_monitor
# Generado por fn-recopilador modo design-e2e
# Fecha: 2026-05-19
# Issue: 0121a wave 3
#
# Diagnostico:
# app_id=services_monitor, lang=cpp, framework=imgui (fn::run_app)
# domain=tools, version=0.1.0
# modulos: main.cpp + http_client.cpp (TCP raw, no libcurl)
# deps externas: fn_module_data_table (issue 0097), ws2_32 (WIN32)
# vendor: vendor/nlohmann/json.hpp (header-only, bundled)
# HTTP client: HttpClient propio sobre sockets POSIX/WIN32
# target API: services_api en 127.0.0.1:8485 — GET /api/services, POST /api/check
# tag 'service': NO (es frontend GUI, no daemon)
# operations.db: NO usa (ops_audit: OMITIDO)
# tests/: NO (directorio ausente, check tests: OMITIDO)
# --self-test: fn::run_app no parsea argv (piloto 0120 confirmado)
# appicon.ico: PRESENTE (phosphor=pulse, accent=#10b981)
# integration check: services_api en :8485 — dependencia externa; severity=warning
#
# Patron: C++ ImGui — checks estructurales sin lanzar GUI ni GPU.
# El check de integracion (integration_api) es warning porque services_api
# puede estar parada en el entorno de CI y no debe bloquear el gate.
app_id: services_monitor
e2e_checks:
# Build: compila el target services_monitor via cmake.
# Valida main.cpp + http_client.cpp + enlace con fn_module_data_table
# (data_table::render, issue 0097) y ws2_32 en WIN32.
# Detecta regresiones de API en data_table o cambios de firma en http_client.h.
- id: build
cmd: "cmake --build /home/lucas/fn_registry/cpp/build/windows --target services_monitor -j"
timeout_s: 300
severity: critical
# Verifica que el .exe existe tras el build.
# Detecta casos donde cmake sale con exit 0 pero el linker fallo silenciosamente
# (ha ocurrido con fn_module_data_table cuando el target es condicional via
# if(TARGET fn_module_data_table) sin hacer REQUIRED).
- id: binary_exists
cmd: "test -f /home/lucas/fn_registry/cpp/build/windows/apps/services_monitor/services_monitor.exe"
timeout_s: 5
severity: critical
# Verifica que el .ico esta presente junto al fuente de la app.
# add_imgui_app genera services_monitor_appicon.rc que windres embebe en el .exe;
# si el .ico falta el build pasa pero el .exe queda sin icono (phosphor=pulse
# accent=#10b981 segun app.md). Visible al copiar a Desktop/apps/.
- id: icon_exists
cmd: "test -f /home/lucas/fn_registry/apps/services_monitor/appicon.ico"
timeout_s: 5
severity: warning
# Integration check: si services_api esta corriendo en :8485, GET /api/services
# debe responder 200 con un JSON que contenga la clave "services".
# Severity WARNING: services_api puede no estar activa en CI. Este check sirve
# como smoke de conectividad y parseo de respuesta, no como gate de merge.
# Para activarlo en entornos donde services_api siempre corre, escalar a critical.
- id: integration_api
cmd: >
curl -sf --max-time 5 http://127.0.0.1:8485/api/services
| python3 -c "import sys,json; d=json.load(sys.stdin); assert 'services' in d, 'key services missing'"
timeout_s: 10
severity: warning
# Justificacion de checks incluidos / omitidos:
#
# | check | razon |
# |-----------------|-------|
# | build | valida compilacion de main.cpp + http_client.cpp + linkado data_table |
# | binary_exists | detecta linker silencioso cuando fn_module_data_table es condicional |
# | icon_exists | app.md declara phosphor+accent; .ico debe existir para windres |
# | integration_api | app es un cliente HTTP puro; sin conexion a services_api no hay datos |
# | ops_audit | OMITIDO — no usa operations.db |
# | tests | OMITIDO — sin directorio tests/ ni *_test.* detectados |
# | self_test | OMITIDO — fn::run_app no parsea argv (confirmado piloto 0120) |
# | smoke (GUI) | OMITIDO — app GUI, requiere display + GPU, no viable en CI headless |
@@ -0,0 +1,149 @@
# Propuesta e2e_checks para apps/tables_qa
# Generado por fn-recopilador modo design-e2e
# app_id: tables_qa
# Issue: 0121a wave 3
# Fecha: 2026-05-19
#
# Diagnostico:
# lang=cpp, framework=imgui (fn::run_app), domain=tools
# toolchain: mingw-w64 (cross-compile Windows desde WSL) — mismo toolchain que el resto del ecosistema
# modulos propios: main.cpp + qa_state + qa_panel + test_suite + perf_tests + 10 tabs (tab_*.cpp)
# dependencia clave: fn_module_data_table (target CMake opcional — linked si existe)
# Enlaza via: target_link_libraries(tables_qa PRIVATE fn_module_data_table)
# Si fn_module_data_table no existe, el build procede sin el modulo (tabs muestran stubs).
# sin frontend/ — no hay pnpm/vite
# sin tests/ ni pytest — suite propia en test_suite.cpp (run_test_suite(), 10 checks in-process)
# sin migrations/ — no usa BD propia
# sin operations.db — no usa el ciclo reactivo de operations (ops_audit: OMITIDO)
# sin tag 'service' — no expone HTTP (smoke/health: OMITIDO)
# appicon.ico: PRESENTE en apps/tables_qa/appicon.ico
#
# FLAG --self-test:
# Parseado en main.cpp (L77-84) pero MARCADO como WIP fase 2 TBD.
# Retorno actual: siempre exit 0 con mensaje "SKIPPED (fase 2 TBD)".
# El self-test headless real no esta implementado — requiere init parcial del
# framework (logger) + imgui_test_engine (fase 2 del issue 0108).
# Dado que exit 0 es garantizado por el stub, el check se incluye como WARNING:
# verifica que el binario acepta el flag sin crash y confirma el estado WIP.
# Se podra ascender a critical cuando la fase 2 este implementada.
#
# test_suite.cpp (in-process):
# run_test_suite() ejecuta 10 smoke tests sobre la API publica de data_table.
# Tests: TableInput construction, ColumnSpec enums, BadgeRule/ChipRule fields,
# State default-constructible, TableEvent enums, ColorScale config, Duration
# thresholds, Button setup, Multi-table input, ColorStop ordering.
# NO requiere display ni contexto GL — opera solo sobre estructuras C++ en memoria.
# Sin embargo, se invoca desde el QA panel en runtime (boton "Run Tests"),
# NO desde argv. Por tanto NO hay un --run-tests CLI flag que pueda usarse
# como check headless directo. El check tests_binary_link (ver abajo) verifica
# que el modulo data_table linka sin error como proxy del test suite.
#
# BUILD path: cmake --build cpp/build --target tables_qa -j
# BINARY path: cpp/build/apps/tables_qa/tables_qa (Linux/WSL)
# o cpp/build/windows/apps/tables_qa/tables_qa.exe (Windows cross)
# app.md documenta el run command como:
# ./cpp/build/apps/tables_qa/tables_qa (Linux/WSL nativo)
# No se detecta referencia a build de Windows en app.md — se usa build nativo WSL.
#
# Patron: C++ ImGui app testbed (QA visual, sin modo capture propio, sin HTTP)
app_id: tables_qa
e2e_checks:
# Build del target tables_qa en el directorio de build WSL nativo.
# Enlaza fn_module_data_table (data_table::render, TQL, renderers, etc.) si el
# target existe. Este check valida: (a) los 10 tabs compilan sin error, (b) la
# API publica de data_table_cpp es ABI-compatible con las cabeceras usadas en
# los tabs, (c) ninguna TU del modulo rompe ODR.
# Es el build gate de data_table v2.0+ para issue 0081 BeginTable migration.
- id: build
cmd: "cmake --build /home/lucas/fn_registry/cpp/build --target tables_qa -j"
timeout_s: 300
severity: critical
# Nota: si fn_module_data_table aun no esta buildado, cmake lo buildara como
# dependencia transitiva antes de tables_qa (order dado por target_link_libraries).
# Verifica que el binario existe tras el build.
# cmake --build puede retornar exit 0 en rebuilds parciales sin producir binario
# si el target ya esta up-to-date pero el archivo fue borrado manualmente.
- id: binary_exists
cmd: "test -f /home/lucas/fn_registry/cpp/build/apps/tables_qa/tables_qa"
timeout_s: 5
severity: critical
# Prueba el flag --self-test declarado en main.cpp.
# Estado actual (v0.1.0): stub WIP que imprime "SKIPPED (fase 2 TBD)" y sale exit 0.
# El check confirma: (a) el binario acepta el flag sin SIGSEGV ni abort,
# (b) el logger se inicializa correctamente antes del early exit,
# (c) exit 0 consistente con el contrato del stub.
# Marcado WARNING porque el test suite real no esta corriendo — cuando fase 2
# implemente --self-test real con imgui_test_engine, ascender a critical y
# añadir expect_stdout_contains para verificar resultados concretos.
- id: self_test_stub
cmd: "/home/lucas/fn_registry/cpp/build/apps/tables_qa/tables_qa --self-test"
timeout_s: 15
expect_exit: 0
expect_stdout_contains: "SKIPPED"
severity: warning
# Cuando fase 2 este lista, cambiar expect_stdout_contains a "pass" o similar
# y ascender severity a critical.
# Verifica que el .ico esta presente junto al fuente.
# add_imgui_app genera tables_qa_appicon.rc que windres incluye en el .exe
# (recurso .rsrc). Si appicon.ico falta, el build WSL pasa pero el .exe
# Windows queda sin icono embebido. Fallo aqui detecta borrado accidental
# del .ico antes de cross-compile.
- id: icon_exists
cmd: "test -f /home/lucas/fn_registry/apps/tables_qa/appicon.ico"
timeout_s: 5
severity: warning
# Verifica que los 10 tabs estan declarados en tabs.h como funciones render_*.
# tables_qa crece anadiendo tabs (10 en v0.1.0: basic, renderers, buttons,
# color_rules, dots, joins, tql, drill, events, compat).
# Un tab anadido en tab_*.cpp pero no declarado en tabs.h produce linker error
# solo si main.cpp lo referencia; este check detecta drift entre tabs.h y
# el conteo esperado sin necesitar build.
# Cuenta "render_" en tabs.h como proxy del numero de tabs declarados.
- id: tabs_declared
cmd: >
count=$(grep -c 'render_' /home/lucas/fn_registry/apps/tables_qa/tabs.h 2>/dev/null);
echo "render_ declarations in tabs.h: $count";
test "$count" -ge 10
timeout_s: 5
severity: warning
# Nota: si se añaden tabs futuros, el umbral -ge 10 es minimo; no necesita
# actualizarse salvo que se eliminen tabs (lo que requeriria revision manual).
# Verifica que CMakeLists.txt lista los 10 tab_*.cpp en add_imgui_app.
# Un tab_foo.cpp creado pero no añadido al CMakeLists no se compila y sus
# funciones quedan como undefined symbols (detectado en link, no en compile).
# Este check estático es mas rapido que el build completo y da feedback antes.
- id: cmakelists_tab_srcs
cmd: >
count=$(grep -c '^ tab_' /home/lucas/fn_registry/apps/tables_qa/CMakeLists.txt 2>/dev/null);
echo "tab_*.cpp in CMakeLists: $count";
test "$count" -ge 10
timeout_s: 5
severity: warning
# Justificacion por check:
# | check | razon |
# |---------------------|------------------------------------------------------------------------------------|
# | build | enlaza fn_module_data_table — gate de API data_table v2+ para issue 0081 |
# | binary_exists | confirma que cmake produjo binario (no solo exit 0) |
# | self_test_stub | verifica flag --self-test sin crash; estado WIP documentado; escala a critical |
# | icon_exists | .ico requerido para windres cross-compile; faltante no rompe build WSL |
# | tabs_declared | detecta drift entre tabs.h y numero esperado de tabs del QA testbed |
# | cmakelists_tab_srcs | detecta tab_*.cpp creado pero no registrado en add_imgui_app(...) |
#
# checks OMITIDOS y razon:
# | check | razon de omision |
# |----------------|------------------------------------------------------------------------------------|
# | ops_audit | no usa operations.db — no hay bucle reactivo en esta app |
# | smoke/health | no es service, no expone HTTP — es testbed GUI |
# | capture_mode | no implementado — "Export golden" en app.md es boton UI, no flag CLI |
# | | (tab_compat.cpp L: "TBD: requires capture API integration") |
# | run_test_suite | run_test_suite() es in-process vía botón UI, no accessible via CLI flag |
# | pytest | sin tests/ dir, sin pytest |
# | perf_test | perf_tests son in-process (run_perf_test via UI), no CLI invocable headless |