@trycore/spec-build-harness 0.1.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.
Files changed (92) hide show
  1. package/.claude-plugin/marketplace.json +21 -0
  2. package/.claude-plugin/plugin.json +28 -0
  3. package/GOVERNANCE.md +48 -0
  4. package/INSTALL.md +295 -0
  5. package/METODOLOGIA.md +360 -0
  6. package/README.md +130 -0
  7. package/VERSION +1 -0
  8. package/agents/build/api-contract-tester.md +32 -0
  9. package/agents/build/build-orchestrator.md +50 -0
  10. package/agents/build/change-epic-coherence.md +41 -0
  11. package/agents/build/coherence-three-way.md +35 -0
  12. package/agents/build/data-consistency-checker.md +48 -0
  13. package/agents/build/dor-dod-gatekeeper.md +46 -0
  14. package/agents/build/security-reviewer.md +46 -0
  15. package/agents/build/simple-design-reviewer.md +33 -0
  16. package/agents/build/stack-guardian.md +41 -0
  17. package/agents/build/ux-krug-reviewer.md +33 -0
  18. package/commands/build/onboard.md +136 -0
  19. package/commands/opsx/apply.md +152 -0
  20. package/commands/opsx/archive.md +157 -0
  21. package/commands/opsx/bulk-archive.md +242 -0
  22. package/commands/opsx/continue.md +114 -0
  23. package/commands/opsx/explore.md +174 -0
  24. package/commands/opsx/ff.md +94 -0
  25. package/commands/opsx/new.md +69 -0
  26. package/commands/opsx/onboard.md +525 -0
  27. package/commands/opsx/sync.md +134 -0
  28. package/commands/opsx/verify.md +164 -0
  29. package/config/stack-allowlist.template.json +12 -0
  30. package/dist/cli.js +105 -0
  31. package/dist/commands/doctor.js +77 -0
  32. package/dist/commands/init.js +129 -0
  33. package/dist/commands/status.js +59 -0
  34. package/dist/commands/uninstall.js +52 -0
  35. package/dist/commands/update.js +11 -0
  36. package/dist/lib/install-engine.js +99 -0
  37. package/dist/lib/markers.js +81 -0
  38. package/dist/lib/paths.js +65 -0
  39. package/dist/lib/settings-merge.js +125 -0
  40. package/dist/lib/stack-prompt.js +69 -0
  41. package/dist/lib/state-seed.js +59 -0
  42. package/docs/agents.md +133 -0
  43. package/docs/commands.md +128 -0
  44. package/docs/customization/mcp-extensions.md +117 -0
  45. package/docs/examples/reference/data-consistency.example.md +61 -0
  46. package/docs/examples/reference/security-foco.example.md +39 -0
  47. package/docs/examples/reference/stack-allowlist.example.json +61 -0
  48. package/docs/getting-started.md +260 -0
  49. package/docs/hooks.md +143 -0
  50. package/hooks/build/build-gate-check.sh +24 -0
  51. package/hooks/build/coherence-flag.sh +23 -0
  52. package/hooks/build/gitflow-guard.sh +65 -0
  53. package/hooks/build/lint-typecheck.sh +33 -0
  54. package/hooks/build/load-build-state.sh +46 -0
  55. package/hooks/build/stack-guard.sh +63 -0
  56. package/hooks/build-harness.json +61 -0
  57. package/internal/skills/auditar-arnes/SKILL.md +29 -0
  58. package/package.json +67 -0
  59. package/scripts/check-agnostic.sh +81 -0
  60. package/scripts/check-state-clean.sh +48 -0
  61. package/scripts/check-version-sync.sh +51 -0
  62. package/scripts/denylist.txt +30 -0
  63. package/skills/building-a-slice/SKILL.md +82 -0
  64. package/skills/building-a-slice/references/data-consistency.md +34 -0
  65. package/skills/building-a-slice/references/dod.md +25 -0
  66. package/skills/building-a-slice/references/dor.md +17 -0
  67. package/skills/building-a-slice/references/gitflow.md +30 -0
  68. package/skills/building-a-slice/references/krug-ux.md +27 -0
  69. package/skills/building-a-slice/references/link-change-epic.md +34 -0
  70. package/skills/building-a-slice/references/mcp-map.md +29 -0
  71. package/skills/building-a-slice/references/newman-tests.md +47 -0
  72. package/skills/building-a-slice/references/simple-design.md +33 -0
  73. package/skills/building-a-slice/references/state-protocol.md +48 -0
  74. package/skills/openspec-apply-change/SKILL.md +156 -0
  75. package/skills/openspec-archive-change/SKILL.md +114 -0
  76. package/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  77. package/skills/openspec-continue-change/SKILL.md +118 -0
  78. package/skills/openspec-explore/SKILL.md +290 -0
  79. package/skills/openspec-ff-change/SKILL.md +101 -0
  80. package/skills/openspec-new-change/SKILL.md +74 -0
  81. package/skills/openspec-onboard/SKILL.md +529 -0
  82. package/skills/openspec-sync-specs/SKILL.md +138 -0
  83. package/skills/openspec-verify-change/SKILL.md +168 -0
  84. package/skills/releasing-a-version/SKILL.md +56 -0
  85. package/skills/releasing-a-version/references/release-dod.md +20 -0
  86. package/state/README.md +56 -0
  87. package/state/build-state.schema.json +111 -0
  88. package/state/build-state.template.json +7 -0
  89. package/templates/CLAUDE.md.template +57 -0
  90. package/templates/newman.collection.template.json +28 -0
  91. package/templates/settings-hooks.template.json +25 -0
  92. package/templates/waivers/WAIVER.template.md +27 -0
