Files
motor-de-encuestas/sprints/sprint-4/ETAPA_4C_PROMPT.md

124 lines
6.3 KiB
Markdown

# ETAPA 4C — Motor de resolución de flujo (módulo puro, cliente)
## 1. Objetivo
Construir el motor que interpreta el esquema declarativo del formulario y resuelve
la secuencia de pantallas según el estado de respuestas. Es un módulo puro y aislado
en `lib/`, sin dependencias de React ni del DOM — entrada→salida determinista,
testeable con Node. El componente (Etapa 4D) lo consume; el motor no conoce al componente.
## 2. Contexto previo
- ADR-005: la lógica de flujo vive en el esquema (datos). El motor la interpreta.
- El esquema v3 está en la DB: questions con `type`, `conditional_rules`,
`instance_generator`, `instance_of`, `hint`, más filas `type='section'`.
- Decisión confirmada: el motor corre en el CLIENTE (interpretación de flujo, no validación
de seguridad — esa va server-side en 4G).
- Decisión confirmada: las secciones (`type='section'`) son PANTALLAS propias en el grafo.
- La lógica de v2 (`lib/conditional.ts`, `survey-form.tsx`) es INCOMPATIBLE y se reemplaza:
- v2 evalúa AND (`rules.every`); v3 necesita OR entre condiciones de ocultamiento.
- v2 solo conoce `eq`/`eq_any` y acción `show`; v3 necesita `contains`, `eq_sole`, `not_in`, acción `hide`.
- v2 infiere secciones por regex de prefijo; v3 las tiene como datos.
- El comportamiento esperado está validado en el mockup `wizard_formulario_mapeo_v3.html`
(función `buildVisible` y navegación) — usar como referencia de comportamiento, NO de arquitectura.
## 3. DECISIONES YA TOMADAS — no consultar de nuevo
- Motor puro en `lib/` (proponé el nombre: ej. `lib/form-engine.ts`), sin React/DOM.
- Vocabulario de operadores: `eq`, `eq_any`, `not_in` (escalares), `contains`, `eq_sole` (array).
- Acciones: `show`, `hide`.
- Combinación: múltiples reglas en el array de una pregunta se evalúan en OR.
(Una pregunta se oculta si CUALQUIER regla `hide` aplica; se muestra si CUALQUIER regla `show` aplica.
Definí la semántica precisa de show+hide combinados y documentala.)
- Secciones = pantallas propias en el grafo.
- Instancias: 4.1 (`instance_generator=true`) genera N instancias; las preguntas con
`instance_of='4.1'` se repiten una vez por instancia activa, en orden por familiar
(familiar1: 4.2→4.3, familiar2: 4.2→4.3, ...) como en el mockup.
- Estado de respuestas con clave compuesta `question_code:instance_id` (instancias) o
`question_code` con `instance_id='default'` (normales).
## 4. Tareas
### 4.1 Tipos del motor (`lib/types.ts` ampliado o nuevo)
Definir/ampliar:
- `ConditionalRule`: operadores y acciones completos del vocabulario v3.
- `FormSchema`: la representación del formulario que el motor consume (secciones, preguntas,
reglas, instanciación) — derivada de las filas de `questions`.
- `WizardState`: respuestas (con instancias), instancia activa, pantalla actual.
- `Screen`: una pantalla resoluble (sección-intro | pregunta | pregunta-de-instancia | fin).
### 4.2 Evaluador de reglas
Reescribir la evaluación (reemplaza `lib/conditional.ts`):
- Implementar los 5 operadores y 2 acciones.
- `contains` / `eq_sole` operan sobre respuestas array (multiple_choice).
- Semántica OR documentada y correcta para el caso `r_hide_ning_sn`.
- Función pura: `(rule, answers) => boolean` y `(question, answers) => 'show'|'hide'`.
### 4.3 Resolución del grafo de pantallas
Función pura que dado el esquema + estado devuelve la lista ordenada de pantallas visibles:
- Expande instancias (4.2/4.3 por cada familiar activo declarado en 4.1).
- Aplica visibilidad (oculta secciones/preguntas según reglas).
- Incluye las pantallas de sección.
- Equivale conceptualmente al `buildVisible()` del mockup, pero como módulo puro.
### 4.4 Navegación
Funciones puras `next(state, schema)` y `back(state, schema)` que devuelven el nuevo
estado (pantalla actual actualizada), resolviendo saltos. Identificar la pantalla actual
por ID estable, no por índice (lección del mockup: el índice se desincroniza cuando
cambian las instancias).
### 4.5 Carga del esquema
Actualizar la query (`app/page.tsx`) para traer las 3 columnas nuevas
(`hint`, `instance_generator`, `instance_of`). Transformar las filas de `questions`
en el `FormSchema` que consume el motor.
### 4.6 Tests del motor (Node, sin navegador)
Tests puros que verifiquen:
- Recorrido completo (todos los vínculos) genera las pantallas esperadas.
- "Solo niño sin discapacidad" (eq_sole) → recorrido liviano correcto (5.3, 8.4, 9.1, 9.4).
- "Ninguna de las anteriores" (contains) → salta a sección 10.
- 3.1='No' oculta 3.2-3.5.
- 3 familiares → 6 pantallas de instancia en orden por familiar.
- Navegación next/back coherente cuando cambian las instancias.
## 5. Entregables (DoD)
- [ ] Motor puro en `lib/` sin dependencias de React/DOM.
- [ ] Los 5 operadores y 2 acciones implementados y testeados.
- [ ] Resolución de grafo con instancias y secciones-pantalla.
- [ ] Navegación por ID estable, no por índice.
- [ ] Query actualizada con las 3 columnas nuevas.
- [ ] Tests Node que cubren los recorridos del punto 4.6, todos en verde.
- [ ] NO se toca el componente todavía (es 4D) — el motor se entrega standalone + tests.
## 6. Qué reportar
```
Verificado:
- Motor en [archivo], puro (sin React/DOM) ✓
- Operadores implementados: eq, eq_any, not_in, contains, eq_sole ✓
- Acciones: show, hide ✓ — semántica de combinación: [descripción]
- Tests: N/N en verde
- recorrido completo ✓
- solo niño (eq_sole) → 5.3/8.4/9.1/9.4 ✓
- ninguna (contains) → salta S10 ✓
- 3.1=No oculta 3.2-3.5 ✓
- 3 familiares → 6 pantallas en orden ✓
- next/back coherente ✓
Asumido:
- [supuestos de diseño del motor]
```
## 7. Qué NO hacer
- ❌ No poner lógica de flujo en un componente React (el motor es puro, lib/).
- ❌ No tocar el componente de formulario todavía (es 4D).
- ❌ No implementar validación de seguridad acá (es 4G, server-side).
- ❌ No usar índices numéricos para la pantalla actual — usar ID estable.
- ❌ No tocar v2.1.0-stable ni el seed.
## 8. Versionado
Commit sugerido:
```
feat(engine): motor de resolución de flujo declarativo [4C]
Módulo puro que interpreta el esquema v3 y resuelve pantallas.
5 operadores (eq, eq_any, not_in, contains, eq_sole), acciones show/hide.
Instancias de vínculo y secciones-pantalla. Navegación por ID estable.
Tests Node cubren los 3 recorridos. Reemplaza lib/conditional.ts de v2.
```