Files
motor-de-encuestas/sprints/sprint-2/ETAPA_2E_PROMPT.md

14 KiB
Raw Blame History

ETAPA 2E — Refactorización del dashboard alineada al instrumento real

1. Objetivo

Corregir la deuda semántica de Etapa 2D: las RPC, KPIs y subtítulos del dashboard se construyeron a partir de códigos de pregunta inventados en el prompt original, no de los códigos reales de sprints/sprint-1/SEED_SPEC.md. Esto generó métricas mal etiquetadas que el dashboard mostraría como verdaderas cuando lleguen datos reales.

Esta etapa toca la capa de datos (Nivel 3, autorizado por el director). Reescribe RPCs, agrega una pregunta nueva al instrumento, elimina un KPI sin sustento, redefine un widget y renombra otro.


2. Contexto previo

  • Etapa 2D entregada con subtítulos basados en códigos inventados.
  • El director auditó subtítulo por subtítulo contra SEED_SPEC.md y encontró que 11 de 12 widgets/KPIs tenían discrepancias.
  • El instrumento real (SEED_SPEC.md v2) tiene 44 preguntas. Está en el repo.
  • En base de Cloud hay respuestas de testing — se truncan en esta etapa.

3. DECISIONES YA TOMADAS — no consultar de nuevo

3.1 Truncado de datos de testing

Antes de aplicar migraciones nuevas, borrar todas las respuestas de testing del survey piloto. Mantener surveys, questions, consent_versions. Borrar:

  • responses del survey 30000000-0000-0000-0000-000000000001
  • answers asociadas
  • consent_records asociados

3.2 Nueva pregunta del instrumento — A1b Departamento

Agregar al seed, antes de A2 (Ciudad):

A1b · single_choice · "¿En qué departamento de Paraguay vivís?" *
Opciones (18 departamentos):
Asunción · Central · Alto Paraná · Itapúa · Caaguazú · San Pedro ·
Cordillera · Paraguarí · Concepción · Guairá · Caazapá · Misiones ·
Ñeembucú · Amambay · Canindeyú · Presidente Hayes · Boquerón · Alto Paraguay
  • qi_zone ← A1b (cuasi-identificador para el k-anonimato).
  • A1 (País) se mantiene por ahora (lo decidiremos en BACKLOG).

3.3 KPI 4 (NPS) — ELIMINADO

El instrumento no tiene pregunta NPS. Eliminar el KPI completamente del layout. El grid de KPIs queda en 3 cards, no 4. Quitar rpc_nps_* si existe.

3.4 Widget 6 (Políticas) — REDEFINIDO

El instrumento no captura "políticas que la empresa ya ofrece". Eliminar el componente de comparación. El widget muestra solo demanda desde 6.2 (apoyos que ayudarían más, multi-select, top 8).

3.5 Widget 8 — RENOMBRADO

"Tabla de riesgo de retención" → "Saturación del cuidador". El instrumento no captura intención de salida directa; el indicador compuesto mide saturación, no intención de irse. Cambiar título y subtítulo.

3.6 Mapeo final widget → códigos del seed real

KPI Cards (3, sin NPS)

# Título Definición y código real Subtítulo
K1 CUIDADORES ACTIVOS % con 1.6='Sí' OR 1.13='Sí' 1.6 + 1.13 · % de la plantilla con responsabilidades de cuidado de otros
K2 FRECUENCIA DE AUSENTISMO % con 5.2 IN ('Varias veces (410 veces al año)', 'Con frecuencia (más de 10 veces al año)') 5.2 · % con ausencias laborales recurrentes (4 o más veces al año)
K3 BIENESTAR Promedio del rating 4.3 (escala 15, mostrar como /5 o como %) 4.3 · autorreporte de bienestar general · escala 15

Widgets (9, con W6 redefinido y W8 renombrado)

