name: evals # Puerta de calidad CLÍNICA: bloquea el merge si el motor determinista regresa o si la suite # de evaluación cae bajo sus umbrales o registra violaciones de seguridad. # # Este sí filtra por rutas —es el workflow caro— pero el filtro anterior era demasiado # estrecho: nombraba `backend/app/ai/**` y `backend/app/rag/**`, dejando fuera `schemas.py` # (que define `InterpretacionClinica`, la forma misma que las evals puntúan) y `config.py` # (umbrales y ruta de modelo por defecto). Un cambio ahí alteraba la salida evaluada sin # disparar la puerta. Las puertas de código —ruff, pytest, tsc, eslint— viven en `ci.yml`, # que corre en TODOS los PR sin filtro. on: pull_request: paths: - "frontend/**" - "backend/**" - "evals/**" - "data/**" push: branches: [main] # Disparo manual: además de para relanzar tras un fallo de infraestructura, esta puerta va # filtrada por rutas, así que a veces interesa correrla a mano sobre un cambio que el filtro # no coge. Ver la nota en ci.yml. workflow_dispatch: jobs: motor-regresion: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "22" - name: Instalar frontend working-directory: frontend run: npm ci - name: Suite de regresión del motor (vitest) working-directory: frontend run: npm test evals-clinicas: runs-on: ubuntu-latest needs: motor-regresion steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "22" - uses: astral-sh/setup-uv@v5 - name: Sincronizar backend working-directory: backend run: uv sync - name: Instalar deps del motor (para el puente Node) working-directory: frontend run: npm ci # Antes de la puerta, la puerta misma: métricas, rúbrica, umbrales y esquema del dataset # son código sin cobertura de nadie más. Si el medidor está roto, el resultado de la # puerta no significa nada (visto: el simulador dejaba `fuera_de_alcance` sin declarar y # suspendía una métrica de tolerancia cero por su cuenta). - name: Pruebas unitarias de los scripts de evals working-directory: backend run: uv run pytest -q ../evals/tests # En CI real, sustituir --simular por --modelo medgemma apuntando a un endpoint, # o subir un archivo de predicciones generado en un job con GPU. # # Sobre el juez: con --simular se omite a propósito (juzgaría el simulador, no el # modelo). Sobre salidas reales se activa solo, en este orden: CLI de Claude Code (no # existe en el runner), Ollama local (tampoco, salvo que se instale en el job) y SDK de # Claude si ANTHROPIC_API_KEY está en los secrets. Sin ninguno la puerta sigue siendo # válida, sólo más ciega: las métricas deterministas se calculan igual. - name: Ejecutar evals (puerta de CI — split dev) working-directory: backend env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: uv run python ../evals/run_evals.py --simular --split dev # El split reservado no se usa para iterar, pero sí tiene que seguir verde antes de # llegar a main: si sólo se mirara en el despliegue, se descubriría demasiado tarde. - name: Ejecutar evals sobre el split reservado working-directory: backend env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: uv run python ../evals/run_evals.py --simular --split test