# Guía del Verificador USEE

## Sistema de Validación Automática de Piezas

**Versión 1.0**

---

## Propósito

El Verificador USEE es el guardián del protocolo. Su función es garantizar que toda pieza publicada cumple con los estándares definidos, protegiendo tanto a los usuarios que confían en las piezas como a los creadores que construyen sobre ellas.

### Principios del Verificador

| Principio | Aplicación |
|-----------|------------|
| **Útil** | Solo verifica lo que impacta la funcionalidad real |
| **Simple** | Cualquiera puede entender por qué una pieza pasó o falló |
| **Esencial** | Verifica requisitos del protocolo, no preferencias estéticas |
| **Estable** | Los criterios no cambian arbitrariamente |

### Garantías

Una pieza que pasa la verificación garantiza:

1. Tiene todos los archivos obligatorios
2. Los metadatos están completos y son válidos
3. Se ejecuta correctamente con la entrada de ejemplo
4. Todas las pruebas incluidas pasan
5. Respeta el formato de comunicación USEE

---

## Niveles de Verificación

El verificador evalúa las piezas en tres niveles progresivos:

```
Nivel 1: Estructura
    ↓
Nivel 2: Funcionalidad
    ↓
Nivel 3: Calidad
```

### Nivel 1: Estructura

Verifica que la pieza tiene la forma correcta.

- Archivos obligatorios presentes
- Formato de metadatos válido
- Documentación completa

**Resultado:** La pieza existe y está bien formada.

### Nivel 2: Funcionalidad

Verifica que la pieza funciona.

- El ejecutable responde
- Procesa la entrada de ejemplo correctamente
- Todas las pruebas pasan
- Los errores se manejan apropiadamente

**Resultado:** La pieza hace lo que dice que hace.

### Nivel 3: Calidad

Verifica que la pieza cumple estándares de calidad.

- Tiempo de respuesta aceptable
- Documentación clara y completa
- Manejo de errores informativo
- Adherencia a convenciones USEE

**Resultado:** La pieza es confiable para uso en producción.

---

## Verificaciones de Nivel 1: Estructura

### 1.1 Archivos Obligatorios

| Verificación | Criterio |
|--------------|----------|
| `PIEZA.usee` existe | El archivo debe existir en la raíz |
| `LEEME.md` existe | El archivo debe existir en la raíz |
| `ENTRADA.ejemplo` existe | El archivo debe existir en la raíz |
| `SALIDA.ejemplo` existe | El archivo debe existir en la raíz |
| `ejecutar` existe | El archivo debe existir en la raíz |
| `ejecutar` es ejecutable | Permisos de ejecución activos |
| `pruebas/` existe | El directorio debe existir |
| Pruebas mínimas presentes | Al menos 4 casos de prueba |

**Código de verificación:**

```
verificar_archivos_obligatorios(ruta_pieza):
    archivos_requeridos = [
        "PIEZA.usee",
        "LEEME.md",
        "ENTRADA.ejemplo",
        "SALIDA.ejemplo",
        "ejecutar"
    ]
    
    para cada archivo en archivos_requeridos:
        si no existe(ruta_pieza + "/" + archivo):
            fallar("Archivo obligatorio faltante: " + archivo)
    
    si no es_ejecutable(ruta_pieza + "/ejecutar"):
        fallar("El archivo 'ejecutar' no tiene permisos de ejecución")
    
    si no existe_directorio(ruta_pieza + "/pruebas"):
        fallar("Directorio 'pruebas/' no encontrado")
    
    casos_prueba = contar_casos_prueba(ruta_pieza + "/pruebas")
    si casos_prueba < 4:
        fallar("Se requieren al menos 4 casos de prueba, encontrados: " + casos_prueba)
```

### 1.2 Metadatos PIEZA.usee

#### Campos Obligatorios