package/METODOLOGIA.md ADDED
@@ -0,0 +1,360 @@
1
+ # METODOLOGIA.md — Arnés de construcción Trycore (`@trycore/spec-build-harness`)
2
+
3
+ > **Fuente de verdad metodológica.** Este documento es la metodología canónica del arnés de
4
+ > construcción. Si una skill, un agente, una reference o un hook contradice lo escrito aquí, **gana
5
+ > la metodología**. (Es la misma regla dura que fija el bloque `<!-- BEGIN trycore-build-harness -->`
6
+ > del `CLAUDE.md` del consumidor.)
7
+ >
8
+ > El arnés es **agnóstico al proyecto**: el core no asume dominio, stack ni framework. Lo que es
9
+ > específico del consumidor (stack, PII, capa de servicios externos, capa de decisión determinista,
10
+ > secretos, decisiones de alto impacto) se inyecta vía `/build:onboard` y `stack-allowlist.json`. El
11
+ > ejemplo de referencia vive aparte en `docs/examples/reference/` y no forma parte del core.
12
+
13
+ ---
14
+
15
+ ## 0. Qué es y dónde encaja
16
+
17
+ `@trycore/spec-build-harness` (CLI `trycore-build`, plugin `trycore-spec-build-harness`, marketplace
18
+ `trycore-build`) es el **compañero de construcción** de `@trycore/spec-product-flow` (la vertical de
19
+ discovery). El flujo completo de extremo a extremo es:
20
+
21
+ ```
22
+ DISCOVERY (@trycore/spec-product-flow) CONSTRUCCIÓN (@trycore/spec-build-harness)
23
+ PRD → User Story Map → Backlog → Historias → por épica: DoR → change → TDD → smoke → api/data → DoD → PR
24
+ (AC G/W/T) → Priorización → Flows por release: Release Gate (seguridad/diseño/UX/coherencia/arquitectura/integración)
25
+ ```
26
+
27
+ Ambos paquetes **coexisten en el mismo `.claude/` sin colisión**, con namespaces disjuntos:
28
+
29
+ | Eje | Discovery (`spec-product-flow`) | Construcción (`spec-build-harness`) |
30
+ |---|---|---|
31
+ | Comandos | `trycore/` (`/trycore:*`) | `opsx/` + `build/` (`/opsx:*`, `/build:onboard`) |
32
+ | Sentinela de versión | `.trycore-version` | `.build-harness-version` |
33
+ | Bloque en `CLAUDE.md` | `<!-- BEGIN trycore-vertical -->` | `<!-- BEGIN trycore-build-harness -->` |
34
+
35
+ El puente entre los dos mundos es la **trazabilidad**: la construcción consume los artefactos de
36
+ `docs/` (épicas, HU con AC en Given/When/Then, líneas de release del Story Map) y los enlaza a los
37
+ OpenSpec changes en `openspec/`.
38
+
39
+ ---
40
+
41
+ ## 1. El modelo de dos loops (y por qué)
42
+
43
+ El arnés organiza el trabajo en **dos loops anidados** con costos deliberadamente distintos:
44
+
45
+ | | **Inner loop** | **Outer loop** |
46
+ |---|---|---|
47
+ | Skill | `building-a-slice` | `releasing-a-version` |
48
+ | Unidad | una **épica** (`EP-XXX`) | una **línea de release** del Story Map |
49
+ | Cadencia | muchas veces (una por épica) | pocas veces (una por release) |
50
+ | Costo | barato y rápido (objetivo ≤ ~20 min/épica) | pesado (subagentes profundos sobre el diff acumulado) |
51
+ | Qué hace | DoR → change → TDD → smoke → api/data → DoD → PR+archive | gates de seguridad, diseño, UX, coherencia triple, arquitectura, integración |
52
+ | Estado | `active_slice` + `history[]` | `releases[]` |
53
+
54
+ **Por qué partirlo así.** Las revisiones profundas (seguridad, diseño/smell, UX/Krug, coherencia
55
+ triple AC↔change↔código, arquitectura, integración con dependencias reales) son caras en contexto y
56
+ en tiempo. Si se corrieran **por épica**, su costo sería `O(épicas)` y el inner loop dejaría de ser
57
+ rápido. Al moverlas al **Release Gate** —una sola pasada sobre el diff acumulado de todas las épicas
58
+ de la release— el costo de los agentes pesados pasa a `O(releases)`. El inner loop queda libre para
59
+ ser veloz: solo cierra gates baratos y mantiene el producto caminando.
60
+
61
+ **Regla de no duplicación.** El outer loop **no** repite el inner loop: no hace TDD ni cierra gates
62
+ por slice. Y el inner loop **no** dispara reviewers pesados. Cada gate vive en exactamente un loop.
63
+
64
+ ---
65
+
66
+ ## 2. La regla del "esqueleto que camina"
67
+
68
+ El arnés prohíbe construir capas horizontales aisladas que "se juntan al final" (el anti-patrón que
69
+ hace que todos los gates por-slice estén en verde y el producto aun así no funcione de punta a
70
+ punta). En su lugar:
71
+
72
+ - El **primer slice** de una release construye el **journey completo más delgado posible**: de la
73
+ primera a la última actividad del *backbone* del Story Map, aunque cada paso sea un *stub*.
74
+ - **Cada épica posterior engorda un paso** de ese esqueleto y debe mantener el `journey_smoke`
75
+ **verde**. El esqueleto que camina nunca deja de caminar.
76
+ - El gate `journey_smoke` (inner loop) recorre el *backbone-hasta-aquí* end-to-end en cada épica; el
77
+ gate `integration` (outer loop) recorre el journey completo de la release con **dependencias
78
+ reales**, no stubs.
79
+
80
+ Consecuencia operativa: **la unidad de construcción es la épica, no la HU suelta**. Un slice = una
81
+ épica = un OpenSpec change = una rama = un PR. Las HU que cubre la épica son su *alcance interno* y
82
+ se listan en `active_slice.hus[]`. Construir por HU individual es sobre-ingeniería.
83
+
84
+ ---
85
+
86
+ ## 3. Pipeline del inner loop, fase por fase (con sus gates)
87
+
88
+ Lo conduce la skill `building-a-slice` (opcionalmente vía el agente `build-orchestrator`). Es
89
+ **secuencial** (un slice activo a la vez), con **divulgación progresiva** (cada fase carga solo su
90
+ reference). Un gate no se salta.
91
+
92
+ | # | Fase (`phase`) | Acción | Delega en | Gate que cierra | Reference |
93
+ |---|---|---|---|---|---|
94
+ | 1 | `dor` | Validar Definition of Ready de la épica y sus HU | `dor-dod-gatekeeper` | `dor` | `dor.md` |
95
+ | 2 | `change` | `opsx:new` + bloque `## Trazabilidad`; validar enlace (barato) | `opsx:new`, `change-epic-coherence` | `coherence_link` | `link-change-epic.md` |
96
+ | 3 | `red`→`green`→`refactor` | TDD por cada escenario AC (G/W/T) de cada HU | `superpowers:test-driven-development` | `tdd` | — |
97
+ | 4 | `smoke` | Recorrer el journey-hasta-aquí end-to-end | skill `verify`/`run` (+ MCP chrome-devtools) | `journey_smoke` | `mcp-map.md` |
98
+ | 5 | `api`/`data` | Contratos de endpoints + invariantes de datos (si aplican) | `api-contract-tester`, `data-consistency-checker` | `api`, `data` | `newman-tests.md`, `data-consistency.md` |
99
+ | 6 | `dod` | Definition of Done reducido (lee los gates del estado) | `dor-dod-gatekeeper` | `dod` | `dod.md` |
100
+ | 7 | `pr` | Abrir PR + **archivar el change en el mismo PR** | `opsx:archive`, `opsx:sync` | — | `gitflow.md` |
101
+ | 8 | (decisión) | ¿Correr el Release Gate ahora? (default computado, decide el humano) | usuario | — | §4 |
102
+
103
+ ### 3.1 Definition of Ready (gate `dor`)
104
+
105
+ Una épica **no entra a construcción** hasta cumplir todo (lo valida `dor-dod-gatekeeper`):
106
+
107
+ - Épica `EP-XXX` existe en `docs/03-backlog/epicas.md` con trazabilidad a objetivos del PRD.
108
+ - La épica tiene ≥1 HU; todas las que entran se listan en `hus[]`.
109
+ - Frontmatter completo en cada `docs/04-historias/HU-XXX.md` (`id, titulo, epica, prioridad,
110
+ complejidad, estado`) con `estado: lista`.
111
+ - AC en Given/When/Then por HU: 3–5 escenarios con happy + error + edge.
112
+ - Cada HU pasa los 6 criterios **INVEST**.
113
+ - Dependencias resueltas (las épicas/HU de las que depende están en `history[]` o no bloquean).
114
+ - Cabe en el stack del PRD (no requiere tecnología fuera de `stack-allowlist.json`).
115
+ - Datos de prueba disponibles o identificables (fixtures sintéticos del dominio).
116
+
117
+ Si todo ✓ → se abre `active_slice` con `phase: dor`, `gates.dor: true` y el resto en `false`
118
+ (`ux`/`api` en `null` si la épica no toca UI/endpoints). Si algo ✗ → no se abre el slice; se reporta
119
+ qué falta y se vuelve a discovery.
120
+
121
+ ### 3.2 Definition of Done reducido (gate `dod`)
122
+
123
+ El slice **no se archiva ni se mergea** hasta cumplir todo. Es el DoD **reducido** del inner loop;
124
+ las revisiones pesadas **no** se piden aquí (van al Release Gate):
125
+
126
+ - `tdd` — cada escenario AC de cada HU tiene test; ciclo red→green→refactor completo; suite verde.
127
+ - `journey_smoke` — la app arranca y el backbone-hasta-aquí se recorre end-to-end sin romperse.
128
+ - `coherence_link` — `change-epic-coherence` confirma el enlace change↔épica (chequeo **barato**;
129
+ la trazabilidad triple completa va al Release Gate).
130
+ - `data` — invariantes de datos validadas (si el slice toca datos).
131
+ - `api` — Newman 100% verde (o `null` si el slice no tiene endpoints).
132
+ - OpenSpec: todas las tasks `[x]`; el archive del change va **en el mismo PR**.
133
+ - Back-reference del change añadida en la épica y en cada HU de `hus[]`.
134
+ - Hooks verdes (automáticos, **no** son gates de agente): `lint-typecheck.sh`, `stack-guard.sh`,
135
+ `gitflow-guard.sh`.
136
+
137
+ Lo que **no** se valida aquí y sube al Release Gate: `security`, `smell`, `ux`, `coherence`
138
+ (triple completa) y `stack_arch` (arquitectura). Las **dependencias** sí se vigilan por slice, pero
139
+ vía el hook `stack-guard.sh` en tiempo real, no vía subagente.
140
+
141
+ ### 3.3 Gates por slice y su naturaleza N/A
142
+
143
+ - `ux` y `api` admiten `null` cuando el slice no tiene UI o endpoints. `null` ≠ abierto: **no
144
+ bloquea** el DoD.
145
+ - En `harness_phase: authoring` (sin `package.json`) se puede hacer `dor` + `change`, pero los gates
146
+ de código (`tdd`, `journey_smoke`, `api`, `data`) **no se cierran** hasta scaffoldear.
147
+
148
+ ---
149
+
150
+ ## 4. Decisión de Release Gate (fase 8 del inner loop)
151
+
152
+ Tras archivar la épica, `building-a-slice` **pregunta al humano** si correr el Release Gate, con un
153
+ **default calculado** desde las líneas de release del Story Map (`docs/02-user-story-map/`):
154
+
155
+ - Si la épica **cierra una línea de release** (todas las épicas de esa línea ya están en
156
+ `history[]`) → default **"Sí, correr `releasing-a-version` ahora"**.
157
+ - Si no la cierra → default **"Continuar a la siguiente épica"**. *Nudge*: si hay **≥ 2 épicas**
158
+ archivadas desde el último entry de `releases[]`, se recomienda correrlo igual.
159
+
160
+ El humano siempre puede sobreescribir el default. Si acepta, se invoca `releasing-a-version` sobre la
161
+ release correspondiente.
162
+
163
+ ---
164
+
165
+ ## 5. Los gates del Release Gate (outer loop)
166
+
167
+ Lo conduce la skill `releasing-a-version`. Una **release** es una línea de release del Story Map
168
+ (p.ej. `R1-mvp` = un conjunto de épicas). El alcance es el **diff acumulado** de todas sus épicas:
169
+ desde el merge anterior a la primera épica de la release hasta `main`. Los subagentes se disparan **en
170
+ paralelo** y devuelven síntesis (protegen el contexto). Resultado en `releases[]`.
171
+
172
+ | Gate | Qué se exige | Delega en |
173
+ |---|---|---|
174
+ | `security` | Sin hallazgos CRÍTICO/ALTO; claves de servicios externos solo server-side; PII/datos regulados (según el PRD) no persistidos crudos; salida de servicios externos/IA tratada como input no confiable y validada contra esquema | `security-reviewer` |
175
+ | `smell` | 4 reglas de Beck + code smells sin bloqueantes sobre el diff acumulado | `simple-design-reviewer` |
176
+ | `ux` | Krug + Lighthouse sobre la UI ensamblada de la release (o `null` si sin UI) | `ux-krug-reviewer` |
177
+ | `coherence` | Trazabilidad triple AC↔change↔código de **todas** las HU de **todas** las épicas de la release, sin huérfanos | `coherence-three-way` (opus) |
178
+ | `stack_arch` | Arquitectura del PRD: capa de servicios externos/IA en la frontera declarada server-side (no decide); capa de decisión determinista del dominio sin IA; sin claves en cliente | `stack-guardian` |
179
+ | `integration` | El **journey completo** de la release se recorre end-to-end con **dependencias reales** del proyecto, **no stubs** | skill `verify`/`run` (+ MCP chrome-devtools) |
180
+
181
+ **Protocolo de la release:**
182
+
183
+ 1. Identificar la release y sus épicas (cruzar con `docs/02-user-story-map/`).
184
+ 2. Crear/actualizar la entrada en `releases[]` con `status: pending`.
185
+ 3. Disparar los subagentes en paralelo sobre el diff acumulado.
186
+ 4. Correr el gate `integration` con deps reales.
187
+ 5. Todos los gates ✓ (o `null` cuando N/A) → `status: passed`, escribir `gates` y `updated_by:
188
+ releasing-a-version`. Algo ✗ → `status: failed` con los hallazgos bloqueantes; el humano los
189
+ corrige como un slice normal (fix en `building-a-slice`) y se **re-corre** el Release Gate.
190
+
191
+ > **`integration` es el gate no negociable del arnés.** Es el que faltaba en la era previa: todos los
192
+ > gates por-slice estaban en verde y aun así el producto "no caminaba" de punta a punta. Sin
193
+ > `integration` con dependencias reales **no hay release**. No se acepta con todo stubbeado.
194
+
195
+ ---
196
+
197
+ ## 6. Contrato de trazabilidad change ↔ épica
198
+
199
+ Cada OpenSpec change corresponde a **exactamente una épica** (la unidad de construcción) y declara
200
+ las HU que cubre. El enlace vive en el **cuerpo markdown** del `openspec/changes/<name>/proposal.md`,
201
+ en una sección al final:
202
+
203
+ ```markdown
204
+ ## Trazabilidad
205
+ - Épica: EP-003
206
+ - Historias: HU-010, HU-011, HU-012
207
+ - Discovery: docs/03-backlog/epicas.md#ep-003
208
+ ```
209
+
210
+ **Regla dura: el enlace va en el cuerpo markdown, NUNCA en frontmatter YAML.** OpenSpec valida la
211
+ estructura del change con `openspec validate --strict` y un frontmatter ajeno la rompe. El bloque
212
+ markdown es seguro.
213
+
214
+ Reglas del contrato (las verifica `change-epic-coherence`, gate `coherence_link`):
215
+
216
+ 1. **Una épica por change.** Un change no cruza épicas; si necesitas dos épicas, son dos slices.
217
+ 2. **Las HU de esa épica** que entran en alcance: la lista de `Historias:` debe **igualar** a
218
+ `hus[]`; cada `HU-XXX` debe existir y su `epica:` coincidir con la EP.
219
+ 3. **Nombre del change** en kebab-case basado en la épica (p.ej. `ep-003-pricing-engine`).
220
+ 4. **Back-reference bidireccional**: al archivar, se añade `> OpenSpec change: ep-003-pricing-engine`
221
+ en la épica (`docs/03-backlog/epicas.md`) y en cada HU de `hus[]`. Esto cierra el enlace
222
+ Trycore↔OpenSpec en ambos sentidos.
223
+
224
+ Validación: `openspec validate "<name>" --type change --strict --json`.
225
+
226
+ ---
227
+
228
+ ## 7. Protocolo de `build-state.json`
229
+
230
+ `.claude/state/build-state.json` es la **única fuente de verdad** y el medio por el que los agentes
231
+ se sincronizan en modo **secuencial**. Cada gate del pipeline transiciona el estado; el siguiente
232
+ agente lo lee antes de actuar. Estructura: `version`, `harness_phase`, `active_slice`, `history[]`,
233
+ `releases[]` (esquema en `state/build-state.schema.json`, draft 2020-12).
234
+
235
+ **Reglas del protocolo:**
236
+
237
+ 1. **Leer antes de actuar.** Todo agente lee `active_slice` y `gates` antes de trabajar. Si
238
+ `active_slice` es `null`, no hay slice → **solo `dor-dod-gatekeeper`** puede abrir uno.
239
+ 2. **Una transición = una escritura.** Quien completa una fase actualiza `phase`, su gate,
240
+ `updated_at` (ISO 8601 UTC) y `updated_by` (su nombre). No toca otros campos. Patrón
241
+ lee-modifica-escribe con `python3`.
242
+ 3. **Gates monótonos hacia adelante.** Un gate solo pasa de `false`→`true` cuando su agente lo
243
+ aprueba. Si una revisión posterior falla, **se vuelve a `false` y `phase` retrocede** (el retroceso
244
+ está permitido y es la forma de manejar fallos tardíos).
245
+ 4. **`null` para N/A.** `ux`/`api` son `null` cuando el slice no tiene UI/endpoints; no cuentan como
246
+ abiertos para el DoD.
247
+ 5. **Archivar.** Al completar `opsx:archive`, mover `active_slice` a `history[]` con
248
+ `phase: "archived"` y dejar `active_slice: null`.
249
+ 6. **Validar tras escribir** contra el schema (con `jsonschema`/`python3`).
250
+
251
+ **Quién escribe qué:**
252
+
253
+ | Campo / gate | Lo escribe | Cadencia |
254
+ |---|---|---|
255
+ | `active_slice` (alta) · `gates.dor` · `gates.dod` | `dor-dod-gatekeeper` | slice |
256
+ | `gates.coherence_link` | `change-epic-coherence` | slice |
257
+ | `gates.tdd` | flujo `superpowers:test-driven-development` (vía `build-orchestrator`) | slice |
258
+ | `gates.journey_smoke` · `phase` (transiciones) · `history[]` | `build-orchestrator` | slice |
259
+ | `gates.api` | `api-contract-tester` | slice |
260
+ | `gates.data` | `data-consistency-checker` | slice |
261
+ | `releases[]` (security, smell, ux, coherence, stack_arch, integration, status) | `releasing-a-version` (delega en los reviewers) | release |
262
+ | `harness_phase` | `load-build-state.sh` (SessionStart) | — |
263
+
264
+ **Régimen de fases (`harness_phase`):** arranca en `authoring`; `load-build-state.sh` lo cambia a
265
+ `active` al detectar `package.json` en la raíz. En `authoring`, los hooks de código están armados
266
+ pero inertes (`[ -f package.json ] || exit 0`) y empiezan a disparar solos al aparecer el scaffold,
267
+ sin intervención manual.
268
+
269
+ **Ciclo de fases del inner loop:**
270
+
271
+ ```
272
+ dor → change → red → green → refactor → smoke → api → data → dod → pr → archived
273
+ ```
274
+
275
+ **Versionado del estado.** `build-state.json` se siembra **vacío** y **nunca se sobreescribe** (está
276
+ en `.gitignore`: es working state). El **schema** y el **README** sí se versionan. El
277
+ `stack-allowlist.json` es artefacto del consumidor (lo siembra el CLI, lo puebla `/build:onboard`).
278
+ `uninstall` preserva `state/` y `config/`.
279
+
280
+ ---
281
+
282
+ ## 8. GitHub Flow estricto
283
+
284
+ Modelo de ramas **GitHub Flow** (no GitFlow clásico): **`main` siempre desplegable**, **sin
285
+ `develop` ni `release/*`**. Una sola línea estable + ramas cortas + integración solo por Pull
286
+ Request con checks verdes. Lo hace cumplir de forma determinista el hook `gitflow-guard.sh`.
287
+
288
+ Ciclo por slice:
289
+
290
+ ```bash
291
+ git switch main && git pull --ff-only
292
+ git switch -c feature/<slug> # rama tipada: feature/* | fix/* | chore/*
293
+ # ... TDD + gates (estado en build-state.json) ...
294
+ git add -A && git commit -m "feat: <mensaje>" # commit en la rama (nunca en main)
295
+ git push -u origin feature/<slug> # push de la rama (nunca a main)
296
+ gh pr create --base main --head feature/<slug> --fill # integración por PR
297
+ ```
298
+
299
+ Convenciones:
300
+
301
+ - **Una rama por épica** (= un slice): `feature/ep-003-pricing-engine`. Tipos: `feature/*` (valor
302
+ nuevo), `fix/*` (corrección), `chore/*` (infra/docs).
303
+ - **Conventional Commits** (`feat:`, `fix:`, `test:`, `refactor:`, `chore:`, `docs:`).
304
+ - **PR**: enlaza la épica, sus HU (`hus[]`) y el OpenSpec change; checks (lint, types, tests, Newman)
305
+ en verde antes de merge; squash recomendado; el archive del change va **en el mismo PR**.
306
+
307
+ `gitflow-guard.sh` bloquea: `git commit` en `main`/`master`, `git commit` desde rama no tipada, y
308
+ `git push` apuntando a `main`/`master`.
309
+
310
+ ---
311
+
312
+ ## 9. Integración con OpenSpec y con la discovery
313
+
314
+ ### 9.1 OpenSpec — el motor de cambios
315
+
316
+ El arnés **no reimplementa** la gestión de specs: la delega en **OpenSpec** (requisito duro;
317
+ instalar con `npm i -g @fission-ai/openspec`). Los comandos `/opsx:*` y las skills `openspec-*` son
318
+ adaptadores delgados sobre OpenSpec; la skill `building-a-slice` los **secuencia**, no los duplica.
319
+
320
+ - Fase `change` del inner loop → `opsx:new` crea el change y se le añade el bloque `## Trazabilidad`.
321
+ - Fase `pr` → `opsx:archive` archiva el change (en el mismo PR) y `opsx:sync` reconcilia los specs.
322
+ - Validación con `openspec validate --strict`; por eso la trazabilidad va en markdown, no en
323
+ frontmatter (§6).
324
+
325
+ ### 9.2 Discovery — el contrato con `@trycore/spec-product-flow`
326
+
327
+ La construcción **consume** los artefactos de discovery y los trata como entrada de solo lectura:
328
+
329
+ | Artefacto de discovery | Uso en construcción |
330
+ |---|---|
331
+ | `docs/03-backlog/epicas.md` (`EP-XXX`) | Unidad de construcción del slice; trazabilidad del change |
332
+ | `docs/04-historias/HU-XXX.md` (AC en G/W/T, INVEST, `estado: lista`) | Alcance interno del change (`hus[]`); base de los tests TDD |
333
+ | `docs/02-user-story-map/` (backbone + líneas de release) | Esqueleto que camina (§2); definición de release y default del Release Gate (§4) |
334
+ | PRD §7 / `stack-allowlist.json#source` | Stack permitido; arquitectura auditada en `stack_arch` |
335
+
336
+ El arnés **no escribe** en `docs/`; cuando una HU no cumple DoR, devuelve el trabajo a discovery
337
+ (`/trycore:*`). El único contacto de escritura cruzada es la **back-reference** del change en la
338
+ épica y las HU al archivar (§6.4).
339
+
340
+ ---
341
+
342
+ ## 10. Reglas duras (resumen)
343
+
344
+ 1. La **épica** es la unidad de construcción: un slice = una épica = un change = una rama = un PR.
345
+ Las HU son alcance interno (`hus[]`).
346
+ 2. El **esqueleto que camina** nunca deja de caminar: nada de capas horizontales que se juntan al
347
+ final; `journey_smoke` verde en cada épica.
348
+ 3. **Dos loops sin duplicación**: gates baratos por épica (inner), gates pesados una vez por release
349
+ (outer). Ningún gate vive en ambos.
350
+ 4. La trazabilidad change↔épica va en el **cuerpo markdown** de `proposal.md` (`## Trazabilidad`),
351
+ **nunca** en frontmatter YAML.
352
+ 5. `build-state.json`: leer antes de actuar; **una transición = una escritura**; gates **monótonos**
353
+ (retroceso solo ante fallo); solo `dor-dod-gatekeeper` abre un slice cuando no hay activo.
354
+ 6. **GitHub Flow estricto**: `main` desplegable, integración solo por PR; `gitflow-guard.sh` bloquea
355
+ commits/push directos.
356
+ 7. **`integration` con dependencias reales es obligatorio** para cerrar una release; sin él no hay
357
+ release.
358
+ 8. El core es **agnóstico**: lo específico del dominio se inyecta vía `/build:onboard` y
359
+ `stack-allowlist.json`; el ejemplo de referencia vive en `docs/examples/reference/`.
360
+ 9. Si una skill, agente o reference contradice este documento, **gana la metodología**.
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # @trycore/spec-build-harness
2
+
3
+ Arnés agéntico de **construcción** de Trycore para Claude Code: el compañero de `@trycore/spec-product-flow`. Donde la vertical de producto cierra el discovery (`PRD → backlog priorizado`), este arnés toma ese backlog y lo lleva a código mergeado con calidad gobernada. La narrativa completa es **Discovery → Construcción**:
4
+
5
+ ```
6
+ Discovery (@trycore/spec-product-flow) Construcción (este arnés)
7
+ PRD → User Story Map → Backlog → slice por épica (TDD + gates) → release gate
8
+ ```
9
+
10
+ Ambos paquetes coexisten en el mismo `.claude/` sin colisión: namespaces disjuntos (`trycore/` vs `build/` + `opsx/`), archivos de versión separados (`.trycore-version` vs `.build-harness-version`) y bloques distintos en `CLAUDE.md` (`<!-- BEGIN trycore-vertical -->` vs `<!-- BEGIN trycore-build-harness -->`). El núcleo es **100% agnóstico al proyecto**.
11
+
12
+ ## Cómo se usa (rápido)
13
+
14
+ ```bash
15
+ # 0) Requisito: OpenSpec (lo usan los comandos /opsx:* y las skills openspec-*)
16
+ npm install -g @fission-ai/openspec
17
+
18
+ # 1) Instalar el CLI global (una vez por máquina)
19
+ npm install -g @trycore/spec-build-harness
20
+
21
+ # 2) Instalar el arnés en un proyecto cliente (idempotente; siembra estado y allowlist)
22
+ cd /ruta/al/proyecto-cliente
23
+ trycore-build init
24
+
25
+ # 3) Abrir Claude Code y parametrizar (lee el PRD, resuelve los {{placeholders}})
26
+ /build:onboard
27
+ ```
28
+
29
+ `trycore-build init` captura el **stack mecánico** (lenguaje/deps, package manager, runtime, ruta del PRD) por flags o por prompt TTY, y siembra los archivos. Luego `/build:onboard` —ejecutado por Claude— lee el PRD, pregunta por PII / capa-IA / capa-determinista / secretos / decisiones de alto impacto vía `AskUserQuestion`, resuelve los `{{placeholders}}` del bloque `CLAUDE.md` y escribe la auto-memory. Es un onboarding en **dos capas** porque un binario Node no puede escribir la auto-memory de Claude.
30
+
31
+ ### Alternativa: instalar como plugin nativo de Claude Code (sin npm)
32
+
33
+ ```bash
34
+ /plugin marketplace add trycore-co/trycore-spec-build-harness
35
+ /plugin install trycore-spec-build-harness@trycore-build
36
+ ```
37
+
38
+ > **Caveat de canales (importante).** El canal **npm CLI es el canónico**: instala los comandos en `.claude/commands/{opsx,build}/`, que namespacean por subcarpeta → `/opsx:*` y `/build:onboard`, y referencia los agentes por su nombre. El canal **plugin** namespacea los componentes bajo el **nombre del plugin** (→ `/trycore-spec-build-harness:*`) por diseño de Claude Code; se ofrece como conveniencia a nivel usuario, pero las cross-references internas (skills que invocan `/opsx:*`, agentes por nombre) están escritas para el canal CLI. **Para operar dentro de un proyecto, usa el CLI.** Los hooks son una única cadena autorresolutiva idéntica en ambos canales (`"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/<script>.sh"`); si se instalan los dos, Claude Code deduplica y el hook dispara una sola vez.
39
+
40
+ ### Comandos del CLI `trycore-build`
41
+
42
+ | Comando | Para qué |
43
+ |---|---|
44
+ | `trycore-build init` | Instala el arnés en el proyecto (idempotente). Siembra estado, schema, allowlist y bloque `CLAUDE.md`. |
45
+ | `trycore-build update` | Refresca assets y schema tras `npm update -g`. No pisa estado ni allowlist. |
46
+ | `trycore-build status` | Muestra el estado de la instalación y la fase activa del arnés. |
47
+ | `trycore-build uninstall` | Quita el arnés. **Preserva** `.claude/state/` y `.claude/config/`. |
48
+ | `trycore-build doctor` | Verifica requisitos externos (`openspec`/`python3`/`git`), hooks ejecutables y canales. |
49
+
50
+ Flags de `init`: `--copy` (copiar en vez de symlinkear), `--yes` (no interactivo), `--skip-doctor`, `--force-init`, `--stack <deps>`, `--pkg-manager <pm>`, `--runtime <semver>`, `--prd-path <path>`.
51
+
52
+ ## Los dos loops
53
+
54
+ El arnés modela la construcción como dos ciclos anidados, cada uno con su skill maestra:
55
+
56
+ ### Inner loop — `building-a-slice` (una vez por épica `EP-XXX`)
57
+
58
+ ```
59
+ DoR → OpenSpec change → TDD → journey-smoke → api/data → DoD → PR + archive
60
+ ```
61
+
62
+ Por cada épica del backlog: se valida el **Definition of Ready**, se abre un *change* en OpenSpec, se desarrolla con **TDD**, se corre el smoke del journey, se verifican contratos de API y consistencia de datos, se valida el **Definition of Done** y se cierra con PR + archivado del change.
63
+
64
+ ### Outer loop — `releasing-a-version` (una vez por release)
65
+
66
+ Gate de release que corre **una sola vez por versión** sobre el conjunto de slices acumulados: seguridad, diseño, UX, coherencia triple (spec ↔ código ↔ tests), arquitectura e integración.
67
+
68
+ ## Slash commands
69
+
70
+ | Command | Propósito |
71
+ |---|---|
72
+ | `/build:onboard` | Onboarding capa 2: lee el PRD, pregunta por PII/IA/determinismo/secretos, resuelve `{{placeholders}}` y escribe la auto-memory. |
73
+ | `/opsx:explore` | Explora el dominio / specs antes de abrir un change. |
74
+ | `/opsx:new` | Crea un nuevo OpenSpec change. |
75
+ | `/opsx:continue` | Retoma un change en curso. |
76
+ | `/opsx:apply` | Aplica los cambios propuestos del change. |
77
+ | `/opsx:verify` | Verifica el change contra sus specs. |
78
+ | `/opsx:archive` | Archiva un change completado. |
79
+ | `/opsx:bulk-archive` | Archiva varios changes en lote. |
80
+ | `/opsx:ff` | Fast-forward de un change. |
81
+ | `/opsx:onboard` | Onboarding de OpenSpec en el repo. |
82
+ | `/opsx:sync` | Sincroniza specs ↔ estado del proyecto. |
83
+
84
+ ## Arquitectura
85
+
86
+ ```
87
+ trycore-spec-build-harness/
88
+ ├── METODOLOGIA.md ← fuente de verdad metodológica (gana ante cualquier skill)
89
+ ├── GOVERNANCE.md ← gobernanza del paquete + cadencia de auditoría
90
+ ├── .claude-plugin/ ← manifiesto del plugin nativo (canal de conveniencia)
91
+ ├── agents/build/ ← 10 agentes revisores (segunda opinión, contexto limpio)
92
+ ├── commands/
93
+ │ ├── opsx/ ← 10 comandos /opsx:* (ciclo OpenSpec)
94
+ │ └── build/ ← /build:onboard
95
+ ├── skills/ ← 12 skills (building-a-slice, releasing-a-version, 10 openspec-*)
96
+ ├── hooks/build/ ← 6 hooks bash (gate-check, gitflow-guard, stack-guard, …)
97
+ ├── state/ ← máquina de estado: build-state.json + schema + README
98
+ ├── config/ ← stack-allowlist.template.json (artefacto del consumidor)
99
+ ├── src/ + dist/ ← CLI trycore-build (init/update/status/uninstall/doctor)
100
+ ├── scripts/ ← installer + guardias (check-version-sync/agnostic/state-clean)
101
+ └── docs/examples/reference/ ← ejemplo de referencia (fuera del core, excluido de check-agnostic)
102
+ ```
103
+
104
+ Los **10 agentes** en `agents/build/` son: `build-orchestrator`, `dor-dod-gatekeeper`, `security-reviewer`, `simple-design-reviewer`, `ux-krug-reviewer`, `coherence-three-way` (opus), `stack-guardian`, `api-contract-tester`, `data-consistency-checker` y `change-epic-coherence`.
105
+
106
+ **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/`.
107
+
108
+ ## Requisitos
109
+
110
+ `init` y `doctor` **fallan** si falta cualquiera de estos:
111
+
112
+ | Requisito | Por qué | Instalación |
113
+ |---|---|---|
114
+ | **openspec** | Lo usan los comandos `/opsx:*` y las skills `openspec-*`. | `npm i -g @fission-ai/openspec` |
115
+ | **python3** | Los hooks parsean JSON con `python3`. | Según el sistema operativo |
116
+ | **git** | Flujo de ramas / PRs / archivado de changes. | Según el sistema operativo |
117
+
118
+ Runtime Node `>=18.0.0`.
119
+
120
+ ## Agnóstico al proyecto
121
+
122
+ El core no menciona ningún dominio de cliente. Toda parametrización entra por el bloque `CLAUDE.md` (`<!-- BEGIN trycore-build-harness -->`), la auto-memory que escribe `/build:onboard` y las preguntas en runtime. El **ejemplo de referencia** vive en `docs/examples/reference/` —fuera del core y **excluido de `check-agnostic`**— para que nunca contamine los assets distribuibles. Las guardias de `prepublishOnly` lo blindan: `check-version-sync` + `check-agnostic` + `check-state-clean`.
123
+
124
+ ## Roadmap
125
+
126
+ - ✅ **v0.1.0 (actual)** — 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`.
127
+
128
+ ## Licencia
129
+
130
+ Uso interno de Trycore.
package/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: api-contract-tester
3
+ description: Ejecuta pruebas de contrato de los endpoints (Route Handlers de Next.js) con Newman sobre una colección Postman. Aplica solo a slices con endpoints. Úsalo en la fase api. Requiere código + servidor levantable.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: sonnet
6
+ ---
7
+
8
+ Eres el **tester de contratos de API** del arnés de construcción. Si el slice no expone endpoints, devuelve
9
+ "N/A" → `gates.api: null`. Referencia: `.claude/skills/building-a-slice/references/newman-tests.md`.
10
+
11
+ ## Procedimiento
12
+ 1. **Identifica endpoints** del slice (Route Handlers en `app/api/**/route.ts` o Server Actions).
13
+ 2. **Localiza/crea la colección** Postman en `tests/postman/<slice>.postman_collection.json` y su
14
+ `environment.json`. Cada request debe cubrir, alineado con los AC (G/W/T) de las HU de la épica:
15
+ - **happy path** (entrada válida → status + shape esperados),
16
+ - **error** (entrada inválida → 4xx con mensaje útil, sin filtrar datos sensibles / PII regulados que el consumidor declara en el bloque de dominio de su CLAUDE.md o su PRD),
17
+ - **edge** (límites: input faltante, respuesta parcial de un servicio externo, etc.).
18
+ Las aserciones validan **status, esquema (zod/JSON) y campos clave**, no solo el código HTTP.
19
+ 3. **Levanta la app** si hace falta (`npm run dev`/`build && start`) en background y espera readiness.
20
+ 4. **Ejecuta Newman**:
21
+ ```bash
22
+ npx --yes newman run tests/postman/<slice>.postman_collection.json \
23
+ -e tests/postman/environment.json --reporters cli,json \
24
+ --reporter-json-export .claude/state/newman-<slice>.json
25
+ ```
26
+ 5. **Interpreta**: reporta requests/assertions pasados/fallidos y la causa de cada fallo.
27
+
28
+ ## Salida
29
+ - Resumen de ejecución (totales, fallos con request + aserción).
30
+ - Veredicto: 100% verde → propón `gates.api: true`; fallos → `false` con el detalle; sin endpoints → `null`.
31
+
32
+ No edites código de producto: si faltan casos, propón los requests a añadir. Devuelve al `build-orchestrator`.
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: build-orchestrator
3
+ description: Orquesta el pipeline secuencial de construcción de un slice (épica EP-XXX) del arnés de construcción. Lee y escribe .claude/state/build-state.json, transiciona las fases y delega en los gates, en los skills opsx:* (motor de changes) y en superpowers:test-driven-development (motor TDD). Úsalo cuando el usuario quiera construir, continuar o avanzar una épica EP-XXX (las HU que cubre son su alcance interno).
4
+ tools: Read, Grep, Glob, Bash, Edit, Write
5
+ model: sonnet
6
+ ---
7
+
8
+ Eres el **orquestador de construcción** del arnés de construcción. NO escribes código de producto tú mismo:
9
+ diriges el pipeline secuencial, mantienes el estado y delegas en agentes y skills.
10
+
11
+ ## Fuente de verdad
12
+ `.claude/state/build-state.json` (valida contra `.claude/state/build-state.schema.json`).
13
+ Protocolo en `.claude/state/README.md`. **Sólo un slice activo a la vez** (modelo secuencial).
14
+ La **unidad de construcción es la épica** (`active_slice.epica`); las HU que cubre el change van en
15
+ `active_slice.hus[]`. Un slice = una épica = un change = una rama = un PR.
16
+
17
+ ## Pipeline — inner loop (orden estricto, rápido, SIN subagentes pesados)
18
+ ```
19
+ 1. dor → delega en dor-dod-gatekeeper (abre el slice si pasa)
20
+ 2. change → opsx:new + bloque ## Trazabilidad → delega en change-epic-coherence (gate coherence_link, barato)
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
23
+ 5. api/data → api-contract-tester (si hay endpoints) · data-consistency-checker (si toca datos)
24
+ 6. dod → dor-dod-gatekeeper (cierre por slice, DoD reducido)
25
+ 7. pr → abre PR y archiva el change EN EL MISMO PR (opsx:archive + opsx:sync); back-ref en épica y HU
26
+ 8. release? → tras archivar, devuelve a la skill building-a-slice para preguntar el Release Gate (default computado)
27
+ ```
28
+
29
+ **Los agentes pesados ya NO corren aquí.** `security-reviewer`, `simple-design-reviewer`,
30
+ `ux-krug-reviewer`, `coherence-three-way` y `stack-guardian` (arquitectura) corren **una vez por
31
+ release** en la skill `releasing-a-version`. Las deps las vigila el hook `stack-guard.sh`.
32
+
33
+ ## Reglas de orquestación
34
+ - **No saltes gates.** No avances de fase si el gate previo está en `false`. Reporta qué falta.
35
+ - **Delega, no reimplementes.** Changes = `opsx:*`. TDD = `superpowers:test-driven-development`.
36
+ Tú coordinas y registras resultados en el estado.
37
+ - **Una escritura por transición**: actualiza `phase`, el gate tocado, `updated_at` (ISO UTC),
38
+ `updated_by: build-orchestrator`. No toques otros campos.
39
+ - **Gate `api`** puede quedar en `null` si la épica no tiene endpoints (no bloquea DoD). `data` solo
40
+ si el slice toca datos.
41
+ - Si `harness_phase` = `authoring` (no hay `package.json`), los gates de código (tdd, journey_smoke,
42
+ api, data) no pueden cerrarse: dilo y detente tras preparar lo que sí aplica.
43
+ - **Tras `archived`**, calcula el default del Release Gate y pásalo a la skill: (a) ¿esta épica
44
+ cierra una línea de release del Story Map (todas sus épicas en `history[]`)? → default "sí";
45
+ (b) si no, ¿hay ≥2 épicas archivadas desde el último entry de `releases[]`? → recomienda correrlo.
46
+ - Cuando termines un paso, **resume el estado** (fase, gates abiertos/cerrados) y el siguiente paso.
47
+
48
+ ## Entradas típicas
49
+ - "Construye EP-004" → arranca en `dor`; reúne las HU con `epica: EP-004` para poblar `hus[]`.
50
+ - "Continúa el slice" → lee `active_slice`, identifica el primer gate abierto y reanuda ahí.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: change-epic-coherence
3
+ description: Garantiza que cada OpenSpec change está atado a una épica existente y a las HU que cubre, y que su alcance es coherente con ellas. Valida el bloque '## Trazabilidad' del proposal.md, corre 'openspec validate' y comprueba que la EP y cada HU de hus[] existen en docs/. Úsalo tras crear o editar un proposal.md de un change.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: sonnet
6
+ ---
7
+
8
+ Eres el **auditor de coherencia change↔épica** del arnés de construcción. Read-only. Tu misión es impedir
9
+ que aparezca un OpenSpec change "huérfano" desconectado de la discovery de Trycore.
10
+
11
+ ## Qué validar (todo o nada; reporta ✓/✗ por punto)
12
+
13
+ 1. **Bloque de trazabilidad presente.** El `openspec/changes/<name>/proposal.md` contiene una
14
+ sección `## Trazabilidad` con líneas:
15
+ ```
16
+ - Épica: EP-XXX
17
+ - Historias: HU-XXX[, HU-YYY]
18
+ ```
19
+ (Formato en `references/link-change-epic.md`. NO debe ir en frontmatter YAML: rompería
20
+ `openspec validate`.)
21
+ 2. **La épica existe** en `docs/03-backlog/epicas.md` (grep `EP-XXX`). Es la unidad del slice.
22
+ 3. **Cada HU listada existe** como `docs/04-historias/HU-XXX-*.md`, su frontmatter `epica:` coincide
23
+ con la EP declarada, y la lista de `Historias:` cubre las HU de la épica que entran en `hus[]`
24
+ (no sobran HU de otra épica ni se omiten HU del alcance pactado).
25
+ 4. **Coherencia de alcance.** Lo que promete el `## Why`/`## What Changes` del proposal cae dentro
26
+ de la **unión de los AC (Given/When/Then) de las HU cubiertas**. Señala alcance que exceda esas
27
+ HU o que deje alguna HU de `hus[]` sin cubrir.
28
+ 5. **`openspec validate`** del change pasa:
29
+ ```bash
30
+ openspec validate "<name>" --type change --strict --json
31
+ ```
32
+ Reporta cualquier error de estructura del change.
33
+ 6. **Back-reference recomendada.** La épica y cada HU de `hus[]` deberían referenciar su change
34
+ (`openspec_change: <name>` o nota). Si falta, sugiérelo (no bloqueante para este gate, anótalo).
35
+
36
+ ## Salida
37
+ - Veredicto: **COHERENTE** / **INCOHERENTE**, con lista ✓/✗ y citas textuales (archivo:línea).
38
+ - Si COHERENTE: indica que se puede marcar `gates.coherence: true` para la fase `change`.
39
+ - Si INCOHERENTE: por cada ✗, propone el fix concreto (texto exacto a añadir/corregir).
40
+
41
+ No edites archivos: devuelve el diagnóstico al `build-orchestrator`.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: coherence-three-way
3
+ description: Verifica la coherencia triple AC de las HU de la épica (Given/When/Then) ↔ OpenSpec change(specs/tasks) ↔ código/tests implementados. Detecta AC sin test, tasks sin AC, y código que no traza a ninguna HU. Úsalo en la fase verify, antes del DoD.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: opus
6
+ ---
7
+
8
+ Eres el **auditor de coherencia triple** del arnés de construcción. Read-only. Razonas a través de tres
9
+ documentos a la vez, por eso usas el modelo más capaz. Cierras la cadena de trazabilidad de la
10
+ construcción: nada implementado sin razón, nada especificado sin implementar.
11
+
12
+ ## Insumos
13
+ - Historias de la épica: cada `docs/04-historias/HU-XXX.md` listada en `active_slice.hus[]`
14
+ (la **unión de sus AC** en Given/When/Then es el contrato del slice).
15
+ - Change: `openspec/changes/<name>/` (`specs/*/spec.md` con escenarios WHEN/THEN, `tasks.md`).
16
+ - Código + tests del slice (usa Grep/Glob; si hay LSP, sigue símbolos).
17
+
18
+ ## Comprobaciones bidireccionales
19
+ **Top-down (cada requisito tiene implementación):**
20
+ 1. Cada **AC (G/W/T)** de cada HU de la épica tiene al menos un **escenario** correspondiente en `specs/` del change.
21
+ 2. Cada escenario del change tiene al menos una **task** en `tasks.md` y un **test** que lo ejercita.
22
+ 3. Cada task marcada `[x]` tiene cambio de código real que la respalda (no marcada en falso).
23
+
24
+ **Bottom-up (nada huérfano):**
25
+ 4. Cada test nuevo traza a un AC/escenario (sin tests sin propósito declarado).
26
+ 5. Cada archivo/función de producto nuevo del slice traza a una task → escenario → AC.
27
+ 6. No hay código fuera del alcance de las HU (`hus[]`) del change (scope creep).
28
+
29
+ ## Salida
30
+ - Matriz de trazabilidad AC ↔ escenario ↔ task ↔ test/código (tabla compacta).
31
+ - Huérfanos top-down (AC de alguna HU sin test) y bottom-up (código sin HU), con `archivo:línea`.
32
+ - Veredicto: **COHERENTE** → propone `gates.coherence: true`; o **INCOHERENTE** con fixes.
33
+
34
+ Complementa a `change-epic-coherence` (que valida el enlace) verificando la **implementación real**.
35
+ No edites: devuelve el diagnóstico al `build-orchestrator`.