@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.
- package/.claude-plugin/plugin.json +1 -1
- package/GOVERNANCE.md +10 -2
- package/INSTALL.md +4 -4
- package/README.md +6 -4
- package/VERSION +1 -1
- package/agents/build/build-orchestrator.md +6 -1
- package/agents/build/dor-dod-gatekeeper.md +10 -5
- package/agents/build/ux-fidelity-reviewer.md +61 -0
- package/commands/build/onboard.md +20 -4
- package/dist/lib/settings-merge.js +1 -1
- package/dist/lib/state-seed.js +1 -0
- package/docs/agents.md +2 -1
- package/docs/getting-started.md +4 -4
- package/docs/hooks.md +12 -6
- package/hooks/build/design-source-guard.sh +52 -0
- package/hooks/build-harness.json +4 -0
- package/package.json +1 -1
- package/skills/building-a-slice/SKILL.md +20 -1
- package/skills/building-a-slice/references/dod.md +4 -0
- package/skills/building-a-slice/references/dor.md +4 -1
- package/skills/building-a-slice/references/mcp-map.md +1 -0
- package/state/README.md +11 -0
- package/state/build-state.schema.json +16 -0
- package/state/build-state.template.json +8 -0
- package/templates/CLAUDE.md.template +2 -1
- package/templates/settings-hooks.template.json +1 -1
|
@@ -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.
|
|
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 |
|
|
12
|
-
| Hooks | settings.json +
|
|
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.
|
|
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.
|
|
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/` —
|
|
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/` —
|
|
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/ ←
|
|
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/ ←
|
|
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 **
|
|
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
|
|
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.
|
|
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;
|
|
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.
|
|
47
|
-
|
|
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
|
|
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
|
|
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
|
];
|
package/dist/lib/state-seed.js
CHANGED
|
@@ -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 **
|
|
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
|
|
package/docs/getting-started.md
CHANGED
|
@@ -73,12 +73,12 @@ trycore-build init
|
|
|
73
73
|
|
|
74
74
|
`init` es **idempotente** (re-correrlo es seguro) y siembra:
|
|
75
75
|
|
|
76
|
-
- **
|
|
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
|
-
- **
|
|
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 **
|
|
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 **
|
|
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
|
|
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
|
|
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
|
-
>
|
|
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
|
|
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
|
|
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
|
package/hooks/build-harness.json
CHANGED
|
@@ -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.
|
|
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` (`
|
|
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 `
|
|
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\"" } ] }
|