| Campo | Validación |
|-------|------------|
| `nombre` | No vacío, solo minúsculas y guiones |
| `version` | Formato X.Y.Z |
| `creador` | Formato de correo válido |
| `fecha_creacion` | Formato YYYY-MM-DD |
| `descripcion_corta` | No vacío, máximo 100 caracteres |
| `descripcion_larga` | No vacío |
| `categoria` | Valor de lista predefinida |
| `accion` | No vacío, formato "verbo sustantivo" |
| `entrada_descripcion` | No vacío |
| `salida_descripcion` | No vacío |
| `lenguaje` | No vacío |
| `costo_por_uso` | Número >= 0 |
| `moneda` | Código ISO 4217 (ej: usd, mxn, eur) |
| `modelo_cobro` | Valor válido: por_llamada, por_minuto, por_registro |

**Categorías válidas:**

```
autenticacion
almacenamiento
comunicacion
datos
documentos
imagenes
integracion
pagos
reportes
seguridad
utilidades
otro
```

**Código de verificación:**

```
verificar_metadatos(ruta_pieza):
    contenido = leer_ftu(ruta_pieza + "/PIEZA.usee")
    
    campos_obligatorios = [
        "nombre", "version", "creador", "fecha_creacion",
        "descripcion_corta", "descripcion_larga", "categoria",
        "accion", "entrada_descripcion", "salida_descripcion",
        "lenguaje", "costo_por_uso", "moneda", "modelo_cobro"
    ]
    
    para cada campo en campos_obligatorios:
        si campo no está en contenido:
            fallar("Campo obligatorio faltante en PIEZA.usee: " + campo)
        si contenido[campo] está vacío:
            fallar("Campo obligatorio vacío en PIEZA.usee: " + campo)
    
    # Validaciones específicas
    si no coincide(contenido["nombre"], "^[a-z][a-z0-9-]*$"):
        fallar("Nombre inválido: solo minúsculas, números y guiones")
    
    si no coincide(contenido["version"], "^[0-9]+\.[0-9]+\.[0-9]+$"):
        fallar("Versión inválida: debe ser formato X.Y.Z")
    
    si no es_correo_valido(contenido["creador"]):
        fallar("Creador debe ser un correo electrónico válido")
    
    si longitud(contenido["descripcion_corta"]) > 100:
        fallar("Descripción corta excede 100 caracteres")
    
    si contenido["categoria"] no está en CATEGORIAS_VALIDAS:
        fallar("Categoría inválida: " + contenido["categoria"])
    
    si no es_numero(contenido["costo_por_uso"]) o numero(contenido["costo_por_uso"]) < 0:
        fallar("Costo por uso debe ser un número >= 0")
```

### 1.3 Documentación LEEME.md

#### Secciones Obligatorias

| Sección | Identificación |
|---------|----------------|
| Título | Línea que inicia con `# ` |
| Qué Hace | Encabezado `## Qué Hace` |
| Qué No Hace | Encabezado `## Qué No Hace` |
| Uso Rápido | Encabezado `## Uso Rápido` |
| Entrada | Encabezado `## Entrada` |
| Salida | Encabezado `## Salida` |
| Errores Comunes | Encabezado `## Errores Comunes` |

**Código de verificación:**

```
verificar_documentacion(ruta_pieza):
    contenido = leer_archivo(ruta_pieza + "/LEEME.md")
    
    secciones_requeridas = [
        "# ",           # Título (cualquier título)
        "## Qué Hace",
        "## Qué No Hace",
        "## Uso Rápido",
        "## Entrada",
        "## Salida",
        "## Errores Comunes"
    ]
    
    para cada seccion en secciones_requeridas:
        si seccion no está en contenido:
            fallar("Sección faltante en LEEME.md: " + seccion)
    
    # Verificar que Qué No Hace tiene contenido
    contenido_que_no_hace = extraer_seccion(contenido, "## Qué No Hace")
    si contenido_que_no_hace está vacío:
        fallar("La sección 'Qué No Hace' no puede estar vacía")
```

### 1.4 Pruebas Mínimas

#### Casos Obligatorios

| Caso | Archivos Requeridos |
|------|---------------------|
| Caso básico | `caso-basico.entrada`, `caso-basico.salida` |
| Caso completo | `caso-completo.entrada`, `caso-completo.salida` |
| Error entrada vacía | `error-entrada-vacia.entrada`, `error-entrada-vacia.salida`, `error-entrada-vacia.codigo` |
| Error campo faltante | `error-campo-faltante.entrada`, `error-campo-faltante.salida`, `error-campo-faltante.codigo` |

