diff --git a/sprints/sprint-4/BRIEF.md b/sprints/sprint-4/BRIEF.md new file mode 100644 index 0000000..1f7e524 --- /dev/null +++ b/sprints/sprint-4/BRIEF.md @@ -0,0 +1,96 @@ +# BRIEF — Sprint 4: Formulario Wizard v3 + +> Versión objetivo: **3.0.0** · Rama de trabajo: `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. + +--- + +## 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`) +- 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 +- 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) +- ❌ 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) + +--- + +## 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. + +--- + +## 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) +- [ ] 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 + +--- + +## Etapas del Sprint 4 + +| Etapa | Nombre | Entregable | Dependencia | +|---|---|---|---| +| **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 | +| **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 | + +--- + +## 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. + +--- + +## 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. \ No newline at end of file diff --git a/sprints/sprint-4/ETAPA_4A_PROMPT.md b/sprints/sprint-4/ETAPA_4A_PROMPT.md new file mode 100644 index 0000000..5318583 --- /dev/null +++ b/sprints/sprint-4/ETAPA_4A_PROMPT.md @@ -0,0 +1,104 @@ +# ETAPA 4A — Modelo de datos: instance_id en answers + +## 1. Objetivo +Agregar la columna `instance_id` a la tabla `answers` y cambiar la constraint +única para soportar múltiples respuestas a la misma pregunta (una por instancia +de vínculo familiar). Es el cambio de base que habilita todo el wizard v3. + +## 2. Contexto previo +- v3 se desarrolla en `main`. v2 está preservado en `v2.1.0-stable`. +- La tabla `answers` actual tiene constraint `UNIQUE (response_id, question_id)`. +- El wizard v3 genera múltiples respuestas para las preguntas 4.2 y 4.3 (una por + cada familiar declarado en 4.1). Sin `instance_id`, esas respuestas colisionan. +- Las preguntas no-vinculadas (la gran mayoría) usan `instance_id = 'default'`. + +## 3. DECISIONES YA TOMADAS — no consultar de nuevo +- Nombre de la columna: `instance_id`, tipo `text`, `DEFAULT 'default'`, NOT NULL. +- Nueva constraint: `UNIQUE (response_id, question_id, instance_id)`. +- Para preguntas normales: `instance_id = 'default'`. +- Para instancias de vínculo: `instance_id = 'familiar_1'`, `'familiar_2'`, etc. +- Esto es una migración nueva, NO modifica migraciones existentes. +- NO se migran datos v2 — el seed v3 arranca limpio (etapa posterior). + +## 4. Tareas + +### 4.1 Nueva migración +Crear `supabase/migrations/20260620000001_add_instance_id.sql`: + +```sql +-- Sprint 4 (v3.0.0) — instance_id para respuestas multi-instancia +-- Habilita el mini-wizard de vínculos familiares (una respuesta por familiar) + +-- 1. Agregar la columna con default para filas existentes +ALTER TABLE public.answers + ADD COLUMN IF NOT EXISTS instance_id text NOT NULL DEFAULT 'default'; + +-- 2. Eliminar la constraint única vieja (nombre real verificado en DB) +ALTER TABLE public.answers + DROP CONSTRAINT IF EXISTS answers_response_id_question_id_key; + +-- 3. Crear la nueva constraint que incluye instance_id +ALTER TABLE public.answers + ADD CONSTRAINT answers_response_question_instance_key + UNIQUE (response_id, question_id, instance_id); + +-- 4. Índice para consultas por instancia (análisis de vínculos) +CREATE INDEX IF NOT EXISTS idx_answers_instance + ON public.answers (question_id, instance_id) + WHERE instance_id != 'default'; +``` + +### 4.2 Verificar el nombre real de la constraint actual +ANTES de escribir el DROP, verificar el nombre exacto de la constraint única +actual de `answers`. El nombre asumido es `answers_response_id_question_id_key` +(convención Postgres), pero confirmar con: + +```sql +SELECT conname FROM pg_constraint +WHERE conrelid = 'public.answers'::regclass AND contype = 'u'; +``` + +Si el nombre difiere, ajustar el `DROP CONSTRAINT` en la migración. +NO ejecutar la migración en producción — solo crear el archivo. + +### 4.3 Actualizar DATA_MODEL.md +Documentar el cambio en `DATA_MODEL.md`: la tabla `answers` ahora tiene +`instance_id` y la nueva constraint. Explicar el patrón 'default' vs 'familiar_N'. + +## 5. Entregables (DoD) +- [ ] Migración `20260620000001_add_instance_id.sql` creada. +- [ ] Nombre real de la constraint actual verificado y usado en el DROP. +- [ ] `DATA_MODEL.md` actualizado con el nuevo esquema de `answers`. +- [ ] La migración es idempotente (`IF EXISTS` / `IF NOT EXISTS`). +- [ ] NO ejecutada en producción. + +## 6. Qué reportar +``` +Verificado: +- Migración creada ✓ +- Nombre real de constraint actual: [nombre] +- DATA_MODEL.md actualizado ✓ +- Idempotencia confirmada ✓ + +Asumido: +- [supuestos sobre el esquema] + +NO ejecutado en producción (pendiente aprobación del director). +``` + +## 7. Qué NO hacer +- ❌ No ejecutar la migración en la DB de producción. +- ❌ No modificar migraciones existentes. +- ❌ No tocar el seed todavía (es la etapa 4B). +- ❌ No migrar datos de v2. +- ❌ No tocar la rama v2.1.0-stable. + +## 8. Versionado +Commit sugerido al cerrar: +``` +feat(data): agregar instance_id a answers para multi-instancia [4A] + +Habilita respuestas múltiples por pregunta (mini-wizard de vínculos). +Nueva constraint UNIQUE(response_id, question_id, instance_id). +Parte del Sprint 4 hacia v3.0.0. +``` \ No newline at end of file diff --git a/sprints/sprint-4/ETAPA_4B_PROMPT.md b/sprints/sprint-4/ETAPA_4B_PROMPT.md new file mode 100644 index 0000000..9fcff30 --- /dev/null +++ b/sprints/sprint-4/ETAPA_4B_PROMPT.md @@ -0,0 +1,111 @@ +# ETAPA 4B — Esquema declarativo del formulario v3 + seed + +## 1. Objetivo +Definir el formulario de cuidadores v3 como un esquema declarativo persistido: +extender el modelo de `questions` para soportar instanciación y nuevos operadores +de flujo, y cargar el instrumento completo (10 secciones) en el seed. La lógica del +flujo vive en estos datos, no en el frontend (ver ADR-005). + +## 2. Contexto previo +- ADR-005 define la arquitectura: esquema declarativo, frontend renderer sin reglas. +- `instance_id` ya existe en `answers` (Etapa 4A). +- El esquema actual de `questions` ya tiene `conditional_rules` JSONB con operadores + `eq` / `eq_any` y acción `show`, auto-target implícito. +- El contenido exacto del instrumento v3 está validado en el mockup aprobado + (`wizard_formulario_mapeo_v3.html`) y en el Excel `Formulario_Mapeo_Corregido.xlsx`. +- El dataset de barrios está en `geo_paraguay_full.json` (va a `public/data/`). + +## 3. DECISIONES YA TOMADAS — no consultar de nuevo +- Se EXTIENDE el modelo existente, no se crea tabla de definición separada (ADR-005). +- Nuevos campos declarativos en `questions`: + - `instance_generator boolean DEFAULT false` — marca la pregunta que genera instancias (4.1) + - `instance_of text DEFAULT NULL` — código del generador del que depende (4.2/4.3 → '4.1') +- Nuevos operadores en `conditional_rules`: agregar acción `hide` y operador para + expresar el salto "Ninguna de las anteriores → salta a sección final". +- Secciones con nombre y descripción (el "porqué"): representación a definir por Claude Code + según lo más limpio (tabla `sections` o registros con metadata) — proponer antes de ejecutar. +- v3 arranca con seed LIMPIO, sin datos migrados. +- El contenido de preguntas es EXACTAMENTE el del mockup validado. + +## 4. Tareas + +### 4.1 Migración de esquema declarativo +Crear `supabase/migrations/20260620000002_form_schema_v3.sql`: +- Agregar `instance_generator boolean NOT NULL DEFAULT false` a `questions`. +- Agregar `instance_of text` a `questions` (nullable). +- Documentar (comentario SQL) el vocabulario extendido de `conditional_rules`: + operadores `eq`, `eq_any`, `not_in`; acciones `show`, `hide`. +- Idempotente (`IF NOT EXISTS`). + +### 4.2 Representación de secciones +Proponer e implementar cómo persistir las 10 secciones con su nombre y descripción +("Texto de ayuda" del Excel). Reportar la propuesta antes de ejecutar si implica +cambio de esquema. Las descripciones de sección están en el BRIEF y el mockup. + +### 4.3 Seed v3 del instrumento +Reescribir el seed del survey (o crear seed v3 separado) con las 10 secciones y todas +las preguntas EXACTAMENTE como el mockup validado: +- Sección 1: Consentimiento (2 checkboxes: requerido + opcional) +- Sección 2: Datos generales (2.1-2.7) +- Sección 3: Prevalencia discapacidad propia (3.1-3.5; 3.1='No' oculta 3.2-3.5) +- Sección 4: Vinculación familiar (4.1 generador de instancias; 4.2 y 4.3 instance_of='4.1') +- Sección 5: Responsabilidad (5.1-5.4; ocultas si "solo niño sin discapacidad") +- Sección 6: Intensidad (6.1-6.4; idem) +- Sección 7: Impacto laboral (7.1-7.6; idem) +- Sección 8: Impacto económico (8.1-8.4) +- Sección 9: Conciencia organizacional (9.1-9.4) +- Sección 10: Comentarios (10.1) +- Flujo "Ninguna de las anteriores" en 4.1 → salta a Sección 10. +- Todas las opciones, hints ("Podés marcar más de una opción"), y flags is_sensitive + exactamente como el mockup. + +### 4.4 Dataset geográfico +Copiar `geo_paraguay_full.json` a `public/data/geo_paraguay.json` del repo. + +### 4.5 Actualizar SEED_SPEC.md +Documentar el instrumento v3 completo como contrato (Principio 4 / AP.11). + +## 5. Entregables (DoD) +- [ ] Migración de esquema declarativo creada (campos de instanciación). +- [ ] Propuesta de representación de secciones reportada (y aplicada si se aprueba). +- [ ] Seed v3 con las 10 secciones, contenido exacto del mockup. +- [ ] `instance_generator` y `instance_of` correctamente seteados en 4.1/4.2/4.3. +- [ ] Flujo declarativo: 3.1='No' oculta 3.2-3.5; "Ninguno" en 4.1 salta a S10; + "solo niño" oculta S5-S7. +- [ ] `geo_paraguay.json` en `public/data/`. +- [ ] `SEED_SPEC.md` actualizado. +- [ ] NO ejecutado en producción (solo archivos). + +## 6. Qué reportar +``` +Verificado: +- Migración de esquema creada ✓ +- Representación de secciones: [propuesta] +- Seed v3: N preguntas, 10 secciones ✓ +- instance_generator/instance_of correctos ✓ +- Reglas de flujo declarativas: [listar las 3 reglas principales] +- geo JSON en public/data ✓ +- SEED_SPEC.md actualizado ✓ + +Asumido: +- [supuestos sobre representación de secciones y operadores] + +NO ejecutado en producción. +``` + +## 7. Qué NO hacer +- ❌ No ejecutar en producción (lo aplica el director vía CLI del VPS). +- ❌ No poner lógica de flujo en el frontend (es la etapa 4D y será renderer). +- ❌ No migrar datos v2. +- ❌ No tocar v2.1.0-stable. +- ❌ No construir el motor genérico (Fase 2). + +## 8. Versionado +Commit sugerido: +``` +feat(schema): esquema declarativo + seed v3 del formulario [4B] + +Extiende questions con instance_generator/instance_of. +Instrumento v3 completo (10 secciones) como datos declarativos. +Flujo del formulario en el esquema, no en presentación (ADR-005). +``` \ No newline at end of file diff --git a/sprints/sprint-4/PASO_0_PRESERVACION.md b/sprints/sprint-4/PASO_0_PRESERVACION.md new file mode 100644 index 0000000..528c698 --- /dev/null +++ b/sprints/sprint-4/PASO_0_PRESERVACION.md @@ -0,0 +1,95 @@ +# PASO 0 — Preservación de v2.1.0 antes de arrancar Sprint 4 + +> Ejecutar ANTES de tocar nada de v3. Estos pasos preservan el estado actual +> estable como punto de retorno seguro. + +--- + +## Objetivo +1. Crear tag `v2.1.0` sobre el commit actual de `main`. +2. Crear rama `v2.1.0-stable` que preserva el código de v2. +3. Generar un dump de la base de datos de producción y versionarlo en esa rama. +4. Crear `CHANGELOG.md` en `main`. +5. Dejar `main` listo para desarrollo de v3. + +--- + +## Secuencia de comandos + +### 1. Asegurarse de estar en main actualizado +```bash +git checkout main +git pull origin main +git status # debe estar limpio +``` + +### 2. Crear el tag de la versión estable actual +```bash +git tag -a v2.1.0 -m "Versión 2.1.0 — formulario lineal, dashboard multitenante, instrumento v2.1" +git push origin v2.1.0 +``` + +### 3. Crear la rama de preservación +```bash +git checkout -b v2.1.0-stable +git push -u origin v2.1.0-stable +``` + +### 4. Generar el dump de la base de datos (en el VPS) +```bash +# En el VPS inq-mart-2: +docker exec supabase-db pg_dump -U postgres --clean --if-exists postgres \ + | gzip > ~/dump_v2.1.0_$(date +%Y%m%d).sql.gz + +# Verificar tamaño +ls -lh ~/dump_v2.1.0_*.sql.gz +``` + +### 5. Traer el dump a la máquina local y agregarlo a la rama +```bash +# En tu Mac, desde el repo, estando en la rama v2.1.0-stable: +mkdir -p db-snapshots +scp administrator@172.20.5.11:~/dump_v2.1.0_*.sql.gz db-snapshots/ + +git add db-snapshots/ +git commit -m "chore(v2.1.0): snapshot de base de datos de producción + +Dump completo de la DB de producción al momento del corte v2.1.0. +Incluye: 3 organizaciones, 3 surveys, 132 questions, 15 responses, ~500 answers. +Preservado antes de iniciar el desarrollo de v3 (wizard)." +git push origin v2.1.0-stable +``` + +### 6. Volver a main y crear el CHANGELOG +```bash +git checkout main +# Crear CHANGELOG.md (contenido en el archivo adjunto) +git add CHANGELOG.md +git commit -m "docs: agregar CHANGELOG con versionado semántico + +Establece la convención SemVer para el proyecto. +v2.1.0 documentada como versión estable actual. +v3.0.0 (wizard) marcada como en desarrollo." +git push origin main +``` + +--- + +## Verificación final +```bash +git tag -l # debe mostrar v2.1.0 +git branch -a # debe mostrar main y v2.1.0-stable +git log --oneline -3 # en main, último commit es el CHANGELOG +``` + +A partir de acá, todo el trabajo de v3 va en `main`. La rama `v2.1.0-stable` +queda congelada como referencia y punto de retorno. + +--- + +## Nota sobre el dump +El dump en `db-snapshots/` permite recrear la DB de v2.1.0 si fuera necesario +volver atrás. Para restaurarlo: +```bash +gunzip -c dump_v2.1.0_YYYYMMDD.sql.gz | docker exec -i supabase-db psql -U postgres -d postgres +``` \ No newline at end of file diff --git a/sprints/sprint-4/referencias/Formulario_Mapeo_Corregido.xlsx b/sprints/sprint-4/referencias/Formulario_Mapeo_Corregido.xlsx new file mode 100644 index 0000000..44ea26c Binary files /dev/null and b/sprints/sprint-4/referencias/Formulario_Mapeo_Corregido.xlsx differ diff --git a/sprints/sprint-4/referencias/wizard_formulario_mapeo_v3.html b/sprints/sprint-4/referencias/wizard_formulario_mapeo_v3.html new file mode 100644 index 0000000..9be940b --- /dev/null +++ b/sprints/sprint-4/referencias/wizard_formulario_mapeo_v3.html @@ -0,0 +1,481 @@ + + +
+ + +