feat(engine): motor de resolución de flujo declarativo [4C]
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user