**Código de verificación:**

```
verificar_pruebas_minimas(ruta_pieza):
    ruta_pruebas = ruta_pieza + "/pruebas"
    
    casos_obligatorios = [
        ("caso-basico", falso),
        ("caso-completo", falso),
        ("error-entrada-vacia", verdadero),
        ("error-campo-faltante", verdadero)
    ]
    
    para cada (nombre, es_error) en casos_obligatorios:
        entrada = ruta_pruebas + "/" + nombre + ".entrada"
        salida = ruta_pruebas + "/" + nombre + ".salida"
        
        si no existe(entrada):
            fallar("Prueba obligatoria faltante: " + nombre + ".entrada")
        si no existe(salida):
            fallar("Prueba obligatoria faltante: " + nombre + ".salida")
        
        si es_error:
            codigo = ruta_pruebas + "/" + nombre + ".codigo"
            si no existe(codigo):
                fallar("Archivo de código de salida faltante: " + nombre + ".codigo")
```

---

## Verificaciones de Nivel 2: Funcionalidad

### 2.1 Ejecutable Responde

| Verificación | Criterio |
|--------------|----------|
| `--ayuda` funciona | Retorna código 0 y muestra texto |
| `--version` funciona | Retorna código 0 y muestra versión |
| Versión coincide | La versión mostrada coincide con PIEZA.usee |

**Código de verificación:**

```
verificar_ejecutable_responde(ruta_pieza):
    ejecutable = ruta_pieza + "/ejecutar"
    
    # Verificar --ayuda
    resultado = ejecutar_comando(ejecutable + " --ayuda")
    si resultado.codigo != 0:
        fallar("El comando --ayuda no retornó código 0")
    si resultado.salida está vacía:
        fallar("El comando --ayuda no produjo salida")
    
    # Verificar --version
    resultado = ejecutar_comando(ejecutable + " --version")
    si resultado.codigo != 0:
        fallar("El comando --version no retornó código 0")
    
    # Verificar coincidencia de versión
    version_ejecutable = resultado.salida.trim()
    version_metadatos = leer_ftu(ruta_pieza + "/PIEZA.usee")["version"]
    si version_ejecutable != version_metadatos:
        fallar("Versión del ejecutable (" + version_ejecutable + 
               ") no coincide con PIEZA.usee (" + version_metadatos + ")")
```

### 2.2 Ejemplo Funciona

| Verificación | Criterio |
|--------------|----------|
| Procesa entrada de ejemplo | No produce error |
| Salida coincide | La salida coincide con SALIDA.ejemplo |
| Código de salida es 0 | Ejecución exitosa |

**Código de verificación:**

```
verificar_ejemplo_funciona(ruta_pieza):
    ejecutable = ruta_pieza + "/ejecutar"
    entrada = leer_archivo(ruta_pieza + "/ENTRADA.ejemplo")
    salida_esperada = leer_archivo(ruta_pieza + "/SALIDA.ejemplo")
    
    resultado = ejecutar_comando(ejecutable, stdin=entrada)
    
    si resultado.codigo != 0:
        fallar("La entrada de ejemplo produjo error (código " + resultado.codigo + ")")
    
    si not salidas_equivalentes(resultado.salida, salida_esperada):
        fallar("La salida no coincide con SALIDA.ejemplo")
```

### 2.3 Pruebas Pasan

| Verificación | Criterio |
|--------------|----------|
| Todas las pruebas ejecutan | Ninguna produce error inesperado |
| Salidas coinciden | Cada salida coincide con la esperada |
| Códigos coinciden | Los códigos de salida son los esperados |

**Código de verificación:**