# Título Códigos reales Subtítulo
W1 Prevalencia de cuidadores por departamento A1b (nueva) cruzado con 1.6 1.13 A1b · % cuidadores activos por departamento
W2 Perfil de la población 1.1 + 1.6 + 1.13 (no excluyentes) 1.1 + 1.6 + 1.13 · discapacidad propia, cuidador familiar y de adulto mayor (no excluyentes)
W3 Madurez organizacional Score = 0.7 × 6.1_norm + 0.3 × 6.5_norm, ambas normalizadas 0100 6.1 + 6.5 · comprensión percibida y expectativa hacia la empresa · score 0100
W4 Horas de cuidado × Frecuencia de ausentismo 2.2 × 5.2 2.2 × 5.2 · correlación entre intensidad de cuidado y ausentismo recurrente
W5 Pirámide demográfica A5 × A6 A5 × A6 · rango etario por género (celdas con k ≥ 5)
W6 Apoyos más demandados 6.2 (multi-select, max 3) 6.2 · apoyos de la empresa que los respondentes consideran que más los ayudarían
W7 Intensidad de cuidado vs. Bienestar 2.2 × 4.3 2.2 × 4.3 · cruce agregado intensidad de cuidado × bienestar (bins con k ≥ 5)
W8 Saturación del cuidador Compuesto: 4.3 ≤ 2 AND 5.1 = "Casi todos los días" AND 5.2 ≥ "Varias veces (410 veces al año)" 4.3 + 5.1 + 5.2 · indicador compuesto de saturación (bienestar bajo + rendimiento afectado + ausentismo)

Definición de segmentos para W8 (Saturación):

  • Alta saturación: los 3 criterios se cumplen
  • Saturación media: 2 de los 3 criterios
  • Baja saturación: 1 o ninguno

Columnas de la tabla: Segmento · N · % del total · Apoyo más demandado del segmento (de 6.2). Cada segmento con N < 5 se muestra como "—" (suprimido).

3.7 Normalización para Madurez (W3)

6.1 tiene 4 opciones, normalizar:

  • "Sí, me siento acompañado/a" = 100
  • "Parcialmente, hay cierta comprensión" = 66
  • "No, es algo bastante invisible" = 33
  • "No, nunca se ha hablado del tema" = 0

6.5 tiene 4 opciones, normalizar:

  • "Sí, definitivamente" = 100
  • "Tal vez, dependería del caso" = 66
  • "No lo considero necesario" = 33
  • "No lo sé" = 0 (o NULL — decidir en RPC, ver tarea 4.3)

Score final = 0.7 × promedio(6.1_norm) + 0.3 × promedio(6.5_norm)


4. Tareas

4.1 Migración 009 — Truncado + nueva pregunta A1b

Crear supabase/migrations/0YYYYMMDDHHMMSS_009_add_departamento_paraguay.sql:

  1. BEGIN;
  2. TRUNCATE answers, responses, consent_records CASCADE; (de Cloud)
  3. INSERT en questions la pregunta A1b con sus 18 opciones (question_options). Posición: entre A1 y A2.
  4. Actualizar el orden de las preguntas de la sección A si es necesario.
  5. COMMIT;

Validación post-migración:

  • SELECT COUNT(*) FROM answers; → 0
  • SELECT code, text FROM questions WHERE code='A1b'; → 1 fila
  • SELECT COUNT(*) FROM question_options qo JOIN questions q ON qo.question_id=q.id WHERE q.code='A1b'; → 18

4.2 Migración 010 — Refactor de RPCs del dashboard

Crear supabase/migrations/0YYYYMMDDHHMMSS_010_dashboard_rpc_v2.sql.

DROP y recreate todas las funciones del dashboard con los nuevos mapeos. Lista:

  • rpc_dashboard_kpis — devuelve 3 KPIs (sin NPS), con los códigos correctos
  • rpc_prevalencia_por_depto — usa A1b, NO A1
  • rpc_perfil_poblacion (antes rpc_distribucion_cuidado) — 1.1 + 1.6 + 1.13
  • rpc_score_organizacional — nueva fórmula 70/30
  • rpc_heatmap_intensidad — 2.2 × 5.2
  • rpc_piramide_demografica — sin cambios estructurales
  • rpc_apoyos_demandados (antes rpc_politicas_gap) — solo 6.2, sin comparación
  • rpc_intensidad_vs_bienestar (antes rpc_intensidad_vs_productividad) — 2.2 × 4.3
  • rpc_saturacion_cuidador (antes rpc_riesgo_retencion) — 4.3 + 5.1 + 5.2

