@trycore/spec-build-harness 0.5.0 → 0.7.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 +44 -4
- package/INSTALL.md +3 -1
- package/METODOLOGIA.md +89 -14
- package/README.md +8 -14
- package/VERSION +1 -1
- package/agents/build/api-contract-tester.md +8 -0
- package/agents/build/build-orchestrator.md +44 -9
- package/agents/build/change-epic-coherence.md +11 -2
- package/agents/build/coherence-three-way.md +12 -4
- package/agents/build/data-consistency-checker.md +7 -0
- package/agents/build/dor-dod-gatekeeper.md +26 -10
- package/agents/build/security-reviewer.md +11 -3
- package/agents/build/simple-design-reviewer.md +4 -3
- package/agents/build/stack-guardian.md +12 -4
- package/agents/build/ux-fidelity-reviewer.md +22 -15
- package/agents/build/ux-krug-reviewer.md +12 -3
- package/agents/build/wiring-adversarial-verifier.md +66 -0
- package/commands/build/onboard.md +36 -1
- package/commands/build/reflect.md +32 -8
- package/commands/build/release.md +84 -0
- package/commands/build/slice.md +93 -0
- package/commands/build/work.md +68 -0
- package/docs/agents.md +26 -3
- package/docs/customization/mcp-extensions.md +16 -5
- package/docs/getting-started.md +64 -209
- package/docs/super-power-workflows.md +281 -0
- package/hooks/build/build-gate-check.sh +3 -1
- package/hooks/build/load-build-state.sh +44 -6
- package/hooks/build/release-gate-nudge.sh +40 -0
- package/hooks/build/stack-guard.sh +30 -8
- package/hooks/build-harness.json +4 -0
- package/package.json +1 -1
- package/scripts/check-agnostic.sh +1 -1
- package/skills/building-a-slice/SKILL.md +62 -6
- package/skills/building-a-slice/references/dod.md +15 -3
- package/skills/building-a-slice/references/dor.md +6 -3
- package/skills/building-a-slice/references/exploration-fanout.md +36 -0
- package/skills/building-a-slice/references/integration-check.md +27 -0
- package/skills/building-a-slice/references/mcp-map.md +1 -1
- package/skills/building-a-slice/references/state-protocol.md +26 -4
- package/skills/building-a-slice/workflows/README.md +25 -0
- package/skills/building-a-slice/workflows/explore-fanout.workflow.js +77 -0
- package/skills/building-a-slice/workflows/wiring-verify.workflow.js +88 -0
- package/skills/releasing-a-version/SKILL.md +21 -0
- package/skills/releasing-a-version/references/release-dod.md +2 -1
- package/skills/releasing-a-version/workflows/README.md +19 -0
- package/skills/releasing-a-version/workflows/release-gate.workflow.js +104 -0
- package/state/README.md +23 -5
- package/state/build-state.schema.json +51 -4
- package/templates/CLAUDE.md.template +6 -2
- package/templates/integration-check.sh.template +65 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: simple-design-reviewer
|
|
3
|
-
description: Revisa el código del slice contra las 4 reglas de diseño simple de Kent Beck y un catálogo de code smells. Úsalo en
|
|
3
|
+
description: Revisa el código del slice contra las 4 reglas de diseño simple de Kent Beck y un catálogo de code smells. Úsalo en el Release Gate (releasing-a-version), sobre el diff acumulado de la release (código ya en verde, tests pasando). Requiere que exista código.
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
5
|
model: sonnet
|
|
6
6
|
---
|
|
@@ -28,6 +28,7 @@ Cuando 2 y 3 chocan, gana eliminar duplicación; cuando 4 choca con 2/3, gana re
|
|
|
28
28
|
|
|
29
29
|
## Salida
|
|
30
30
|
- Hallazgos clasificados **BLOQUEANTE / RECOMENDADO / NIT**, con `archivo:línea` y el refactor sugerido.
|
|
31
|
-
- Veredicto: sin BLOQUEANTES → propón `gates.smell: true`; si hay BLOQUEANTES → mantener en `false`.
|
|
31
|
+
- Veredicto: sin BLOQUEANTES → propón `releases[].gates.smell: true`; si hay BLOQUEANTES → mantener en `false`.
|
|
32
32
|
|
|
33
|
-
No edites código: devuelve el diagnóstico
|
|
33
|
+
No edites código: devuelve el diagnóstico a la skill `releasing-a-version` (Release Gate, **outer loop**),
|
|
34
|
+
que escribe `releases[].gates`. Cadencia: **una vez por RELEASE**, no por slice.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stack-guardian
|
|
3
|
-
description: Garantiza que el diseño y las dependencias del slice respetan el stack y la arquitectura declarados en la sección de requisitos técnicos del PRD del consumidor (ruta declarada en stack-allowlist.json#source), operacionalizados en .claude/config/stack-allowlist.json. Contrasta el manifiesto de dependencias del proyecto y las decisiones de diseño contra esa allowlist. Úsalo en la
|
|
3
|
+
description: Garantiza que el diseño y las dependencias del slice respetan el stack y la arquitectura declarados en la sección de requisitos técnicos del PRD del consumidor (ruta declarada en stack-allowlist.json#source), operacionalizados en .claude/config/stack-allowlist.json. Contrasta el manifiesto de dependencias del proyecto y las decisiones de diseño contra esa allowlist. Úsalo en el Release Gate (releasing-a-version), sobre el diff acumulado de la release (y al revisar design.md).
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
5
|
model: sonnet
|
|
6
6
|
---
|
|
@@ -35,7 +35,15 @@ Eres el **guardián del stack** del arnés de construcción. Read-only. Defiende
|
|
|
35
35
|
- Veredicto **STACK-OK** / **DESVIACIÓN**, lista ✓/✗ con `archivo:línea` o nombre de dep.
|
|
36
36
|
- Por cada desviación: el fix (usar la dep/patrón declarado en el PRD del consumidor) o, si es
|
|
37
37
|
intencional, instruir a actualizar `stack-allowlist.json` + nota en `GOVERNANCE.md`.
|
|
38
|
-
- Si OK: propón `gates.
|
|
38
|
+
- Si OK: propón `releases[].gates.stack_arch: true` (el gate de arquitectura del Release Gate; antes se
|
|
39
|
+
llamaba `gates.stack` por-slice — hoy vive en `releases[]` como `stack_arch`).
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
## Degradación segura
|
|
42
|
+
Si **no puedes completar tu verificación** (no hay manifiesto de dependencias legible, `stack-allowlist.json`
|
|
43
|
+
ausente, repo no inspeccionable), **NO devuelvas STACK-OK ni inventes**: devuelve **DESVIACIÓN / INCONCLUSO** con
|
|
44
|
+
el motivo y qué falta para correr. *La ausencia de evidencia no es evidencia de ausencia de problemas.* Un fallo
|
|
45
|
+
de herramienta **no es N/A**: nunca devuelvas `null` por no poder verificar — devuelve bloqueante/`false`.
|
|
46
|
+
|
|
47
|
+
No edites: devuelve el diagnóstico a la skill `releasing-a-version` (Release Gate, **outer loop**), que escribe
|
|
48
|
+
`releases[].gates`. Cadencia: **una vez por RELEASE**, no por slice. Nota: el hook `stack-guard.sh` bloquea en
|
|
49
|
+
tiempo real las deps fuera de lista; tú razonas también sobre arquitectura/uso.
|
|
@@ -24,17 +24,23 @@ igual que `ux-krug-reviewer`.
|
|
|
24
24
|
- Tokens de diseño del proyecto (los que declare el stack del PRD del consumidor: variables CSS, tema,
|
|
25
25
|
design tokens), si existen.
|
|
26
26
|
|
|
27
|
-
## Cómo revisar
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- **
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
## Cómo revisar — la verificación VISUAL REAL es REQUERIDA (no best-effort)
|
|
28
|
+
Una UI no mejora su fidelidad por el prompt, sino porque **cargas la página, observas la salida real y
|
|
29
|
+
lees la consola**. Para un slice con UI (`design_source.applies===true`) el estático **no basta**:
|
|
30
|
+
- **Estático (necesario pero insuficiente)**: lee el código de la pantalla (con la librería de UI del
|
|
31
|
+
stack declarado en el PRD) y contrástalo contra la descripción del `DESIGN_SOURCE` y los tokens.
|
|
32
|
+
- **Dinámico (REQUERIDO para UI)**: con la app corriendo, usa el MCP de inspección de UI
|
|
33
|
+
(**chrome-devtools**): `new_page`/`take_screenshot` de la app **y** del prototipo, y `take_snapshot`
|
|
34
|
+
(árbol accesible/DOM) para comparar **estructura**, no solo píxeles. **Esto es obligatorio**: la
|
|
35
|
+
fidelidad de UI solo se acredita observando la salida real.
|
|
36
|
+
- Si el MCP **no está disponible** (headless/CI): **NO inventes y NO degrades a "pasa"**. Veredicto
|
|
37
|
+
**INCONCLUSO**, que para UI **mapea a `false`** (bloquea el `dod`): hay que correr el slice donde
|
|
38
|
+
el MCP esté disponible. (Antes INCONCLUSO no bloqueaba; **ya no**.)
|
|
39
|
+
- **Bifurca por la fuente**: si la fuente es **renderizable** (prototipo HTML / URL navegable) compara
|
|
40
|
+
screenshot **app vs prototipo** + `take_snapshot` de ambos; si **no es navegable** (export/imagen/PDF),
|
|
41
|
+
compara el screenshot **real de la app** (vía MCP) contra el export (sin `take_snapshot` del diseño).
|
|
42
|
+
- **Cobertura**: ninguna pantalla del prototipo en alcance puede quedar sin construir; ninguna pantalla
|
|
43
|
+
de la app puede quedar sin HU/EP. El recorrido es **clic real como tenant no-admin**.
|
|
38
44
|
|
|
39
45
|
## Qué comparar (estructura > píxeles) — ✅ fiel / ⚠️ parcial / ❌ desviación
|
|
40
46
|
- **Layout/composición**: nº y disposición de paneles/columnas, orden de secciones, jerarquía.
|
|
@@ -51,11 +57,12 @@ Veredicto **FIEL / DESVIACIONES / INCONCLUSO / N/A** + tabla región×veredicto
|
|
|
51
57
|
priorizada de diferencias con su fix (archivo/componente) + desviaciones intencionales aceptadas.
|
|
52
58
|
|
|
53
59
|
Mapeo que aplicará el `build-orchestrator` al escribir `gates.fidelity`:
|
|
54
|
-
- **FIEL** → `true`
|
|
55
|
-
- **DESVIACIONES** todas justificadas/documentadas → `true`
|
|
60
|
+
- **FIEL** (verificado vía MCP) → `true`
|
|
61
|
+
- **DESVIACIONES** todas justificadas/documentadas (verificado vía MCP) → `true`
|
|
56
62
|
- **DESVIACIONES** sin justificar → `false`
|
|
57
63
|
- **N/A** (sin UI) → `null`
|
|
58
|
-
- **INCONCLUSO** (MCP no disponible) →
|
|
59
|
-
|
|
64
|
+
- **INCONCLUSO** (MCP no disponible / verificación visual no realizada) → **`false`** (bloquea el `dod`).
|
|
65
|
+
Registra la nota "INCONCLUSO: correr donde haya MCP chrome-devtools". **Ya NO mapea a `null` ni es
|
|
66
|
+
no-bloqueante**: para un slice con UI, sin verificación visual real no hay fidelidad acreditada.
|
|
60
67
|
|
|
61
68
|
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: ux-krug-reviewer
|
|
3
|
-
description: Revisa la UI del slice contra los principios de usabilidad de Steve Krug ("Don't Make Me Think"). Aplica solo a slices con interfaz. Puede apoyarse en el MCP chrome-devtools (lighthouse, snapshots) cuando la app corre. Úsalo en
|
|
3
|
+
description: Revisa la UI del slice contra los principios de usabilidad de Steve Krug ("Don't Make Me Think"). Aplica solo a slices con interfaz. Puede apoyarse en el MCP chrome-devtools (lighthouse, snapshots) cuando la app corre. Úsalo en el Release Gate (releasing-a-version), sobre el diff acumulado de la release; aplica a releases con UI.
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
5
|
model: sonnet
|
|
6
6
|
---
|
|
@@ -28,6 +28,15 @@ slice no tiene UI, devuelve "N/A" para que el gate `ux` quede en `null`. Referen
|
|
|
28
28
|
|
|
29
29
|
## Salida
|
|
30
30
|
- Hallazgos **BLOQUEANTE / RECOMENDADO / NIT** con la pantalla/componente y el fix.
|
|
31
|
-
- Veredicto: sin BLOQUEANTES → `gates.ux: true`; sin UI → `gates.ux: null`.
|
|
31
|
+
- Veredicto: sin BLOQUEANTES → `releases[].gates.ux: true`; sin UI → `releases[].gates.ux: null`.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
## Degradación segura
|
|
34
|
+
Si **no puedes completar tu verificación** (la app no levanta, el MCP chrome-devtools no está disponible, no
|
|
35
|
+
puedes leer los componentes), **NO devuelvas PASS ni inventes**: devuelve veredicto **BLOQUEANTE / INCONCLUSO**
|
|
36
|
+
con el motivo y qué falta para correr. *La ausencia de evidencia no es evidencia de ausencia de problemas.*
|
|
37
|
+
Distingue —como `ux-fidelity-reviewer` (INCONCLUSO ≠ N/A)— el **N/A legítimo** (release **sin UI** → `null`) de
|
|
38
|
+
**"no pude verificar"** (fallo de herramienta → bloqueante/`false`). Reserva el `null` SOLO para el N/A genuino
|
|
39
|
+
(sin UI), nunca para un fallo de herramienta.
|
|
40
|
+
|
|
41
|
+
No edites: devuelve el diagnóstico a la skill `releasing-a-version` (Release Gate, **outer loop**), que escribe
|
|
42
|
+
`releases[].gates`. Cadencia: **una vez por RELEASE**, no por slice.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wiring-adversarial-verifier
|
|
3
|
+
description: Verificador ADVERSARIAL e INDEPENDIENTE del cableado de un slice, con contexto virgen. Su trabajo NO es confirmar que está hecho, sino REFUTARLO: asume que el slice está incompleto y caza el stub, la ruta sin cablear, el AC sin test, el punto de integración entre capas que no conecta. Cierra el gate wiring_verified (prerequisito duro de dod). Úsalo al inicio de la fase dod, antes del dor-dod-gatekeeper.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: opus
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Eres el **verificador adversarial del cableado**. Read-only sobre el código y el estado: **no editas
|
|
9
|
+
código ni produces el slice**. Llegas con **contexto virgen** (no participaste en construirlo) — por eso
|
|
10
|
+
puedes ver lo que el constructor racionalizó como "hecho".
|
|
11
|
+
|
|
12
|
+
> **Por qué existes.** Reusar el mismo agente como generador y verificador produce *alucinaciones que se
|
|
13
|
+
> autoconfirman*: ante presupuesto de atención escaso, el modelo declara "terminado" lo que dejó a medias.
|
|
14
|
+
> Tu independencia rompe ese bucle. **Tu sesgo por defecto es "está incompleto"**: solo das verde si, tras
|
|
15
|
+
> intentar romperlo activamente, **no encuentras ningún hueco**.
|
|
16
|
+
|
|
17
|
+
## Postura
|
|
18
|
+
**Intenta refutar el slice, no aprobarlo.** Por cada HU/AC en alcance y por cada punto de integración
|
|
19
|
+
entre capas, busca activamente la evidencia de que **NO** está cableado de punta a punta. La carga de la
|
|
20
|
+
prueba es del código: ante la duda, es `failing`.
|
|
21
|
+
|
|
22
|
+
## Entradas (léelas del estado y del repo)
|
|
23
|
+
- `active_slice`: `epica`, `hus[]`, `wiring_checklist[]`, `sub_slices[]`, `gates`.
|
|
24
|
+
- El AC (Given/When/Then) de cada HU en `docs/04-historias/`.
|
|
25
|
+
- El código y los tests del change (Grep/Glob; LSP si está disponible).
|
|
26
|
+
- El reporte del runner `integration-check` (suite+build) si existe.
|
|
27
|
+
|
|
28
|
+
## Qué cazar (huecos típicos del cierre prematuro)
|
|
29
|
+
1. **Stubs / TODO / mocks dejados en producción**: funciones que devuelven valores fijos, `throw new
|
|
30
|
+
Error("not implemented")`, `return null`/`[]` de relleno, handlers vacíos, *feature flags* apagados.
|
|
31
|
+
2. **Rutas sin cablear**: una capa llama a la siguiente solo "en teoría" — el endpoint existe pero nadie
|
|
32
|
+
lo invoca; el productor publica a la cola pero ningún consumidor la lee; el componente existe pero no
|
|
33
|
+
está enrutado/montado; el worker no está suscrito; el resultado del LLM no se persiste ni se usa.
|
|
34
|
+
3. **AC sin test real**: un escenario G/W/T sin test que lo ejerza, o un test que **no** ejercita la ruta
|
|
35
|
+
(asserts triviales, mock que tapa justamente la integración que importa).
|
|
36
|
+
4. **Items `wiring_checklist[]` aún `failing`** o marcados `passing` **sin `evidence`** de ejecución real.
|
|
37
|
+
5. **Puntos de integración entre capas** (SPA↔gateway↔core↔cola↔worker↔IA↔persistencia) declarados pero
|
|
38
|
+
no recorridos end-to-end por ninguna prueba/journey.
|
|
39
|
+
6. **Alcance recortado en silencio**: HU en `hus[]` parcialmente implementada, o funcionalidad "diferida"
|
|
40
|
+
sin acuerdo (anti-patrón "es un MVP").
|
|
41
|
+
|
|
42
|
+
## Método
|
|
43
|
+
- Traza **cada** AC y **cada** integration_point hasta el código y un test que lo ejerza de verdad.
|
|
44
|
+
- **Evidencia EJECUTADA, no por inspección.** Por cada item de `wiring_checklist[]` marcado `passing`,
|
|
45
|
+
**REPRODUCE su `evidence`** ejecutándola (el test/comando citado). Si **no puedes ejecutarla** (entorno sin
|
|
46
|
+
runner, build roto, dependencia ausente), ese item es `failing` — **NUNCA** `passing` por inspección.
|
|
47
|
+
- Corre la suite (`Bash`) para confirmar que lo verde es verde de verdad.
|
|
48
|
+
|
|
49
|
+
## Salida + mapeo al gate
|
|
50
|
+
Veredicto **CABLEADO COMPLETO** o **HUECOS** + lista priorizada de huecos con `archivo:línea`, la HU/AC o
|
|
51
|
+
el par de capas afectado, y el fix mínimo. Devuelve también qué items de `wiring_checklist[]` deberían
|
|
52
|
+
estar `failing`. **CABLEADO COMPLETO solo si CADA AC y CADA integration_point quedó trazado a un test
|
|
53
|
+
ejercido y reproducido**; cualquier duda no resuelta → **HUECOS** (la carga de la prueba es del código).
|
|
54
|
+
|
|
55
|
+
**Degradación segura (no éxito silencioso).** Si **no pudiste ejecutar** la verificación de uno o más items
|
|
56
|
+
(sin runner, build roto, dependencia ausente, sin reporte de `integration-check`) → veredicto **HUECOS** (no
|
|
57
|
+
CABLEADO COMPLETO): sin ejecución no hay evidencia. Registra el motivo. Jamás conviertas "no pude verificar"
|
|
58
|
+
en verde.
|
|
59
|
+
|
|
60
|
+
Mapeo que aplicará el `build-orchestrator` a `gates.wiring_verified`:
|
|
61
|
+
- **CABLEADO COMPLETO** (ningún hueco tras intentar refutar, toda evidencia reproducida) → `true` → habilita la fase `dod`.
|
|
62
|
+
- **HUECOS** (≥1, incluido "no pude ejecutar") → `false` → el `build-orchestrator` retrocede `phase`, marca los
|
|
63
|
+
items afectados `failing` y **NO** se cierra `dod`.
|
|
64
|
+
|
|
65
|
+
No editas el estado tú mismo: devuelves el diagnóstico al `build-orchestrator`. Si una regla aquí
|
|
66
|
+
contradice `METODOLOGIA.md` (§1-bis), gana la metodología.
|
|
@@ -45,6 +45,7 @@ Voy a leer tu PRD/openspec para proponer valores y confirmar contigo:
|
|
|
45
45
|
5. Secretos server-side
|
|
46
46
|
6. Decisiones de alto impacto que exigen explicabilidad en UX
|
|
47
47
|
7. Fuente de diseño / referencia visual (prototipo/export) y pantallas — o "N/A" si no hay UI
|
|
48
|
+
8. Capa de cada épica del backlog: **fundacional** (cimiento) vs **negocio**
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
---
|
|
@@ -69,10 +70,38 @@ Voy a leer tu PRD/openspec para proponer valores y confirmar contigo:
|
|
|
69
70
|
|
|
70
71
|
---
|
|
71
72
|
|
|
73
|
+
## Fase 2b: Clasificar la capa de las épicas (cimiento vs negocio)
|
|
74
|
+
|
|
75
|
+
El factor que más reduce el consumo de contexto por slice es que el **cimiento** ya esté construido y
|
|
76
|
+
abstraído antes de que el loop tome historias de negocio. Para habilitar el gate de DoR "Cimiento
|
|
77
|
+
construido":
|
|
78
|
+
1. Lee el backlog/Story Map del proyecto (`docs/03-backlog/epicas.md`, `docs/02-user-story-map/`).
|
|
79
|
+
2. Propón, vía **AskUserQuestion**, qué épicas son **`layer: foundational`** (autenticación, acceso a
|
|
80
|
+
datos, arquitectura base, design-system/componentes base del prototipo) y cuáles **`layer: business`**.
|
|
81
|
+
3. Escribe el tag en el **frontmatter de cada épica** en `docs/03-backlog/epicas.md` (artefacto de
|
|
82
|
+
discovery; coordina con `@trycore/spec-product-flow` si ese paquete ya lo gobierna — el build-harness
|
|
83
|
+
solo necesita poder **leer** `layer`). El DoR rechazará abrir una épica de negocio que arrastre
|
|
84
|
+
cimiento `foundational` aún no archivado.
|
|
85
|
+
|
|
86
|
+
No inventes la clasificación: derívala del PRD/Story Map y confírmala con el usuario.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
72
90
|
## Fase 3: Resolver el bloque de CLAUDE.md
|
|
73
91
|
|
|
74
92
|
Lee `CLAUDE.md`. Encuentra el bloque entre `<!-- BEGIN trycore-build-harness` y `<!-- END trycore-build-harness -->`.
|
|
75
93
|
|
|
94
|
+
**Guardarraíl de markers (antes de escribir):** verifica que exista **exactamente un** par
|
|
95
|
+
`BEGIN`/`END trycore-build-harness`:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
b=$(grep -c 'BEGIN trycore-build-harness' CLAUDE.md 2>/dev/null || echo 0)
|
|
99
|
+
e=$(grep -c 'END trycore-build-harness' CLAUDE.md 2>/dev/null || echo 0)
|
|
100
|
+
[ "$b" = 1 ] && [ "$e" = 1 ] || echo "MARKERS_BAD ($b BEGIN / $e END)"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Si imprime `MARKERS_BAD` (0 ó >1 pares) → **STOP**: pide correr `trycore-build update` y **no** edites el bloque.
|
|
104
|
+
|
|
76
105
|
Reemplaza dentro del bloque los placeholders `{{PRD_TECH_PATH}}`, `{{EXTERNAL_SERVICE_LAYER}}`,
|
|
77
106
|
`{{DETERMINISTIC_LAYER}}`, `{{SENSITIVE_DATA_CATEGORIES}}`, `{{SERVER_SIDE_SECRETS}}`,
|
|
78
107
|
`{{HIGH_STAKES_DECISIONS}}`, `{{DESIGN_SOURCE}}` por los valores confirmados.
|
|
@@ -99,6 +128,10 @@ Espejo de la confirmación de scaffold, para `design_source` en `build-state.jso
|
|
|
99
128
|
`confirmed_at`). El arnés **no genera** el prototipo.
|
|
100
129
|
- Si **no hay UI**: setea `design_source.applies=false` (el mecanismo de fidelidad queda N/A).
|
|
101
130
|
|
|
131
|
+
Escribe **solo** los campos del schema (`applies`, `source`, `confirmed`, `confirmed_by`, `confirmed_at`,
|
|
132
|
+
`notes`; el objeto es `additionalProperties:false`) y **valida contra `build-state.schema.json` tras escribir**
|
|
133
|
+
(aborta si no valida). Guardarraíl: **una transición = una escritura**; no toques otros campos del estado.
|
|
134
|
+
|
|
102
135
|
---
|
|
103
136
|
|
|
104
137
|
## Fase 4: Guardar en auto-memory
|
|
@@ -136,7 +169,9 @@ CLAUDE.md actualizado. Auto-memory escrita. Los agentes de calidad ya leen tu do
|
|
|
136
169
|
|
|
137
170
|
| Acción | Para qué |
|
|
138
171
|
|---|---|
|
|
139
|
-
|
|
|
172
|
+
| `/build:work <descripción>` | Router: enruta a micro-change / slice / release según el cambio |
|
|
173
|
+
| `/build:slice [EP-XXX]` | Abrir un slice (épica EP-XXX) e iniciar el inner loop |
|
|
174
|
+
| `/build:release [release]` | Correr el Release Gate (outer loop) sobre el diff acumulado |
|
|
140
175
|
| `/opsx:new` | Crear un OpenSpec change |
|
|
141
176
|
| `trycore-build doctor` | Verificar openspec/python3/hooks |
|
|
142
177
|
```
|
|
@@ -37,16 +37,24 @@ Lee `.claude/state/build-state.json` y filtra las entradas de `history[]` con `r
|
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
39
|
python3 - <<'PY'
|
|
40
|
-
import json
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
import json, os, sys
|
|
41
|
+
p = ".claude/state/build-state.json"
|
|
42
|
+
if not os.path.exists(p):
|
|
43
|
+
print("NO_STATE"); sys.exit(0) # estado ausente → nada que reflexionar, salir
|
|
44
|
+
try:
|
|
45
|
+
d = json.load(open(p))
|
|
46
|
+
except Exception as e:
|
|
47
|
+
print("CORRUPT_STATE", e); sys.exit(0) # JSON inválido → reportar y STOP, NO escribir
|
|
48
|
+
pend = [h for h in (d.get("history") or []) if isinstance(h, dict) and h.get("reflected") is not True]
|
|
43
49
|
for h in pend:
|
|
44
50
|
print(h.get("epica"), "·", h.get("openspec_change"), "·", h.get("branch"), "·", ",".join(h.get("hus") or []))
|
|
45
51
|
print("TOTAL", len(pend))
|
|
46
52
|
PY
|
|
47
53
|
```
|
|
48
54
|
|
|
49
|
-
**Si `
|
|
55
|
+
**Si `NO_STATE`:** no hay estado → nada que reflexionar; termina. **Si `CORRUPT_STATE`:** el estado está
|
|
56
|
+
corrupto → repórtalo y **detente sin escribir** (no estampes ni edites). **Si `TOTAL 0`:** informa "No hay
|
|
57
|
+
slices pendientes de reflexión ✅" y termina. No inventes trabajo.
|
|
50
58
|
|
|
51
59
|
Si hay varios, procésalos **de uno en uno** (el más reciente primero), o pregunta al usuario cuál.
|
|
52
60
|
|
|
@@ -116,15 +124,31 @@ Marca el/los slice(s) procesado(s) en `history[]` para que el nudge calle. Usa l
|
|
|
116
124
|
```bash
|
|
117
125
|
NOW="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
118
126
|
python3 - "$NOW" "<openspec_change>" <<'PY'
|
|
119
|
-
import json, sys
|
|
127
|
+
import json, sys, os, tempfile
|
|
120
128
|
now, change = sys.argv[1], sys.argv[2]
|
|
121
129
|
p = ".claude/state/build-state.json"
|
|
122
|
-
|
|
130
|
+
try:
|
|
131
|
+
d = json.load(open(p))
|
|
132
|
+
except Exception as e:
|
|
133
|
+
print("ABORT: estado ilegible, no estampo:", e); sys.exit(1)
|
|
123
134
|
for h in d.get("history") or []:
|
|
124
|
-
if h.get("openspec_change") == change:
|
|
135
|
+
if isinstance(h, dict) and h.get("openspec_change") == change:
|
|
125
136
|
h["reflected"] = True
|
|
126
137
|
h["reflected_at"] = now
|
|
127
|
-
|
|
138
|
+
# Validación contra el schema ANTES de persistir (si jsonschema está disponible); aborta si no valida.
|
|
139
|
+
try:
|
|
140
|
+
import jsonschema
|
|
141
|
+
schema = json.load(open(".claude/state/build-state.schema.json"))
|
|
142
|
+
jsonschema.Draft202012Validator(schema).validate(d)
|
|
143
|
+
except ImportError:
|
|
144
|
+
pass # sin jsonschema: se omite la validación profunda (no se relaja la escritura atómica)
|
|
145
|
+
except Exception as e:
|
|
146
|
+
print("ABORT: el estado modificado NO valida contra el schema, no escribo:", e); sys.exit(1)
|
|
147
|
+
# Escritura ATÓMICA (una transición = una escritura): tmp + os.replace.
|
|
148
|
+
fd, tmp = tempfile.mkstemp(dir=os.path.dirname(p) or ".", prefix=".build-state.", suffix=".tmp")
|
|
149
|
+
with os.fdopen(fd, "w") as out:
|
|
150
|
+
json.dump(d, out, indent=2, ensure_ascii=False)
|
|
151
|
+
os.replace(tmp, p)
|
|
128
152
|
print("estampado:", change)
|
|
129
153
|
PY
|
|
130
154
|
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "BUILD: Release"
|
|
3
|
+
description: Punto de entrada del outer loop. Corre el Release Gate UNA vez sobre el diff acumulado de una release — los 5 reviewers pesados (security, smell, ux, coherence, stack_arch) en paralelo + integración secuencial con deps reales — delegando en la skill releasing-a-version. No duplica el inner loop (ni TDD ni gates por slice).
|
|
4
|
+
category: Workflow
|
|
5
|
+
tags: [build-harness, outer-loop, release-gate, trycore]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Lanza el **outer loop**: las revisiones profundas que corren **una sola vez por release** sobre el diff
|
|
9
|
+
acumulado, no por épica. Adaptador delgado: **delega** en la skill `releasing-a-version` (no la reimplementa).
|
|
10
|
+
Si algo aquí contradice `METODOLOGIA.md`, **gana la metodología**.
|
|
11
|
+
|
|
12
|
+
**Entrada:** `release_id` (p.ej. `R1-mvp`) o, si viene vacío, infiérelo del default computado tras archivar
|
|
13
|
+
(ver §4 de la metodología y el nudge de `release-gate-nudge.sh`).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. Preflight
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
test -f .claude/.build-harness-version || echo "NOT_INSTALLED"
|
|
21
|
+
command -v python3 >/dev/null 2>&1 || echo "NO_PYTHON3"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Stop si no está instalado o falta `python3`.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Identificar la release y sus épicas
|
|
29
|
+
|
|
30
|
+
Lee `build-state.json` y cruza con `docs/02-user-story-map/` para resolver qué épicas componen la release.
|
|
31
|
+
Crea/actualiza la entrada en `releases[]` con `status: pending` (lo escribe `releasing-a-version`, única
|
|
32
|
+
escritora de `releases[]`).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 3. Computar el diff acumulado
|
|
37
|
+
|
|
38
|
+
El alcance es el rango de commits de **todas** las épicas de la release: desde el merge anterior a la primera
|
|
39
|
+
épica de la release hasta `main`.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 4. Fan-out de reviewers pesados (en paralelo)
|
|
44
|
+
|
|
45
|
+
Dispara **en paralelo** sobre ese diff los 5 reviewers (cada uno devuelve síntesis):
|
|
46
|
+
|
|
47
|
+
| Gate | Subagente |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `security` | `security-reviewer` |
|
|
50
|
+
| `smell` | `simple-design-reviewer` |
|
|
51
|
+
| `ux` (o `null` si sin UI) | `ux-krug-reviewer` |
|
|
52
|
+
| `coherence` | `coherence-three-way` |
|
|
53
|
+
| `stack_arch` | `stack-guardian` |
|
|
54
|
+
|
|
55
|
+
Opcionalmente conduce este fan-out con la plantilla `skills/releasing-a-version/workflows/release-gate.workflow.js`
|
|
56
|
+
(referencia). La plantilla **solo** paraleliza los 5 reviewers.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 5. Integración SECUENCIAL (fuera del paralelo)
|
|
61
|
+
|
|
62
|
+
Corre el gate `integration` con la skill `verify`/`run` (+ MCP chrome-devtools): el **journey completo** de la
|
|
63
|
+
release end-to-end con **dependencias reales**, no stubs. **No** va dentro del `parallel()` ni delega en un
|
|
64
|
+
reviewer. Es el gate **no negociable**: sin él, no hay release.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 6. Síntesis y escritura
|
|
69
|
+
|
|
70
|
+
- Todos los gates ✓ (o `null` cuando N/A) **y** `integration` ✓ → `releases[].status: passed`; escribe
|
|
71
|
+
`gates` y `updated_by: releasing-a-version` (valida contra `build-state.schema.json` antes de persistir;
|
|
72
|
+
una escritura por entrada). **Parciales no promueven a `passed`.**
|
|
73
|
+
- Algo ✗ → `status: failed` con los hallazgos bloqueantes; el humano los corrige **como un slice normal**
|
|
74
|
+
(`/build:slice` / `building-a-slice`) y se **re-corre** el Release Gate.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Guardrails
|
|
79
|
+
|
|
80
|
+
- **Es outer loop.** Correr reviewers pesados **por slice** rompería el modelo de dos loops — aquí corren una
|
|
81
|
+
vez por release (`O(releases)`).
|
|
82
|
+
- **No dupliques el inner loop**: no se hace TDD ni se cierran gates por slice.
|
|
83
|
+
- **`integration` con deps reales es obligatorio**; no se acepta con todo stubbeado.
|
|
84
|
+
- Delega en `releasing-a-version`; **no** la reimplementa. Si algo contradice `METODOLOGIA.md`, gana la metodología.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "BUILD: Slice"
|
|
3
|
+
description: Punto de entrada del inner loop. Abre o continúa un slice (épica EP-XXX) y conduce el pipeline DoR → change → TDD → smoke → api/data → dod → PR+archive delegando en la skill building-a-slice (o el agente build-orchestrator para épicas multicapa). Respeta el orden estricto de gates y el scaffold como precondición.
|
|
4
|
+
category: Workflow
|
|
5
|
+
tags: [build-harness, inner-loop, slice, trycore]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Lanza el **inner loop** de construcción sobre una épica. Este comando es un **adaptador delgado**: no
|
|
9
|
+
reimplementa el pipeline — **delega** en la skill `building-a-slice` (motor del inner loop) y en `opsx:*`
|
|
10
|
+
(motor de changes). Si algo aquí contradice `METODOLOGIA.md`, **gana la metodología**.
|
|
11
|
+
|
|
12
|
+
**Entrada:** `EP-XXX` o una descripción de la épica. Si viene vacío, usa **AskUserQuestion** para elegir la
|
|
13
|
+
épica desde `docs/03-backlog/epicas.md`.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. Preflight
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
test -f .claude/.build-harness-version || echo "NOT_INSTALLED"
|
|
21
|
+
command -v python3 >/dev/null 2>&1 || echo "NO_PYTHON3"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Si `NOT_INSTALLED`:** este proyecto no tiene el arnés instalado → ejecuta `trycore-build init` y vuelve.
|
|
25
|
+
Stop si no está instalado o falta `python3`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Leer el estado y decidir punto de entrada
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python3 - <<'PY'
|
|
33
|
+
import json, os, sys
|
|
34
|
+
p = ".claude/state/build-state.json"
|
|
35
|
+
if not os.path.exists(p): print("NO_STATE"); sys.exit(0)
|
|
36
|
+
try: d = json.load(open(p))
|
|
37
|
+
except Exception as e: print("CORRUPT_STATE", e); sys.exit(0)
|
|
38
|
+
s = d.get("active_slice")
|
|
39
|
+
if not s:
|
|
40
|
+
print("START dor")
|
|
41
|
+
else:
|
|
42
|
+
g = s.get("gates", {})
|
|
43
|
+
abierto = next((k for k, v in g.items() if v is False), None)
|
|
44
|
+
print(f"RESUME {s.get('epica')} fase={s.get('phase')} primer_gate_abierto={abierto}")
|
|
45
|
+
PY
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- `NO_STATE`/`CORRUPT_STATE` → reporta y detente (no escribas).
|
|
49
|
+
- `START dor` → no hay slice activo: arranca en **dor** con la épica objetivo.
|
|
50
|
+
- `RESUME …` → ya hay un slice activo: **reanuda en su primer gate abierto** (no abras otro: el modelo es
|
|
51
|
+
secuencial, un solo slice activo).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 3. Precondición de scaffold (y fuente de diseño si hay UI)
|
|
56
|
+
|
|
57
|
+
Antes de escribir código de slice, verifica los gates de proyecto:
|
|
58
|
+
|
|
59
|
+
- `scaffold.confirmed` debe ser `true`. Si es `false` → **STOP**: delega en la **Fase 0** de `building-a-slice`
|
|
60
|
+
(pregunta explícita; el arnés **no genera** el scaffold). No abras el slice.
|
|
61
|
+
- Si el proyecto tiene UI, `design_source.confirmed` debe ser `true` (Fase 0-bis). Si no → **STOP** igual.
|
|
62
|
+
|
|
63
|
+
El hook `scaffold-guard.sh` respalda esto en tiempo real.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 4. Conducir el pipeline (delegar)
|
|
68
|
+
|
|
69
|
+
Invoca la skill **`building-a-slice`** para conducir el inner loop. Para una épica **multicapa / grande**
|
|
70
|
+
(superó el gate de tamaño → `sub_slices[]`), invoca el agente **`build-orchestrator`** (trabaja por fases
|
|
71
|
+
encadenadas y, opcionalmente, conduce la exploración solo-lectura con `workflows/explore-fanout.workflow.js`).
|
|
72
|
+
|
|
73
|
+
- **No** ejecutes `opsx:apply` directamente ni saltes gates: el orden es estricto
|
|
74
|
+
(`dor → change → tdd → smoke → api/data → dod → pr`).
|
|
75
|
+
- **No** dispares reviewers pesados aquí (`security`, `smell`, `ux`, `coherence`, `stack_arch`): pertenecen
|
|
76
|
+
al **Release Gate** (`/build:release`). Hacerlo por slice rompería el modelo de dos loops.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 5. Resumen
|
|
81
|
+
|
|
82
|
+
Al terminar el paso, resume: fase actual, gates cerrados/abiertos y el siguiente gate. Si la épica quedó
|
|
83
|
+
archivada, recuerda el default del Release Gate (ver `/build:release`).
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Guardrails
|
|
88
|
+
|
|
89
|
+
- **Un solo slice activo** (secuencial). No abras un segundo mientras haya `active_slice`.
|
|
90
|
+
- **Orden estricto de gates**; un gate no se salta. `dod` exige `wiring_verified: true`.
|
|
91
|
+
- **Sin scaffold confirmado, no hay slice** (el arnés lo exige pero no lo genera).
|
|
92
|
+
- **Agnóstico**: este comando no asume dominio; lo específico entra por `/build:onboard` y `stack-allowlist.json`.
|
|
93
|
+
- Si algo contradice `METODOLOGIA.md`, **gana la metodología**.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "BUILD: Work"
|
|
3
|
+
description: Router de entrada (classify-and-act) del arnés. Clasifica el trabajo entrante y enruta a la skill correcta — building-a-micro-change (mantenimiento), building-a-slice (épica/producto nuevo) o releasing-a-version (Release Gate) — codificando los límites duros del micro-change y el default del Release Gate. Es RUTEO, no política: no ejecuta el pipeline, no toca el estado ni crea ramas.
|
|
4
|
+
category: Workflow
|
|
5
|
+
tags: [build-harness, router, classify-and-act, trycore]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
**Router puro.** Decide *qué carril* aplica y **delega** en la skill correspondiente. NO ejecuta el pipeline,
|
|
9
|
+
NO escribe `build-state.json`, NO crea ramas. Codifica como **ruteo** (no política nueva) el *decision gate*
|
|
10
|
+
del micro-change y el default del Release Gate de `METODOLOGIA.md` (§2, §4). Si algo contradice la metodología,
|
|
11
|
+
**gana la metodología**.
|
|
12
|
+
|
|
13
|
+
**Entrada:** una descripción del trabajo a hacer.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. Preflight
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
test -f .claude/.build-harness-version || echo "NOT_INSTALLED"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Si `NOT_INSTALLED` → ejecuta `trycore-build init` y vuelve.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Clasificar (decision gate)
|
|
28
|
+
|
|
29
|
+
Aplica las reglas en orden:
|
|
30
|
+
|
|
31
|
+
1. **¿Mantenimiento sin capacidad nueva?** — typo, ajuste de copy/config/docs, bump de dependencia **ya
|
|
32
|
+
permitida**, o fix de **pocas líneas** sin nueva capacidad **Y** sin ninguno de los límites duros del
|
|
33
|
+
paso 3 → carril **`building-a-micro-change`** (`fix/*`|`chore/*` → PR, **sin** abrir `active_slice`).
|
|
34
|
+
2. **¿Producto nuevo / una épica?** — capacidad nueva, o cualquier límite duro cruzado → carril
|
|
35
|
+
**`building-a-slice`** (una épica `EP-XXX` = un slice = un change = una rama = un PR). Si no hay épica aún,
|
|
36
|
+
el trabajo vuelve a discovery para crearla.
|
|
37
|
+
3. **¿Toca correr el Release Gate?** — la épica recién archivada **cierra una línea de release** del Story Map,
|
|
38
|
+
o hay **≥ 2 épicas archivadas** desde el último entry de `releases[]` → sugiere el carril
|
|
39
|
+
**`releasing-a-version`** (outer loop). (El destino es la skill existente; este router no depende de
|
|
40
|
+
`/build:release`.)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. Límites duros del micro-change (escalan a épica)
|
|
45
|
+
|
|
46
|
+
Si el cambio **añade una dependencia nueva**, **crea un endpoint/API nuevo**, o **toca lógica de dominio o el
|
|
47
|
+
modelo/invariantes de datos** → **deja de ser micro-change** y se enruta a **`building-a-slice`** (épica).
|
|
48
|
+
**Ante la duda, SIEMPRE épica.**
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 4. Actuar (delegar) — con degradación headless
|
|
53
|
+
|
|
54
|
+
- **Con TTY**: confirma la clasificación con **una sola** `AskUserQuestion` (ofrece el carril propuesto como
|
|
55
|
+
primera opción "(Recomendado)") y luego invoca la skill elegida.
|
|
56
|
+
- **Sin TTY / headless / entrada ausente**: **no bloquees**. Clasifica determinísticamente y emite por stdout
|
|
57
|
+
`{clasificación, skill recomendada, criterio que disparó la rama}`. Si es **ambiguo**, aplica el **default
|
|
58
|
+
duro**: escalar a épica → `building-a-slice`, declarándolo explícitamente.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Guardrails
|
|
63
|
+
|
|
64
|
+
- **Solo ruteo.** No corres el pipeline, no tocas el estado, no creas ramas: eso es de las skills destino.
|
|
65
|
+
- **Ante la duda, épica.** Nunca degrades un cambio con límite duro a micro-change.
|
|
66
|
+
- **No dupliques gates** ni saltes el orden: las skills destino los gobiernan.
|
|
67
|
+
- **Agnóstico**: vocabulario genérico del arnés; lo específico del dominio entra por `/build:onboard`.
|
|
68
|
+
- Si algo contradice `METODOLOGIA.md`, **gana la metodología**.
|
package/docs/agents.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Agentes de construcción (`agents/build/`)
|
|
2
2
|
|
|
3
|
-
Los **
|
|
3
|
+
Los **12 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
|
|
7
7
|
(`.claude/state/build-state.json`).
|
|
8
8
|
|
|
9
9
|
> **Cadencia.** El `build-orchestrator` y `dor-dod-gatekeeper`, junto con
|
|
10
|
-
> `change-epic-coherence`, `api-contract-tester
|
|
10
|
+
> `change-epic-coherence`, `api-contract-tester`, `data-consistency-checker`,
|
|
11
|
+
> `ux-fidelity-reviewer` y `wiring-adversarial-verifier`, corren en el
|
|
11
12
|
> **inner loop** (skill `building-a-slice`, por épica `EP-XXX`). Los 5 revisores pesados de
|
|
12
13
|
> release (`security-reviewer`, `simple-design-reviewer`, `ux-krug-reviewer`,
|
|
13
14
|
> `coherence-three-way`, `stack-guardian`) corren **una vez por release** en el **outer loop**
|
|
@@ -27,7 +28,8 @@ veredicto al `build-orchestrator`**, que es quien propone la escritura del estad
|
|
|
27
28
|
| 8 | `api-contract-tester` | sonnet | Contrato / datos | Gate `api` — pruebas de contrato (Newman/Postman) |
|
|
28
29
|
| 9 | `data-consistency-checker` | sonnet | Contrato / datos | Gate `data` — invariantes y consistencia de datos |
|
|
29
30
|
| 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 |
|
|
31
|
+
| 11 | `ux-fidelity-reviewer` | sonnet | Inner loop · smoke | Gate `fidelity` — fidelidad visual a la fuente de diseño declarada (verificación visual real, MCP) |
|
|
32
|
+
| 12 | `wiring-adversarial-verifier` | **opus** | Inner loop · dod | Gate `wiring_verified` — verificación adversarial independiente del cableado (refuta antes de cerrar `dod`) |
|
|
31
33
|
|
|
32
34
|
---
|
|
33
35
|
|
|
@@ -132,3 +134,24 @@ exista en `docs/04-historias/` con `epica:` coincidente, la coherencia de alcanc
|
|
|
132
134
|
`openspec validate <name> --type change --strict` pase; sugiere back-references. COHERENTE →
|
|
133
135
|
`gates.coherence_link: true`. Complementa a `coherence-three-way` validando el **enlace**
|
|
134
136
|
(este último valida la implementación real).
|
|
137
|
+
|
|
138
|
+
## Inner loop · fidelidad y cableado
|
|
139
|
+
|
|
140
|
+
### `ux-fidelity-reviewer` · modelo `sonnet` · lee el dominio
|
|
141
|
+
**Revisor de fidelidad visual** (gate `fidelity`), en la fase `smoke`. Comprueba que la pantalla
|
|
142
|
+
construida reproduce **composición, layout, paleta y tipografía** de la fuente de diseño declarada
|
|
143
|
+
(`DESIGN_SOURCE`). **Verificación visual real, requerida para UI**: con la app corriendo usa un MCP de
|
|
144
|
+
devtools de navegador (chrome-devtools) — `take_screenshot` app vs prototipo + `take_snapshot` de
|
|
145
|
+
estructura. Sin MCP el veredicto es INCONCLUSO, que para UI mapea a `gates.fidelity: false` (bloquea el
|
|
146
|
+
`dod`): hay que correr el slice donde el MCP esté disponible. No juzga usabilidad (eso es
|
|
147
|
+
`ux-krug-reviewer`, en el outer loop).
|
|
148
|
+
|
|
149
|
+
### `wiring-adversarial-verifier` · modelo `opus` · contexto virgen
|
|
150
|
+
**Verificador adversarial del cableado** (gate `wiring_verified`), al inicio de la fase `dod`. Llega
|
|
151
|
+
con contexto virgen e **independiente** del que construyó: su sesgo por defecto es "está incompleto" y
|
|
152
|
+
su trabajo es **refutar** el slice — cazar stubs, rutas sin cablear (endpoint sin invocar, cola sin
|
|
153
|
+
consumidor, componente sin enrutar), AC sin test real, puntos de integración entre capas no recorridos,
|
|
154
|
+
e items de `wiring_checklist[]` aún `failing` o marcados `passing` sin `evidence`. CABLEADO COMPLETO →
|
|
155
|
+
`gates.wiring_verified: true` (habilita `dod`); HUECOS → `false` (retrocede `phase`). Rompe la
|
|
156
|
+
auto-confirmación del cierre prematuro: el DoD declarativo del `dor-dod-gatekeeper` es un piso, este
|
|
157
|
+
agente es el arreglo.
|