```
verificar_pruebas_pasan(ruta_pieza):
    ejecutable = ruta_pieza + "/ejecutar"
    ruta_pruebas = ruta_pieza + "/pruebas"
    
    archivos_entrada = listar_archivos(ruta_pruebas, "*.entrada")
    
    para cada archivo_entrada en archivos_entrada:
        nombre_caso = extraer_nombre(archivo_entrada)
        
        entrada = leer_archivo(archivo_entrada)
        salida_esperada = leer_archivo(ruta_pruebas + "/" + nombre_caso + ".salida")
        
        # Código esperado: 0 para casos normales, leer de archivo para errores
        si existe(ruta_pruebas + "/" + nombre_caso + ".codigo"):
            codigo_esperado = numero(leer_archivo(ruta_pruebas + "/" + nombre_caso + ".codigo"))
        sino:
            codigo_esperado = 0
        
        resultado = ejecutar_comando(ejecutable, stdin=entrada, timeout=30)
        
        # Verificar código de salida
        si resultado.codigo != codigo_esperado:
            fallar("Prueba '" + nombre_caso + "': código esperado " + 
                   codigo_esperado + ", obtenido " + resultado.codigo)
        
        # Verificar salida (stdout para éxito, stderr para error)
        si codigo_esperado == 0:
            salida_real = resultado.stdout
        sino:
            salida_real = resultado.stderr
        
        si no salidas_equivalentes(salida_real, salida_esperada):
            fallar("Prueba '" + nombre_caso + "': salida no coincide")
    
    reportar("Todas las pruebas pasaron: " + longitud(archivos_entrada) + " casos")
```

### 2.4 Comparación de Salidas

La comparación de salidas debe ser flexible para ignorar diferencias no significativas:

```
salidas_equivalentes(salida_real, salida_esperada):
    # Parsear ambas como FTU
    registros_real = parsear_ftu(salida_real)
    registros_esperada = parsear_ftu(salida_esperada)
    
    # Deben tener la misma cantidad de registros
    si longitud(registros_real) != longitud(registros_esperada):
        retornar falso
    
    para i en rango(longitud(registros_real)):
        real = registros_real[i]
        esperado = registros_esperada[i]
        
        # Todas las claves esperadas deben existir con valores equivalentes
        para cada clave en esperado:
            si clave no está en real:
                retornar falso
            
            si no valores_equivalentes(real[clave], esperado[clave]):
                retornar falso
    
    retornar verdadero

valores_equivalentes(valor_real, valor_esperado):
    # Comodín: * coincide con cualquier valor
    si valor_esperado == "*":
        retornar verdadero
    
    # Comparación exacta después de normalizar espacios
    retornar normalizar(valor_real) == normalizar(valor_esperado)
```

**Uso de comodín en pruebas:**

```
# SALIDA.ejemplo con valores dinámicos
estado: ok
sesion_id: *
expira: *
usuario_id: usr_001
```

El comodín `*` permite que campos como `sesion_id` (que cambia en cada ejecución) pasen la verificación.

---

## Verificaciones de Nivel 3: Calidad

### 3.1 Tiempo de Respuesta

| Verificación | Criterio |
|--------------|----------|
| Caso básico | Completa en menos de 5 segundos |
| Promedio | Promedio de 10 ejecuciones < 2 segundos |
| Consistencia | Desviación estándar < 50% del promedio |

**Código de verificación:**

```
verificar_tiempo_respuesta(ruta_pieza):
    ejecutable = ruta_pieza + "/ejecutar"
    entrada = leer_archivo(ruta_pieza + "/ENTRADA.ejemplo")
    
    tiempos = []
    
    para i en rango(10):
        inicio = tiempo_actual()
        resultado = ejecutar_comando(ejecutable, stdin=entrada)
        fin = tiempo_actual()
        
        si resultado.codigo != 0:
            fallar("Error durante prueba de rendimiento en iteración " + i)
        
        tiempos.agregar(fin - inicio)
    
    # Verificar que ninguna ejecución exceda 5 segundos
    si maximo(tiempos) > 5.0:
        fallar("Tiempo de respuesta excede 5 segundos: " + maximo(tiempos))
    
    # Verificar promedio
    promedio = suma(tiempos) / longitud(tiempos)
    si promedio > 2.0:
        advertir("Tiempo de respuesta promedio alto: " + promedio + "s")
    
    # Verificar consistencia
    desviacion = desviacion_estandar(tiempos)
    si desviacion > promedio * 0.5:
        advertir("Tiempo de respuesta inconsistente: desviación " + desviacion)
    
    reportar("Tiempo de respuesta promedio: " + promedio + "s")
```

### 3.2 Manejo de Errores