Todas las RPC mantienen:

  • SECURITY DEFINER con search_path fijado
  • Supresión k ≥ 5 por construcción (devuelven status='suppressed' si N<5)
  • Casteo seguro de TEXT a numérico cuando aplique
  • Filtros globales (departamento ahora viene de A1b, no A1)

El sidebar de filtros también cambia:

  • "Departamento" ahora hace dropdown contra las 18 opciones reales de A1b
  • "Género" sigue contra A6
  • "Modalidad" sigue contra A7
  • "Etario" sigue contra A5

4.3 Decisión local: cómo tratar "No lo sé" en 6.5

Si el agente lo decide localmente, debe reportar la decisión como Nivel 2. Opciones razonables:

  • Tratar como NULL → no entra al promedio
  • Tratar como 0 → baja el score Recomendación: tratar como NULL (no entra al promedio) — "no lo sé" no es opinión.

4.4 Cliente — eliminar K4 (NPS)

  • Quitar el componente del grid de KPIs
  • Reajustar el layout del grid (de 4 cols a 3 cols, o 3 cards en 4 cols con la cuarta vacía)
  • Eliminar tipo TypeScript asociado y query del cliente
  • grep -r "NPS\|nps" components/dashboard/ app/dashboard/ lib/dashboard* debe retornar vacío después

4.5 Cliente — redefinir Widget 6 (Apoyos)

  • Renombrar archivo politicas-bar.tsxapoyos-bar.tsx (o equivalente)
  • Eliminar la lógica de comparación "demandadas vs ofrecidas"
  • Mostrar solo barras horizontales con top 8 de 6.2 (multi-select, max 3 por respondente)
  • Color único: #43BBC8. Eliminar el color secundario #F8AD13 para "ofrecidas".

4.6 Cliente — renombrar Widget 8 (Saturación)

  • Renombrar archivo tabla-riesgo.tsxtabla-saturacion.tsx
  • Título: "Saturación del cuidador" (no "Riesgo de retención")
  • Etiquetas de segmentos: "Alta saturación" / "Saturación media" / "Baja saturación"
  • Columnas: Segmento · N · % del total · Apoyo más demandado

4.7 Cliente — aplicar todos los subtítulos correctos

Reemplazar los 11 subtítulos con los textos exactos de la tabla en sección 3.6.

4.8 Documentar deuda técnica

Agregar a TECH_DEBT.md (o crearlo si no existe) los siguientes ítems:

[TECH-DEBT-002] KPI NPS Cuidador
- Estado: el instrumento actual no tiene pregunta NPS.
- Si en el futuro se quiere medir NPS hacia la empresa de cuidadores, agregar
  pregunta en próxima versión del instrumento: "En una escala de 0 a 10,
  ¿qué tan probable es que recomiendes esta empresa a otra persona cuidadora?"
- Hasta entonces, el KPI no existe en el dashboard.

[TECH-DEBT-003] Brecha de políticas (oferta vs demanda)
- Estado: el instrumento captura solo demanda (6.2 = apoyos que ayudarían).
- No captura qué políticas la empresa ya ofrece.
- Para construir el widget de brecha, agregar pregunta en próxima versión:
  "¿Qué apoyos para el cuidado ofrece tu empresa hoy?" (multi-select con las
  mismas opciones de 6.2 + "Ninguno" + "No lo sé").
- Hasta entonces, W6 muestra solo demanda.

[TECH-DEBT-004] Intención directa de salida laboral
- Estado: el instrumento no pregunta directamente "¿considerás dejar este trabajo?".
- El widget W8 usa indicador compuesto (4.3 + 5.1 + 5.2) renombrado a "Saturación".
- Para construir un indicador de intención de salida real, agregar pregunta:
  "En los últimos 6 meses, ¿pensaste en dejar este empleo por razones relacionadas
  al cuidado?" (Sí/Frecuentemente · Sí/A veces · No · Prefiero no decir).

[TECH-DEBT-005] A1 (País) vs A1b (Departamento)
- A1 sigue presente en el seed después de Etapa 2E.
- En contexto del piloto (Paraguay únicamente), A1 es redundante: 100% responde Paraguay.
- Decidir antes de Sprint 3: eliminar A1 del instrumento, o mantenerlo si la
  plataforma se va a regionalizar (Uruguay, Bolivia, etc.) en el corto plazo.

