@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.
- package/.claude-plugin/marketplace.json +21 -0
- package/.claude-plugin/plugin.json +28 -0
- package/GOVERNANCE.md +48 -0
- package/INSTALL.md +295 -0
- package/METODOLOGIA.md +360 -0
- package/README.md +130 -0
- package/VERSION +1 -0
- package/agents/build/api-contract-tester.md +32 -0
- package/agents/build/build-orchestrator.md +50 -0
- package/agents/build/change-epic-coherence.md +41 -0
- package/agents/build/coherence-three-way.md +35 -0
- package/agents/build/data-consistency-checker.md +48 -0
- package/agents/build/dor-dod-gatekeeper.md +46 -0
- package/agents/build/security-reviewer.md +46 -0
- package/agents/build/simple-design-reviewer.md +33 -0
- package/agents/build/stack-guardian.md +41 -0
- package/agents/build/ux-krug-reviewer.md +33 -0
- package/commands/build/onboard.md +136 -0
- package/commands/opsx/apply.md +152 -0
- package/commands/opsx/archive.md +157 -0
- package/commands/opsx/bulk-archive.md +242 -0
- package/commands/opsx/continue.md +114 -0
- package/commands/opsx/explore.md +174 -0
- package/commands/opsx/ff.md +94 -0
- package/commands/opsx/new.md +69 -0
- package/commands/opsx/onboard.md +525 -0
- package/commands/opsx/sync.md +134 -0
- package/commands/opsx/verify.md +164 -0
- package/config/stack-allowlist.template.json +12 -0
- package/dist/cli.js +105 -0
- package/dist/commands/doctor.js +77 -0
- package/dist/commands/init.js +129 -0
- package/dist/commands/status.js +59 -0
- package/dist/commands/uninstall.js +52 -0
- package/dist/commands/update.js +11 -0
- package/dist/lib/install-engine.js +99 -0
- package/dist/lib/markers.js +81 -0
- package/dist/lib/paths.js +65 -0
- package/dist/lib/settings-merge.js +125 -0
- package/dist/lib/stack-prompt.js +69 -0
- package/dist/lib/state-seed.js +59 -0
- package/docs/agents.md +133 -0
- package/docs/commands.md +128 -0
- package/docs/customization/mcp-extensions.md +117 -0
- package/docs/examples/reference/data-consistency.example.md +61 -0
- package/docs/examples/reference/security-foco.example.md +39 -0
- package/docs/examples/reference/stack-allowlist.example.json +61 -0
- package/docs/getting-started.md +260 -0
- package/docs/hooks.md +143 -0
- package/hooks/build/build-gate-check.sh +24 -0
- package/hooks/build/coherence-flag.sh +23 -0
- package/hooks/build/gitflow-guard.sh +65 -0
- package/hooks/build/lint-typecheck.sh +33 -0
- package/hooks/build/load-build-state.sh +46 -0
- package/hooks/build/stack-guard.sh +63 -0
- package/hooks/build-harness.json +61 -0
- package/internal/skills/auditar-arnes/SKILL.md +29 -0
- package/package.json +67 -0
- package/scripts/check-agnostic.sh +81 -0
- package/scripts/check-state-clean.sh +48 -0
- package/scripts/check-version-sync.sh +51 -0
- package/scripts/denylist.txt +30 -0
- package/skills/building-a-slice/SKILL.md +82 -0
- package/skills/building-a-slice/references/data-consistency.md +34 -0
- package/skills/building-a-slice/references/dod.md +25 -0
- package/skills/building-a-slice/references/dor.md +17 -0
- package/skills/building-a-slice/references/gitflow.md +30 -0
- package/skills/building-a-slice/references/krug-ux.md +27 -0
- package/skills/building-a-slice/references/link-change-epic.md +34 -0
- package/skills/building-a-slice/references/mcp-map.md +29 -0
- package/skills/building-a-slice/references/newman-tests.md +47 -0
- package/skills/building-a-slice/references/simple-design.md +33 -0
- package/skills/building-a-slice/references/state-protocol.md +48 -0
- package/skills/openspec-apply-change/SKILL.md +156 -0
- package/skills/openspec-archive-change/SKILL.md +114 -0
- package/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/skills/openspec-continue-change/SKILL.md +118 -0
- package/skills/openspec-explore/SKILL.md +290 -0
- package/skills/openspec-ff-change/SKILL.md +101 -0
- package/skills/openspec-new-change/SKILL.md +74 -0
- package/skills/openspec-onboard/SKILL.md +529 -0
- package/skills/openspec-sync-specs/SKILL.md +138 -0
- package/skills/openspec-verify-change/SKILL.md +168 -0
- package/skills/releasing-a-version/SKILL.md +56 -0
- package/skills/releasing-a-version/references/release-dod.md +20 -0
- package/state/README.md +56 -0
- package/state/build-state.schema.json +111 -0
- package/state/build-state.template.json +7 -0
- package/templates/CLAUDE.md.template +57 -0
- package/templates/newman.collection.template.json +28 -0
- package/templates/settings-hooks.template.json +25 -0
- package/templates/waivers/WAIVER.template.md +27 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openspec-verify-change
|
|
3
|
+
description: Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires openspec CLI.
|
|
6
|
+
metadata:
|
|
7
|
+
author: openspec
|
|
8
|
+
version: "1.0"
|
|
9
|
+
generatedBy: "1.0.2"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Verify that an implementation matches the change artifacts (specs, tasks, design).
|
|
13
|
+
|
|
14
|
+
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
15
|
+
|
|
16
|
+
**Steps**
|
|
17
|
+
|
|
18
|
+
1. **If no change name provided, prompt for selection**
|
|
19
|
+
|
|
20
|
+
Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
|
|
21
|
+
|
|
22
|
+
Show changes that have implementation tasks (tasks artifact exists).
|
|
23
|
+
Include the schema used for each change if available.
|
|
24
|
+
Mark changes with incomplete tasks as "(In Progress)".
|
|
25
|
+
|
|
26
|
+
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
|
|
27
|
+
|
|
28
|
+
2. **Check status to understand the schema**
|
|
29
|
+
```bash
|
|
30
|
+
openspec status --change "<name>" --json
|
|
31
|
+
```
|
|
32
|
+
Parse the JSON to understand:
|
|
33
|
+
- `schemaName`: The workflow being used (e.g., "spec-driven")
|
|
34
|
+
- Which artifacts exist for this change
|
|
35
|
+
|
|
36
|
+
3. **Get the change directory and load artifacts**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
openspec instructions apply --change "<name>" --json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This returns the change directory and context files. Read all available artifacts from `contextFiles`.
|
|
43
|
+
|
|
44
|
+
4. **Initialize verification report structure**
|
|
45
|
+
|
|
46
|
+
Create a report structure with three dimensions:
|
|
47
|
+
- **Completeness**: Track tasks and spec coverage
|
|
48
|
+
- **Correctness**: Track requirement implementation and scenario coverage
|
|
49
|
+
- **Coherence**: Track design adherence and pattern consistency
|
|
50
|
+
|
|
51
|
+
Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.
|
|
52
|
+
|
|
53
|
+
5. **Verify Completeness**
|
|
54
|
+
|
|
55
|
+
**Task Completion**:
|
|
56
|
+
- If tasks.md exists in contextFiles, read it
|
|
57
|
+
- Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete)
|
|
58
|
+
- Count complete vs total tasks
|
|
59
|
+
- If incomplete tasks exist:
|
|
60
|
+
- Add CRITICAL issue for each incomplete task
|
|
61
|
+
- Recommendation: "Complete task: <description>" or "Mark as done if already implemented"
|
|
62
|
+
|
|
63
|
+
**Spec Coverage**:
|
|
64
|
+
- If delta specs exist in `openspec/changes/<name>/specs/`:
|
|
65
|
+
- Extract all requirements (marked with "### Requirement:")
|
|
66
|
+
- For each requirement:
|
|
67
|
+
- Search codebase for keywords related to the requirement
|
|
68
|
+
- Assess if implementation likely exists
|
|
69
|
+
- If requirements appear unimplemented:
|
|
70
|
+
- Add CRITICAL issue: "Requirement not found: <requirement name>"
|
|
71
|
+
- Recommendation: "Implement requirement X: <description>"
|
|
72
|
+
|
|
73
|
+
6. **Verify Correctness**
|
|
74
|
+
|
|
75
|
+
**Requirement Implementation Mapping**:
|
|
76
|
+
- For each requirement from delta specs:
|
|
77
|
+
- Search codebase for implementation evidence
|
|
78
|
+
- If found, note file paths and line ranges
|
|
79
|
+
- Assess if implementation matches requirement intent
|
|
80
|
+
- If divergence detected:
|
|
81
|
+
- Add WARNING: "Implementation may diverge from spec: <details>"
|
|
82
|
+
- Recommendation: "Review <file>:<lines> against requirement X"
|
|
83
|
+
|
|
84
|
+
**Scenario Coverage**:
|
|
85
|
+
- For each scenario in delta specs (marked with "#### Scenario:"):
|
|
86
|
+
- Check if conditions are handled in code
|
|
87
|
+
- Check if tests exist covering the scenario
|
|
88
|
+
- If scenario appears uncovered:
|
|
89
|
+
- Add WARNING: "Scenario not covered: <scenario name>"
|
|
90
|
+
- Recommendation: "Add test or implementation for scenario: <description>"
|
|
91
|
+
|
|
92
|
+
7. **Verify Coherence**
|
|
93
|
+
|
|
94
|
+
**Design Adherence**:
|
|
95
|
+
- If design.md exists in contextFiles:
|
|
96
|
+
- Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:")
|
|
97
|
+
- Verify implementation follows those decisions
|
|
98
|
+
- If contradiction detected:
|
|
99
|
+
- Add WARNING: "Design decision not followed: <decision>"
|
|
100
|
+
- Recommendation: "Update implementation or revise design.md to match reality"
|
|
101
|
+
- If no design.md: Skip design adherence check, note "No design.md to verify against"
|
|
102
|
+
|
|
103
|
+
**Code Pattern Consistency**:
|
|
104
|
+
- Review new code for consistency with project patterns
|
|
105
|
+
- Check file naming, directory structure, coding style
|
|
106
|
+
- If significant deviations found:
|
|
107
|
+
- Add SUGGESTION: "Code pattern deviation: <details>"
|
|
108
|
+
- Recommendation: "Consider following project pattern: <example>"
|
|
109
|
+
|
|
110
|
+
8. **Generate Verification Report**
|
|
111
|
+
|
|
112
|
+
**Summary Scorecard**:
|
|
113
|
+
```
|
|
114
|
+
## Verification Report: <change-name>
|
|
115
|
+
|
|
116
|
+
### Summary
|
|
117
|
+
| Dimension | Status |
|
|
118
|
+
|--------------|------------------|
|
|
119
|
+
| Completeness | X/Y tasks, N reqs|
|
|
120
|
+
| Correctness | M/N reqs covered |
|
|
121
|
+
| Coherence | Followed/Issues |
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Issues by Priority**:
|
|
125
|
+
|
|
126
|
+
1. **CRITICAL** (Must fix before archive):
|
|
127
|
+
- Incomplete tasks
|
|
128
|
+
- Missing requirement implementations
|
|
129
|
+
- Each with specific, actionable recommendation
|
|
130
|
+
|
|
131
|
+
2. **WARNING** (Should fix):
|
|
132
|
+
- Spec/design divergences
|
|
133
|
+
- Missing scenario coverage
|
|
134
|
+
- Each with specific recommendation
|
|
135
|
+
|
|
136
|
+
3. **SUGGESTION** (Nice to fix):
|
|
137
|
+
- Pattern inconsistencies
|
|
138
|
+
- Minor improvements
|
|
139
|
+
- Each with specific recommendation
|
|
140
|
+
|
|
141
|
+
**Final Assessment**:
|
|
142
|
+
- If CRITICAL issues: "X critical issue(s) found. Fix before archiving."
|
|
143
|
+
- If only warnings: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)."
|
|
144
|
+
- If all clear: "All checks passed. Ready for archive."
|
|
145
|
+
|
|
146
|
+
**Verification Heuristics**
|
|
147
|
+
|
|
148
|
+
- **Completeness**: Focus on objective checklist items (checkboxes, requirements list)
|
|
149
|
+
- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty
|
|
150
|
+
- **Coherence**: Look for glaring inconsistencies, don't nitpick style
|
|
151
|
+
- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL
|
|
152
|
+
- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable
|
|
153
|
+
|
|
154
|
+
**Graceful Degradation**
|
|
155
|
+
|
|
156
|
+
- If only tasks.md exists: verify task completion only, skip spec/design checks
|
|
157
|
+
- If tasks + specs exist: verify completeness and correctness, skip design
|
|
158
|
+
- If full artifacts: verify all three dimensions
|
|
159
|
+
- Always note which checks were skipped and why
|
|
160
|
+
|
|
161
|
+
**Output Format**
|
|
162
|
+
|
|
163
|
+
Use clear markdown with:
|
|
164
|
+
- Table for summary scorecard
|
|
165
|
+
- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION)
|
|
166
|
+
- Code references in format: `file.ts:123`
|
|
167
|
+
- Specific, actionable recommendations
|
|
168
|
+
- No vague suggestions like "consider reviewing"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: releasing-a-version
|
|
3
|
+
description: Use when closing a release of the product — runs the heavy review gates ONCE over the accumulated diff of a release line (security, design/smell, UX/Krug, three-way coherence, architecture, and full end-to-end integration with real deps), instead of per epic. This is the outer loop; the per-epic inner loop lives in building-a-slice. Trigger after archiving an epic when the user accepts the Release Gate, or when a Story Map release line is complete. Records results in build-state.json releases[].
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Release Gate (outer loop) — Build
|
|
7
|
+
|
|
8
|
+
El **outer loop** del arnés. Mientras `building-a-slice` (inner loop) construye épica a épica de
|
|
9
|
+
forma barata y rápida, esta skill ejecuta las **revisiones profundas una sola vez por release**,
|
|
10
|
+
sobre el **diff acumulado** de todas las épicas de esa release. Así el costo de los agentes pesados
|
|
11
|
+
pasa de `O(épicas)` a `O(releases)`.
|
|
12
|
+
|
|
13
|
+
## Qué es una release
|
|
14
|
+
Una **línea de release del Story Map** (`docs/02-user-story-map/`). P.ej. **R1-mvp** = EP-001 +
|
|
15
|
+
EP-002 + EP-003 + EP-004 ("Resolver un caso de punta a punta con resultado explicable"). El conjunto
|
|
16
|
+
de épicas de la release son las que vas a auditar en bloque.
|
|
17
|
+
|
|
18
|
+
## Cuándo se invoca
|
|
19
|
+
- Tras archivar una épica, `building-a-slice` pregunta con un default computado y el usuario acepta.
|
|
20
|
+
- O explícitamente: "corre el Release Gate de R1".
|
|
21
|
+
|
|
22
|
+
## Principio de operación
|
|
23
|
+
- **Una sola fuente de verdad**: `.claude/state/build-state.json` → array `releases[]`. Lee antes,
|
|
24
|
+
escribe una entrada por release.
|
|
25
|
+
- **Sobre el diff acumulado**: el alcance es el rango de commits de todas las épicas de la release
|
|
26
|
+
(desde el merge anterior a la primera épica de la release hasta `main`).
|
|
27
|
+
- **Delega en subagentes** (devuelven síntesis, protegen el contexto).
|
|
28
|
+
|
|
29
|
+
## Pipeline del Release Gate
|
|
30
|
+
|
|
31
|
+
| Gate | Acción | Delega en | Referencia |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| `security` | Vectores generales + foco de dominio del consumidor (PII/secretos/authz, claves de servicios externos server-side) sobre todo el diff | `security-reviewer` | — |
|
|
34
|
+
| `smell` | 4 reglas de Beck + code smells sobre el diff acumulado | `simple-design-reviewer` | `building-a-slice/references/simple-design.md` |
|
|
35
|
+
| `ux` | Krug + lighthouse sobre la UI ensamblada de la release (o `null` si sin UI) | `ux-krug-reviewer` | `building-a-slice/references/krug-ux.md` |
|
|
36
|
+
| `coherence` | Trazabilidad triple AC↔change↔código de **todas** las HU de la release | `coherence-three-way` | — |
|
|
37
|
+
| `stack_arch` | Arquitectura del PRD del consumidor (capa de servicios externos en la frontera declarada, capa de decisión determinista del dominio sin IA) | `stack-guardian` | — |
|
|
38
|
+
| `integration` | Recorrer el **journey completo** de la release con **deps reales** del proyecto, no stubs | skill `verify` / `run` (+ MCP chrome-devtools) | `release-dod.md` |
|
|
39
|
+
|
|
40
|
+
Checklist de cierre: `references/release-dod.md`.
|
|
41
|
+
|
|
42
|
+
## Cómo proceder
|
|
43
|
+
1. Lee `build-state.json`; identifica la release y sus épicas (cruza con `docs/02-user-story-map/`).
|
|
44
|
+
2. Crea/actualiza la entrada en `releases[]` con `status: pending`.
|
|
45
|
+
3. Dispara los subagentes **en paralelo** sobre el diff acumulado (devuelven síntesis).
|
|
46
|
+
4. Corre el gate de **integración** con la skill `verify`/`run`: el journey completo, deps reales.
|
|
47
|
+
5. Cuando todos los gates pasan (o `null` cuando N/A) → `status: passed`, escribe los `gates` y
|
|
48
|
+
`updated_by: releasing-a-version`. Si algo falla → `status: failed` y lista los hallazgos
|
|
49
|
+
bloqueantes; el usuario los corrige como un slice normal (fix en `building-a-slice`) y se
|
|
50
|
+
re-corre el Release Gate.
|
|
51
|
+
|
|
52
|
+
## Reglas duras
|
|
53
|
+
- **No dupliques el inner loop.** Aquí no se hace TDD ni se cierran gates por slice.
|
|
54
|
+
- **Integración con deps reales es obligatoria** para `status: passed` — es el gate que faltaba y
|
|
55
|
+
por el que el producto "no funcionaba al terminar". No se acepta con todo stubbeado.
|
|
56
|
+
- Si una regla aquí contradice la metodología Trycore (`METODOLOGIA.md`), **gana la metodología**.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Release Gate — checklist de salida (outer loop)
|
|
2
|
+
|
|
3
|
+
Una **release** (línea de release del Story Map) no se da por cerrada hasta cumplir TODO esto. Se
|
|
4
|
+
corre **una vez** sobre el diff acumulado de todas sus épicas. Resultado en `build-state.json` →
|
|
5
|
+
`releases[]`.
|
|
6
|
+
|
|
7
|
+
- [ ] **`security`** — `security-reviewer` sin hallazgos CRÍTICO/ALTO sobre el diff completo de la release; claves de servicios externos solo server-side; datos sensibles / PII regulados (según el PRD del consumidor) no persistidos crudos; salida de cualquier servicio externo/IA tratada como input no confiable y validada contra esquema antes de alimentar la capa de decisión.
|
|
8
|
+
- [ ] **`smell`** — `simple-design-reviewer` sin bloqueantes sobre el diff acumulado; 4 reglas de Beck respetadas.
|
|
9
|
+
- [ ] **`ux`** — `ux-krug-reviewer` ok sobre la UI ensamblada (o `null` si la release no tiene UI). Lighthouse/accesibilidad si la app corre.
|
|
10
|
+
- [ ] **`coherence`** — `coherence-three-way` confirma trazabilidad AC↔change↔código de **todas** las HU de **todas** las épicas de la release, sin huérfanos.
|
|
11
|
+
- [ ] **`stack_arch`** — `stack-guardian` confirma la arquitectura del PRD del consumidor: la capa de servicios externos/IA en la frontera declarada server-side (no decide), la capa de decisión determinista del dominio sin IA, sin claves de servicios externos en cliente.
|
|
12
|
+
- [ ] **`integration`** — el **journey completo** de la release se recorre end-to-end con **dependencias reales** del proyecto (servicios externos/IA y capa de decisión reales, según el PRD del consumidor), no stubs. Verificado con la skill `verify`/`run` (+ MCP `chrome-devtools`).
|
|
13
|
+
|
|
14
|
+
**Todo ✓ (o `null` cuando N/A)** → `releases[].status: "passed"`, escribe `gates` y `updated_by:
|
|
15
|
+
releasing-a-version`. **Algo ✗** → `status: "failed"`, lista hallazgos bloqueantes; se corrigen como
|
|
16
|
+
un slice normal en `building-a-slice` y se re-corre el Release Gate.
|
|
17
|
+
|
|
18
|
+
> El gate `integration` es el que faltaba en la era anterior: todos los gates por-slice estaban en
|
|
19
|
+
> verde y aun así el producto no caminaba de punta a punta. Sin `integration` con deps reales no hay
|
|
20
|
+
> release.
|
package/state/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Estado del arnés de construcción (`build-state.json`)
|
|
2
|
+
|
|
3
|
+
`build-state.json` es la **única fuente de verdad** del slice (épica) en construcción y el medio por
|
|
4
|
+
el que los agentes se sincronizan en modo **secuencial**. La unidad de construcción es la **épica
|
|
5
|
+
(`EP-XXX`)**; las HU que cubre el change se listan en `hus[]` (trazabilidad al alcance interno).
|
|
6
|
+
Cada gate del pipeline transiciona el estado; el siguiente agente lo lee antes de actuar.
|
|
7
|
+
|
|
8
|
+
- **Esquema**: `build-state.schema.json` (versionado, draft 2020-12). Valida con:
|
|
9
|
+
```bash
|
|
10
|
+
# Recomendado (funciona sin plugins de formato):
|
|
11
|
+
python3 -c "import jsonschema,json; jsonschema.Draft202012Validator(json.load(open('.claude/state/build-state.schema.json'))).validate(json.load(open('.claude/state/build-state.json'))); print('OK')"
|
|
12
|
+
# Alternativa con ajv (requiere spec + formatos):
|
|
13
|
+
npx --yes ajv-cli@5 validate --spec=draft2020 -c ajv-formats -s .claude/state/build-state.schema.json -d .claude/state/build-state.json
|
|
14
|
+
```
|
|
15
|
+
- **No versionar el estado vivo**: `build-state.json` está en `.gitignore` (working state). El
|
|
16
|
+
schema y este README sí se versionan.
|
|
17
|
+
|
|
18
|
+
## Protocolo de lectura/escritura
|
|
19
|
+
|
|
20
|
+
1. **Leer antes de actuar.** Todo agente del pipeline lee `active_slice` y `gates` antes de
|
|
21
|
+
trabajar. Si `active_slice` es `null`, no hay slice en curso → solo `dor-dod-gatekeeper` puede
|
|
22
|
+
abrir uno.
|
|
23
|
+
2. **Una sola escritura por transición.** Quien completa una fase actualiza `phase`, el gate
|
|
24
|
+
correspondiente, `updated_at` (ISO 8601 UTC) y `updated_by` (su nombre). No tocar otros campos.
|
|
25
|
+
3. **Gates monótonos hacia adelante.** Un gate solo pasa de `false`→`true` cuando su agente lo
|
|
26
|
+
aprueba. Si una revisión posterior falla, se vuelve a `false` y `phase` retrocede.
|
|
27
|
+
4. **`ux`/`api` admiten `null`** cuando el slice no tiene UI o endpoints (N/A, no bloquea DoD).
|
|
28
|
+
5. **Archivar**: al completar `opsx:archive`, mover el `active_slice` a `history[]` con
|
|
29
|
+
`phase: "archived"` y dejar `active_slice: null`.
|
|
30
|
+
6. **Dos loops**: el slice (inner loop) cierra gates baratos por épica; los gates pesados viven en
|
|
31
|
+
`releases[]` (outer loop), que escribe la skill `releasing-a-version` una vez por release.
|
|
32
|
+
|
|
33
|
+
## Ciclo de fases
|
|
34
|
+
|
|
35
|
+
**Inner loop (por slice):**
|
|
36
|
+
```
|
|
37
|
+
dor → change → red → green → refactor → smoke → api → data → dod → pr → archived
|
|
38
|
+
```
|
|
39
|
+
Luego se pregunta el **Release Gate** (outer loop, skill `releasing-a-version`) con default
|
|
40
|
+
computado desde las líneas de release del Story Map.
|
|
41
|
+
|
|
42
|
+
`harness_phase` arranca en `authoring` y lo cambia `load-build-state.sh` a `active` cuando
|
|
43
|
+
detecta `package.json` en la raíz (aparición del scaffold Next.js).
|
|
44
|
+
|
|
45
|
+
## Quién escribe qué
|
|
46
|
+
|
|
47
|
+
| Campo / gate | Lo escribe | Cadencia |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `active_slice` (alta) · `gates.dor` · `gates.dod` | `dor-dod-gatekeeper` | slice |
|
|
50
|
+
| `gates.coherence_link` | `change-epic-coherence` | slice |
|
|
51
|
+
| `gates.tdd` | flujo `superpowers:test-driven-development` (vía `build-orchestrator`) | slice |
|
|
52
|
+
| `gates.journey_smoke` · `phase` (transiciones) · `history[]` (archivado) | `build-orchestrator` | slice |
|
|
53
|
+
| `gates.api` | `api-contract-tester` | slice |
|
|
54
|
+
| `gates.data` | `data-consistency-checker` | slice |
|
|
55
|
+
| `releases[]` (`security`, `smell`, `ux`, `coherence`, `stack_arch`, `integration`, `status`) | `releasing-a-version` (delega en `security-reviewer`, `simple-design-reviewer`, `ux-krug-reviewer`, `coherence-three-way`, `stack-guardian`) | release |
|
|
56
|
+
| `harness_phase` | `load-build-state.sh` (SessionStart) | — |
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://trycore.com/spec-build-harness/build-state.schema.json",
|
|
4
|
+
"title": "Build Harness State",
|
|
5
|
+
"description": "Single source of truth para el handoff secuencial entre agentes de construcción. Lo escriben build-orchestrator y los gates; lo lee load-build-state.sh.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["version", "harness_phase", "active_slice", "history", "releases"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"version": { "type": "string", "const": "1.0" },
|
|
11
|
+
"harness_phase": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"enum": ["authoring", "active"],
|
|
14
|
+
"description": "authoring = aún no hay package.json; active = scaffold de código presente."
|
|
15
|
+
},
|
|
16
|
+
"active_slice": {
|
|
17
|
+
"description": "El slice (épica) en construcción. null si no hay ninguno activo.",
|
|
18
|
+
"oneOf": [
|
|
19
|
+
{ "type": "null" },
|
|
20
|
+
{ "$ref": "#/$defs/slice" }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"history": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"description": "Slices archivados, en orden cronológico.",
|
|
26
|
+
"items": { "$ref": "#/$defs/slice" }
|
|
27
|
+
},
|
|
28
|
+
"releases": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"description": "Release Gates (outer loop). Una entrada por línea de release del Story Map auditada en bloque.",
|
|
31
|
+
"items": { "$ref": "#/$defs/release" }
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"$defs": {
|
|
35
|
+
"slice": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"required": ["epica", "hus", "openspec_change", "branch", "phase", "gates", "updated_at", "updated_by"],
|
|
39
|
+
"properties": {
|
|
40
|
+
"epica": { "type": "string", "pattern": "^EP-[0-9]{3}$", "description": "Unidad de construcción del slice." },
|
|
41
|
+
"hus": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"description": "HU de la épica cubiertas por este change. Trazabilidad al alcance interno; al menos una.",
|
|
44
|
+
"items": { "type": "string", "pattern": "^HU-[0-9]{3}$" },
|
|
45
|
+
"minItems": 1,
|
|
46
|
+
"uniqueItems": true
|
|
47
|
+
},
|
|
48
|
+
"openspec_change": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
|
|
49
|
+
"branch": { "type": "string", "pattern": "^(feature|fix|chore)/[a-z0-9._-]+$" },
|
|
50
|
+
"phase": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": ["dor", "change", "red", "green", "refactor", "smoke", "api", "data", "dod", "pr", "archived"]
|
|
53
|
+
},
|
|
54
|
+
"gates": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"additionalProperties": false,
|
|
57
|
+
"description": "Inner loop (por slice): dor, tdd, journey_smoke, data, api(null), coherence_link, dod. Los gates pesados (stack, security, smell, ux, coherence) se cerraron por slice en la era anterior y hoy viven en releases[]; se mantienen como propiedades opcionales para validar historial.",
|
|
58
|
+
"required": ["dor", "tdd", "dod"],
|
|
59
|
+
"properties": {
|
|
60
|
+
"dor": { "type": "boolean" },
|
|
61
|
+
"tdd": { "type": "boolean" },
|
|
62
|
+
"journey_smoke": { "type": "boolean", "description": "El backbone-hasta-aquí camina end-to-end (verificado con la skill verify/run)." },
|
|
63
|
+
"coherence_link": { "type": "boolean", "description": "Enlace change↔épica válido (change-epic-coherence, barato, por slice)." },
|
|
64
|
+
"data": { "type": "boolean" },
|
|
65
|
+
"api": { "type": ["boolean", "null"], "description": "null = N/A (slice sin endpoints)." },
|
|
66
|
+
"ux": { "type": ["boolean", "null"], "description": "null = N/A (slice sin UI). Legado: hoy se audita en releases[]." },
|
|
67
|
+
"stack": { "type": "boolean", "description": "Legado por-slice; deps las cubre el hook stack-guard.sh, la arquitectura se audita en releases[]." },
|
|
68
|
+
"security": { "type": "boolean", "description": "Legado por-slice; hoy se audita en releases[]." },
|
|
69
|
+
"smell": { "type": "boolean", "description": "Legado por-slice; hoy se audita en releases[]." },
|
|
70
|
+
"coherence": { "type": "boolean", "description": "Legado por-slice (trazabilidad 3-way completa); hoy se audita en releases[]." },
|
|
71
|
+
"dod": { "type": "boolean" }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"updated_at": { "type": "string", "format": "date-time" },
|
|
75
|
+
"updated_by": { "type": "string", "description": "Agente o hook que escribió el estado." },
|
|
76
|
+
"notes": { "type": "string", "description": "Nota libre opcional (p.ej. changes/branches adicionales de una épica construida en varios pasos)." }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"release": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"additionalProperties": false,
|
|
82
|
+
"required": ["release_id", "epicas", "status", "created_at", "updated_by"],
|
|
83
|
+
"properties": {
|
|
84
|
+
"release_id": { "type": "string", "description": "Mapea a una línea de release del Story Map (p.ej. R1-mvp)." },
|
|
85
|
+
"epicas": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"description": "Épicas cubiertas por esta release.",
|
|
88
|
+
"items": { "type": "string", "pattern": "^EP-[0-9]{3}$" },
|
|
89
|
+
"minItems": 1,
|
|
90
|
+
"uniqueItems": true
|
|
91
|
+
},
|
|
92
|
+
"status": { "type": "string", "enum": ["pending", "passed", "failed"] },
|
|
93
|
+
"gates": {
|
|
94
|
+
"type": "object",
|
|
95
|
+
"additionalProperties": false,
|
|
96
|
+
"description": "Gates pesados del Release Gate (outer loop). Ausentes mientras status=pending.",
|
|
97
|
+
"properties": {
|
|
98
|
+
"security": { "type": ["boolean", "null"] },
|
|
99
|
+
"smell": { "type": ["boolean", "null"] },
|
|
100
|
+
"ux": { "type": ["boolean", "null"], "description": "null = N/A (release sin UI)." },
|
|
101
|
+
"coherence": { "type": ["boolean", "null"] },
|
|
102
|
+
"stack_arch": { "type": ["boolean", "null"] },
|
|
103
|
+
"integration": { "type": ["boolean", "null"], "description": "Journey completo recorrido con deps reales." }
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"created_at": { "type": "string", "format": "date-time" },
|
|
107
|
+
"updated_by": { "type": "string" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
<!-- BEGIN trycore-build-harness v{{BUILD_HARNESS_VERSION}} -->
|
|
4
|
+
## Arnés de construcción (Trycore Build Harness)
|
|
5
|
+
|
|
6
|
+
Este proyecto usa el arnés `@trycore/spec-build-harness` para **construir** sobre la discovery
|
|
7
|
+
(compañero de `@trycore/spec-product-flow`: Discovery → Construcción). Modelo de **dos loops**:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Inner loop (por épica EP-XXX): DoR → OpenSpec change → TDD → journey-smoke → api/data → DoD → PR + archive
|
|
11
|
+
Outer loop (por release): Release Gate (seguridad · diseño · UX · coherencia triple · arquitectura · integración)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- **Unidad de construcción**: la épica (`EP-XXX`). Un slice = una épica = un OpenSpec change = una rama = un PR.
|
|
15
|
+
- **Una sola fuente de verdad**: `.claude/state/build-state.json` (schema + protocolo en `.claude/state/README.md`).
|
|
16
|
+
- **Skills**: `building-a-slice` (inner loop), `releasing-a-version` (outer loop), `openspec-*` (ciclo de changes).
|
|
17
|
+
- **Agentes** en `.claude/agents/build/`; **comandos** `/opsx:*`; gates automatizados por **hooks** en `.claude/hooks/build/`.
|
|
18
|
+
|
|
19
|
+
### Slash commands
|
|
20
|
+
|
|
21
|
+
| Comando | Propósito |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `/build:onboard` | Parametriza el dominio del arnés (rellena el bloque de dominio de abajo) y escribe memoria |
|
|
24
|
+
| `/opsx:explore` `/opsx:new` `/opsx:continue` `/opsx:apply` | Ciclo OpenSpec: explorar → crear change → artefactos → implementar |
|
|
25
|
+
| `/opsx:verify` `/opsx:archive` `/opsx:sync` `/opsx:ff` `/opsx:bulk-archive` | Verificar, archivar, sincronizar specs |
|
|
26
|
+
|
|
27
|
+
### Reglas duras (no negociables)
|
|
28
|
+
|
|
29
|
+
1. **GitHub Flow estricto**: `main` siempre desplegable; integración solo por PR (el hook `gitflow-guard.sh` bloquea commit/push directo a `main`).
|
|
30
|
+
2. El enlace change↔épica va en el bloque `## Trazabilidad` del `proposal.md`, **nunca** en frontmatter YAML (rompe `openspec validate`).
|
|
31
|
+
3. Las dependencias se vigilan contra `.claude/config/stack-allowlist.json` (hook `stack-guard.sh`), derivado de la sección de requisitos técnicos del PRD.
|
|
32
|
+
4. Las revisiones pesadas (seguridad/diseño/UX/coherencia triple/arquitectura/integración) corren **una vez por release** (outer loop), no por épica.
|
|
33
|
+
5. Si una regla del arnés contradice la metodología Trycore (`METODOLOGIA.md`), **gana la metodología**.
|
|
34
|
+
|
|
35
|
+
### Bloque de dominio (lo resuelve `/build:onboard`)
|
|
36
|
+
|
|
37
|
+
Estos puntos de extensión los leen los agentes `security-reviewer`, `stack-guardian`,
|
|
38
|
+
`data-consistency-checker`, `ux-krug-reviewer` y `simple-design-reviewer`:
|
|
39
|
+
|
|
40
|
+
- **PRD técnico (fuente del stack)**: {{PRD_TECH_PATH}}
|
|
41
|
+
- **Capa de servicios externos / IA (frontera)**: {{EXTERNAL_SERVICE_LAYER}}
|
|
42
|
+
- **Lógica que debe ser determinista (no-IA)**: {{DETERMINISTIC_LAYER}}
|
|
43
|
+
- **Categorías de datos sensibles / PII reguladas**: {{SENSITIVE_DATA_CATEGORIES}}
|
|
44
|
+
- **Secretos server-side**: {{SERVER_SIDE_SECRETS}}
|
|
45
|
+
- **Decisiones de alto impacto que exigen explicabilidad UX**: {{HIGH_STAKES_DECISIONS}}
|
|
46
|
+
|
|
47
|
+
(Si aparecen como `{{...}}`, ejecuta `/build:onboard` para parametrizarlos.)
|
|
48
|
+
|
|
49
|
+
### Requisitos
|
|
50
|
+
|
|
51
|
+
- `openspec` CLI instalado (`npm i -g @fission-ai/openspec`) — lo usan `/opsx:*` y las skills `openspec-*`.
|
|
52
|
+
- `python3` y `git` disponibles — los usan los hooks de `.claude/hooks/build/`.
|
|
53
|
+
- Verifica con `trycore-build doctor`.
|
|
54
|
+
|
|
55
|
+
<!-- END trycore-build-harness -->
|
|
56
|
+
|
|
57
|
+
<!-- A partir de aquí, el equipo del proyecto puede agregar instrucciones específicas del cliente. -->
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"info": {
|
|
3
|
+
"name": "<proyecto> — contratos API",
|
|
4
|
+
"description": "Plantilla de colección Postman/Newman. Sustituye con los endpoints y aserciones del contrato del consumidor. La usa el agente api-contract-tester.",
|
|
5
|
+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
|
6
|
+
},
|
|
7
|
+
"item": [
|
|
8
|
+
{
|
|
9
|
+
"name": "<endpoint de ejemplo>",
|
|
10
|
+
"request": {
|
|
11
|
+
"method": "GET",
|
|
12
|
+
"url": "{{base_url}}/<ruta>"
|
|
13
|
+
},
|
|
14
|
+
"event": [
|
|
15
|
+
{
|
|
16
|
+
"listen": "test",
|
|
17
|
+
"script": {
|
|
18
|
+
"exec": [
|
|
19
|
+
"pm.test('status 200', () => pm.response.to.have.status(200));",
|
|
20
|
+
"// Añade aserciones del contrato del consumidor (forma de la respuesta, casos borde)."
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"variable": [{ "key": "base_url", "value": "http://localhost:3000" }]
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "ESPEJO DOCUMENTAL del bloque que `trycore-build init` mergea en el settings.json del consumidor (canal CLI). La fuente de verdad es src/lib/settings-merge.ts. Misma cadena de comando que hooks/build-harness.json (canal plugin) → si se instalan ambos canales, Claude Code deduplica y el hook dispara UNA vez. Permisos MÍNIMOS y enumerados (sin mcp__* ni rutas absolutas).",
|
|
3
|
+
"permissions": {
|
|
4
|
+
"allow": [
|
|
5
|
+
"Bash(openspec validate *)",
|
|
6
|
+
"Bash(openspec list *)",
|
|
7
|
+
"Bash(openspec show *)"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"hooks": {
|
|
11
|
+
"SessionStart": [
|
|
12
|
+
{ "matcher": "startup|clear|compact", "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/load-build-state.sh\"" } ] }
|
|
13
|
+
],
|
|
14
|
+
"PreToolUse": [
|
|
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\"" } ] }
|
|
17
|
+
],
|
|
18
|
+
"PostToolUse": [
|
|
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\"" } ] }
|
|
20
|
+
],
|
|
21
|
+
"Stop": [
|
|
22
|
+
{ "matcher": ".*", "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/build-gate-check.sh\"" } ] }
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Waiver — Release <RELEASE_ID> (<EP-XXX..EP-YYY>)
|
|
2
|
+
|
|
3
|
+
> Plantilla. Un waiver documenta una excepción CONSCIENTE a un gate (típicamente seguridad)
|
|
4
|
+
> aceptada para una release concreta, con su mitigación y fecha de caducidad.
|
|
5
|
+
|
|
6
|
+
## Contexto
|
|
7
|
+
|
|
8
|
+
<Por qué se acepta la excepción para esta release — ej. demo, entorno sin datos reales.>
|
|
9
|
+
|
|
10
|
+
## Hallazgos exceptuados
|
|
11
|
+
|
|
12
|
+
| Severidad | Hallazgo | Acción de remediación | Responsable | Vence |
|
|
13
|
+
|---|---|---|---|---|
|
|
14
|
+
| ALTO | <descripción> | <qué se hará y cuándo> | <rol/persona> | <release/fecha> |
|
|
15
|
+
|
|
16
|
+
## Mitigaciones aplicadas
|
|
17
|
+
|
|
18
|
+
- <mitigación 1>
|
|
19
|
+
- <mitigación 2>
|
|
20
|
+
|
|
21
|
+
## Hallazgos NO exceptuados (al backlog)
|
|
22
|
+
|
|
23
|
+
- <medio/bajo que no bloquean pero quedan registrados>
|
|
24
|
+
|
|
25
|
+
## Vigencia
|
|
26
|
+
|
|
27
|
+
Este waiver aplica SOLO a la release **<RELEASE_ID>**. Caduca al <condición/fecha>.
|