| Verificación | Criterio |
|--------------|----------|
| Errores a stderr | Los errores se escriben a stderr, no stdout |
| Formato de error | Los errores siguen el formato FTU con campos obligatorios |
| Códigos consistentes | Los códigos de salida siguen la convención USEE |

**Código de verificación:**

```
verificar_manejo_errores(ruta_pieza):
    ejecutable = ruta_pieza + "/ejecutar"
    
    # Ejecutar con entrada vacía
    resultado = ejecutar_comando(ejecutable, stdin="")
    
    si resultado.codigo == 0:
        fallar("La entrada vacía debería producir error")
    
    si resultado.stdout no está vacío:
        advertir("Los errores deberían ir a stderr, no stdout")
    
    # Verificar formato de error
    error = parsear_ftu(resultado.stderr)
    
    campos_error_obligatorios = ["estado", "codigo", "mensaje"]
    para cada campo en campos_error_obligatorios:
        si campo no está en error[0]:
            fallar("Error mal formado: falta campo '" + campo + "'")
    
    si error[0]["estado"] != "error":
        fallar("El campo 'estado' debe ser 'error' en respuestas de error")
    
    # Verificar código de salida válido
    si resultado.codigo < 1 o resultado.codigo > 99:
        advertir("Código de salida fuera del rango recomendado (1-99): " + resultado.codigo)
```

### 3.3 Documentación Clara

| Verificación | Criterio |
|--------------|----------|
| Descripción corta es corta | Máximo 100 caracteres, una oración |
| Qué No Hace tiene contenido | Al menos 2 elementos listados |
| Errores documentados | Todos los códigos de error de pruebas están en LEEME.md |
| Ejemplos presentes | La sección Uso Rápido tiene código ejecutable |

**Código de verificación:**

```
verificar_documentacion_clara(ruta_pieza):
    metadatos = leer_ftu(ruta_pieza + "/PIEZA.usee")
    leeme = leer_archivo(ruta_pieza + "/LEEME.md")
    
    # Verificar descripción corta
    desc = metadatos["descripcion_corta"]
    si longitud(desc) > 100:
        fallar("Descripción corta excede 100 caracteres")
    si desc.contiene(". "):  # Más de una oración
        advertir("Descripción corta debería ser una sola oración")
    
    # Verificar Qué No Hace
    seccion = extraer_seccion(leeme, "## Qué No Hace")
    lineas_contenido = contar_lineas_no_vacias(seccion)
    si lineas_contenido < 2:
        advertir("La sección 'Qué No Hace' debería listar al menos 2 cosas")
    
    # Verificar que errores de pruebas estén documentados
    codigos_error = extraer_codigos_error_pruebas(ruta_pieza + "/pruebas")
    seccion_errores = extraer_seccion(leeme, "## Errores Comunes")
    
    para cada codigo en codigos_error:
        si codigo no está en seccion_errores:
            advertir("Código de error '" + codigo + "' no documentado en LEEME.md")
    
    # Verificar ejemplo ejecutable
    seccion_uso = extraer_seccion(leeme, "## Uso Rápido")
    si no contiene_bloque_codigo(seccion_uso):
        advertir("La sección 'Uso Rápido' debería incluir un ejemplo de código")
```

### 3.4 Adherencia a Convenciones

| Verificación | Criterio |
|--------------|----------|
| Claves FTU válidas | Todas las claves de salida siguen reglas FTU |
| Booleanos correctos | Usa `si`/`no`, no `true`/`false` |
| Fechas ISO | Las fechas usan formato ISO 8601 |
| Sin campos extra en errores | Los errores solo tienen campos documentados |

**Código de verificación:**

```
verificar_convenciones(ruta_pieza):
    ejecutable = ruta_pieza + "/ejecutar"
    entrada = leer_archivo(ruta_pieza + "/ENTRADA.ejemplo")
    
    resultado = ejecutar_comando(ejecutable, stdin=entrada)
    salida = parsear_ftu(resultado.stdout)
    
    para cada registro en salida:
        para cada (clave, valor) en registro:
            # Verificar formato de clave
            si no coincide(clave, "^[a-z][a-z0-9_.]*$"):
                fallar("Clave inválida en salida: '" + clave + "'")
            
            # Verificar booleanos
            si valor.lower() en ["true", "false"]:
                advertir("Usar 'si'/'no' en lugar de 'true'/'false': " + clave)
            
            # Verificar fechas
            si parece_fecha(valor) y no es_iso8601(valor):
                advertir("Fecha no sigue formato ISO 8601: " + clave + "=" + valor)
```

