feat(engine): motor de resolución de flujo declarativo [4C]

This commit is contained in:
markosbenitez
2026-06-23 07:21:35 -03:00
parent ed524af16b
commit eba93db452
2 changed files with 236 additions and 65 deletions

View File

@@ -1,96 +1,143 @@
# BRIEF — Sprint 4: Formulario Wizard v3
# BRIEF — Sprint 4: Formulario Wizard v3 (esquema declarativo)
> Versión objetivo: **3.0.0** · Rama de trabajo: `main` · Preservación: `v2.1.0-stable`
> Versión objetivo: **3.0.0** · Rama: `main` · Preservación: `v2.1.0-stable`
---
## Objetivo en una frase
Reescribir el formulario de encuesta como un wizard pregunta-por-pantalla con
mini-wizard anidado para vínculos familiares, sobre un nuevo instrumento de 10
secciones, habilitando análisis de datos multi-instancia.
Construir el formulario de cuidadores como un wizard pregunta-por-pantalla cuyo
flujo, instancias y condiciones se definen en un **esquema declarativo** (datos),
renderizado por un frontend sin lógica de negocio — funcionando para los dos
clientes inminentes, y en la dirección arquitectónica del motor de formularios.
---
## Decisión arquitectónica rectora (ADR pendiente de registrar)
**El motor de formularios es el producto; la encuesta de cuidadores es su primer
caso de uso.** Por lo tanto, la lógica del flujo del formulario vive en una capa
de **definición declarativa** (datos), no en el presentador ni dispersa en columnas
sueltas de la base.
### Estrategia en dos fases (deuda intencional, registrada — no oculta)
**Fase 1 (este sprint, para el deadline de 10-20 días):**
Se construye el formulario de cuidadores con su flujo definido como esquema
declarativo persistido. El frontend es un renderer de ese esquema — sin reglas
hardcodeadas. La resolución de "qué pantalla sigue" se calcula desde esquema +
estado. NO se construye todavía el intérprete genérico universal.
**Fase 2 (sprints posteriores, post-deadline):**
Se extrae el intérprete a un motor genérico de formularios. Como el formulario de
cuidadores ya está definido como esquema declarativo, se vuelve el primer caso de
prueba del motor sin reescribir el contrato. Registrado en `BACKLOG.md`.
**Por qué esta estrategia:** entrega valor en plazo sin generar retrabajo. La
lógica en datos (no en presentación) es lo que habilita guardado parcial,
reanudación, validación consistente y progreso preciso — la mejor UX — y lo que
hace que la Fase 2 sea generalización, no reescritura.
---
## Alcance (qué entra)
- Nuevo modelo de datos: columna `instance_id` en `answers`, nueva constraint única
- Nuevo instrumento v3 (10 secciones, ~38 preguntas base + preguntas por instancia)
- Motor de wizard: grafo de pantallas, navegación, estado, instancias dinámicas
- Componente de pantalla única (una pregunta por pantalla)
- Mini-wizard anidado para vínculos familiares (pregunta 4.1 → instancias)
- Autocomplete de barrios desde dataset INE/DGEEC (`geo_paraguay.json`)
- Esquema declarativo del formulario de cuidadores (flujo, instancias, condiciones como datos)
- Persistencia del esquema (en seed/DB, versionado)
- `instance_id` en `answers` (Etapa 4A — ya aplicada)
- Motor de resolución de flujo para este formulario (interpreta el esquema)
- Frontend wizard como renderer del esquema (sin reglas de negocio)
- Mini-wizard de vínculos familiares (instancias declaradas en el esquema)
- Autocomplete de barrios desde dataset INE/DGEEC
- Subtítulos del "porqué" por sección
- Submit actualizado para enviar `instance_id` por answer
- Barra de progreso dinámica
- RPCs nuevas para preguntas de vínculo con instancias
- Submit con `instance_id` por answer
- Barra de progreso dinámica (calculada desde el esquema + estado)
- RPCs para preguntas de vínculo con instancias
- Seed v3 limpio (sin migración de datos v2)
---
## Fuera de alcance (explícito)
- ❌ Migración de datos v2.1 → v3 (se decide más adelante, cuando v3 esté estable)
- ❌ Motor genérico universal de formularios (Fase 2 — BACKLOG)
- ❌ Backend de construcción/edición de formularios (sprint posterior)
- ❌ Migración de datos v2.1 → v3 (se decide cuando v3 esté estable)
- ❌ Tocar la rama `v2.1.0-stable`
- ❌ RE Index (sprint posterior)
- ❌ Informe descargable (sprint posterior)
- ❌ Autenticación de `/admin/responses` (TECH-DEBT-008)
- ❌ Backup remoto S3 (TECH-DEBT-006)
---
- ❌ RE Index, informe descargable, auth de /admin/responses, backup S3
## Decisiones ya tomadas (no renegociar)
1. v3 se desarrolla en `main`. v2 queda preservado en `v2.1.0-stable` + tag `v2.1.0`.
2. v3 arranca con seed limpio — sin datos migrados.
3. `instance_id text DEFAULT 'default'` en `answers`. Constraint:
`UNIQUE (response_id, question_id, instance_id)`.
4. Wizard pregunta-por-pantalla para TODO el formulario tras el consentimiento.
5. Mini-wizard de familiares: una pregunta por pantalla, con badge de contexto
"Familiar X de N".
6. Numeración desde Sección 1 (no "Sección A").
7. Barrio: autocomplete para ciudades con datos INE, texto libre para el resto.
8. Texto de consentimiento: el del Excel del instrumento v3 (Sección 1).
9. Versionado SemVer + CHANGELOG + tags de Git en cada versión estable.
10. 2-3 familiares es el caso típico; soportar N sin límite duro.
---
1. v3 en `main`; v2 preservado en `v2.1.0-stable` + tag `v2.1.0`.
2. Lógica de flujo en esquema declarativo (datos), NO en el frontend.
3. Frontend wizard = renderer sin reglas de negocio.
4. Estrategia dos fases: formulario-como-esquema ahora, motor genérico después.
5. v3 arranca con seed limpio, sin datos migrados.
6. `instance_id` ya implementado (4A). Instancias declaradas en el esquema.
7. Wizard pregunta-por-pantalla para todo el formulario tras consentimiento.
8. Mini-wizard de familiares: una pregunta por pantalla, badge "Familiar X de N".
9. Numeración desde Sección 1.
10. Barrio: autocomplete con datos INE, texto libre para el resto.
11. Texto de consentimiento: el del Excel del instrumento v3.
12. SemVer + CHANGELOG + tags en cada versión estable.
13. Migraciones se aplican vía CLI del VPS (`docker exec -i supabase-db psql`).
14. **Motor de flujo (4C): corre en el cliente** como módulo puro y aislado (entrada→salida
determinista, testeable con Node). Interpreta el esquema declarativo; no embebe lógica
en el componente React.
15. **Validación de integridad server-side en el submit (4G): REQUISITO NO NEGOCIABLE.**
El servidor valida contra el esquema que: las preguntas existen, los valores son opciones
válidas, las instancias corresponden a un generador real, y no se inyectan respuestas a
preguntas que el flujo nunca debió mostrar. La validación de cliente es UX, NO seguridad.
Para datos sensibles de salud, confiar solo en validación de cliente sería una falla de
seguridad. Esto NO se difiere a Fase 2.
## Criterios de éxito (checklist)
- [ ] El formulario funciona end-to-end como wizard, una pregunta por pantalla
- [ ] El mini-wizard de familiares genera instancias correctamente (verificable en DB)
- [ ] El flujo del formulario está definido como esquema declarativo persistido
- [ ] El frontend no contiene reglas de negocio del flujo (verificable por revisión)
- [ ] El wizard funciona end-to-end, una pregunta por pantalla
- [ ] El mini-wizard de familiares genera instancias según el esquema
- [ ] Los datos se guardan con `instance_id` correcto por familiar
- [ ] El dashboard sigue funcionando (las preguntas no-instancia usan `instance_id='default'`)
- [ ] Las nuevas RPCs agregan datos de vínculo por instancia
- [ ] El autocomplete de barrios funciona para las ciudades principales
- [ ] La validación visual del wizard coincide con el mockup aprobado
- [ ] `v2.1.0-stable` permanece intacta y restaurable
- [ ] El dashboard sigue funcionando (preguntas no-instancia con `instance_id='default'`)
- [ ] El autocomplete de barrios funciona para ciudades principales
- [ ] La validación visual coincide con el mockup aprobado
- [ ] `v2.1.0-stable` permanece intacta
- [ ] La deuda de Fase 2 está registrada en BACKLOG
---
## Etapas del Sprint 4
| Etapa | Nombre | Entregable | Dependencia |
| Etapa | Nombre | Entregable | Estado |
|---|---|---|---|
| **4.0** | Preservación v2 | Tag v2.1.0, rama stable, dump, CHANGELOG | |
| **4A** | Modelo de datos | Migración `instance_id` + constraint | 4.0 |
| **4B** | Seed v3 | Instrumento v3 completo en seed.sql + geo JSON | 4A |
| **4C** | Motor del wizard | Grafo de pantallas, estado, navegación (lógica) | 4B |
| **4D** | Componente de pantalla | UI una-pregunta-por-pantalla + secciones | 4C |
| **4E** | Mini-wizard instancias | Vínculos 4.1 + pantallas por familiar | 4D |
| **4.0** | Preservación v2 | Tag, rama stable, dump, CHANGELOG | ✅ Completada |
| **4A** | Persistencia instance_id | Migración + DATA_MODEL | ✅ Completada |
| **4B** | Esquema declarativo + seed v3 | Esquema del formulario como datos + geo JSON | |
| **4C** | Motor de resolución de flujo | Intérprete del esquema (este formulario) | 4B |
| **4D** | Frontend renderer | Wizard que renderiza el esquema, una preg/pantalla | 4C |
| **4E** | Instancias de vínculo | Mini-wizard de familiares desde el esquema | 4D |
| **4F** | Autocomplete barrios | Campo barrio con dataset INE | 4D |
| **4G** | Submit con instance_id | Guardado correcto multi-instancia | 4E |
| **4H** | RPCs de vínculo | Agregados de datos por instancia en dashboard | 4G |
| **4I** | Validación e2e + tag v3.0.0 | QA visual completo + release | todas |
---
| **4G** | Submit con instance_id | Guardado multi-instancia | 4E |
| **4H** | RPCs de vínculo | Agregados por instancia en dashboard | 4G |
| **4I** | Validación e2e + tag v3.0.0 | QA visual + release + ADR + BACKLOG Fase 2 | todas |
## Orden de ejecución
4.0 → 4A → 4B → 4C → 4D → (4E ∥ 4F) → 4G → 4H → 4I
Las etapas 4E y 4F pueden ir en paralelo si hay capacidad; si no, 4E primero
(es la más crítica), 4F después.
4B → 4C → 4D → (4E ∥ 4F) → 4G → 4H → 4I
---
## Notas de versionado por etapa
- Cada etapa cierra con un commit versionado descriptivo.
- Las versiones `3.0.0-alpha.N` se pueden usar para hitos intermedios si se
despliega a un entorno de prueba.
- El tag `v3.0.0` se crea solo en la etapa 4I, cuando todo está validado.
## Definición del esquema declarativo (guía para 4B)
El esquema describe el formulario como datos. Estructura conceptual:
```
formulario:
version, secciones[]
seccion:
numero, nombre, descripcion (el "porqué")
preguntas[]
pregunta:
codigo, tipo, enunciado, hint, opciones[], required, sensitive
flujo:
condiciones_visibilidad[] (cuándo se muestra — evaluado por el motor)
genera_instancias? (si esta pregunta crea instancias, ej. 4.1)
pertenece_a_instancia_de? (de qué generador depende, ej. 4.2/4.3 → 4.1)
validaciones[]
```
La forma técnica exacta de persistir esto (columnas en `questions` +
`conditional_rules` JSONB extendido, o tabla de definición de flujo separada)
la decide la Etapa 4B según el esquema actual. Principio: declarativo, versionado,
interpretable por el motor sin conocer el caso de uso.