4.9 Verificación cruzada — patrón nuevo C.8

Antes de declarar terminado, el agente ejecuta este check (Patrón C.8 propuesto):

# Cada subtítulo referenciado en el cliente debe tener su código documentado en SEED_SPEC.md
grep -oE '"[0-9A-Z]+(\.[0-9]+)?b?\s*[·+×]' components/dashboard/*.tsx | \
  awk '{print $1}' | sort -u
# El agente verifica esta lista contra los códigos de SEED_SPEC.md

Si algún código del cliente no está en SEED_SPEC.md, DETENERSE y reportar antes de declarar terminado. No ejecutar literalmente y delegar al director (eso sería AP.10 — propagación silenciosa de inconsistencia).


5. Entregables (DoD)

  • Migración 009 aplicada en Cloud (truncado + A1b con 18 opciones)
  • Migración 010 aplicada en Cloud (9 RPCs refactorizadas)
  • Test post-migración: con N=0 (truncado) todas las RPCs devuelven suppressed
  • Test con N≥5 de datos sintéticos (insertados ad-hoc) — al menos 1 RPC devuelve ok
  • grep -r "NPS\|nps" components/dashboard/ app/dashboard/ lib/dashboard* → vacío
  • Subtítulos del cliente match exactamente con la tabla 3.6 del prompt
  • Sidebar de filtros: dropdown de Departamento usa A1b, no A1
  • Verificación cruzada (4.9) ejecutada sin discrepancias
  • TECH_DEBT.md actualizado con TECH-DEBT-002, 003, 004, 005
  • Build sin errores (next build)
  • git diff --name-only HEAD solo en scope (migrations, components/dashboard, lib/dashboard*, TECH_DEBT.md)
  • Captura del dashboard en estado suppressed compartida (Principio 2)

6. Qué reportar

Verificado:
- Migración 009 aplicada: rows truncados=X, A1b insertada con 18 opciones ✓
- Migración 010 aplicada: 9 RPCs DROPped y CREATEd ✓
- Test N=0: todas las RPCs → suppressed ✓
- Test con datos sintéticos: [lista de RPCs con ok / suppressed]
- grep NPS: vacío ✓
- Subtítulos: 13 textos exactos verificados contra tabla 3.6 ✓
- Sidebar Departamento usa A1b ✓
- Verificación cruzada C.8: [resultado]
- TECH_DEBT.md: ítems 002005 agregados ✓
- Build exitoso · diff en scope ✓

Asumido:
- Decisión local "No lo sé" en 6.5 → [NULL / 0 / otra]
- [lo que no se pudo verificar]

Decisiones proactivas (Nivel 2):
- [lista]

Conflictos de scope detectados (Patrón C.8):
- [si los hubo, listarlos AQUÍ y DETENER antes de ejecutar]

7. Qué NO hacer

  • No tocar el formulario (/app/(survey)/, app/actions/submit-survey.ts).
  • No tocar RLS de write existente (la migración 011 anterior es intocable).
  • No agregar dependencias npm.
  • No inventar códigos de pregunta. Si un código nombrado en este prompt no coincide con SEED_SPEC.md, DETENERSE y reportar (Patrón C.8). NO ejecutar "literalmente" y delegar al director.
  • No tocar la estructura de capas (sigue siendo cliente → Route Handler → RPC).
  • No agregar widgets nuevos. Esta etapa es refactor, no extensión.
  • No resolver ítems del backlog que no sean los 4 listados en sección 4.8.

Apéndice — Patrón nuevo propuesto C.8

Si esta etapa cierra limpia, agregar a method/PATTERNS.md:

C.8 — Verificación de códigos contra fuente única · deriva de P3, P4 · origen: 2do proyecto. Cuando un prompt menciona códigos de un instrumento, esquema o contrato (preguntas, columnas, campos), el agente verifica cada código contra la fuente única (SEED_SPEC.md, schema.sql, etc.) antes de ejecutar. Si detecta una discrepancia, DETIENE la ejecución y reporta el conflicto. Ejecutar "literalmente" y delegar la verificación semántica al director es AP.10 (propagación silenciosa de inconsistencia). Respuesta directa al caso Etapa 2D del proyecto Datos País.