Verificación

El motor de verificación ejecuta checks de aceptación definidos en acceptance.yaml contra el directorio del proyecto. Responde la pregunta: “¿la implementación cumple con la spec?”


Comando

intake verify <SPEC_DIR> -p <PROJECT_DIR> [opciones]
# Verificar con reporte en terminal
intake verify specs/api-de-usuarios/ -p .

# Solo checks con tag "api"
intake verify specs/api-de-usuarios/ -p . -t api -t security

# Formato JUnit para CI
intake verify specs/api-de-usuarios/ -p . -f junit > test-results.xml

# Detenerse en el primer fallo
intake verify specs/api-de-usuarios/ -p . --fail-fast

Estructura de acceptance.yaml

checks:
  - id: check-01
    name: "Tests unitarios pasan"
    type: command
    command: "python -m pytest tests/ -q"
    required: true
    tags: [tests, ci]

  - id: check-02
    name: "Archivo de rutas existe"
    type: files_exist
    paths:
      - src/routes.py
      - src/models.py
    required: true
    tags: [structure]

  - id: check-03
    name: "Endpoints tienen autenticación"
    type: pattern_present
    glob: "src/**/*.py"
    patterns:
      - "auth_required|@login_required|verify_token"
    required: true
    tags: [security]

  - id: check-04
    name: "Sin passwords hardcodeados"
    type: pattern_absent
    glob: "src/**/*.py"
    patterns:
      - "password\\s*=\\s*['\"]\\w+"
    required: true
    tags: [security]

Los 4 tipos de check

command

Ejecuta un comando shell y verifica que el exit code sea 0.

- id: check-tests
  name: "Tests pasan"
  type: command
  command: "python -m pytest tests/ -q"
  required: true
CampoTipoDescripción
commandstringComando shell a ejecutar

El comando se ejecuta en el directorio del proyecto (--project-dir). Se captura stdout y stderr (truncados a 1000 y 500 chars respectivamente).

Timeout: configurable via verification.timeout_per_check (default: 120 segundos).

files_exist

Verifica que todos los archivos listados existen.

- id: check-structure
  name: "Archivos principales existen"
  type: files_exist
  paths:
    - src/main.py
    - src/models.py
    - tests/test_main.py
  required: true
CampoTipoDescripción
pathslist[string]Paths relativos al directorio del proyecto

Falla si cualquiera de los paths no existe.

pattern_present

Verifica que patrones regex existen en archivos que matchean un glob.

- id: check-logging
  name: "Módulos tienen logging"
  type: pattern_present
  glob: "src/**/*.py"
  patterns:
    - "import logging|import structlog"
  required: false
  tags: [quality]
CampoTipoDescripción
globstringPatrón glob para encontrar archivos (ej: src/**/*.py)
patternslist[string]Patrones regex a buscar (case-insensitive)

Falla si algún patrón no se encuentra en algún archivo que matchea el glob.

pattern_absent

Verifica que patrones regex NO existen en archivos que matchean un glob.

- id: check-no-secrets
  name: "Sin secrets hardcodeados"
  type: pattern_absent
  glob: "src/**/*.py"
  patterns:
    - "API_KEY\\s*=\\s*['\"]sk-"
    - "password\\s*=\\s*['\"]\\w{8,}"
  required: true
  tags: [security]
CampoTipoDescripción
globstringPatrón glob para encontrar archivos
patternslist[string]Patrones regex que NO deben existir (case-insensitive)

Falla si algún patrón se encuentra en algún archivo.


Campos comunes de cada check

CampoTipoDefaultDescripción
idstring"unknown"Identificador único del check
namestringmismo que idNombre descriptivo
typestring"command"Tipo de check: command, files_exist, pattern_present, pattern_absent
requiredbooltrueSi es obligatorio. Los checks no-required pueden fallar sin afectar el exit code.
tagslist[string][]Tags para filtrado con --tags

Tags y filtrado

Los checks pueden tener tags para ejecutar subconjuntos:

checks:
  - id: check-tests
    tags: [tests, ci]
    ...
  - id: check-security
    tags: [security, ci]
    ...
  - id: check-docs
    tags: [docs]
    ...
# Solo checks con tag "ci"
intake verify specs/my-spec/ -p . -t ci

# Checks con tag "security" O "tests"
intake verify specs/my-spec/ -p . -t security -t tests

Un check se ejecuta si tiene al menos uno de los tags especificados.


Fail-fast

Con --fail-fast, la verificación se detiene en el primer check requerido que falle:

intake verify specs/my-spec/ -p . --fail-fast

Los checks que no se ejecutaron se cuentan como “skipped” en el reporte.


Formatos de reporte

Terminal (default)

Tabla Rich con colores:

                    Verification Report: my-spec
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━┓
┃ ID        ┃ Check             ┃ Status ┃ Required ┃ Time   ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━┩
│ check-01  │ Tests pasan       │ PASS   │ Yes      │ 1.2s   │
│ check-02  │ Archivos existen  │ PASS   │ Yes      │ 0.0s   │
│ check-03  │ Auth presente     │ FAIL   │ Yes      │ 0.1s   │
└───────────┴───────────────────┴────────┴──────────┴────────┘
  Passed: 2  Failed: 1  Skipped: 0

JSON

intake verify specs/my-spec/ -p . -f json
{
  "spec_name": "my-spec",
  "total_checks": 3,
  "passed": 2,
  "failed": 1,
  "skipped": 0,
  "all_required_passed": false,
  "results": [
    {
      "id": "check-01",
      "name": "Tests pasan",
      "passed": true,
      "required": true,
      "output": "3 passed in 1.2s",
      "duration_ms": 1200
    }
  ]
}

JUnit XML

intake verify specs/my-spec/ -p . -f junit > test-results.xml
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="my-spec" tests="3" failures="1" skipped="0">
    <testcase name="Tests pasan" classname="check-01" time="1.200"/>
    <testcase name="Archivos existen" classname="check-02" time="0.001"/>
    <testcase name="Auth presente" classname="check-03" time="0.100">
      <failure message="Pattern 'auth_required' not found in src/routes.py"/>
    </testcase>
  </testsuite>
</testsuites>

Integración con CI/CD

GitHub Actions

name: Verify Spec Compliance
on: [push, pull_request]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install intake
        run: pip install intake-ai-cli

      - name: Run acceptance checks
        run: intake verify specs/my-feature/ -p . -f junit > test-results.xml

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: test-results.xml

Script verify.sh (via export generic)

Si usas el exporter generic, se genera un verify.sh standalone que no necesita intake instalado:

# Exportar
intake export specs/my-feature/ -f generic -o output/

# Ejecutar directamente
./output/verify.sh /path/to/project

Exit codes

CódigoSignificado
0Todos los checks requeridos pasaron (los opcionales pueden haber fallado)
1Al menos un check requerido falló
2Error de ejecución (spec no encontrada, YAML inválido, etc.)