---

## Reporte de Verificación

El verificador produce un reporte estructurado en formato FTU:

### Estructura del Reporte

```
# Reporte de Verificación USEE
# Generado: 2025-01-15T10:30:00Z

pieza.nombre: login
pieza.version: 1.0.0
pieza.ruta: /ruta/a/login

verificacion.fecha: 2025-01-15T10:30:00Z
verificacion.version_verificador: 1.0.0
verificacion.resultado: aprobado

nivel1.resultado: aprobado
nivel1.archivos: ok
nivel1.metadatos: ok
nivel1.documentacion: ok
nivel1.pruebas_minimas: ok

nivel2.resultado: aprobado
nivel2.ejecutable: ok
nivel2.ejemplo: ok
nivel2.pruebas: ok
nivel2.pruebas_total: 8
nivel2.pruebas_pasaron: 8

nivel3.resultado: aprobado
nivel3.tiempo_respuesta_promedio_ms: 45
nivel3.manejo_errores: ok
nivel3.documentacion: ok
nivel3.convenciones: ok

advertencias: 0
---
# Sin advertencias
```

### Reporte con Errores

```
pieza.nombre: login
pieza.version: 1.0.0

verificacion.fecha: 2025-01-15T10:30:00Z
verificacion.resultado: rechazado

nivel1.resultado: rechazado
nivel1.archivos: error
nivel1.metadatos: ok
nivel1.documentacion: ok
nivel1.pruebas_minimas: ok

errores: 1
---
tipo: error
nivel: 1
verificacion: archivos
codigo: archivo_faltante
mensaje: Archivo obligatorio faltante: ENTRADA.ejemplo
```

### Reporte con Advertencias

```
pieza.nombre: login
pieza.version: 1.0.0

verificacion.fecha: 2025-01-15T10:30:00Z
verificacion.resultado: aprobado_con_advertencias

nivel1.resultado: aprobado
nivel2.resultado: aprobado
nivel3.resultado: aprobado_con_advertencias

advertencias: 2
---
tipo: advertencia
nivel: 3
verificacion: documentacion
codigo: que_no_hace_corto
mensaje: La sección 'Qué No Hace' debería listar al menos 2 cosas
---
tipo: advertencia
nivel: 3
verificacion: convenciones
codigo: booleano_incorrecto
mensaje: Usar 'si'/'no' en lugar de 'true'/'false': activo
campo: activo
valor_actual: true
valor_sugerido: si
```

---

## Estados de Verificación

| Estado | Significado | Puede Publicar |
|--------|-------------|----------------|
| `aprobado` | Todos los niveles pasaron sin advertencias | ✓ Sí |
| `aprobado_con_advertencias` | Todos los niveles pasaron con advertencias | ✓ Sí |
| `rechazado` | Al menos un nivel falló | ✗ No |

### Reglas de Aprobación

```
determinar_estado(resultados):
    # Si hay errores en cualquier nivel, rechazar
    si resultados.nivel1.tiene_errores():
        retornar "rechazado"
    si resultados.nivel2.tiene_errores():
        retornar "rechazado"
    si resultados.nivel3.tiene_errores():
        retornar "rechazado"
    
    # Si hay advertencias, aprobar con advertencias
    si resultados.tiene_advertencias():
        retornar "aprobado_con_advertencias"
    
    # Todo limpio
    retornar "aprobado"
```

---

## Ejecución del Verificador

### Comando

```bash
usee-verificar /ruta/a/pieza
```

### Opciones

| Opción | Descripción |
|--------|-------------|
| `--nivel=N` | Ejecutar solo hasta el nivel N (1, 2, o 3) |
| `--reporte=RUTA` | Guardar reporte en archivo |
| `--json` | Salida en formato JSON |
| `--silencioso` | Solo mostrar resultado final |
| `--verbose` | Mostrar detalles de cada verificación |
| `--timeout=S` | Timeout en segundos para pruebas (default: 30) |

