# Validator Quirks — `@modyo/widget-validator`

> **Propósito:** Documentar particularidades conocidas de las herramientas del flujo de generación de widgets, para que el agente las anticipe y evite falsos positivos.
>
> **Audiencia:** agentes IA y desarrolladores que ejecutan el validator vía la Tool MCP `widgets-validate`, vía el hook PostToolUse de Claude Code, o vía `npx @modyo/widget-validator`.

---

## `validateWidget(files)` no soporta directorios vacíos (sigue presente en 0.2.0)

### Síntoma

Cuando se invoca `widgets-validate` con `projectFiles` (en lugar de `projectPath`), el reporte puede contener errores del tipo:

```
Missing required folder: src/hooks
Missing required folder: src/types
```

Aún cuando el código del widget no necesita esos hooks ni esos types — solo el scaffolding del template canonical los declara como estructura esperada.

### Causa

`@modyo/widget-validator` recibe `VirtualFile[]` (objetos `{path, content}`). Los directorios vacíos no tienen representación en ese shape: un directorio sólo "existe" si contiene archivos. Cuando el validator chequea estructura esperada y la carpeta no aparece, reporta `Missing required folder` aunque conceptualmente la carpeta debería existir. Verificado que persiste en `0.2.0` (el código de `validateWidget` sigue escribiendo a un tmp dir y sólo crea los `dirname` de archivos reales).

Bajo el capó, `validateWidget(files)` escribe los archivos a un tmp dir y delega a `validateWidgetPath(tmpDir)`. La pérdida de información ocurre al construir los `VirtualFile[]`, no al ejecutar las reglas.

### Workaround

Incluir un archivo centinela (típicamente `.gitkeep`) en cada directorio estructural vacío al construir `projectFiles`:

```json
[
  { "path": "src/hooks/.gitkeep", "content": "" },
  { "path": "src/types/.gitkeep", "content": "" }
]
```

Esto preserva la presencia del directorio al pasar por el trampolín a disco.

### Cobertura desde el flujo de generación

La Tool `widgets-scaffold` (invocada por el agente a partir del Prompt `widgets-init-project`) clona el template canonical `dynamic-framework/dynamic-react-vite-base-template`. Si el clone incluye `.gitkeep` en las carpetas estructurales requeridas, cualquier `projectFiles` colectado del widget después del scaffolding las incluye naturalmente. **Verificación pendiente** del estado actual del canonical — capturable como parte del PR reemplazo del canonical (Pendiente #15 del Plan Maestro).

### Aplicabilidad

| Caso | ¿Afecta? |
|------|----------|
| Invocar `widgets-validate` con `projectPath` (modo local) | ❌ No — `validateWidgetPath` lee del disco real, los directorios existen físicamente |
| Invocar `widgets-validate` con `projectFiles` sin sentinels | ✅ Sí — falsos positivos posibles |
| Invocar `widgets-validate` con `projectFiles` incluyendo sentinels | ❌ No — workaround aplicado |
| Invocar el CLI standalone `npx @modyo/widget-validator <path>` | ❌ No — equivalente a `validateWidgetPath` |

### Estado upstream

Issue tracked: [`modyo/modyo-widget-validator#1`](https://github.com/modyo/modyo-widget-validator/issues/1) — refactor a filesystem virtual real. Se esperaba en v0.2, pero **`0.2.0` se liberó sin ese refactor** (su cambio fue la convención de carpeta de tests): el constraint sigue vigente. Cuando efectivamente se libere el filesystem virtual, el constraint desaparece y este documento puede archivarse o resignificarse como histórico.

### Decisión que sostiene la documentación

Decisión #24 del Plan Maestro (2026-05-18): el MCP no mitiga el constraint inyectando sentinels sintéticos. Razón principal: preservar separación de responsabilidades (el MCP no conoce internals del paquete consumido). Razón complementaria: hoy faltan datos operativos sobre proporción de uso `projectFiles` vs `projectPath` y frecuencia real de falsos positivos — se recolectan durante las pruebas con widgets complejos (Pendiente #18 del Plan Maestro). Re-evaluable si las pruebas producen falsos positivos en >20% de invocaciones de `widgets-validate`.
