@trycore/spec-build-harness 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/GOVERNANCE.md +17 -2
- package/INSTALL.md +2 -2
- package/METODOLOGIA.md +35 -5
- package/README.md +5 -3
- package/VERSION +1 -1
- package/agents/build/dor-dod-gatekeeper.md +22 -1
- package/agents/build/ux-fidelity-reviewer.md +4 -1
- package/commands/build/onboard.md +49 -2
- package/commands/build/prototype.md +22 -0
- package/commands/build/slice.md +5 -0
- package/commands/build/work.md +9 -0
- package/dist/commands/doctor.js +8 -0
- package/dist/commands/init.js +3 -1
- package/dist/commands/status.js +19 -0
- package/dist/lib/state-seed.js +95 -1
- package/docs/commands.md +9 -3
- package/docs/getting-started.md +1 -1
- package/docs/hooks.md +1 -1
- package/hooks/build/design-source-guard.sh +1 -1
- package/package.json +1 -1
- package/scripts/tests/test-install.sh +88 -0
- package/scripts/tests/test-schema.sh +21 -0
- package/skills/building-a-slice/SKILL.md +3 -2
- package/skills/building-a-slice/references/dor.md +14 -1
- package/skills/building-a-slice/references/foundation-contract.md +44 -0
- package/skills/prototyping-screens/SKILL.md +100 -0
- package/skills/prototyping-screens/assets/DESIGN.md.template +55 -0
- package/skills/prototyping-screens/assets/manifest.schema.json +70 -0
- package/skills/prototyping-screens/assets/screen.template.html +34 -0
- package/skills/prototyping-screens/references/aesthetic-directions.md +42 -0
- package/skills/prototyping-screens/references/extraction.md +57 -0
- package/skills/prototyping-screens/references/self-check.md +40 -0
- package/state/README.md +26 -2
- package/state/build-state.schema.json +41 -2
- package/state/build-state.template.json +8 -0
- package/templates/CLAUDE.md.template +2 -2
package/docs/hooks.md
CHANGED
|
@@ -93,7 +93,7 @@ Cierra el **ciclo autocorrectivo**. Al terminar el turno, si en `history[]` hay
|
|
|
93
93
|
|
|
94
94
|
### 9. `design-source-guard.sh` — `PreToolUse` · Write/Edit/MultiEdit · **bloqueante** (desde v0.5.0)
|
|
95
95
|
|
|
96
|
-
Refuerza el **seguro de fuente de diseño** (espejo de `scaffold-guard`, para slices con UI). Bloquea con `exit 2` la escritura de **código de un slice con UI** —cuando `active_slice.phase` ∈ `red`/`green`/`refactor`/`smoke`/`api`/`data` **y** `active_slice.gates.fidelity === false` (marcado UI-pendiente por la DoR)— mientras el proyecto tenga UI (`design_source.applies === true`) y `design_source.confirmed` no sea `true`. **Permite** todo lo demás: slices sin UI (`gates.fidelity === null` o ausente), proyectos sin UI (`applies !== true`), fases de planificación (`dor`/`change`), o fuente ya confirmada. El arnés **exige** la fuente de diseño
|
|
96
|
+
Refuerza el **seguro de fuente de diseño** (espejo de `scaffold-guard`, para slices con UI). Bloquea con `exit 2` la escritura de **código de un slice con UI** —cuando `active_slice.phase` ∈ `red`/`green`/`refactor`/`smoke`/`api`/`data` **y** `active_slice.gates.fidelity === false` (marcado UI-pendiente por la DoR)— mientras el proyecto tenga UI (`design_source.applies === true`) y `design_source.confirmed` no sea `true`. **Permite** todo lo demás: slices sin UI (`gates.fidelity === null` o ausente), proyectos sin UI (`applies !== true`), fases de planificación (`dor`/`change`), o fuente ya confirmada. El arnés **exige** la fuente de diseño y puede **generarla** vía `/build:prototype` (skill `prototyping-screens`; el mensaje de bloqueo lo sugiere); la confirmación sigue siendo **explícita y humana** (vía `building-a-slice` Fase 0-bis / `dor-dod-gatekeeper`), nunca auto-detectada. Guarda `python3` fail-closed dirigido. En la práctica, como `design_source` es gate de proyecto, solo muerde la **primera** construcción de UI sin fuente declarada.
|
|
97
97
|
|
|
98
98
|
### 10. `release-gate-nudge.sh` — `Stop` · no bloqueante (desde v0.7.0)
|
|
99
99
|
|
|
@@ -46,7 +46,7 @@ PY
|
|
|
46
46
|
if [ "$VERDICT" = "BLOCK" ]; then
|
|
47
47
|
echo "⛔ design-source-guard: el slice con UI está en fase de código pero la fuente de diseño NO está confirmada." >&2
|
|
48
48
|
echo " Declara y confirma primero el DESIGN_SOURCE del proyecto (ver building-a-slice Fase 0-bis / DoR)." >&2
|
|
49
|
-
echo "
|
|
49
|
+
echo " Genera el prototipo con /build:prototype o declara una fuente existente (prototipo/export), y confírmala." >&2
|
|
50
50
|
exit 2
|
|
51
51
|
fi
|
|
52
52
|
exit 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trycore/spec-build-harness",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "Arnés agéntico de construcción de Trycore para Claude Code: pipeline de dos loops (slice por épica + release gate) con gates de calidad, estado compartido y OpenSpec. Compañero de @trycore/spec-product-flow. Agnóstico al proyecto.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -86,4 +86,92 @@ check "hooks/build/reconcile-build-state.py"
|
|
|
86
86
|
check "hooks/build/lib/state-io.sh"
|
|
87
87
|
check "scripts/lib/front-plan.py"
|
|
88
88
|
|
|
89
|
+
# project_kind: el TMP de init es un directorio vacío → greenfield detectado (auto)
|
|
90
|
+
if python3 -c "
|
|
91
|
+
import json,sys
|
|
92
|
+
d=json.load(open('$TMP/.claude/state/build-state.json'))
|
|
93
|
+
assert d.get('project_kind')=='greenfield', d.get('project_kind')
|
|
94
|
+
assert d.get('project_kind_source')=='auto', d.get('project_kind_source')
|
|
95
|
+
" 2>/dev/null; then
|
|
96
|
+
echo "OK install: project_kind=greenfield detectado (auto)"
|
|
97
|
+
else
|
|
98
|
+
echo "FAIL install: project_kind no detectado como greenfield/auto"
|
|
99
|
+
fail=1
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# 5) Brownfield seguro: manifiesto + código + historial git que toca código.
|
|
103
|
+
TMP_BF="$(mktemp -d)"
|
|
104
|
+
echo '{}' > "$TMP_BF/package.json"
|
|
105
|
+
mkdir -p "$TMP_BF/src"
|
|
106
|
+
echo 'export const x = 1;' > "$TMP_BF/src/index.ts"
|
|
107
|
+
(
|
|
108
|
+
cd "$TMP_BF" &&
|
|
109
|
+
git init -q &&
|
|
110
|
+
git add -A &&
|
|
111
|
+
git -c user.email=t@t -c user.name=t commit -qm x
|
|
112
|
+
) >/dev/null 2>&1
|
|
113
|
+
|
|
114
|
+
node "$ROOT/dist/cli.js" init "$TMP_BF" \
|
|
115
|
+
--copy \
|
|
116
|
+
--skip-doctor \
|
|
117
|
+
--yes \
|
|
118
|
+
--stack "" \
|
|
119
|
+
--pkg-manager npm \
|
|
120
|
+
--runtime ">=18.18" \
|
|
121
|
+
--prd-path "docs/01-prd/x.md#req" \
|
|
122
|
+
>"$TMP_BF/.init.log" 2>&1
|
|
123
|
+
rc=$?
|
|
124
|
+
if [ $rc -ne 0 ]; then
|
|
125
|
+
echo "FAIL install: \`trycore-build init\` (brownfield) salió con código $rc"
|
|
126
|
+
cat "$TMP_BF/.init.log"
|
|
127
|
+
fail=1
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
if python3 -c "
|
|
131
|
+
import json,sys
|
|
132
|
+
d=json.load(open('$TMP_BF/.claude/state/build-state.json'))
|
|
133
|
+
assert d.get('project_kind')=='brownfield', d.get('project_kind')
|
|
134
|
+
assert d.get('project_kind_source')=='auto', d.get('project_kind_source')
|
|
135
|
+
" 2>/dev/null; then
|
|
136
|
+
echo "OK install: project_kind=brownfield con historial git"
|
|
137
|
+
else
|
|
138
|
+
echo "FAIL install: project_kind no detectado como brownfield con historial git"
|
|
139
|
+
fail=1
|
|
140
|
+
fi
|
|
141
|
+
rm -rf "$TMP_BF"
|
|
142
|
+
|
|
143
|
+
# 6) Ambiguo: manifiesto + código pero SIN repo git (sin historial) → project_kind null.
|
|
144
|
+
TMP_AMB="$(mktemp -d)"
|
|
145
|
+
echo '{}' > "$TMP_AMB/package.json"
|
|
146
|
+
mkdir -p "$TMP_AMB/src"
|
|
147
|
+
echo 'export const x = 1;' > "$TMP_AMB/src/index.ts"
|
|
148
|
+
|
|
149
|
+
node "$ROOT/dist/cli.js" init "$TMP_AMB" \
|
|
150
|
+
--copy \
|
|
151
|
+
--skip-doctor \
|
|
152
|
+
--yes \
|
|
153
|
+
--stack "" \
|
|
154
|
+
--pkg-manager npm \
|
|
155
|
+
--runtime ">=18.18" \
|
|
156
|
+
--prd-path "docs/01-prd/x.md#req" \
|
|
157
|
+
>"$TMP_AMB/.init.log" 2>&1
|
|
158
|
+
rc=$?
|
|
159
|
+
if [ $rc -ne 0 ]; then
|
|
160
|
+
echo "FAIL install: \`trycore-build init\` (ambiguo) salió con código $rc"
|
|
161
|
+
cat "$TMP_AMB/.init.log"
|
|
162
|
+
fail=1
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
if python3 -c "
|
|
166
|
+
import json,sys
|
|
167
|
+
d=json.load(open('$TMP_AMB/.claude/state/build-state.json'))
|
|
168
|
+
assert d.get('project_kind') is None, d.get('project_kind')
|
|
169
|
+
" 2>/dev/null; then
|
|
170
|
+
echo "OK install: project_kind=null (ambiguo sin historial git)"
|
|
171
|
+
else
|
|
172
|
+
echo "FAIL install: project_kind no quedó null en caso ambiguo"
|
|
173
|
+
fail=1
|
|
174
|
+
fi
|
|
175
|
+
rm -rf "$TMP_AMB"
|
|
176
|
+
|
|
89
177
|
exit $fail
|
|
@@ -43,8 +43,29 @@ cat > "$TMP/bad-layer.json" <<'JSON'
|
|
|
43
43
|
"layer":"WRONG","gates":{"dor":true,"tdd":false,"dod":false},"updated_at":"2026-07-03T00:00:00Z","updated_by":"t"},
|
|
44
44
|
"history":[],"releases":[]}
|
|
45
45
|
JSON
|
|
46
|
+
cat > "$TMP/valid-foundation.json" <<'JSON'
|
|
47
|
+
{"version":"1.0","harness_phase":"authoring","scaffold":{"confirmed":false},
|
|
48
|
+
"project_kind":"greenfield","project_kind_source":"auto",
|
|
49
|
+
"foundation":{"required":true,"epic":"EP-001","completed_at":null,
|
|
50
|
+
"checklist":[{"item":"navegacion-menus","applies":true,"evidence":""},
|
|
51
|
+
{"item":"login-authn","applies":true,"evidence":"smoke login OK"}]},
|
|
52
|
+
"active_slice":null,"history":[],"releases":[]}
|
|
53
|
+
JSON
|
|
54
|
+
cat > "$TMP/bad-project-kind.json" <<'JSON'
|
|
55
|
+
{"version":"1.0","harness_phase":"authoring","scaffold":{"confirmed":false},
|
|
56
|
+
"project_kind":"unknown","active_slice":null,"history":[],"releases":[]}
|
|
57
|
+
JSON
|
|
58
|
+
cat > "$TMP/bad-foundation-item.json" <<'JSON'
|
|
59
|
+
{"version":"1.0","harness_phase":"authoring","scaffold":{"confirmed":false},
|
|
60
|
+
"foundation":{"required":true,"epic":null,"completed_at":null,
|
|
61
|
+
"checklist":[{"applies":true}]},
|
|
62
|
+
"active_slice":null,"history":[],"releases":[]}
|
|
63
|
+
JSON
|
|
46
64
|
check "estado válido con campos nuevos" pass "$TMP/valid.json"
|
|
47
65
|
check "layer inválido rechazado" fail "$TMP/bad-layer.json"
|
|
66
|
+
check "foundation + project_kind válidos" pass "$TMP/valid-foundation.json"
|
|
67
|
+
check "project_kind inválido rechazado" fail "$TMP/bad-project-kind.json"
|
|
68
|
+
check "checklist item sin 'item' rechazado" fail "$TMP/bad-foundation-item.json"
|
|
48
69
|
|
|
49
70
|
CFG="$ROOT/config/build-config.template.json"
|
|
50
71
|
if [ -f "$CFG" ] && python3 -c "import json,sys; d=json.load(open('$CFG'))['context']; assert d['warning_pct']==35 and d['critical_pct']==25 and d['auto_checkpoint'] is False" 2>/dev/null; then
|
|
@@ -105,8 +105,9 @@ Espejo de la Fase 0, para proyectos **con UI**. Antes de abrir el primer slice c
|
|
|
105
105
|
- `confirmed === true` → continúa.
|
|
106
106
|
2. `applies===true && confirmed===false` → **pregunta explícita** (AskUserQuestion): *"¿Existe una
|
|
107
107
|
fuente de diseño declarada (prototipo/export) para la UI de este proyecto?"*
|
|
108
|
-
- **No** → **STOP**.
|
|
109
|
-
|
|
108
|
+
- **No** → **STOP**. Ofrece dos salidas: **generarla con `/build:prototype`** (skill
|
|
109
|
+
`prototyping-screens`; la confirmación sigue siendo humana) o declarar una fuente externa
|
|
110
|
+
(ruta/URL del prototipo o export). No abras el slice con UI sin fuente confirmada.
|
|
110
111
|
- **Sí** → registra `design_source.source`, `confirmed=true`, `confirmed_by`, `confirmed_at`, `notes`.
|
|
111
112
|
3. Lo respalda el hook determinista `design-source-guard.sh` (bloquea código de slice UI sin fuente
|
|
112
113
|
confirmada) y lo valida el `dor-dod-gatekeeper` (criterio duro de DoR).
|
|
@@ -10,6 +10,16 @@ la épica; lo de abajo aplica a la épica y a **cada HU** que cubre (`hus[]`). L
|
|
|
10
10
|
- [ ] **INVEST** por HU: pasa los 6 criterios (Independent, Negotiable, Valuable, Estimable, Small, Testable).
|
|
11
11
|
- [ ] **Dependencias resueltas**: las épicas/HU de las que depende están archivadas (`history[]`) o explícitamente no bloquean. **Excepción dura — cimiento:** si la dependencia es **infraestructura fundacional** (autenticación, acceso a datos, arquitectura base, design-system/componentes base), la cláusula "explícitamente no bloquean" **NO aplica**: debe estar **construida y archivada** antes (ver criterio "Cimiento construido").
|
|
12
12
|
- [ ] **Cimiento construido (épicas de negocio)**: si esta épica es `layer: business`, todo el cimiento que arrastra (auth, acceso a datos, arquitectura base, design-system/componentes base) ya existe como épica(s) `layer: foundational` **archivada(s)** en `history[]`. Si arrastra cimiento no construido → **STOP**: extráelo a una épica fundacional previa y constrúyela primero. Las épicas fundacionales se priorizan **antes** que las de negocio.
|
|
13
|
+
- [ ] **Caparazón construido (solo greenfield — gate PROACTIVO)**: si `project_kind === "greenfield"`
|
|
14
|
+
y `foundation.required === true` en `build-state.json`, ninguna épica `layer: business` entra a
|
|
15
|
+
construcción mientras la épica caparazón (`foundation.epic`) no esté **archivada con su checklist
|
|
16
|
+
evidenciada** (`foundation.completed_at` estampado). Las épicas `layer: foundational` (la
|
|
17
|
+
caparazón `foundation.epic` u otras fundacionales) sí pueden abrir. A diferencia de "Cimiento
|
|
18
|
+
construido" (reactivo: bloquea si *detecta* arrastre), este criterio bloquea **siempre** en
|
|
19
|
+
greenfield hasta que el cimiento exista archivado — no depende de detectar nada. Si
|
|
20
|
+
`foundation.epic` es `null` (no existe la épica caparazón aún) → **STOP**: se define en
|
|
21
|
+
`/build:onboard` Fase 2c o en discovery. Brownfield / `foundation.required: false` → **N/A** (no
|
|
22
|
+
bloquea). Contrato: `references/foundation-contract.md`.
|
|
13
23
|
- [ ] **Tamaño acotado (gate de descomposición)**: si la épica supera el umbral —heurística por defecto **> 3 HU** ó **≥ 3 capas tocadas** (configurable por proyecto)— **no entra como slice único**: se descompone en `sub_slices[]` verificables construidos de a uno, con `journey_smoke` verde entre cada uno. El umbral es proporcional (no cuota rígida): una épica de 1 capa y pocas HU entra directa.
|
|
14
24
|
- [ ] **Cabe en el stack** del PRD §7 (no requiere tecnología fuera de `stack-allowlist.json`).
|
|
15
25
|
- [ ] **Cobertura arquitectónica (ADR)** *(opt-in, retrocompatible)*: si el proyecto adoptó la capa de
|
|
@@ -23,7 +33,10 @@ la épica; lo de abajo aplica a la épica y a **cada HU** que cubre (`hus[]`). L
|
|
|
23
33
|
- [ ] **Datos de prueba disponibles** o identificables (p.ej. los datos de ejemplo / fixtures sintéticos del dominio del consumidor).
|
|
24
34
|
- [ ] **Fuente de diseño identificada (slices con UI)**: la fuente visual de verdad del slice
|
|
25
35
|
(el `DESIGN_SOURCE` del dominio) está declarada y confirmada (`design_source.confirmed`), y este
|
|
26
|
-
slice apunta a la(s) pantalla(s) equivalente(s).
|
|
36
|
+
slice apunta a la(s) pantalla(s) equivalente(s). Si la fuente es un prototipo generado
|
|
37
|
+
(`docs/05-prototipo/`), esas pantallas existen en `manifest.json` con `estado: "aprobada"`
|
|
38
|
+
(un `borrador` no satisface el criterio; genera/aprueba primero con `/build:prototype`).
|
|
39
|
+
No se construye UI fuera de la fuente declarada.
|
|
27
40
|
- [ ] **Clasificación `layer`**: `foundational` (auth/datos/design-system/arquitectura base) | `business`. Se escribe en `active_slice.layer`. Gatea el front paralelo (foundational nunca en paralelo).
|
|
28
41
|
- [ ] **`files_scope`**: globs de los archivos que la épica tocará (p.ej. `src/reports/**`). Fuente de la disjunción inter-épica. Se escribe en `active_slice.files_scope`.
|
|
29
42
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contrato del caparazón (épica fundacional de app shell) — solo greenfield
|
|
2
|
+
|
|
3
|
+
El **caparazón** es el shell con contenido donde aterrizan las features: navegación, layout,
|
|
4
|
+
homepage, login y redirecciones. No es el *scaffold* (shell vacío que arranca — gate
|
|
5
|
+
`scaffold.confirmed`) ni el *walking skeleton* (primer journey de negocio más delgado): es la
|
|
6
|
+
infraestructura de UI/entrada fundacional que, si no existe primero, cada épica de negocio
|
|
7
|
+
improvisa a pedazos y acumula deuda estructural.
|
|
8
|
+
|
|
9
|
+
**Aplica si y solo si `project_kind === "greenfield"`.** En brownfield el mecanismo entero es
|
|
10
|
+
N/A y el arnés no pregunta ni exige nada (`foundation.required: false`).
|
|
11
|
+
|
|
12
|
+
## Checklist base (ids canónicos)
|
|
13
|
+
|
|
14
|
+
| id | Qué cubre | Poda típica |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `navegacion-menus` | Menús / estructura de navegación principal | API sin UI |
|
|
17
|
+
| `layout-panel-central` | Layout base + panel/área central de contenido | API sin UI |
|
|
18
|
+
| `homepage` | Página de inicio real (no placeholder del scaffold) | API sin UI |
|
|
19
|
+
| `login-authn` | Login + autenticación cableada end-to-end | app pública sin cuentas |
|
|
20
|
+
| `redirecciones-guards` | Redirecciones y guards de ruta (authed/anon, 404, deep-links) | API sin UI |
|
|
21
|
+
|
|
22
|
+
- La **poda** se decide una vez, en `/build:onboard` Fase 2c, con el humano (ítem podado =
|
|
23
|
+
`applies: false`; queda en la checklist como decisión trazable, no se borra).
|
|
24
|
+
- El proyecto puede **añadir** ítems propios (id kebab-case) si su caparazón exige más.
|
|
25
|
+
|
|
26
|
+
## Ciclo de vida
|
|
27
|
+
|
|
28
|
+
1. **Onboard (Fase 2c)** — se poda la checklist, se persiste en `foundation.checklist[]` y se
|
|
29
|
+
identifica (o redacta en borrador híbrido) la épica caparazón → `foundation.epic`.
|
|
30
|
+
2. **DoR (gate proactivo)** — mientras la épica caparazón no esté **archivada**, ninguna épica
|
|
31
|
+
`layer: business` abre slice (solo fundacionales). Ver `dor.md`.
|
|
32
|
+
3. **DoD de la épica caparazón** — cada ítem `applies: true` exige `evidence` de ejecución real
|
|
33
|
+
(test, comando, screenshot MCP), patrón `wiring_checklist`. Sin evidencia completa no se
|
|
34
|
+
archiva.
|
|
35
|
+
4. **Cierre** — al archivar con la checklist evidenciada se estampa `foundation.completed_at` y
|
|
36
|
+
las épicas de negocio quedan desbloqueadas.
|
|
37
|
+
|
|
38
|
+
## Reglas duras
|
|
39
|
+
|
|
40
|
+
- El arnés **propone** el borrador de la épica caparazón; **solo** lo escribe en
|
|
41
|
+
`docs/03-backlog/epicas.md` con aprobación humana explícita (carve-out acotado, ver
|
|
42
|
+
METODOLOGIA §9.2). Si el humano rechaza, STOP: la épica se crea en discovery (`/trycore:*`).
|
|
43
|
+
- La evidencia es de **ejecución**, nunca de inspección.
|
|
44
|
+
- Si contradice `METODOLOGIA.md`, gana la metodología.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: prototyping-screens
|
|
3
|
+
description: Use when generating or extending the HTML reference prototype (the DESIGN_SOURCE) — the visual source of truth screens are built against. Two modes — greenfield (full initial prototype from discovery docs + human-chosen aesthetic direction) and feature (new-epic screens extracted live from the already-implemented UI so they look native to the app). Self-verifies visually; human approval gates everything.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Prototipar pantallas de referencia (outer-loop)
|
|
7
|
+
|
|
8
|
+
Genera el **prototipo HTML de referencia** del consumidor: la fuente de verdad visual
|
|
9
|
+
(`DESIGN_SOURCE`) contra la que después se construyen y verifican los slices con UI
|
|
10
|
+
(gate `fidelity`, `ux-fidelity-reviewer`). Si algo aquí contradice `METODOLOGIA.md`,
|
|
11
|
+
**gana la metodología**.
|
|
12
|
+
|
|
13
|
+
**Invariantes:**
|
|
14
|
+
- La skill **genera**; el humano **aprueba**. `design_source.confirmed` y el `estado: "aprobada"`
|
|
15
|
+
del manifest son **siempre** decisiones humanas — esta skill jamás los auto-marca.
|
|
16
|
+
- Es **outer-loop**: se corre antes de abrir slices (como `/build:architect`), nunca dentro del
|
|
17
|
+
inner loop de una épica.
|
|
18
|
+
- Escribe **solo** en `docs/05-prototipo/` (carve-out §9.2 de METODOLOGIA) y, con aprobación
|
|
19
|
+
humana, en `design_source` de `build-state.json` (protocolo de `state/README.md`).
|
|
20
|
+
|
|
21
|
+
## Artefactos que produce (repo del consumidor)
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
docs/05-prototipo/
|
|
25
|
+
├── DESIGN.md ← tokens + reglas visuales en prosa (assets/DESIGN.md.template)
|
|
26
|
+
├── tokens.css ← los mismos tokens como CSS custom properties (fuente única)
|
|
27
|
+
├── manifest.json ← pantalla ↔ épica/HU ↔ archivo ↔ estado (assets/manifest.schema.json)
|
|
28
|
+
└── pantallas/
|
|
29
|
+
└── <slug>.html ← un HTML autocontenido por pantalla (assets/screen.template.html)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Reglas duras del artefacto:**
|
|
33
|
+
- HTML **autocontenido**: cero dependencias externas (sin CDNs, frameworks, fetch ni JS); única
|
|
34
|
+
importación permitida: `tokens.css`; renderiza en `file://` indefinidamente; datos ilustrativos
|
|
35
|
+
estáticos.
|
|
36
|
+
- Cero valores visuales fuera de tokens (color/fuente/spacing/radio/sombra → `var(--token)`).
|
|
37
|
+
- Estados relevantes (vacío, error, cargando…) que la HU exija → **variantes de pantalla**
|
|
38
|
+
(`<slug>--<estado>.html`, campo `variante_de` en el manifest), no interacciones.
|
|
39
|
+
- Solo pantallas `estado: "aprobada"` son fuente de verdad (las lee `ux-fidelity-reviewer`); el
|
|
40
|
+
resto son `borrador`.
|
|
41
|
+
|
|
42
|
+
## Detección de modo
|
|
43
|
+
|
|
44
|
+
1. No existe `docs/05-prototipo/` ni hay `design_source.confirmed` → **greenfield**.
|
|
45
|
+
2. Se pide pantallas para una épica y existe app implementada (o prototipo previo) → **feature**.
|
|
46
|
+
3. Ambigüedad → pregunta al humano antes de tocar nada.
|
|
47
|
+
|
|
48
|
+
## Modo greenfield — prototipo inicial completo
|
|
49
|
+
|
|
50
|
+
1. **Inventario de pantallas**: lee PRD, user story map/flows e historias de discovery; deriva la
|
|
51
|
+
lista pantalla ↔ épica/HU (esqueleto del `manifest.json`) y **preséntala para confirmación
|
|
52
|
+
humana** antes de generar nada.
|
|
53
|
+
2. **Dirección estética**: sigue `references/aesthetic-directions.md` (¿manual de marca? → destilar
|
|
54
|
+
tokens; si no → 2-3 direcciones visuales de una pantalla clave, elección humana en navegador).
|
|
55
|
+
Salida: `DESIGN.md` + `tokens.css`.
|
|
56
|
+
3. **Generación por lotes**: pantallas en orden de flow, cada una desde su HU + tokens, sobre
|
|
57
|
+
`assets/screen.template.html`. Tras cada lote: auto-verificación (`references/self-check.md`)
|
|
58
|
+
y **pausa** para revisión humana en navegador. Registra cada pantalla en el manifest como
|
|
59
|
+
`borrador`.
|
|
60
|
+
|
|
61
|
+
## Modo feature — pantallas de una épica nueva (el caso brownfield)
|
|
62
|
+
|
|
63
|
+
1. **Precondición dura**: la app implementada **corriendo** + un MCP de inspección de UI habilitado
|
|
64
|
+
(p.ej. chrome-devtools para web). Si falta cualquiera → **STOP** con instrucciones (levantar la
|
|
65
|
+
app / habilitar el MCP). **Sin degradación a extracción estática**: el CSS computado real es el
|
|
66
|
+
factor decisivo de fidelidad (misma postura que el gate `fidelity`, donde INCONCLUSO bloquea).
|
|
67
|
+
2. **Extracción viva**: sigue `references/extraction.md` (CSS computado + screenshots en 3 viewports
|
|
68
|
+
+ árbol de componentes de 2-3 pantallas representativas; reconciliación de `tokens.css`: la app
|
|
69
|
+
real gana, las divergencias se reportan como drift).
|
|
70
|
+
3. **Generación**: las pantallas nuevas de la épica usan los tokens reconciliados y los screenshots
|
|
71
|
+
de la app como referencia de composición. Criterio de éxito: la pantalla nueva parece
|
|
72
|
+
**"una pantalla más"** de la app existente.
|
|
73
|
+
4. **Registro**: entradas nuevas en `manifest.json` como `borrador` (con `epica`/`historias`).
|
|
74
|
+
|
|
75
|
+
## Auto-verificación (ambos modos)
|
|
76
|
+
|
|
77
|
+
Sigue `references/self-check.md`: renderizado real de cada HTML (`file://`), screenshot en
|
|
78
|
+
3 viewports + snapshot estructural, comparación (feature → contra lo extraído de la app;
|
|
79
|
+
greenfield → contra tokens + consistencia del lote), corrección y re-render con **máximo
|
|
80
|
+
3 iteraciones**; si no converge, reporte al humano con el delta. Sin pixel-diff.
|
|
81
|
+
|
|
82
|
+
## Aprobación humana → estado
|
|
83
|
+
|
|
84
|
+
1. Abre las pantallas en el navegador del usuario y pide aprobación explícita (por pantalla o por
|
|
85
|
+
lote). Aprobada → `manifest.json` pasa esa entrada a `"aprobada"`.
|
|
86
|
+
2. **Greenfield** con ≥1 pantalla aprobada: ofrece registrar la fuente en `build-state.json` —
|
|
87
|
+
`design_source.source: "docs/05-prototipo/"`, `confirmed: true`, `confirmed_by`, `confirmed_at`,
|
|
88
|
+
`notes` — siguiendo el protocolo de escritura de `state/README.md`. Solo con el **sí** explícito
|
|
89
|
+
del humano.
|
|
90
|
+
3. **Feature**: `design_source` ya está confirmado; solo se amplía el manifest.
|
|
91
|
+
|
|
92
|
+
## Qué NO hace esta skill
|
|
93
|
+
|
|
94
|
+
- **No** hace pixel-diff (comparación estructural/semántica, como el resto del arnés).
|
|
95
|
+
- **No** genera código de producción: eso es el slice normal (`building-a-slice`) con su gate
|
|
96
|
+
`fidelity`; el prototipo es su entrada, no su salida.
|
|
97
|
+
- **No** prototipa interacciones/animaciones (HTML estático; estados como variantes).
|
|
98
|
+
- **No** integra plataformas de diseño externas (exports no navegables ya tienen su rama en
|
|
99
|
+
`ux-fidelity-reviewer`).
|
|
100
|
+
- **No** escribe en `docs/01-…04-…` ni toca otros campos del estado.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# DESIGN.md — reglas visuales del producto
|
|
2
|
+
|
|
3
|
+
> Fuente de verdad **en prosa** de la identidad visual. Los mismos valores viven como CSS custom
|
|
4
|
+
> properties en `tokens.css` (fuente única que importan todos los prototipos). Si este archivo y
|
|
5
|
+
> `tokens.css` divergen, gana `tokens.css` y la divergencia se reporta como drift.
|
|
6
|
+
|
|
7
|
+
## Identidad
|
|
8
|
+
|
|
9
|
+
{{DIRECCION_ELEGIDA}} — dirección visual elegida y por qué (elección humana, ver Procedencia).
|
|
10
|
+
|
|
11
|
+
## Paleta
|
|
12
|
+
|
|
13
|
+
| Token | Valor | Uso |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `--color-primary` | {{HEX}} | {{USO}} |
|
|
16
|
+
| `--color-surface` | {{HEX}} | {{USO}} |
|
|
17
|
+
| `--color-text` | {{HEX}} | {{USO}} |
|
|
18
|
+
| … | … | … |
|
|
19
|
+
|
|
20
|
+
## Tipografía
|
|
21
|
+
|
|
22
|
+
- **Familias**: {{FAMILIA_TITULARES}} (titulares) · {{FAMILIA_CUERPO}} (cuerpo).
|
|
23
|
+
- **Escala**: {{ESCALA}} (p.ej. 12/14/16/20/24/32).
|
|
24
|
+
- **Pesos**: {{PESOS}} y dónde se usa cada uno.
|
|
25
|
+
|
|
26
|
+
## Espaciado y radios
|
|
27
|
+
|
|
28
|
+
- **Spacing scale**: {{SPACING_SCALE}} (todos los márgenes/paddings son múltiplos de la escala).
|
|
29
|
+
- **Radios**: {{RADIOS}} por tipo de componente.
|
|
30
|
+
|
|
31
|
+
## Sombras
|
|
32
|
+
|
|
33
|
+
| Token | Valor | Uso |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `--shadow-1` | {{VALOR}} | {{USO}} |
|
|
36
|
+
|
|
37
|
+
## Componentes
|
|
38
|
+
|
|
39
|
+
Reglas por componente (densidad, alineación, jerarquía) que los prototipos deben respetar:
|
|
40
|
+
|
|
41
|
+
- {{COMPONENTE}}: {{REGLA}}
|
|
42
|
+
|
|
43
|
+
## Don'ts (lista explícita)
|
|
44
|
+
|
|
45
|
+
- No inventar colores, fuentes, spacing ni radios fuera de los tokens.
|
|
46
|
+
- No introducir dependencias externas en los prototipos (CDNs, frameworks, fuentes remotas).
|
|
47
|
+
- No "interpretar" el diseño al construir: copiar valores exactos.
|
|
48
|
+
- {{DONT_ESPECIFICO_DEL_PRODUCTO}}
|
|
49
|
+
|
|
50
|
+
## Procedencia
|
|
51
|
+
|
|
52
|
+
- **Origen de los tokens**: {{ORIGEN}} (manual de marca / extracción viva de la app / dirección
|
|
53
|
+
elegida por el humano entre variantes).
|
|
54
|
+
- **Fecha**: {{FECHA_ISO}}.
|
|
55
|
+
- **Reconciliaciones**: {{NOTAS_DE_DRIFT}} (cuándo la app real corrigió lo declarado).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "trycore-build/prototype-manifest",
|
|
4
|
+
"title": "Manifest del prototipo de referencia (docs/05-prototipo/manifest.json)",
|
|
5
|
+
"description": "Mapa determinista pantalla ↔ épica/HU ↔ archivo HTML ↔ estado. Solo las pantallas con estado 'aprobada' son fuente de verdad visual (las lee ux-fidelity-reviewer y resuelven el puntero por-slice de la DoR).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["version", "pantallas"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"version": {
|
|
11
|
+
"type": "integer",
|
|
12
|
+
"description": "Versión del formato del manifest (hoy: 1)."
|
|
13
|
+
},
|
|
14
|
+
"pantallas": {
|
|
15
|
+
"type": "array",
|
|
16
|
+
"items": { "$ref": "#/$defs/pantalla" }
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"$defs": {
|
|
20
|
+
"pantalla": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"additionalProperties": false,
|
|
23
|
+
"required": ["slug", "archivo", "estado"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"slug": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*(--[a-z0-9]+(-[a-z0-9]+)*)?$",
|
|
28
|
+
"description": "Identificador kebab-case de la pantalla. Las variantes de estado usan sufijo doble guion (p.ej. <slug>--vacio)."
|
|
29
|
+
},
|
|
30
|
+
"archivo": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Ruta relativa al directorio del prototipo (p.ej. pantallas/<slug>.html)."
|
|
33
|
+
},
|
|
34
|
+
"epica": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "^EP-[0-9]{3}$",
|
|
37
|
+
"description": "Épica a la que pertenece la pantalla (puntero por-slice de la DoR)."
|
|
38
|
+
},
|
|
39
|
+
"historias": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"items": { "type": "string", "pattern": "^HU-[0-9]{3}$" },
|
|
42
|
+
"description": "Historias de usuario que la pantalla cubre."
|
|
43
|
+
},
|
|
44
|
+
"estado": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"enum": ["borrador", "aprobada"],
|
|
47
|
+
"description": "borrador = generada, pendiente de aprobación humana; aprobada = fuente de verdad visual (la aprobación es SIEMPRE humana)."
|
|
48
|
+
},
|
|
49
|
+
"generada_en": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"format": "date-time",
|
|
52
|
+
"description": "Cuándo se generó/regeneró (ISO-8601 UTC)."
|
|
53
|
+
},
|
|
54
|
+
"viewports_verificados": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": { "type": "string", "enum": ["desktop", "tablet", "mobile"] },
|
|
57
|
+
"description": "Viewports en los que el self-check renderizó y verificó la pantalla."
|
|
58
|
+
},
|
|
59
|
+
"variante_de": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Slug de la pantalla base si esta entrada es una variante de estado (vacío, error, cargando…)."
|
|
62
|
+
},
|
|
63
|
+
"notas": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Nota libre (p.ej. desviaciones intencionales aceptadas por el humano)."
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<!--
|
|
3
|
+
Prototipo de referencia — pantalla {{SLUG}}
|
|
4
|
+
Reglas duras del artefacto (NO negociables):
|
|
5
|
+
- AUTOCONTENIDO: cero dependencias externas (sin CDNs, sin frameworks, sin fetch, sin JS).
|
|
6
|
+
Única importación permitida: ../tokens.css. Debe renderizar en file:// indefinidamente.
|
|
7
|
+
- TOKENS: todo color, fuente, spacing, radio y sombra sale de las custom properties de
|
|
8
|
+
../tokens.css. Cero valores mágicos fuera de tokens.
|
|
9
|
+
- DATOS ILUSTRATIVOS ESTÁTICOS: contenido de ejemplo neutro, embebido en el HTML.
|
|
10
|
+
- ESTADOS: los estados relevantes (vacío, error, cargando) que la HU exija son VARIANTES
|
|
11
|
+
de pantalla en archivos propios ({{SLUG}}--<estado>.html), no interacciones.
|
|
12
|
+
Trazabilidad: épica {{EPICA}} · historias {{HISTORIAS}} · registrada en ../manifest.json
|
|
13
|
+
-->
|
|
14
|
+
<html lang="es">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charset="utf-8">
|
|
17
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
18
|
+
<title>{{TITULO_PANTALLA}} — prototipo</title>
|
|
19
|
+
<link rel="stylesheet" href="../tokens.css">
|
|
20
|
+
<style>
|
|
21
|
+
/* Estilos propios de esta pantalla: SOLO composición/layout.
|
|
22
|
+
Valores visuales (color, fuente, spacing, radio, sombra) → var(--token). */
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<!-- región: navegación / cabecera -->
|
|
27
|
+
|
|
28
|
+
<!-- región: contenido principal (composición según la HU y el patrón de layout del sistema) -->
|
|
29
|
+
|
|
30
|
+
<!-- región: paneles secundarios / laterales (si el diseño los declara) -->
|
|
31
|
+
|
|
32
|
+
<!-- región: pie / acciones globales (si el diseño lo declara) -->
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Dirección estética (modo greenfield)
|
|
2
|
+
|
|
3
|
+
Protocolo para fijar la identidad visual **antes** de generar pantallas, cuando discovery solo
|
|
4
|
+
entrega docs de texto. La decisión estética es **humana**; la skill produce opciones y destila.
|
|
5
|
+
|
|
6
|
+
## 1. ¿Hay manual de marca?
|
|
7
|
+
|
|
8
|
+
Pregunta primero si el consumidor tiene manual de marca / brand guidelines / design system previo.
|
|
9
|
+
|
|
10
|
+
- **Sí** → destila los tokens directamente de ese insumo (paleta exacta, tipografías, reglas de
|
|
11
|
+
uso) a `DESIGN.md` + `tokens.css`, con **Procedencia: manual de marca**. **No** generes
|
|
12
|
+
variantes: la identidad ya está decidida. Salta al paso 4.
|
|
13
|
+
- **No** → continúa con variantes (pasos 2-3).
|
|
14
|
+
|
|
15
|
+
## 2. Elegir la pantalla clave
|
|
16
|
+
|
|
17
|
+
Una sola pantalla para el ejercicio: la más **representativa del journey** (la que un usuario ve
|
|
18
|
+
más tiempo o la que concentra más componentes distintos — típicamente la pantalla principal de
|
|
19
|
+
trabajo tras entrar). Evita pantallas triviales: no discriminan entre direcciones.
|
|
20
|
+
|
|
21
|
+
## 3. Generar 2-3 direcciones y someterlas a elección humana
|
|
22
|
+
|
|
23
|
+
1. Genera la pantalla clave en **2-3 direcciones visuales genuinamente distintas** — que difieran
|
|
24
|
+
en paleta, tipografía y densidad/tono (p.ej. sobria-densa · aireada-amable · contrastada-enérgica),
|
|
25
|
+
no tres matices del mismo gris. Cada dirección respeta el mismo contenido y la misma HU.
|
|
26
|
+
2. Móntalas **lado a lado en un único HTML comparador** autocontenido (una columna por dirección,
|
|
27
|
+
con nombre y rasgos clave de cada una) y ábrelo en el navegador del usuario.
|
|
28
|
+
3. El humano elige. Se permite **mezclar** ("la paleta de A con la tipografía de B") si lo pide.
|
|
29
|
+
4. El comparador es un artefacto de trabajo: puede guardarse en `docs/05-prototipo/` como
|
|
30
|
+
`_direcciones.html` para la trazabilidad de la decisión, pero **no** entra al manifest.
|
|
31
|
+
|
|
32
|
+
## 4. Destilar `DESIGN.md` + `tokens.css`
|
|
33
|
+
|
|
34
|
+
De la dirección elegida (o del manual de marca):
|
|
35
|
+
- `tokens.css` — custom properties: paleta completa (con variantes de énfasis/estado), familias y
|
|
36
|
+
escala tipográfica, spacing scale, radios, sombras.
|
|
37
|
+
- `DESIGN.md` (`assets/DESIGN.md.template`) — la prosa: identidad y por qué se eligió, tablas de
|
|
38
|
+
tokens con uso, reglas de componentes, **Don'ts** explícitos y **Procedencia** (dirección elegida
|
|
39
|
+
+ fecha).
|
|
40
|
+
|
|
41
|
+
A partir de aquí, **toda** pantalla del prototipo importa `tokens.css` y no introduce valores
|
|
42
|
+
fuera de tokens; el self-check (`self-check.md`) lo verifica.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Extracción viva del UX/UI implementado (modo feature)
|
|
2
|
+
|
|
3
|
+
Protocolo para capturar el **contexto rico real** de la app implementada antes de generar
|
|
4
|
+
pantallas nuevas. La lección de fondo: la fidelidad no sale de "mirar un screenshot", sale de
|
|
5
|
+
**CSS computado real + capturas multi-viewport + estructura**. Todo esto exige la app corriendo
|
|
6
|
+
y un MCP de inspección de UI habilitado (p.ej. chrome-devtools para web); sin ellos, la skill
|
|
7
|
+
ya hizo STOP antes de llegar aquí.
|
|
8
|
+
|
|
9
|
+
## 1. Elegir pantallas representativas (2-3)
|
|
10
|
+
|
|
11
|
+
Criterio: cubrir los patrones que la pantalla nueva va a necesitar —
|
|
12
|
+
- la pantalla de **navegación/layout principal** (caparazón: menús, cabecera, panel central);
|
|
13
|
+
- una pantalla del **mismo tipo** que la que se va a generar (listado si va a haber listado,
|
|
14
|
+
formulario si va a haber formulario, detalle si detalle);
|
|
15
|
+
- si existe, una pantalla ya validada como fiel (`gates.fidelity: true` en `history[]`).
|
|
16
|
+
|
|
17
|
+
## 2. Capturar por cada pantalla
|
|
18
|
+
|
|
19
|
+
1. **Screenshots en 3 viewports** — desktop, tablet y mobile (redimensionar la página antes de
|
|
20
|
+
cada captura). Guardan la referencia de composición y densidad.
|
|
21
|
+
2. **CSS computado de elementos clave** — vía el MCP (evaluar `getComputedStyle` sobre):
|
|
22
|
+
- tipografía real: `font-family`, `font-size`, `font-weight`, `line-height` de titular
|
|
23
|
+
principal, titular secundario, cuerpo y etiquetas;
|
|
24
|
+
- color real: `color`, `background-color`, `border-color` de superficie, texto, acción
|
|
25
|
+
primaria, acción secundaria y estados de énfasis;
|
|
26
|
+
- espaciado real: `padding`/`margin`/`gap` de los contenedores estructurales y de los
|
|
27
|
+
componentes repetidos (tarjetas, filas, campos);
|
|
28
|
+
- `border-radius` y `box-shadow` de los componentes elevados.
|
|
29
|
+
3. **Árbol estructural** — snapshot del árbol accesible/DOM de la pantalla: número y disposición
|
|
30
|
+
de paneles, orden de secciones, jerarquía. Es la referencia de **composición** (estructura >
|
|
31
|
+
píxeles).
|
|
32
|
+
|
|
33
|
+
## 3. Destilar y reconciliar tokens
|
|
34
|
+
|
|
35
|
+
1. Consolida lo capturado en un conjunto de tokens (paleta, tipografía, spacing scale, radios,
|
|
36
|
+
sombras). Los valores repetidos entre pantallas son los tokens; los valores únicos son ruido.
|
|
37
|
+
2. **Si `docs/05-prototipo/tokens.css` ya existe → reconciliar**:
|
|
38
|
+
- **La app real gana** sobre lo declarado: si el token declarado dice un valor y el CSS
|
|
39
|
+
computado dice otro de forma consistente, actualiza el token al valor real.
|
|
40
|
+
- Cada divergencia se **reporta al humano como drift** (tabla token → declarado → real →
|
|
41
|
+
pantallas donde se observó). El drift es señal de que prototipo viejo y app se separaron:
|
|
42
|
+
el humano decide si además hay que corregir la app (fuera del alcance de esta skill).
|
|
43
|
+
3. Si no existe `tokens.css`, créalo desde lo extraído y genera/actualiza `DESIGN.md`
|
|
44
|
+
(`assets/DESIGN.md.template`) con **Procedencia: extracción viva** y la fecha.
|
|
45
|
+
|
|
46
|
+
## 4. Empaquetar el contexto para la generación
|
|
47
|
+
|
|
48
|
+
Antes de generar, deja explícito el paquete de referencia que usará la pantalla nueva:
|
|
49
|
+
- `tokens.css` reconciliado;
|
|
50
|
+
- screenshots de referencia (composición/densidad) de las pantallas capturadas;
|
|
51
|
+
- el árbol estructural del layout principal (dónde vive el contenido en el caparazón);
|
|
52
|
+
- las reglas de componentes observadas (densidad de tablas, anatomía de formularios, etc.),
|
|
53
|
+
anotadas en `DESIGN.md` si no estaban.
|
|
54
|
+
|
|
55
|
+
La generación no "interpreta" este paquete: **copia valores exactos**. Toda desviación deliberada
|
|
56
|
+
se anota como desviación intencional en `notas` del manifest para que `ux-fidelity-reviewer` no
|
|
57
|
+
la penalice después.
|