### Ejemplos de Uso

```bash
# Verificación completa
usee-verificar ./mi-pieza

# Solo verificar estructura
usee-verificar ./mi-pieza --nivel=1

# Guardar reporte
usee-verificar ./mi-pieza --reporte=reporte.usee

# Verificación silenciosa para CI/CD
usee-verificar ./mi-pieza --silencioso
echo $?  # 0 = aprobado, 1 = rechazado
```

### Salida en Terminal

```
$ usee-verificar ./login

═══════════════════════════════════════════════════════
  Verificador USEE v1.0.0
  Pieza: login v1.0.0
═══════════════════════════════════════════════════════

Nivel 1: Estructura
  ✓ Archivos obligatorios
  ✓ Metadatos PIEZA.usee
  ✓ Documentación LEEME.md
  ✓ Pruebas mínimas (4 casos)

Nivel 2: Funcionalidad
  ✓ Ejecutable responde (--ayuda, --version)
  ✓ Ejemplo funciona
  ✓ Pruebas pasan (8/8)

Nivel 3: Calidad
  ✓ Tiempo de respuesta (45ms promedio)
  ✓ Manejo de errores
  ⚠ Documentación (1 advertencia)
  ✓ Convenciones

───────────────────────────────────────────────────────
Advertencias (1):
  • La sección 'Qué No Hace' debería listar al menos 2 cosas
───────────────────────────────────────────────────────

Resultado: APROBADO CON ADVERTENCIAS

La pieza puede publicarse en el marketplace.
Considere atender las advertencias para mejorar la calidad.
```

---

## Verificación en CI/CD

### GitHub Actions

```yaml
name: Verificar Pieza USEE

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  verificar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Instalar verificador USEE
        run: |
          curl -sSL https://usee.dev/instalar.sh | sh
      
      - name: Verificar pieza
        run: |
          usee-verificar . --silencioso
      
      - name: Generar reporte
        if: always()
        run: |
          usee-verificar . --reporte=reporte.usee
      
      - name: Subir reporte
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: reporte-verificacion
          path: reporte.usee
```

### Script de Pre-commit

```bash
#!/bin/bash
# .git/hooks/pre-commit

echo "Verificando pieza USEE..."

if ! usee-verificar . --nivel=2 --silencioso; then
    echo "Error: La pieza no pasa la verificación de Nivel 2"
    echo "Ejecute 'usee-verificar .' para ver detalles"
    exit 1
fi

echo "Verificación pasada"
exit 0
```

---

## Verificación Continua en Marketplace

Una vez publicada, las piezas son verificadas periódicamente:

### Verificaciones Periódicas

| Frecuencia | Verificación |
|------------|--------------|
| Cada hora | Disponibilidad (si tiene adaptador HTTP) |
| Diario | Pruebas completas |
| Semanal | Análisis de dependencias |
| Mensual | Revisión de compatibilidad |

### Métricas Calculadas

| Métrica | Cálculo |
|---------|---------|
| `tiempo_operacional` | Días desde publicación sin cambios incompatibles |
| `cambios_promedio_mes` | Actualizaciones en últimos 30 días |
| `disponibilidad` | Porcentaje de verificaciones exitosas |
| `tiempo_respuesta_p95` | Percentil 95 de tiempos de respuesta |

### Alertas

El marketplace notifica al creador cuando:

- Una verificación diaria falla
- El tiempo de respuesta aumenta significativamente
- Una dependencia tiene vulnerabilidades conocidas
- La disponibilidad cae bajo 99%

---

## Resumen

El Verificador USEE garantiza que cada pieza:

| Nivel | Garantía |
|-------|----------|
| **1. Estructura** | Existe y está bien formada |
| **2. Funcionalidad** | Hace lo que dice que hace |
| **3. Calidad** | Es confiable para producción |

Solo las piezas que pasan los tres niveles pueden publicarse en el marketplace, asegurando que los usuarios siempre encuentren piezas que funcionan.

---

**Verificador USEE**: Confianza automatizada.
