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

6.3 KiB

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.