Con los números de preguntas y secciones
This commit is contained in:
10
BACKLOG.md
10
BACKLOG.md
@@ -48,6 +48,16 @@
|
||||
|
||||
*(Sprint 3 y posteriores — ver ARCHITECTURE.md y BRIEF por sprint)*
|
||||
|
||||
### [BACKLOG-001] Consentimiento inicial editable desde admin
|
||||
- **Estado:** hoy el texto del consentimiento está hardcoded en `consent-screen.tsx`.
|
||||
- **Necesidad:** cuando se construya el motor de formularios (builder), el texto del
|
||||
consentimiento debe ser editable por encuesta desde la administración, para reflejar
|
||||
cambios en política de privacidad o ajustes específicos por tipo de relevamiento.
|
||||
- **Bloquea:** implementación del builder visual.
|
||||
- **Decisión cerrada:** la edición es desde admin, no desde el código.
|
||||
|
||||
---
|
||||
|
||||
- Dashboard / reportes (Sprint 3)
|
||||
- Formulario de consentimiento + persistencia de respuestas (Etapa 2B)
|
||||
- Builder visual de encuestas (post-validación del caso fijo)
|
||||
|
||||
@@ -147,16 +147,6 @@ body {
|
||||
border-radius: 0 var(--radius) var(--radius) 0;
|
||||
color: var(--color-primary-hover);
|
||||
}
|
||||
.section-sensitive-note {
|
||||
font-size: 0.8125rem;
|
||||
color: #92400e;
|
||||
background: var(--color-sensitive);
|
||||
border: 1px solid var(--color-sensitive-border);
|
||||
border-radius: var(--radius);
|
||||
padding: 8px 12px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ── Question wrapper ── */
|
||||
.question-wrapper {
|
||||
background: var(--color-surface);
|
||||
@@ -183,6 +173,12 @@ body {
|
||||
line-height: 1.4;
|
||||
}
|
||||
.required-mark { color: var(--color-error); }
|
||||
.q-code {
|
||||
font-size: 0.78em;
|
||||
font-weight: 700;
|
||||
color: #7A8FA0;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* ── Options list ── */
|
||||
.options-list { display: flex; flex-direction: column; gap: 8px; }
|
||||
|
||||
@@ -32,6 +32,7 @@ export function QuestionRenderer({
|
||||
const error = errors[code]
|
||||
|
||||
// A1 (Departamento) renders a combined geo widget that also handles A2 (Ciudad)
|
||||
// Code badges for A1/A2 are rendered inside GeoSelectWidget.
|
||||
if (code === 'A1') {
|
||||
return (
|
||||
<GeoSelectWidget
|
||||
@@ -47,11 +48,13 @@ export function QuestionRenderer({
|
||||
// A2 is rendered inside the GeoSelectWidget above — skip here to avoid duplication
|
||||
if (code === 'A2') return null
|
||||
|
||||
const legend = <><span className="q-code">{code} ·</span> {prompt}</>
|
||||
|
||||
if (type === 'single_choice' && isArrayOptions(options)) {
|
||||
return (
|
||||
<RadioGroup
|
||||
name={code}
|
||||
legend={prompt}
|
||||
legend={legend}
|
||||
options={options}
|
||||
value={answers[code] as string | undefined}
|
||||
required={required}
|
||||
@@ -65,7 +68,7 @@ export function QuestionRenderer({
|
||||
return (
|
||||
<CheckboxGroup
|
||||
name={code}
|
||||
legend={prompt}
|
||||
legend={legend}
|
||||
options={options}
|
||||
value={(answers[code] as string[]) ?? []}
|
||||
maxSelect={max_select}
|
||||
@@ -80,7 +83,7 @@ export function QuestionRenderer({
|
||||
return (
|
||||
<RatingScale
|
||||
name={code}
|
||||
legend={prompt}
|
||||
legend={legend}
|
||||
ratingOptions={options}
|
||||
value={answers[code] as number | undefined}
|
||||
required={required}
|
||||
@@ -94,7 +97,7 @@ export function QuestionRenderer({
|
||||
return (
|
||||
<TextShortField
|
||||
name={code}
|
||||
label={prompt}
|
||||
label={legend}
|
||||
value={(answers[code] as string) ?? ''}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
@@ -107,7 +110,7 @@ export function QuestionRenderer({
|
||||
return (
|
||||
<TextAreaField
|
||||
name={code}
|
||||
label={prompt}
|
||||
label={legend}
|
||||
value={(answers[code] as string) ?? ''}
|
||||
required={required}
|
||||
onChange={(v) => onChange(code, v)}
|
||||
|
||||
@@ -9,9 +9,9 @@ import { ProgressBar } from './progress-bar'
|
||||
import { QuestionRenderer } from './question-renderer'
|
||||
|
||||
// Section metadata (code prefix → display title)
|
||||
const SECTIONS: { prefix: string; title: string; sensitive?: boolean }[] = [
|
||||
const SECTIONS: { prefix: string; title: string }[] = [
|
||||
{ prefix: 'A', title: 'Datos Generales' },
|
||||
{ prefix: '1', title: 'Prevalencia: cuidado y discapacidad', sensitive: true },
|
||||
{ prefix: '1', title: 'Prevalencia: cuidado y discapacidad' },
|
||||
{ prefix: '2', title: 'Intensidad y rol del cuidado' },
|
||||
{ prefix: '3', title: 'Impacto económico del cuidado' },
|
||||
{ prefix: '4', title: 'Tiempo y descanso' },
|
||||
@@ -190,13 +190,13 @@ export function SurveyForm({ survey, questions }: SurveyFormProps) {
|
||||
return v !== null && v !== undefined && v !== '' && !(Array.isArray(v) && v.length === 0)
|
||||
}).length
|
||||
|
||||
type Section = { prefix: string; title: string; sensitive?: boolean; questions: Question[] }
|
||||
type Section = { prefix: string; title: string; questions: Question[] }
|
||||
const sectionMap = new Map<string, Section>()
|
||||
for (const q of visibleQuestions) {
|
||||
const prefix = getSectionPrefix(q.code)
|
||||
if (!sectionMap.has(prefix)) {
|
||||
const meta = SECTIONS.find((s) => s.prefix === prefix)
|
||||
sectionMap.set(prefix, { prefix, title: meta?.title ?? prefix, sensitive: meta?.sensitive, questions: [] })
|
||||
sectionMap.set(prefix, { prefix, title: meta?.title ?? prefix, questions: [] })
|
||||
}
|
||||
sectionMap.get(prefix)!.questions.push(q)
|
||||
}
|
||||
@@ -242,13 +242,7 @@ export function SurveyForm({ survey, questions }: SurveyFormProps) {
|
||||
aria-labelledby={`section-${section.prefix}`}
|
||||
>
|
||||
<div className="section-header">
|
||||
<h2 id={`section-${section.prefix}`} className="section-title">{section.title}</h2>
|
||||
{section.sensitive && (
|
||||
<p className="section-sensitive-note" role="note">
|
||||
Esta sección contiene preguntas sensibles sobre salud o discapacidad.
|
||||
Responder es completamente voluntario.
|
||||
</p>
|
||||
)}
|
||||
<h2 id={`section-${section.prefix}`} className="section-title">Sección {section.prefix} · {section.title}</h2>
|
||||
</div>
|
||||
{section.questions.map((q) => (
|
||||
<div key={q.id} className="question-wrapper" data-code={q.code}>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { QuestionOption } from '@/lib/types'
|
||||
|
||||
interface CheckboxGroupProps {
|
||||
name: string
|
||||
legend: string
|
||||
legend: ReactNode
|
||||
options: QuestionOption[]
|
||||
value: string[]
|
||||
maxSelect: number | null
|
||||
|
||||
@@ -31,7 +31,7 @@ export function GeoSelectWidget({
|
||||
{/* Departamento */}
|
||||
<div className="geo-select-group">
|
||||
<label className="question-legend" htmlFor="A1">
|
||||
Departamento
|
||||
<span className="q-code">A1 ·</span> Departamento
|
||||
</label>
|
||||
<select
|
||||
id="A1"
|
||||
@@ -58,7 +58,7 @@ export function GeoSelectWidget({
|
||||
className={`question-legend${cityDisabled ? ' geo-label-disabled' : ''}`}
|
||||
htmlFor="A2"
|
||||
>
|
||||
Ciudad
|
||||
<span className="q-code">A2 ·</span> Ciudad
|
||||
{cityDisabled && (
|
||||
<span className="geo-disabled-hint"> (seleccioná un departamento primero)</span>
|
||||
)}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { QuestionOption } from '@/lib/types'
|
||||
|
||||
interface RadioGroupProps {
|
||||
name: string
|
||||
legend: string
|
||||
legend: ReactNode
|
||||
options: QuestionOption[]
|
||||
value: string | undefined
|
||||
required: boolean
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { RatingOptions } from '@/lib/types'
|
||||
|
||||
interface RatingScaleProps {
|
||||
name: string
|
||||
legend: string
|
||||
legend: ReactNode
|
||||
ratingOptions: RatingOptions
|
||||
value: number | undefined
|
||||
required: boolean
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use client'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
interface TextAreaFieldProps {
|
||||
name: string
|
||||
label: string
|
||||
label: ReactNode
|
||||
value: string
|
||||
required: boolean
|
||||
onChange: (value: string) => void
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use client'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
interface TextShortFieldProps {
|
||||
name: string
|
||||
label: string
|
||||
label: ReactNode
|
||||
value: string
|
||||
required: boolean
|
||||
placeholder?: string
|
||||
|
||||
184
sprints/sprint-2/ETAPA_2F_PROMPT.md
Normal file
184
sprints/sprint-2/ETAPA_2F_PROMPT.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# ETAPA 2F — Formulario: numeración visible + eliminar disclaimers por sección
|
||||
|
||||
## 1. Objetivo
|
||||
Dos cambios cosméticos sobre el formulario que ve el respondente:
|
||||
1. Mostrar el número de sección en su encabezado y el código de pregunta junto a cada pregunta.
|
||||
2. Eliminar los disclaimers de "esta sección contiene preguntas sensibles" que aparecen
|
||||
debajo del encabezado de cada sección. La encuesta se trata como un todo atómico:
|
||||
la persona acepta responderla entera al inicio (los 2 checks ya implementados); no se
|
||||
re-pide consentimiento por sección.
|
||||
|
||||
**Etapa Nivel 2 — cambio visible al usuario, sin tocar datos ni lógica.** No toca el
|
||||
seed, ni las RPC, ni los componentes de captura, ni el componente de consentimiento.
|
||||
|
||||
---
|
||||
|
||||
## 2. Contexto previo
|
||||
- Etapa 2E cerrada (refactor de dashboard alineado al instrumento real).
|
||||
- El director observó visualmente el formulario y detectó dos puntos de fricción:
|
||||
(a) las preguntas no muestran su código, lo que dificulta dar feedback con precisión;
|
||||
(b) hay disclaimers por sección que crean fricción innecesaria.
|
||||
- El consentimiento inicial con dos checks (operativo + macro) ya advierte de manera
|
||||
general sobre el tratamiento de datos. Ese es el contrato — no se duplica por sección.
|
||||
|
||||
---
|
||||
|
||||
## 3. DECISIONES YA TOMADAS — no consultar de nuevo
|
||||
|
||||
### 3.1 Numeración de secciones
|
||||
Cada encabezado de sección muestra el número antes del título.
|
||||
Formato: **"Sección {N} · {Título}"** donde {N} es A, 1, 2, 3, 4, 5, 6 o 7.
|
||||
|
||||
Ejemplos finales:
|
||||
- "Sección A · Datos Generales"
|
||||
- "Sección 1 · Prevalencia: cuidado y discapacidad"
|
||||
- "Sección 2 · Intensidad y rol del cuidado"
|
||||
- "Sección 3 · Impacto económico del cuidado"
|
||||
- "Sección 4 · Tiempo y descanso"
|
||||
- "Sección 5 · Impacto en el trabajo"
|
||||
- "Sección 6 · Conciencia organizacional"
|
||||
- "Sección 7 · Para cerrar"
|
||||
|
||||
Los nombres de cada sección se toman literalmente de `SEED_SPEC.md` (sin reinterpretar
|
||||
ni acortar).
|
||||
|
||||
### 3.2 Código de pregunta junto a cada pregunta
|
||||
Cada pregunta muestra su código como tag/etiqueta pequeña antes del texto de la pregunta.
|
||||
|
||||
Especificaciones visuales:
|
||||
- Color: `#43BBC8` (teal RE) o `#7A8FA0` (muted) — elegir el que dé mejor contraste sin
|
||||
competir con el texto principal de la pregunta.
|
||||
- Peso: bold o semibold (que el código se distinga visualmente del texto).
|
||||
- Tamaño: ~0.8× del texto de la pregunta.
|
||||
- Posición: en la misma línea que el inicio del texto, separado por un punto medio (·)
|
||||
o por un espacio + tag con borde. Ejemplo: `1.1 · ¿Vos mismo/a vivís con alguna...?`
|
||||
- Las preguntas dentro de bloques condicionales (1.2-1.5, 1.7-1.12, 1.14-1.16) muestran
|
||||
su código tal cual está en el seed. Los saltos visibles (1.1 → 1.6 si no se dispara
|
||||
el bloque) son intencionales — el respondente ve que existe lógica condicional.
|
||||
|
||||
### 3.3 Eliminación de disclaimers por sección
|
||||
Eliminar TODO disclaimer que aparezca debajo del encabezado de una sección con texto del
|
||||
estilo:
|
||||
- "Esta sección contiene preguntas sensibles..."
|
||||
- "Responder es voluntario..."
|
||||
- Cualquier variante semánticamente equivalente.
|
||||
|
||||
El disclaimer confirmado a eliminar (visto en captura):
|
||||
> "Esta sección contiene preguntas sensibles sobre salud o discapacidad. Responder es completamente voluntario."
|
||||
|
||||
**Verificar si existen disclaimers similares en OTRAS secciones** (ej: Sección 3 por
|
||||
3.4 salario) y eliminarlos también. La eliminación es consistente: ninguna sección lleva
|
||||
disclaimer propio.
|
||||
|
||||
### 3.4 NO tocar el componente de consentimiento
|
||||
El `consent-screen.tsx` (o equivalente) con los dos checks (operativo + macro) **queda
|
||||
intacto**. Esa es la advertencia que la persona acepta al inicio, y es suficiente
|
||||
porque cubre el tratamiento de datos del formulario completo.
|
||||
|
||||
### 3.5 Backlog futuro (NO esta etapa)
|
||||
El texto del consentimiento inicial debería ser editable cuando se construya el motor
|
||||
de formularios (sprint futuro del builder). **Agregar como ítem al BACKLOG.md** (no a
|
||||
TECH_DEBT, porque no es deuda — es feature pendiente):
|
||||
|
||||
```
|
||||
[BACKLOG-XXX] Consentimiento inicial editable desde admin
|
||||
- Estado: hoy el texto del consentimiento está hardcoded en consent-screen.tsx.
|
||||
- Necesidad: cuando se construya el motor de formularios (builder), el texto del
|
||||
consentimiento debe ser editable por encuesta desde la administración, para reflejar
|
||||
cambios en política de privacidad o ajustes específicos por tipo de relevamiento.
|
||||
- Bloquea: implementación del builder visual.
|
||||
- Decisión cerrada: la edición es desde admin, no desde el código.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Tareas
|
||||
|
||||
### 4.1 Verificación previa (Patrón C.8)
|
||||
Antes de tocar nada, verificar contra `SEED_SPEC.md`:
|
||||
- Los 8 nombres exactos de las secciones (A, 1, 2, 3, 4, 5, 6, 7).
|
||||
- Los códigos de pregunta de la sección A y de cada sección numérica.
|
||||
|
||||
Si encontrás discrepancias entre los nombres de las secciones en el código actual y los
|
||||
del seed, **detenete y reportá** antes de aplicar (Patrón C.8). Aplica el aprendizaje
|
||||
de la Etapa 2E: los códigos y nombres son del seed, no de archivos secundarios.
|
||||
|
||||
### 4.2 Localizar dónde se renderizan los encabezados de sección
|
||||
`grep -rE "Prevalencia|Datos Generales|Intensidad y rol|Impacto económico|Tiempo y descanso|Impacto en el trabajo|Conciencia organizacional|Para cerrar"` en `components/` y `app/(survey)/` (o equivalente).
|
||||
|
||||
Encontrar el componente que renderiza el header de cada sección. Probablemente es uno
|
||||
solo que recibe el nombre de sección como prop o lo deriva del seed.
|
||||
|
||||
### 4.3 Modificar el header de sección
|
||||
Aplicar el formato **"Sección {N} · {Título}"** una sola vez en el componente, leyendo
|
||||
el número desde una propiedad del seed o pasándolo como prop. Mantener el estilo
|
||||
visual actual (color teal, tamaño, peso) — solo se agrega el prefijo "Sección {N} · ".
|
||||
|
||||
### 4.4 Modificar el componente de pregunta
|
||||
Localizar el componente que renderiza el texto de cada pregunta. Agregar el tag con el
|
||||
código de la pregunta antes del texto, según las especificaciones de la sección 3.2.
|
||||
|
||||
El código de cada pregunta ya está en la base de datos (`questions.code`) y debería
|
||||
estar disponible en el objeto que recibe el componente. Si no está, propagarlo en una
|
||||
prop (no agregarle un fetch).
|
||||
|
||||
### 4.5 Eliminar disclaimers por sección
|
||||
Eliminar el bloque ámbar con "Esta sección contiene preguntas sensibles...". Buscar
|
||||
todas las instancias:
|
||||
```bash
|
||||
grep -rn "preguntas sensibles\|Responder es completamente voluntario\|Responder es voluntario" \
|
||||
components/ app/(survey)/ 2>/dev/null
|
||||
```
|
||||
Eliminar tanto el JSX como, si existe, el dato del seed/constante que las alimenta. Si
|
||||
el disclaimer está condicionado por `is_sensitive=true` o similar, eliminar también esa
|
||||
lógica de renderizado.
|
||||
|
||||
### 4.6 Backlog
|
||||
Agregar el ítem BACKLOG-XXX descrito en la sección 3.5 a `BACKLOG.md` (crear el archivo
|
||||
si no existe). Numerar según el siguiente correlativo disponible.
|
||||
|
||||
---
|
||||
|
||||
## 5. Entregables (DoD)
|
||||
|
||||
- [ ] Verificación C.8 ejecutada — nombres de secciones match SEED_SPEC.md.
|
||||
- [ ] Los 8 encabezados de sección muestran el prefijo "Sección {N} · ".
|
||||
- [ ] Cada pregunta muestra su código (1.1, A5, 6.2, etc.) antes del texto.
|
||||
- [ ] `grep -rE "preguntas sensibles|Responder es .*voluntario"` retorna vacío.
|
||||
- [ ] `consent-screen.tsx` (o equivalente) sin cambios — confirmar con `git diff`.
|
||||
- [ ] BACKLOG.md actualizado con el ítem del consentimiento editable.
|
||||
- [ ] Build sin errores (`next build`).
|
||||
- [ ] `git diff --name-only HEAD` solo en componentes del formulario y BACKLOG.md.
|
||||
- [ ] Captura del formulario en sección 1 mostrando: encabezado con "Sección 1 · ", al
|
||||
menos 2 preguntas con sus códigos visibles, y SIN disclaimer ámbar.
|
||||
|
||||
## 6. Qué reportar
|
||||
```
|
||||
Verificado:
|
||||
- Verificación C.8 (nombres de secciones vs SEED_SPEC.md): match
|
||||
- Archivos modificados en diff: [lista]
|
||||
- Headers de sección con "Sección {N} · ": confirmado
|
||||
- Códigos de pregunta visibles: [ejemplo de 2-3]
|
||||
- grep de disclaimers: vacío
|
||||
- consent-screen.tsx intacto: confirmado
|
||||
- BACKLOG.md actualizado: ítem [número]
|
||||
- Build exitoso
|
||||
|
||||
Asumido:
|
||||
- [si hay decisión cosmética sobre el estilo del tag de código]
|
||||
|
||||
Decisiones proactivas (Nivel 2):
|
||||
- [si las hubo]
|
||||
|
||||
Conflictos de scope (Patrón C.8):
|
||||
- [si los hubo, listarlos AQUÍ y detener]
|
||||
```
|
||||
|
||||
## 7. Qué NO hacer
|
||||
- ❌ No tocar `consent-screen.tsx` ni el componente de consentimiento de ninguna forma.
|
||||
- ❌ No modificar el seed, las preguntas, ni `SEED_SPEC.md`.
|
||||
- ❌ No tocar las RPCs ni la migración del dashboard.
|
||||
- ❌ No cambiar la lógica condicional de los bloques (1.1→1.2-1.5, etc.).
|
||||
- ❌ No renumerar preguntas — los códigos quedan tal cual están en el seed.
|
||||
- ❌ No agregar dependencias npm.
|
||||
- ❌ No resolver ítems de TECH_DEBT.md ni del BACKLOG salvo el ítem nuevo de esta etapa.
|
||||
142
sprints/sprint-2/ETAPA_2G_PROMPT.md
Normal file
142
sprints/sprint-2/ETAPA_2G_PROMPT.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# ETAPA 2G — Cierre de Sprint 2: promoción de C.8 y documentación de AP.10 + AP.11
|
||||
|
||||
## 1. Objetivo
|
||||
Documentar formalmente en el método los aprendizajes que el Sprint 2 produjo:
|
||||
- **Promover C.8 a estable** en `method/PATTERNS.md` (validado en 3 etapas del proyecto).
|
||||
- **Agregar AP.10 (propagación silenciosa de inconsistencia)** a `method/ANTI_PATTERNS.md`.
|
||||
- **Agregar AP.11 (contrato desactualizado por código)** a `method/ANTI_PATTERNS.md`.
|
||||
|
||||
Etapa de documentación pura. **No toca código, no toca seed, no toca dashboard.**
|
||||
|
||||
---
|
||||
|
||||
## 2. Contexto previo
|
||||
- Sprint 2 cerrado con Etapas 2A-2F entregadas.
|
||||
- Etapa 2D produjo el caso real de AP.10 (subtítulos con códigos discrepantes del seed).
|
||||
- Etapa 2E aplicó por primera vez C.8 y detectó el conflicto A1b-vs-A1 antes de ejecutar
|
||||
(caso real de AP.11 — SEED_SPEC.md desactualizado por Etapa 1D).
|
||||
- Etapa 2F ejecutó con C.8 sin discrepancias (validación de patrón en uso limpio).
|
||||
- Tres usos en proyecto Datos País → patrón estable según el método (`PATTERNS.md`,
|
||||
criterio "tras aplicarlo en un 2do proyecto distinto se promueve a estable" —
|
||||
aplica también a 2 usos limpios consecutivos en un proyecto vivo).
|
||||
|
||||
---
|
||||
|
||||
## 3. Tareas
|
||||
|
||||
### 3.1 Agregar C.8 a `method/PATTERNS.md`
|
||||
Insertar en la **Categoría C — Validación de output**, después de C.7 (Control preventivo
|
||||
de scope con `git diff`):
|
||||
|
||||
```markdown
|
||||
### 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`,
|
||||
ADRs) **antes** de ejecutar. Si detecta una discrepancia entre el código nombrado en el
|
||||
prompt y su definición en la fuente única, **DETIENE la ejecución y reporta el conflicto**.
|
||||
Ejecutar "literalmente" y delegar la verificación semántica al director es AP.10.
|
||||
- ✅ **Correcto:** el reporte del agente incluye una sección "Verificación C.8" con cada
|
||||
código del prompt mapeado a su fila en la fuente única, antes de la ejecución. Si hay
|
||||
discrepancia, la ejecución no arranca hasta que el director resuelva.
|
||||
- ❌ **Violación:** el agente ejecuta el prompt al pie de la letra y reporta "los textos son
|
||||
los solicitados literalmente; la validación semántica la hace el director" — exporta el
|
||||
trabajo de verificar al humano y propaga la inconsistencia.
|
||||
|
||||
**Cómo se incorpora a un prompt:** agregar un paso "Verificación C.8" como primera tarea
|
||||
del DoD, listando los códigos a verificar y la ruta exacta de la fuente única.
|
||||
**Casos reales en Datos País:** Etapa 2D (no se aplicó — daño AP.10), Etapa 2E (se aplicó —
|
||||
detectó conflicto A1/A1b antes de ejecutar), Etapa 2F (se aplicó — sin discrepancias).
|
||||
```
|
||||
|
||||
### 3.2 Agregar AP.10 a `method/ANTI_PATTERNS.md`
|
||||
Insertar al final del listado, antes de "Cómo agregar un anti-patrón":
|
||||
|
||||
```markdown
|
||||
## AP.10 — Propagación silenciosa de inconsistencia entre fuentes
|
||||
**Comportamiento:** un prompt contiene una referencia (código, ruta, esquema) que el agente
|
||||
podría verificar contra otra fuente del repo. En lugar de hacerlo, el agente ejecuta
|
||||
literalmente y traslada la responsabilidad al director con frases como "la validación
|
||||
semántica la hace el director" o "los textos son los solicitados literalmente".
|
||||
**Daño:** las inconsistencias se propagan a producción con apariencia de precisión técnica.
|
||||
*Caso real:* en Etapa 2D del proyecto Datos País, 11 de 12 subtítulos del dashboard
|
||||
quedaron con códigos de pregunta discrepantes del seed real. El dashboard mostraba
|
||||
métricas mal etiquetadas: el KPI "Ausencia promedio · 3.1 · días por mes" referenciaba
|
||||
una pregunta que en el seed real era *gasto en cuidado*, no ausencias. Detectado en la
|
||||
auditoría adversarial posterior, no antes. Si hubieran cargado datos reales, RRHH habría
|
||||
visto guaraníes presentados como días.
|
||||
**Detectar:** el reporte del agente declara "los textos son los solicitados literalmente";
|
||||
hay códigos, rutas o nombres que el agente pudo verificar contra otra fuente y no lo hizo;
|
||||
el agente delega la verificación semántica al humano sin haber verificado lo verificable.
|
||||
**Evitar:** Patrón C.8 + cláusula explícita en el prompt: *"si detectás una discrepancia
|
||||
entre el prompt y la fuente única, DETENÉ la ejecución y reportá antes de avanzar"*.
|
||||
**Distinción:** ≠ AP.3 — AP.3 minimiza un problema observado; AP.10 evita verificar lo
|
||||
verificable. ≠ AP.9 — AP.9 resuelve restricciones contradictorias del propio prompt;
|
||||
AP.10 propaga inconsistencias entre el prompt y otra fuente.
|
||||
```
|
||||
|
||||
### 3.3 Agregar AP.11 a `method/ANTI_PATTERNS.md`
|
||||
Insertar inmediatamente después de AP.10:
|
||||
|
||||
```markdown
|
||||
## AP.11 — Contrato desactualizado por código
|
||||
**Comportamiento:** una etapa modifica el comportamiento real del sistema (seed, esquema,
|
||||
RLS, RPCs) pero no actualiza el documento que sirve como contrato o fuente única
|
||||
(`SEED_SPEC.md`, `ARCHITECTURE.md`, ADRs). El documento queda mintiendo por silencio.
|
||||
**Daño:** el próximo agente o autor de prompts que lo lea va a tomar decisiones basadas
|
||||
en información falsa. *Caso real:* en Etapa 1D del proyecto Datos País se modificó
|
||||
`seed.sql` para que A1/A2/A3 fueran widgets geo (Departamento/Ciudad/Barrio en lugar de
|
||||
texto libre País/Ciudad/Sucursal), pero no se actualizó `SEED_SPEC.md`. Dos sprints
|
||||
después, Etapa 2E se escribió tomando SEED_SPEC como verdad y proponiendo agregar una
|
||||
pregunta A1b que duplicaba la A1 ya existente. El conflicto se detectó antes de ejecutar
|
||||
porque el agente aplicó el Patrón C.8; sin C.8, se habría creado una pregunta duplicada
|
||||
en producción.
|
||||
**Detectar:** cuando una etapa cambia comportamiento del sistema, preguntar explícitamente
|
||||
"¿qué documento de contrato describe esto, y lo actualicé?". Si la respuesta es "no sé"
|
||||
o "después lo veo", AP.11 latente. También: cuando una etapa posterior asume contenido
|
||||
del contrato que ya no coincide con la realidad.
|
||||
**Evitar:** todo prompt que modifique un sistema documentado en un contrato debe incluir,
|
||||
como parte del DoD, "actualizar el documento de contrato correspondiente con los cambios".
|
||||
Es Principio 4 aplicado al mantenimiento, no solo a la creación.
|
||||
**Distinción:** ≠ AP.4 — AP.4 es decisión no registrada; AP.11 es decisión registrada en
|
||||
código pero NO actualizada en el contrato escrito.
|
||||
```
|
||||
|
||||
### 3.4 (Opcional) Agregar referencia cruzada en C.1 del método
|
||||
En `method/PATTERNS.md`, dentro de C.1 (Validación visual mandatoria del artefacto final),
|
||||
si existe la oportunidad, agregar como nota: *"Cuando el output incluye textos que
|
||||
referencian otras fuentes del repo (códigos, IDs, rutas), aplicar también C.8."*
|
||||
|
||||
Esta tarea es opcional — solo si encaja naturalmente. No forzarla.
|
||||
|
||||
---
|
||||
|
||||
## 4. Entregables (DoD)
|
||||
- [ ] `method/PATTERNS.md` actualizado con C.8 como patrón estable.
|
||||
- [ ] `method/ANTI_PATTERNS.md` actualizado con AP.10 y AP.11.
|
||||
- [ ] Tres bloques markdown insertados exactamente como están en este prompt (no
|
||||
reescribir, no resumir, no parafrasear el contenido — copiar literal).
|
||||
- [ ] `git diff --name-only HEAD` retorna **solo** los 2 archivos del método.
|
||||
- [ ] Build no aplica (no hay cambios de código).
|
||||
|
||||
## 5. Qué reportar
|
||||
```
|
||||
Verificado:
|
||||
- archivos en diff: method/PATTERNS.md, method/ANTI_PATTERNS.md
|
||||
- C.8 insertado en Categoría C después de C.7: confirmado
|
||||
- AP.10 y AP.11 insertados al final del listado: confirmado
|
||||
- Texto copiado literal del prompt: confirmado (sin reescritura)
|
||||
- Tarea opcional 3.4: [aplicada / no aplicada — justificación corta]
|
||||
|
||||
Asumido:
|
||||
- [solo si el método tiene una estructura distinta a la esperada]
|
||||
|
||||
Decisiones proactivas (Nivel 2):
|
||||
- [si las hubo]
|
||||
```
|
||||
|
||||
## 6. Qué NO hacer
|
||||
- ❌ No reescribir, resumir ni parafrasear los textos de C.8, AP.10 o AP.11 — copiar literal.
|
||||
- ❌ No agregar otros patrones o anti-patrones por iniciativa.
|
||||
- ❌ No modificar PRINCIPLES.md ni AUTOMATION_STRATEGY.md.
|
||||
- ❌ No tocar nada del proyecto Datos País (esto es del método, no del producto).
|
||||
- ❌ No crear archivos nuevos — solo editar los dos existentes.
|
||||
Reference in New Issue
Block a user