@trycore/spec-build-harness 0.4.0 → 0.5.0

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.
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "trycore-spec-build-harness",
4
4
  "displayName": "Trycore — Spec & Build Harness",
5
- "version": "0.4.0",
5
+ "version": "0.5.0",
6
6
  "description": "Arnés de construcción de dos loops (slice por épica + release gate) para Claude Code, con gates de calidad, estado compartido y OpenSpec. Compañero de @trycore/spec-product-flow. Agnóstico al proyecto.",
7
7
  "author": {
8
8
  "name": "Trycore",
package/GOVERNANCE.md CHANGED
@@ -8,8 +8,8 @@ evoluciona con el modelo y el proyecto. No es "instalar y olvidar".
8
8
  |---|---|---|
9
9
  | Contexto | sección Construcción de CLAUDE.md, `openspec/project.md` | raíz / `openspec/` |
10
10
  | Estado | `build-state.json` (+schema, README) | `.claude/state/` |
11
- | Agentes | 10 agentes de build | `.claude/agents/build/` |
12
- | Hooks | settings.json + 8 scripts | `.claude/settings.json`, `.claude/hooks/build/` |
11
+ | Agentes | 11 agentes de build | `.claude/agents/build/` |
12
+ | Hooks | settings.json + 9 scripts | `.claude/settings.json`, `.claude/hooks/build/` |
13
13
  | Skill | `building-a-slice` (+10 refs) · `building-a-micro-change` (carril ligero de mantenimiento) | `.claude/skills/` |
14
14
  | Config | allowlist de stack | `.claude/config/stack-allowlist.json` |
15
15
 
@@ -44,6 +44,14 @@ Editar `stack-allowlist.json` SOLO si la sección de requisitos técnicos del PR
44
44
  ## Bitácora de cambios de metodología
45
45
  Cambios a la política de construcción (unidad de trabajo, gates, DoR/DoD). Aprueba el DRI; van por PR.
46
46
 
47
+ - **2026-06-03 · v0.5.0** — Seguro de fuente de diseño + verificación de fidelidad. Nuevo gate de
48
+ proyecto `design_source` (espejo de scaffold, confirmado por humano; el arnés no genera el prototipo)
49
+ con hook `design-source-guard.sh`; criterio DoR "fuente de diseño identificada" para slices con UI;
50
+ gate vivo de inner loop `fidelity` computado en `smoke` por el nuevo agente `ux-fidelity-reviewer`
51
+ (agnóstico, estático-primero, degrada sin MCP); 7º extension point `DESIGN_SOURCE` en el onboard.
52
+ Toca gates/DoR/DoD y el schema de estado → aprobado por el DRI (Agent Manager). Origen: revisión de
53
+ la propuesta externa de visual fidelity.
54
+
47
55
  - **2026-06-02 · v0.4.0** — Carril `building-a-micro-change` + DoR proporcional. El mantenimiento que
48
56
  no es producto nuevo (typo, bump de dep permitida, copy/config/docs, fix de pocas líneas) deja de
49
57
  modelarse como épica y usa un carril ligero (`fix/*`|`chore/*` → PR, sin `active_slice`), con
package/INSTALL.md CHANGED
@@ -11,7 +11,7 @@ Es el **compañero** de [`@trycore/spec-product-flow`](https://www.npmjs.com/pac
11
11
  | CLI (bin) | `trycore-build` |
12
12
  | Plugin | `trycore-spec-build-harness` |
13
13
  | Marketplace | `trycore-build` |
14
- | Versión | `0.3.0` |
14
+ | Versión | `0.5.0` |
15
15
 
16
16
  Hay **dos canales** de instalación: el **CLI npm** (canónico, recomendado para operar en un
17
17
  proyecto) y el **plugin nativo** de Claude Code (conveniencia a nivel usuario). Lee el
@@ -28,7 +28,7 @@ npm install -g @trycore/spec-build-harness
28
28
  Esto expone el binario `trycore-build`. Comprueba la versión:
29
29
 
30
30
  ```bash
31
- trycore-build --version # → 0.3.0
31
+ trycore-build --version # → 0.5.0
32
32
  trycore-build --help
33
33
  ```
34
34
 
@@ -84,10 +84,10 @@ Qué hace `init`:
84
84
 
85
85
  1. **Verifica requisitos duros** (a menos que uses `--skip-doctor`).
86
86
  2. **Siembra los assets** en rutas nativas de Claude Code:
87
- - `.claude/agents/build/` — 10 agentes.
87
+ - `.claude/agents/build/` — 11 agentes.
88
88
  - `.claude/commands/opsx/` (10 comandos `/opsx:*`) y `.claude/commands/build/` (`/build:onboard`, `/build:reflect`).
89
89
  - `.claude/skills/` — 12 skills (`building-a-slice`, `releasing-a-version`, `openspec-*`).
90
- - `.claude/hooks/build/` — 8 hooks bash.
90
+ - `.claude/hooks/build/` — 9 hooks bash.
91
91
  3. **Siembra el estado**: `state/build-state.schema.json` y `state/README.md` se versionan;
92
92
  `state/build-state.json` se siembra **vacío y nunca se sobrescribe** (va al `.gitignore`).
93
93
  4. **Siembra `config/stack-allowlist.json`** (artefacto del consumidor; lo puebla `/build:onboard`).
package/README.md CHANGED
@@ -89,12 +89,12 @@ trycore-spec-build-harness/
89
89
  ├── METODOLOGIA.md ← fuente de verdad metodológica (gana ante cualquier skill)
90
90
  ├── GOVERNANCE.md ← gobernanza del paquete + cadencia de auditoría
91
91
  ├── .claude-plugin/ ← manifiesto del plugin nativo (canal de conveniencia)
92
- ├── agents/build/ ← 10 agentes revisores (segunda opinión, contexto limpio)
92
+ ├── agents/build/ ← 11 agentes revisores (segunda opinión, contexto limpio)
93
93
  ├── commands/
94
94
  │ ├── opsx/ ← 10 comandos /opsx:* (ciclo OpenSpec)
95
95
  │ └── build/ ← /build:onboard, /build:reflect
96
96
  ├── skills/ ← 12 skills (building-a-slice, releasing-a-version, 10 openspec-*)
97
- ├── hooks/build/ ← 8 hooks bash (gate-check, reflect-nudge, scaffold-guard, gitflow-guard, stack-guard, …)
97
+ ├── hooks/build/ ← 9 hooks bash (gate-check, reflect-nudge, scaffold-guard, gitflow-guard, stack-guard, …)
98
98
  ├── state/ ← máquina de estado: build-state.json + schema + README
99
99
  ├── config/ ← stack-allowlist.template.json (artefacto del consumidor)
100
100
  ├── src/ + dist/ ← CLI trycore-build (init/update/status/uninstall/doctor)
@@ -102,7 +102,7 @@ trycore-spec-build-harness/
102
102
  └── docs/examples/reference/ ← ejemplo de referencia (fuera del core, excluido de check-agnostic)
103
103
  ```
104
104
 
105
- Los **10 agentes** en `agents/build/` son: `build-orchestrator`, `dor-dod-gatekeeper`, `security-reviewer`, `simple-design-reviewer`, `ux-krug-reviewer`, `coherence-three-way` (opus), `stack-guardian`, `api-contract-tester`, `data-consistency-checker` y `change-epic-coherence`.
105
+ Los **11 agentes** en `agents/build/` son: `build-orchestrator`, `dor-dod-gatekeeper`, `security-reviewer`, `simple-design-reviewer`, `ux-krug-reviewer`, `coherence-three-way` (opus), `stack-guardian`, `api-contract-tester`, `data-consistency-checker`, `change-epic-coherence` y `ux-fidelity-reviewer`.
106
106
 
107
107
  **Estado.** `state/build-state.json` se siembra **vacío** y nunca se sobreescribe (va al `.gitignore`); el schema y el README sí se versionan. `config/stack-allowlist.json` es artefacto del consumidor: lo siembra el CLI y lo puebla `/build:onboard`. `uninstall` preserva `state/` y `config/`.
108
108
 
@@ -126,7 +126,9 @@ El core no menciona ningún dominio de cliente. Toda parametrización entra por
126
126
 
127
127
  - ✅ **v0.1.0** — arnés de dos loops (`building-a-slice` + `releasing-a-version`), 10 agentes, comandos `/opsx:*` + `/build:onboard`, 12 skills, 6 hooks, máquina de estado `build-state.json`, allowlist de stack, CLI `trycore-build` (init/update/status/uninstall/doctor) y plugin nativo. Compañero de `@trycore/spec-product-flow`.
128
128
  - ✅ **v0.2.0** — scaffold como "Paso 1 fundamental": gate de proyecto `scaffold.confirmed` (confirmación **explícita**, no auto), Fase 0 en `building-a-slice`, criterio duro de DoR y hook `scaffold-guard.sh`. El arnés **exige** el scaffold pero **no lo genera**.
129
- - ✅ **v0.3.0 (actual)** — **ciclo autocorrectivo** (hook `reflect-nudge.sh` + comando `/build:reflect`: propone convenciones aprendidas al bloque `trycore-build-learnings` de `CLAUDE.md` tras tu aprobación; campos `reflected`/`reflected_at`) y **LSP opt-in** (`docs/customization/lsp-extensions.md` + sugerencia en `doctor` para stacks tipados). Total: **8 hooks**; comandos `/opsx:*` + `/build:onboard` + `/build:reflect`.
129
+ - ✅ **v0.3.0** — **ciclo autocorrectivo** (hook `reflect-nudge.sh` + comando `/build:reflect`: propone convenciones aprendidas al bloque `trycore-build-learnings` de `CLAUDE.md` tras tu aprobación; campos `reflected`/`reflected_at`) y **LSP opt-in** (`docs/customization/lsp-extensions.md` + sugerencia en `doctor` para stacks tipados). Total: **8 hooks**; comandos `/opsx:*` + `/build:onboard` + `/build:reflect`.
130
+ - ✅ **v0.4.0** — carril `building-a-micro-change` (mantenimiento ligero sin slice) + DoR proporcional a la complejidad.
131
+ - ✅ **v0.5.0 (actual)** — seguro de fuente de diseño (`design_source` + `design-source-guard.sh`) + agente `ux-fidelity-reviewer` (gate `fidelity`, inner loop). Total: **11 agentes**, **9 hooks**.
130
132
 
131
133
  ## Licencia
132
134
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.5.0
@@ -19,7 +19,10 @@ La **unidad de construcción es la épica** (`active_slice.epica`); las HU que c
19
19
  1. dor → delega en dor-dod-gatekeeper (abre el slice si pasa)
20
20
  2. change → opsx:new + bloque ## Trazabilidad → delega en change-epic-coherence (gate coherence_link, barato)
21
21
  3. tdd → conduce superpowers:test-driven-development (red→green→refactor)
22
- 4. smoke → recorre el journey-hasta-aquí end-to-end con la skill verify/run (+ chrome-devtools) → gate journey_smoke
22
+ 4. smoke → recorre el journey-hasta-aquí end-to-end con la skill verify/run (+ chrome-devtools) → gate journey_smoke.
23
+ Slices con UI: con la app levantada, delega en ux-fidelity-reviewer (compara la(s) pantalla(s)
24
+ contra el DESIGN_SOURCE) y ESCRIBE gates.fidelity desde su veredicto (FIEL/DESVIACIONES
25
+ justificadas→true; DESVIACIONES→false; INCONCLUSO (MCP no disponible)→deja con nota; sin UI→null).
23
26
  5. api/data → api-contract-tester (si hay endpoints) · data-consistency-checker (si toca datos)
24
27
  6. dod → dor-dod-gatekeeper (cierre por slice, DoD reducido)
25
28
  7. pr → abre PR y archiva el change EN EL MISMO PR (opsx:archive + opsx:sync); back-ref en épica y HU
@@ -29,6 +32,8 @@ La **unidad de construcción es la épica** (`active_slice.epica`); las HU que c
29
32
  **Los agentes pesados ya NO corren aquí.** `security-reviewer`, `simple-design-reviewer`,
30
33
  `ux-krug-reviewer`, `coherence-three-way` y `stack-guardian` (arquitectura) corren **una vez por
31
34
  release** en la skill `releasing-a-version`. Las deps las vigila el hook `stack-guard.sh`.
35
+ El `ux-fidelity-reviewer` **sí** corre aquí (en `smoke`): es barato (la app ya está levantada) y vivo
36
+ por-slice; no es la revisión pesada de UX/Krug (esa sigue en `releasing-a-version`).
32
37
 
33
38
  ## Reglas de orquestación
34
39
  - **No saltes gates.** No avances de fase si el gate previo está en `false`. Reporta qué falta.
@@ -29,12 +29,15 @@ cumplen; lista cada una con ✓/✗:
29
29
  5. **Cada HU** pasa los 6 criterios **INVEST** (si dudas, invoca al agente `invest-validator`).
30
30
  6. Dependencias declaradas (otras épicas/HU) están en `history[]` del estado o marcadas done.
31
31
  7. El alcance de la épica cabe en el stack declarado del PRD (allowlist) (no exige tecnología fuera de la allowlist).
32
+ 8. **Fuente de diseño (solo slices con UI)**: si la épica toca UI, `design_source.confirmed===true`
33
+ (fuente visual de verdad declarada para el proyecto) y la épica apunta a la(s) pantalla(s)
34
+ equivalente(s) del `DESIGN_SOURCE`. Si no toca UI, este criterio es N/A.
32
35
 
33
36
  Si DoR pasa: propón abrir `active_slice` con `epica`, `hus` (lista de las HU cubiertas),
34
37
  `openspec_change` (kebab del título de la épica), `branch: feature/ep-xxx-<slug>`, `phase: dor`,
35
- `gates: { dor: true, tdd: false, journey_smoke: false, coherence_link: false, data: false, dod: false }`
36
- (`api` en `null` si la épica no toca endpoints; añade `data: null`-equivalente omitiéndolo si no toca
37
- datos). Si falla: reporta ✗ y NO abras el slice.
38
+ `gates: { dor: true, tdd: false, journey_smoke: false, coherence_link: false, data: false, fidelity: false, dod: false }`
39
+ (`api` en `null` si la épica no toca endpoints; **`fidelity` en `null` si la épica NO toca UI**; añade
40
+ `data: null`-equivalente omitiéndolo si no toca datos). Si falla: reporta ✗ y NO abras el slice.
38
41
 
39
42
  ## Definition of Done (gate `dod`) — antes de archivar (DoD **reducido**, por slice)
40
43
  Pasa SOLO si **todos** estos gates del **inner loop** están en `true` (o `null` cuando N/A):
@@ -43,8 +46,10 @@ Pasa SOLO si **todos** estos gates del **inner loop** están en `true` (o `null`
43
46
  3. `coherence_link` — `change-epic-coherence` confirma el enlace change↔épica (`openspec validate` ok).
44
47
  4. `data` — `data-consistency-checker` verde (si el slice toca datos).
45
48
  5. `api` — `api-contract-tester` verde (o `null` si sin endpoints).
46
- 6. Documentación: change con tasks completas; back-ref añadido en la épica y en cada HU de `hus[]`.
47
- 7. Hooks verdes (automáticos): `lint-typecheck.sh`, `stack-guard.sh`, `gitflow-guard.sh`.
49
+ 6. `fidelity` `true` (FIEL o DESVIACIONES justificadas) o `null` (slice sin UI). INCONCLUSO
50
+ (MCP no disponible) se registra en `notes`, no bloquea. Es gate **vivo** de inner loop, no la revisión Krug.
51
+ 7. Documentación: change con tasks completas; back-ref añadido en la épica y en cada HU de `hus[]`.
52
+ 8. Hooks verdes (automáticos): `lint-typecheck.sh`, `stack-guard.sh`, `gitflow-guard.sh`.
48
53
 
49
54
  **NO valides aquí** `security`, `smell`, `ux`, `coherence` (triple completa) ni `stack` (arquitectura):
50
55
  esos son del **Release Gate** (`releasing-a-version`, `release-dod.md`), cadencia por release.
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: ux-fidelity-reviewer
3
+ description: Verifica la FIDELIDAD VISUAL de una pantalla de la app corriendo contra la fuente de diseño declarada (el DESIGN_SOURCE del dominio del consumidor). Complementa al ux-krug-reviewer (que mide usabilidad, no fidelidad). Úsalo en slices con UI, en la fase smoke. Emite FIEL / DESVIACIONES / INCONCLUSO / N/A con diferencias concretas y fixes.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: sonnet
6
+ ---
7
+
8
+ Eres el **revisor de fidelidad visual** del arnés de construcción. Read-only sobre el código. Compruebas
9
+ que una pantalla construida **se parece a la fuente de diseño declarada** por el consumidor (el
10
+ `DESIGN_SOURCE` del bloque de dominio de su CLAUDE.md / su PRD). NO juzgas usabilidad (eso es
11
+ `ux-krug-reviewer`): juzgas si **composición, layout, paleta y tipografía** reproducen el diseño.
12
+
13
+ > Existe porque un re-skin puede acertar los *tokens* (color/fuente) y aun así **ignorar la
14
+ > composición** (p.ej. una sola columna centrada cuando el diseño declara dos paneles).
15
+
16
+ ## Paso 0 — ¿aplica?
17
+ Si el slice **no tiene UI**, devuelve **N/A** y termina (para que el gate `fidelity` quede en `null`),
18
+ igual que `ux-krug-reviewer`.
19
+
20
+ ## Entradas (pídelas si faltan)
21
+ - La(s) pantalla(s) del slice (rutas de la app, p.ej. `<URL-local-del-dev-server>/<ruta>`).
22
+ - La fuente de diseño (`DESIGN_SOURCE`): archivo/URL del prototipo o export, y cómo localizar la
23
+ pantalla equivalente.
24
+ - Tokens de diseño del proyecto (los que declare el stack del PRD del consumidor: variables CSS, tema,
25
+ design tokens), si existen.
26
+
27
+ ## Cómo revisar (estático primero, como ux-krug-reviewer)
28
+ - **Estático (primario)**: lee el código de la pantalla (con la librería de UI del stack declarado en
29
+ el PRD del consumidor) y contrástalo contra la descripción del `DESIGN_SOURCE` y los tokens.
30
+ - **Dinámico (apoyo, si la app corre y hay MCP de inspección de UI habilitado)**: sugiere usar un MCP
31
+ de inspección de UI (p.ej. **chrome-devtools** para web): `new_page`/`take_screenshot` del prototipo
32
+ y de la app, y `take_snapshot` (árbol accesible/DOM) para comparar **estructura**, no solo píxeles.
33
+ Si el MCP **no está disponible** (headless/CI), NO inventes: veredicto **INCONCLUSO (MCP no
34
+ disponible)** + lo que sí se verifique en estático.
35
+ - **Bifurca por la fuente**: si la fuente de diseño es **renderizable** (prototipo HTML / URL
36
+ navegable) usa screenshot + snapshot; si **no es navegable** (export de diseño / imagen / PDF),
37
+ compara contra el export sin `take_snapshot` (no hay DOM que comparar).
38
+
39
+ ## Qué comparar (estructura > píxeles) — ✅ fiel / ⚠️ parcial / ❌ desviación
40
+ - **Layout/composición**: nº y disposición de paneles/columnas, orden de secciones, jerarquía.
41
+ - **Componentes clave presentes**: cada bloque del diseño (barra, hero, tarjetas, footer, callouts) existe.
42
+ - **Paleta**: colores dominantes = tokens declarados; marca usos fuera de paleta.
43
+ - **Tipografía**: familias y escala/peso de titulares vs cuerpo.
44
+ - **Copy estructural**: titulares y CTAs clave coinciden en intención.
45
+ - **Estados**: los estados que el diseño muestra (error, vacío…) existen.
46
+ No penalices desviaciones **justificadas y documentadas** (datos ilustrativos estáticos, copy
47
+ reconciliado por una ADR); lístalas como "desviación intencional". **No pixel-diff** (frágil).
48
+
49
+ ## Salida + mapeo al gate
50
+ Veredicto **FIEL / DESVIACIONES / INCONCLUSO / N/A** + tabla región×veredicto con evidencia + lista
51
+ priorizada de diferencias con su fix (archivo/componente) + desviaciones intencionales aceptadas.
52
+
53
+ Mapeo que aplicará el `build-orchestrator` al escribir `gates.fidelity`:
54
+ - **FIEL** → `true`
55
+ - **DESVIACIONES** todas justificadas/documentadas → `true`
56
+ - **DESVIACIONES** sin justificar → `false`
57
+ - **N/A** (sin UI) → `null`
58
+ - **INCONCLUSO** (MCP no disponible) → el orquestador deja `gates.fidelity: null` con nota
59
+ (INCONCLUSO, MCP no disponible) — **no bloquea** el DoD.
60
+
61
+ Eres read-only: **no editas código ni el estado**. Devuelve el diagnóstico al `build-orchestrator`.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "BUILD: Onboard"
3
- description: Parametriza el dominio del build harness — capa de servicios externos/IA, lógica determinista, PII, secretos y decisiones de alto impacto. Rellena el bloque marcado de CLAUDE.md y escribe auto-memory. Complementa al CLI trycore-build init (que ya sembró los archivos y el stack mecánico).
3
+ description: Parametriza el dominio del build harness — capa de servicios externos/IA, lógica determinista, PII, secretos, decisiones de alto impacto y fuente de diseño (DESIGN_SOURCE). Rellena el bloque marcado de CLAUDE.md y escribe auto-memory. Complementa al CLI trycore-build init (que ya sembró los archivos y el stack mecánico).
4
4
  category: Workflow
5
5
  tags: [onboarding, parametrizacion, build-harness, trycore]
6
6
  ---
@@ -35,7 +35,7 @@ Stop aquí si no está instalado.
35
35
 
36
36
  El CLI ya instaló agentes, comandos /opsx:*, hooks y el estado. Ahora voy a parametrizar el
37
37
  DOMINIO del arnés (2-3 min) — los puntos de extensión que leen los agentes de calidad
38
- (security-reviewer, stack-guardian, data-consistency-checker, ux-krug-reviewer, simple-design-reviewer).
38
+ (security-reviewer, stack-guardian, data-consistency-checker, ux-krug-reviewer, simple-design-reviewer, ux-fidelity-reviewer).
39
39
 
40
40
  Voy a leer tu PRD/openspec para proponer valores y confirmar contigo:
41
41
  1. Ruta#ancla del PRD técnico (fuente del stack)
@@ -44,6 +44,7 @@ Voy a leer tu PRD/openspec para proponer valores y confirmar contigo:
44
44
  4. Categorías de datos sensibles / PII reguladas
45
45
  5. Secretos server-side
46
46
  6. Decisiones de alto impacto que exigen explicabilidad en UX
47
+ 7. Fuente de diseño / referencia visual (prototipo/export) y pantallas — o "N/A" si no hay UI
47
48
  ```
48
49
 
49
50
  ---
@@ -61,6 +62,9 @@ Voy a leer tu PRD/openspec para proponer valores y confirmar contigo:
61
62
  - **Datos sensibles / PII** (`SENSITIVE_DATA_CATEGORIES`): categorías reguladas del dominio.
62
63
  - **Secretos server-side** (`SERVER_SIDE_SECRETS`): claves/tokens que jamás van al cliente.
63
64
  - **Decisiones de alto impacto** (`HIGH_STAKES_DECISIONS`): decisiones que exigen explicabilidad/justificación en la UI.
65
+ - **Fuente de diseño** (`DESIGN_SOURCE`): ¿el producto tiene UI? Si sí, ruta/URL de la fuente
66
+ visual de verdad (prototipo, export de diseño o mockups) y cómo localizar cada pantalla; si no,
67
+ "N/A". (La escritura del estado `design_source` en `build-state.json` se hace en la Fase 3c.)
64
68
  3. Si un punto no aplica al proyecto, registra explícitamente "no aplica" (no lo dejes como `{{...}}`).
65
69
 
66
70
  ---
@@ -71,7 +75,7 @@ Lee `CLAUDE.md`. Encuentra el bloque entre `<!-- BEGIN trycore-build-harness` y
71
75
 
72
76
  Reemplaza dentro del bloque los placeholders `{{PRD_TECH_PATH}}`, `{{EXTERNAL_SERVICE_LAYER}}`,
73
77
  `{{DETERMINISTIC_LAYER}}`, `{{SENSITIVE_DATA_CATEGORIES}}`, `{{SERVER_SIDE_SECRETS}}`,
74
- `{{HIGH_STAKES_DECISIONS}}` por los valores confirmados.
78
+ `{{HIGH_STAKES_DECISIONS}}`, `{{DESIGN_SOURCE}}` por los valores confirmados.
75
79
 
76
80
  **NO toques nada fuera de los markers.**
77
81
 
@@ -87,6 +91,16 @@ Si el usuario lo desea y existe `package.json` en el proyecto:
87
91
 
88
92
  ---
89
93
 
94
+ ## Fase 3c: (Si hay UI) Confirmar la fuente de diseño en el estado
95
+
96
+ Espejo de la confirmación de scaffold, para `design_source` en `build-state.json`:
97
+ - Si el producto **tiene UI**: setea `design_source.applies=true`, `source` (el puntero confirmado) y
98
+ `confirmed=true` **solo si** el usuario confirma que la fuente de diseño existe (con `confirmed_by`,
99
+ `confirmed_at`). El arnés **no genera** el prototipo.
100
+ - Si **no hay UI**: setea `design_source.applies=false` (el mecanismo de fidelidad queda N/A).
101
+
102
+ ---
103
+
90
104
  ## Fase 4: Guardar en auto-memory
91
105
 
92
106
  Crear/actualizar memorias **tipo `project`** (los valores cambian por proyecto):
@@ -97,6 +111,7 @@ Crear/actualizar memorias **tipo `project`** (los valores cambian por proyecto):
97
111
  - `build_sensitive_data.md` → categorías PII/datos regulados
98
112
  - `build_server_side_secrets.md` → secretos server-side
99
113
  - `build_high_stakes_decisions.md` → decisiones de alto impacto
114
+ - `build_design_source.md` → fuente de diseño / referencia visual
100
115
 
101
116
  Cada memoria con frontmatter `type: project`. Agrega entradas a `MEMORY.md`.
102
117
 
@@ -113,6 +128,7 @@ Determinista: <...>
113
128
  PII/datos: <...>
114
129
  Secretos: <...>
115
130
  Decisiones clave: <...>
131
+ Fuente diseño: <...>
116
132
 
117
133
  CLAUDE.md actualizado. Auto-memory escrita. Los agentes de calidad ya leen tu dominio.
118
134
 
@@ -129,7 +145,7 @@ CLAUDE.md actualizado. Auto-memory escrita. Los agentes de calidad ya leen tu do
129
145
 
130
146
  ## Guardrails
131
147
 
132
- - No avances sin confirmar los 6 puntos. Si el usuario omite alguno, repregunta o marca "no aplica".
148
+ - No avances sin confirmar los 7 puntos. Si el usuario omite alguno, repregunta o marca "no aplica".
133
149
  - Si CLAUDE.md no tiene el bloque marcado (caso raro post-install), pide correr `trycore-build init` (o `update`) antes de seguir.
134
150
  - No inventes valores de dominio que no estén en el PRD ni confirmados por el usuario.
135
151
  - Si un valor ya existe en memory y cambió, sobrescríbelo (los proyectos evolucionan).
@@ -18,7 +18,7 @@ function cmd(script) {
18
18
  const HOOK_SPECS = [
19
19
  { event: 'SessionStart', matcher: 'startup|clear|compact', scripts: ['load-build-state.sh'] },
20
20
  { event: 'PreToolUse', matcher: 'Bash', scripts: ['gitflow-guard.sh'] },
21
- { event: 'PreToolUse', matcher: 'Write|Edit|MultiEdit', scripts: ['stack-guard.sh', 'scaffold-guard.sh'] },
21
+ { event: 'PreToolUse', matcher: 'Write|Edit|MultiEdit', scripts: ['stack-guard.sh', 'scaffold-guard.sh', 'design-source-guard.sh'] },
22
22
  { event: 'PostToolUse', matcher: 'Write|Edit|MultiEdit', scripts: ['lint-typecheck.sh', 'coherence-flag.sh'] },
23
23
  { event: 'Stop', matcher: '.*', scripts: ['build-gate-check.sh', 'reflect-nudge.sh'] },
24
24
  ];
@@ -11,6 +11,7 @@ const EMPTY_STATE = {
11
11
  version: '1.0',
12
12
  harness_phase: 'authoring',
13
13
  scaffold: { confirmed: false, confirmed_by: null, confirmed_at: null, notes: '' },
14
+ design_source: { applies: false, confirmed: false, confirmed_by: null, confirmed_at: null, source: '', notes: '' },
14
15
  active_slice: null,
15
16
  history: [],
16
17
  releases: [],
package/docs/agents.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Agentes de construcción (`agents/build/`)
2
2
 
3
- Los **10 agentes** de `@trycore/spec-build-harness` ejecutan los *gates* del arnés de
3
+ Los **11 agentes** de `@trycore/spec-build-harness` ejecutan los *gates* del arnés de
4
4
  construcción de dos loops. Ninguno edita código de producto: son read-only sobre el
5
5
  repositorio (algunos ejecutan tests o levantan la app), diagnostican y **devuelven el
6
6
  veredicto al `build-orchestrator`**, que es quien propone la escritura del estado
@@ -27,6 +27,7 @@ veredicto al `build-orchestrator`**, que es quien propone la escritura del estad
27
27
  | 8 | `api-contract-tester` | sonnet | Contrato / datos | Gate `api` — pruebas de contrato (Newman/Postman) |
28
28
  | 9 | `data-consistency-checker` | sonnet | Contrato / datos | Gate `data` — invariantes y consistencia de datos |
29
29
  | 10 | `change-epic-coherence` | sonnet | Trazabilidad | Gate `coherence_link` — enlace change↔épica↔HU |
30
+ | 11 | `ux-fidelity-reviewer` | sonnet | Inner loop · smoke | Gate `fidelity` — fidelidad visual a la fuente de diseño declarada |
30
31
 
31
32
  ---
32
33
 
@@ -73,12 +73,12 @@ trycore-build init
73
73
 
74
74
  `init` es **idempotente** (re-correrlo es seguro) y siembra:
75
75
 
76
- - **10 agentes** en `.claude/agents/build/` (build-orchestrator, dor-dod-gatekeeper,
76
+ - **11 agentes** en `.claude/agents/build/` (build-orchestrator, dor-dod-gatekeeper,
77
77
  security-reviewer, simple-design-reviewer, ux-krug-reviewer, coherence-three-way, stack-guardian,
78
- api-contract-tester, data-consistency-checker, change-epic-coherence).
78
+ api-contract-tester, data-consistency-checker, change-epic-coherence, ux-fidelity-reviewer).
79
79
  - **Comandos** `/opsx:*` (10) en `.claude/commands/opsx/` + `/build:onboard` y `/build:reflect` en `.claude/commands/build/`.
80
80
  - **12 skills** en `.claude/skills/` (`building-a-slice`, `releasing-a-version`, 10 `openspec-*`).
81
- - **8 hooks** bash en `.claude/hooks/build/` + permisos mínimos en `settings.json`.
81
+ - **9 hooks** bash en `.claude/hooks/build/` + permisos mínimos en `settings.json`.
82
82
  - **Estado**: `.claude/state/build-state.json` (sembrado **vacío** y **nunca** sobreescrito; va al
83
83
  `.gitignore`), más el schema y el README versionados.
84
84
  - **Config**: `.claude/config/stack-allowlist.json` (artefacto del consumidor; lo siembra el CLI y
@@ -136,7 +136,7 @@ trycore-build doctor
136
136
  Comprueba:
137
137
 
138
138
  - Los **3 requisitos duros** (`git`, `python3`, `openspec`) — **falla con exit 1** si falta alguno.
139
- - Que los **8 hooks** tengan bit ejecutable (si no, sugiere `trycore-build init --copy` o `chmod +x`).
139
+ - Que los **9 hooks** tengan bit ejecutable (si no, sugiere `trycore-build init --copy` o `chmod +x`).
140
140
  - **Doble canal**: si detecta hooks del arnés en `settings.json` (canal CLI) y además instalaste el
141
141
  plugin, te recuerda que la cadena de comando es idéntica en ambos canales y Claude Code
142
142
  **deduplica** → el hook dispara **una sola vez**. No requiere acción.
package/docs/hooks.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Hooks del arnés de construcción
2
2
 
3
- Este documento describe los **8 hooks** que `@trycore/spec-build-harness` instala en el proyecto del consumidor. Todos viven en `hooks/build/` (un script bash por hook) y se cablean a los eventos de Claude Code mediante una **cadena de comando única**, idéntica en ambos canales de instalación.
3
+ Este documento describe los **9 hooks** que `@trycore/spec-build-harness` instala en el proyecto del consumidor. Todos viven en `hooks/build/` (un script bash por hook) y se cablean a los eventos de Claude Code mediante una **cadena de comando única**, idéntica en ambos canales de instalación.
4
4
 
5
- Los hooks son el sistema nervioso del arnés: vigilan GitFlow, el stack declarado y el scaffold (bloqueantes), inyectan el estado del build al iniciar la sesión, delegan estilo/typecheck a herramientas, y recuerdan validar trazabilidad, gates abiertos y reflexionar al cerrar un slice. No reemplazan a los agentes ni a las skills; los **complementan** liberando capacidad de razonamiento del modelo y poniendo barandillas mecánicas donde un olvido cuesta caro.
5
+ Los hooks son el sistema nervioso del arnés: vigilan GitFlow, el stack declarado, el scaffold y la fuente de diseño (bloqueantes), inyectan el estado del build al iniciar la sesión, delegan estilo/typecheck a herramientas, y recuerdan validar trazabilidad, gates abiertos y reflexionar al cerrar un slice. No reemplazan a los agentes ni a las skills; los **complementan** liberando capacidad de razonamiento del modelo y poniendo barandillas mecánicas donde un olvido cuesta caro.
6
6
 
7
7
  ---
8
8
 
9
- ## Resumen de los 8 hooks
9
+ ## Resumen de los 9 hooks
10
10
 
11
11
  | Hook | Evento | Matcher | Qué hace | ¿Bloqueante? |
12
12
  |---|---|---|---|---|
@@ -14,12 +14,13 @@ Los hooks son el sistema nervioso del arnés: vigilan GitFlow, el stack declarad
14
14
  | `gitflow-guard.sh` | `PreToolUse` | `Bash` | Enforce GitHub Flow estricto sobre `git commit` / `git push`. | **Sí (exit 2)** |
15
15
  | `stack-guard.sh` | `PreToolUse` | `Write\|Edit\|MultiEdit` | Bloquea dependencias en `package.json` fuera de la allowlist del stack del PRD. | **Sí (exit 2)** |
16
16
  | `scaffold-guard.sh` | `PreToolUse` | `Write\|Edit\|MultiEdit` | Bloquea escribir código de slice (fases `red…data`) si el scaffold no está confirmado (`scaffold.confirmed`). | **Sí (exit 2)** |
17
+ | `design-source-guard.sh` | `PreToolUse` | `Write\|Edit\|MultiEdit` | Bloquea escribir código de un slice **con UI** (`gates.fidelity===false`, fases `red…data`) si la fuente de diseño del proyecto no está confirmada (`design_source.confirmed`). | **Sí (exit 2)** |
17
18
  | `lint-typecheck.sh` | `PostToolUse` | `Write\|Edit\|MultiEdit` | Corre prettier/eslint/tsc sobre el archivo `.ts`/`.tsx` editado. | No |
18
19
  | `coherence-flag.sh` | `PostToolUse` | `Write\|Edit\|MultiEdit` | Recuerda validar la trazabilidad de un `proposal.md` de OpenSpec recién tocado. | No |
19
20
  | `build-gate-check.sh` | `Stop` | `.*` | Al cerrar el turno, avisa si el slice activo tiene gates abiertos. | No |
20
21
  | `reflect-nudge.sh` | `Stop` | `.*` | Al cerrar el turno, sugiere `/build:reflect` si hay slice(s) archivado(s) sin reflexionar (`reflected != true`). | No |
21
22
 
22
- > Tres bloqueantes (`gitflow-guard`, `stack-guard`, `scaffold-guard`) y cinco informativos. Los bloqueantes usan `exit 2`: Claude Code devuelve el `stderr` al modelo y aborta la herramienta; el resto siempre sale `0`.
23
+ > Cuatro bloqueantes (`gitflow-guard`, `stack-guard`, `scaffold-guard`, `design-source-guard`) y cinco informativos. Los bloqueantes usan `exit 2`: Claude Code devuelve el `stderr` al modelo y aborta la herramienta; el resto siempre sale `0`.
23
24
 
24
25
  ---
25
26
 
@@ -84,6 +85,10 @@ Refuerza el **scaffold como "Paso 1 fundamental"**. Bloquea con `exit 2` la escr
84
85
 
85
86
  Cierra el **ciclo autocorrectivo**. Al terminar el turno, si en `history[]` hay slice(s) archivado(s) con `reflected != true`, imprime un *nudge* sugiriendo ejecutar `/build:reflect` para capturar las convenciones aprendidas (y errores recurrentes) en el bloque `trycore-build-learnings` de `CLAUDE.md`. **Nunca bloquea** el cierre de sesión: si falta `python3` o el estado, sale `0` en silencio (**fail-open**). El razonamiento —qué se aprendió— vive en el comando `/build:reflect`, no en el hook; este solo recuerda. Tras reflexionar y estampar `reflected: true`, el nudge calla.
86
87
 
88
+ ### 9. `design-source-guard.sh` — `PreToolUse` · Write/Edit/MultiEdit · **bloqueante** (desde v0.5.0)
89
+
90
+ 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 pero **no genera** el prototipo; la confirmación es **explícita** (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.
91
+
87
92
  ---
88
93
 
89
94
  ## La cadena de comando única (sin doble disparo entre canales)
@@ -107,7 +112,7 @@ Como la cadena es **carácter por carácter idéntica** en ambos canales, si el
107
112
 
108
113
  Los hooks parsean el JSON del evento con `python3`. Qué pasa si **falta** `python3` depende de si el hook es bloqueante:
109
114
 
110
- - **Bloqueantes** (`gitflow-guard`, `stack-guard`, `scaffold-guard`) → **fail-closed dirigido**: si no pueden analizar el comando/edición, solo bloquean (`exit 2`) cuando la entrada *cruda* parece relevante (un `git commit`/`push`, una edición que menciona `package.json`, o código de slice sin scaffold confirmado); en cualquier otro caso salen `0`. Esto evita falsos negativos peligrosos sin frenar el trabajo no relacionado. El mensaje pide instalar `python3` (verificable con `trycore-build doctor`).
115
+ - **Bloqueantes** (`gitflow-guard`, `stack-guard`, `scaffold-guard`, `design-source-guard`) → **fail-closed dirigido**: si no pueden analizar el comando/edición, solo bloquean (`exit 2`) cuando la entrada *cruda* parece relevante (un `git commit`/`push`, una edición que menciona `package.json`, o código de slice sin scaffold/fuente de diseño confirmados); en cualquier otro caso salen `0`. Esto evita falsos negativos peligrosos sin frenar el trabajo no relacionado. El mensaje pide instalar `python3` (verificable con `trycore-build doctor`).
111
116
  - **No bloqueantes** (`load-build-state`, `lint-typecheck`, `coherence-flag`, `build-gate-check`, `reflect-nudge`) → si falta `python3`, simplemente **omiten** su trabajo y salen `0` (fail-open).
112
117
 
113
118
  > `python3` es un **requisito duro**: `trycore-build init` y `trycore-build doctor` **fallan** si no está presente, justo porque toda la cadena de hooks depende de él para leer el JSON del evento.
@@ -126,6 +131,7 @@ Los hooks que tocan el código construido se **auto-arman**: permanecen **inerte
126
131
  | `lint-typecheck.sh` | Inerte (sale `0` de inmediato). |
127
132
  | `coherence-flag.sh` | Funciona siempre (depende de OpenSpec, no del código). |
128
133
  | `scaffold-guard.sh` | Permite (sin slice en fases de código no hay nada que bloquear; también permite crear el scaffold). |
134
+ | `design-source-guard.sh` | Permite (sin slice UI en fases de código, o sin `design_source.applies=true`, no hay nada que bloquear). |
129
135
  | `build-gate-check.sh` | Inerte (sale `0` de inmediato). |
130
136
  | `reflect-nudge.sh` | Silencioso (en `authoring` no hay slices archivados que reflexionar). |
131
137
 
@@ -141,7 +147,7 @@ Una sola definición de hooks, expresada en dos archivos espejo según el canal:
141
147
 
142
148
  `trycore-build init` hace un **merge idempotente y aditivo** en el `settings.json` del consumidor (lógica en `src/lib/settings-merge.ts`; espejo documental en `templates/settings-hooks.template.json`):
143
149
 
144
- - Agrega las 5 agrupaciones de hooks (las 8 invocaciones: `PreToolUse·Write` agrupa `stack-guard` + `scaffold-guard`; `PostToolUse·Write` agrupa `lint-typecheck` + `coherence-flag`; `Stop` agrupa `build-gate-check` + `reflect-nudge`) sin pisar lo que ya exista.
150
+ - Agrega las 5 agrupaciones de hooks (las 9 invocaciones: `PreToolUse·Write` agrupa `stack-guard` + `scaffold-guard` + `design-source-guard`; `PostToolUse·Write` agrupa `lint-typecheck` + `coherence-flag`; `Stop` agrupa `build-gate-check` + `reflect-nudge`) sin pisar lo que ya exista.
145
151
  - Agrega **permisos mínimos y enumerados** (sin `mcp__*` ni rutas absolutas):
146
152
 
147
153
  ```
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env bash
2
+ # design-source-guard.sh — PreToolUse · Write/Edit/MultiEdit
3
+ # Backstop determinista del "seguro de fuente de diseño": no se escribe código de un slice
4
+ # CON UI sin que la fuente de diseño del proyecto esté confirmada. Espejo de scaffold-guard.sh.
5
+ # Bloquea (exit 2) SOLO si: hay active_slice en fase de código (red/green/refactor/smoke/api/data),
6
+ # el proyecto tiene UI (design_source.applies===true), el slice está marcado UI-pendiente
7
+ # (gates.fidelity===false) y design_source.confirmed!==true.
8
+ # AUTO-ARME: si no existe build-state.json, exit 0.
9
+ set -uo pipefail
10
+
11
+ ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "${CLAUDE_PROJECT_DIR:-$(pwd)}")"
12
+ STATE="$ROOT/.claude/state/build-state.json"
13
+ [ -f "$STATE" ] || exit 0
14
+
15
+ INPUT="$(cat)" # consumir stdin (protocolo de hook); la decisión es por estado.
16
+
17
+ # Guarda python3 [H4]: si falta, no podemos leer el estado de forma fiable. Fail-closed.
18
+ if ! command -v python3 >/dev/null 2>&1; then
19
+ echo "⛔ design-source-guard: python3 no disponible; no puedo verificar el gate de fuente de diseño. Instala python3 (trycore-build doctor)." >&2
20
+ exit 2
21
+ fi
22
+
23
+ VERDICT="$(STATE="$STATE" python3 <<'PY' 2>/dev/null
24
+ import os, sys, json
25
+ try:
26
+ d = json.load(open(os.environ["STATE"]))
27
+ except Exception:
28
+ sys.exit(0) # estado ilegible -> no bloquear (auto-arme)
29
+ slice_ = d.get("active_slice")
30
+ if not slice_:
31
+ sys.exit(0) # sin slice: permitir declarar / planificar
32
+ code_phases = {"red", "green", "refactor", "smoke", "api", "data"}
33
+ if slice_.get("phase") not in code_phases:
34
+ sys.exit(0) # fases dor/change/pr/archived: permitido
35
+ ds = d.get("design_source") or {}
36
+ if ds.get("applies") is not True:
37
+ sys.exit(0) # proyecto sin UI (o indeterminado): mecanismo apagado
38
+ if (slice_.get("gates") or {}).get("fidelity") is not False:
39
+ sys.exit(0) # solo UI-pendiente (false) cuenta; null/ausente -> no bloquear
40
+ if ds.get("confirmed") is True:
41
+ sys.exit(0) # fuente de diseño confirmada: permitido
42
+ print("BLOCK")
43
+ PY
44
+ )"
45
+
46
+ if [ "$VERDICT" = "BLOCK" ]; then
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
+ echo " Declara y confirma primero el DESIGN_SOURCE del proyecto (ver building-a-slice Fase 0-bis / DoR)." >&2
49
+ echo " El arnés NO genera el prototipo: declara la fuente (prototipo/export) y confírmala." >&2
50
+ exit 2
51
+ fi
52
+ exit 0
@@ -31,6 +31,10 @@
31
31
  {
32
32
  "type": "command",
33
33
  "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/scaffold-guard.sh\""
34
+ },
35
+ {
36
+ "type": "command",
37
+ "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/design-source-guard.sh\""
34
38
  }
35
39
  ]
36
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trycore/spec-build-harness",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
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": {
@@ -56,6 +56,21 @@ camina* se construye **encima** del scaffold ya existente.
56
56
  3. El gate lo valida también el `dor-dod-gatekeeper` (criterio duro de DoR) y lo respalda el hook
57
57
  determinista `scaffold-guard.sh` (bloquea escribir código de slice sin scaffold confirmado).
58
58
 
59
+ ## Fase 0-bis · Fuente de diseño (seguro para slices con UI)
60
+
61
+ Espejo de la Fase 0, para proyectos **con UI**. Antes de abrir el primer slice con UI:
62
+ 1. Lee `design_source` en `build-state.json`.
63
+ - `applies` indeterminado (ausente) → pregunta *"¿este proyecto tiene UI?"* y fija `applies`.
64
+ - `applies === false` → N/A, salta esta fase.
65
+ - `confirmed === true` → continúa.
66
+ 2. `applies===true && confirmed===false` → **pregunta explícita** (AskUserQuestion): *"¿Existe una
67
+ fuente de diseño declarada (prototipo/export) para la UI de este proyecto?"*
68
+ - **No** → **STOP**. Indica declararla (ruta/URL del prototipo o export). El arnés **NO la genera**.
69
+ No abras el slice con UI.
70
+ - **Sí** → registra `design_source.source`, `confirmed=true`, `confirmed_by`, `confirmed_at`, `notes`.
71
+ 3. Lo respalda el hook determinista `design-source-guard.sh` (bloquea código de slice UI sin fuente
72
+ confirmada) y lo valida el `dor-dod-gatekeeper` (criterio duro de DoR).
73
+
59
74
  ## Pipeline — inner loop (carga la referencia indicada en cada paso)
60
75
 
61
76
  | Fase | Acción | Delega en | Gate | Referencia |
@@ -63,7 +78,7 @@ camina* se construye **encima** del scaffold ya existente.
63
78
  | 1 · dor | Validar Definition of Ready | `dor-dod-gatekeeper` | `dor` | `dor.md` |
64
79
  | 2 · change | `opsx:new` + bloque `## Trazabilidad`; validar enlace (barato) | `opsx:new`, `change-epic-coherence` | `coherence_link` | `link-change-epic.md` |
65
80
  | 3 · tdd | red → green → refactor | `superpowers:test-driven-development` | `tdd` | — |
66
- | 4 · smoke | Recorrer el journey-hasta-aquí end-to-end | skill `verify` / `run` (+ MCP chrome-devtools) | `journey_smoke` | `mcp-map.md` |
81
+ | 4 · smoke | Recorrer el journey-hasta-aquí end-to-end; **slices con UI:** verificar fidelidad a la fuente de diseño | skill `verify` / `run` (+ MCP chrome-devtools), `ux-fidelity-reviewer` | `journey_smoke`,`fidelity` | `mcp-map.md` |
67
82
  | 5 · api/data | contratos + consistencia (si aplican al slice) | `api-contract-tester`, `data-consistency-checker` | `api`,`data` | `newman-tests.md`, `data-consistency.md` |
68
83
  | 6 · dod | Definition of Done (por slice, reducido) | `dor-dod-gatekeeper` | `dod` | `dod.md` |
69
84
  | 7 · pr | Abrir PR + archivar change en el mismo PR | `opsx:archive`, `opsx:sync` | — | `gitflow.md` |
@@ -73,6 +88,10 @@ Los gates `stack`, `security`, `smell`, `ux` y la coherencia triple completa **y
73
88
  aquí**: pertenecen al Release Gate. Las **deps** siguen vigiladas en tiempo real por el hook
74
89
  `stack-guard.sh`; lint/tsc/gitflow por sus hooks.
75
90
 
91
+ El gate `fidelity` (fidelidad a la fuente de diseño) **sí** es de inner loop: es barato (se computa
92
+ en `smoke`, con la app ya levantada) y vivo por-slice; complementa al `ux-krug-reviewer` (usabilidad),
93
+ que sigue en el Release Gate.
94
+
76
95
  MCP/LSP por gate: ver `references/mcp-map.md`. Protocolo de estado: `references/state-protocol.md`.
77
96
 
78
97
  ## Fase 8 · ¿Release Gate ahora? (default computado, humano decide)
@@ -11,6 +11,10 @@ pesadas (seguridad, diseño, UX, coherencia triple, arquitectura, integración)
11
11
  - [ ] **`coherence_link`** — `change-epic-coherence` confirma el enlace change↔épica (bloque `## Trazabilidad`, `openspec validate` ok). Es el chequeo **barato**; la trazabilidad triple completa va al Release Gate.
12
12
  - [ ] **`data`** — `data-consistency-checker` valida invariantes de datos (salida de servicios externos validada contra esquema antes de alimentar la capa de decisión determinista del dominio) (si el slice toca datos).
13
13
  - [ ] **`api`** — `api-contract-tester` (Newman) 100% verde (o `null` si el slice no tiene endpoints).
14
+ - [ ] **`fidelity` (slices con UI)** — `ux-fidelity-reviewer` devuelve **FIEL** (o DESVIACIONES todas
15
+ justificadas/documentadas) → `gates.fidelity: true`; `null` si el slice no tiene UI. INCONCLUSO
16
+ (MCP no disponible) se registra, **no bloquea**. Es gate **vivo** de inner loop (no la revisión Krug,
17
+ que sigue en el Release Gate).
14
18
  - [ ] **OpenSpec**: todas las tasks `[x]`; el archive del change va **en el mismo PR** (no PR aparte).
15
19
  - [ ] **Docs/trazabilidad**: back-ref del change añadida en la épica y en cada HU de `hus[]`.
16
20
  - [ ] **Hooks verdes (automáticos, no son gates de agente)**: `lint-typecheck.sh` (lint + chequeo de tipos del stack declarado), `stack-guard.sh` (deps en allowlist según la sección de requisitos técnicos del PRD del consumidor, ruta declarada en `stack-allowlist.json#source`), `gitflow-guard.sh` (rama `feature/*`, sin commits directos a `main`).
@@ -11,7 +11,10 @@ la épica; lo de abajo aplica a la épica y a **cada HU** que cubre (`hus[]`). L
11
11
  - [ ] **Dependencias resueltas**: las épicas/HU de las que depende están archivadas (`history[]`) o explícitamente no bloquean.
12
12
  - [ ] **Cabe en el stack** del PRD §7 (no requiere tecnología fuera de `stack-allowlist.json`).
13
13
  - [ ] **Datos de prueba disponibles** o identificables (p.ej. los datos de ejemplo / fixtures sintéticos del dominio del consumidor).
14
+ - [ ] **Fuente de diseño identificada (slices con UI)**: la fuente visual de verdad del slice
15
+ (el `DESIGN_SOURCE` del dominio) está declarada y confirmada (`design_source.confirmed`), y este
16
+ slice apunta a la(s) pantalla(s) equivalente(s). No se construye UI fuera de la fuente declarada.
14
17
 
15
18
  **Si todo ✓** → `dor-dod-gatekeeper` abre `active_slice` en `build-state.json` con `epica`, `hus[]`,
16
- `phase: dor`, `gates.dor: true` y el resto en `false` (`ux`/`api` en `null` si la épica no toca UI/endpoints).
19
+ `phase: dor`, `gates.dor: true` y el resto en `false` (`fidelity`/`api` en `null` si la épica no toca UI/endpoints).
17
20
  **Si algo ✗** → no se abre el slice; se reporta qué falta y se vuelve a discovery (Trycore).
@@ -15,6 +15,7 @@ los expone, el gate se cubre con las alternativas CLI/test indicadas.
15
15
  | Fase / agente | MCP (ejemplo, si habilitado) | Para qué |
16
16
  |---|---|---|
17
17
  | `review` · `ux-krug-reviewer` | **chrome-devtools** | `take_snapshot` (árbol accesible), `lighthouse_audit` (Accessibility/Best-Practices), `take_screenshot`, `list_console_messages` para verificar la UI **corriendo**. |
18
+ | `smoke` · `ux-fidelity-reviewer` | **chrome-devtools** *(ejemplo opt-in)* | `new_page`/`navigate_page`, `take_screenshot`, `take_snapshot` para comparar **composición/paleta/tipografía** del diseño vs la app corriendo. Requiere la app levantada; úsalo en fase `active`. Si no hay MCP, el agente degrada a comparación estática (INCONCLUSO). |
18
19
  | `api` · `api-contract-tester` | — (Newman CLI) | Contratos de endpoints. Newman no es MCP; corre vía Bash. |
19
20
  | `data` · `data-consistency-checker` | **postgresql** *(solo si el slice usa Postgres)* | `read_query`/`describe_table` para validar consistencia en BD. Con un almacén embebido/cliente (según el stack declarado en el PRD del consumidor) se valida por tests, sin MCP. |
20
21
  | perf (opcional, fuera del DoD) | **k6** | `execute_k6_test` para carga/latencia si una HU de la épica lo exige. |
package/state/README.md CHANGED
@@ -51,6 +51,17 @@ Arranca en `confirmed: false` y **solo** pasa a `true` por **confirmación expl
51
51
  restrictiva para abrir cualquier slice: el hook `scaffold-guard.sh` bloquea escribir código de
52
52
  slice (fases `red…data`) mientras `confirmed` no sea `true`. El arnés **no genera** el scaffold.
53
53
 
54
+ ### `design_source` (gate de proyecto, slices con UI)
55
+
56
+ Espejo de `scaffold` para la UI: `applies` (¿el proyecto tiene UI?), `confirmed` (humano confirmó que
57
+ existe una fuente de diseño declarada), `source` (puntero al prototipo/export). El arnés NO genera el
58
+ prototipo. Lo respalda `design-source-guard.sh`.
59
+
60
+ ### gate `fidelity` (por-slice, inner loop)
61
+
62
+ `true` = FIEL (o desviaciones justificadas); `false` = desviaciones sin justificar; `null` = slice sin
63
+ UI. Lo computa `ux-fidelity-reviewer` en la fase `smoke` y lo escribe el `build-orchestrator`.
64
+
54
65
  ### Reflexión post-slice (ciclo autocorrectivo)
55
66
 
56
67
  Tras archivar un slice, su entrada en `history[]` puede llevar `reflected` / `reflected_at`. El
@@ -14,6 +14,7 @@
14
14
  "description": "Señal INFORMATIVA auto-detectada: authoring = aún no hay package.json; active = scaffold de código presente. El gate de avance es `scaffold.confirmed`, NO esta señal."
15
15
  },
16
16
  "scaffold": { "$ref": "#/$defs/scaffold" },
17
+ "design_source": { "$ref": "#/$defs/design_source" },
17
18
  "active_slice": {
18
19
  "description": "El slice (épica) en construcción. null si no hay ninguno activo.",
19
20
  "oneOf": [
@@ -45,6 +46,20 @@
45
46
  "notes": { "type": "string", "description": "Evidencia libre (p.ej. 'build/dev arranca vacío sin error')." }
46
47
  }
47
48
  },
49
+ "design_source": {
50
+ "type": "object",
51
+ "additionalProperties": false,
52
+ "description": "Gate de PROYECTO para slices con UI: existe una fuente de diseño declarada (prototipo/export). Espejo de scaffold: confirmed pasa a true SOLO por confirmación humana, nunca por auto-detección. El arnés NO genera el prototipo. applies=false apaga todo el mecanismo (proyecto sin UI).",
53
+ "required": ["applies", "confirmed"],
54
+ "properties": {
55
+ "applies": { "type": "boolean", "description": "¿el proyecto tiene UI / hay diseño que respetar? false → mecanismo N/A." },
56
+ "confirmed": { "type": "boolean", "description": "true solo tras confirmación humana de que existe una fuente de diseño declarada." },
57
+ "confirmed_by": { "type": ["string", "null"], "description": "Agente/skill que registró la confirmación." },
58
+ "confirmed_at": { "type": ["string", "null"], "format": "date-time" },
59
+ "source": { "type": "string", "description": "Puntero a la fuente: ruta/URL del prototipo o export (el DESIGN_SOURCE del dominio)." },
60
+ "notes": { "type": "string", "description": "Evidencia libre (p.ej. 'prototipo en docs/… revisado y vigente')." }
61
+ }
62
+ },
48
63
  "slice": {
49
64
  "type": "object",
50
65
  "additionalProperties": false,
@@ -75,6 +90,7 @@
75
90
  "journey_smoke": { "type": "boolean", "description": "El backbone-hasta-aquí camina end-to-end (verificado con la skill verify/run)." },
76
91
  "coherence_link": { "type": "boolean", "description": "Enlace change↔épica válido (change-epic-coherence, barato, por slice)." },
77
92
  "data": { "type": "boolean" },
93
+ "fidelity": { "type": ["boolean", "null"], "description": "Gate VIVO de inner loop (slices con UI): fidelidad visual a la fuente de diseño declarada, computado en fase smoke por ux-fidelity-reviewer. true = FIEL (o DESVIACIONES justificadas); false = DESVIACIONES sin justificar; null = N/A (slice sin UI). NO es legado (los legados viven en releases[])." },
78
94
  "api": { "type": ["boolean", "null"], "description": "null = N/A (slice sin endpoints)." },
79
95
  "ux": { "type": ["boolean", "null"], "description": "null = N/A (slice sin UI). Legado: hoy se audita en releases[]." },
80
96
  "stack": { "type": "boolean", "description": "Legado por-slice; deps las cubre el hook stack-guard.sh, la arquitectura se audita en releases[]." },
@@ -7,6 +7,14 @@
7
7
  "confirmed_at": null,
8
8
  "notes": ""
9
9
  },
10
+ "design_source": {
11
+ "applies": false,
12
+ "confirmed": false,
13
+ "confirmed_by": null,
14
+ "confirmed_at": null,
15
+ "source": "",
16
+ "notes": ""
17
+ },
10
18
  "active_slice": null,
11
19
  "history": [],
12
20
  "releases": []
@@ -35,7 +35,7 @@ Outer loop (por release): Release Gate (seguridad · diseño · UX · cohe
35
35
  ### Bloque de dominio (lo resuelve `/build:onboard`)
36
36
 
37
37
  Estos puntos de extensión los leen los agentes `security-reviewer`, `stack-guardian`,
38
- `data-consistency-checker`, `ux-krug-reviewer` y `simple-design-reviewer`:
38
+ `data-consistency-checker`, `ux-krug-reviewer`, `simple-design-reviewer` y `ux-fidelity-reviewer`:
39
39
 
40
40
  - **PRD técnico (fuente del stack)**: {{PRD_TECH_PATH}}
41
41
  - **Capa de servicios externos / IA (frontera)**: {{EXTERNAL_SERVICE_LAYER}}
@@ -43,6 +43,7 @@ Estos puntos de extensión los leen los agentes `security-reviewer`, `stack-guar
43
43
  - **Categorías de datos sensibles / PII reguladas**: {{SENSITIVE_DATA_CATEGORIES}}
44
44
  - **Secretos server-side**: {{SERVER_SIDE_SECRETS}}
45
45
  - **Decisiones de alto impacto que exigen explicabilidad UX**: {{HIGH_STAKES_DECISIONS}}
46
+ - **Fuente de diseño / referencia visual**: {{DESIGN_SOURCE}}
46
47
 
47
48
  (Si aparecen como `{{...}}`, ejecuta `/build:onboard` para parametrizarlos.)
48
49
 
@@ -13,7 +13,7 @@
13
13
  ],
14
14
  "PreToolUse": [
15
15
  { "matcher": "Bash", "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/gitflow-guard.sh\"" } ] },
16
- { "matcher": "Write|Edit|MultiEdit", "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/stack-guard.sh\"" }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/scaffold-guard.sh\"" } ] }
16
+ { "matcher": "Write|Edit|MultiEdit", "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/stack-guard.sh\"" }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/scaffold-guard.sh\"" }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/design-source-guard.sh\"" } ] }
17
17
  ],
18
18
  "PostToolUse": [
19
19
  { "matcher": "Write|Edit|MultiEdit", "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/lint-typecheck.sh\"" }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/coherence-flag.sh\"" } ] }