specleap-framework 2.1.0 → 2.1.5
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/.agents/backend.md +3 -3
- package/.agents/frontend.md +2 -2
- package/.agents/producto.md +9 -11
- package/.claude/hooks/spec-guard.sh +132 -0
- package/.claude/settings.json.template +15 -0
- package/.clinerules +3 -3
- package/.coderabbit.yaml +2 -4
- package/.commands/compliance.md +89 -0
- package/.commands/inicio.md +15 -15
- package/.commands/nuevo/README.md +2 -2
- package/.commands/planificar.md +1 -1
- package/.continue/rules/04-git-workflow.md +5 -5
- package/.continuerules +3 -4
- package/.cursorrules +1 -1
- package/.github/copilot-instructions.md +1 -1
- package/.specleap/i18n/en.json +177 -0
- package/.specleap/i18n/es.json +177 -0
- package/.specleap/i18n.sh +63 -0
- package/CHANGELOG.md +276 -0
- package/CLAUDE.md +54 -13
- package/README.md +169 -528
- package/SETUP.md +16 -13
- package/openspec/INDEX.md +53 -0
- package/openspec/README.md +104 -0
- package/openspec/SPEC-FORMAT.md +168 -0
- package/openspec/changes/.gitkeep +0 -0
- package/openspec/cli/COMMAND_REFERENCE.md +817 -0
- package/openspec/cli/README.md +189 -0
- package/openspec/cli/apply.sh +229 -0
- package/openspec/cli/archive.sh +240 -0
- package/openspec/cli/code-review.sh +207 -0
- package/openspec/cli/common.sh +171 -0
- package/openspec/cli/enrich.sh +188 -0
- package/openspec/cli/ff.sh +329 -0
- package/openspec/cli/new.sh +260 -0
- package/openspec/cli/openspec +82 -0
- package/openspec/cli/report.sh +244 -0
- package/openspec/cli/status.sh +178 -0
- package/openspec/cli/verify.sh +246 -0
- package/openspec/config.yaml +76 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/00-original-user-story.md +5 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/01-refined-user-story.md +106 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/README.md +333 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/design.md +461 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/proposal.md +124 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/specs/functional/F001-authentication.spec.md +399 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/specs/technical/T001-jwt-implementation.spec.md +606 -0
- package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/tasks.md +433 -0
- package/openspec/examples/MERMAID_DIAGRAMS.md +481 -0
- package/openspec/examples/README.md +334 -0
- package/openspec/specs/functional/.gitkeep +0 -0
- package/openspec/specs/integration/.gitkeep +0 -0
- package/openspec/specs/security/.gitkeep +0 -0
- package/openspec/specs/technical/.gitkeep +0 -0
- package/openspec/templates/.coderabbit.yaml +259 -0
- package/openspec/templates/design.md +181 -0
- package/openspec/templates/proposal.md +79 -0
- package/openspec/templates/tasks.md +193 -0
- package/package.json +10 -5
- package/rules/git-workflow.md +3 -3
- package/rules/session-protocol.md +3 -3
- package/scripts/README.md +13 -25
- package/scripts/compliance-audit.sh +325 -0
- package/scripts/generate-contract.sh +4 -4
- package/scripts/install-skills.sh +12 -11
- package/scripts/lib/render-contrato.py +1 -1
- package/scripts/quality-baseline.sh +210 -0
- package/scripts/quality-healing.sh +241 -0
- package/setup.sh +3 -3
- package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/search.cpython-314.pyc +0 -0
- package/scripts/lib/jira-project-utils.sh +0 -222
- package/scripts/setup-mcp.sh +0 -654
- package/scripts/test-cuestionario.sh +0 -428
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# openspec ff — Fast-forward: generar propuesta completa con AI
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
7
|
+
|
|
8
|
+
source "$SCRIPT_DIR/common.sh"
|
|
9
|
+
|
|
10
|
+
usage() {
|
|
11
|
+
cat <<EOF
|
|
12
|
+
openspec ff — Fast-forward: generar propuesta completa con AI
|
|
13
|
+
|
|
14
|
+
USAGE:
|
|
15
|
+
openspec ff <CHANGE-ID> [options]
|
|
16
|
+
|
|
17
|
+
OPTIONS:
|
|
18
|
+
--model <model> Modelo AI a usar (default: auto)
|
|
19
|
+
--skip-proposal Omitir generación de proposal.md
|
|
20
|
+
--skip-design Omitir generación de design.md
|
|
21
|
+
--skip-tasks Omitir generación de tasks.md
|
|
22
|
+
-h, --help Mostrar ayuda
|
|
23
|
+
|
|
24
|
+
DESCRIPTION:
|
|
25
|
+
Genera automáticamente con AI:
|
|
26
|
+
- proposal.md completo (si tiene user story base)
|
|
27
|
+
- design.md técnico (arquitectura, API, datos)
|
|
28
|
+
- tasks.md desglosado (tareas + estimaciones)
|
|
29
|
+
|
|
30
|
+
IMPORTANTE: Revisa y ajusta la salida del AI antes de aplicar.
|
|
31
|
+
|
|
32
|
+
EXAMPLES:
|
|
33
|
+
openspec ff CHANGE-001
|
|
34
|
+
openspec ff CHANGE-002 --model anthropic/claude-sonnet-4
|
|
35
|
+
openspec ff CHANGE-003 --skip-tasks
|
|
36
|
+
|
|
37
|
+
PREREQUISITES:
|
|
38
|
+
- Propuesta creada con: openspec new
|
|
39
|
+
- Al menos proposal.md con contexto básico
|
|
40
|
+
|
|
41
|
+
EOF
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Parse arguments
|
|
45
|
+
CHANGE_ID=""
|
|
46
|
+
MODEL="auto"
|
|
47
|
+
SKIP_PROPOSAL=false
|
|
48
|
+
SKIP_DESIGN=false
|
|
49
|
+
SKIP_TASKS=false
|
|
50
|
+
|
|
51
|
+
while [[ $# -gt 0 ]]; do
|
|
52
|
+
case $1 in
|
|
53
|
+
-h|--help)
|
|
54
|
+
usage
|
|
55
|
+
exit 0
|
|
56
|
+
;;
|
|
57
|
+
--model)
|
|
58
|
+
MODEL="$2"
|
|
59
|
+
shift 2
|
|
60
|
+
;;
|
|
61
|
+
--skip-proposal)
|
|
62
|
+
SKIP_PROPOSAL=true
|
|
63
|
+
shift
|
|
64
|
+
;;
|
|
65
|
+
--skip-design)
|
|
66
|
+
SKIP_DESIGN=true
|
|
67
|
+
shift
|
|
68
|
+
;;
|
|
69
|
+
--skip-tasks)
|
|
70
|
+
SKIP_TASKS=true
|
|
71
|
+
shift
|
|
72
|
+
;;
|
|
73
|
+
CHANGE-*)
|
|
74
|
+
CHANGE_ID="$1"
|
|
75
|
+
shift
|
|
76
|
+
;;
|
|
77
|
+
*)
|
|
78
|
+
error "Argumento desconocido: $1"
|
|
79
|
+
usage
|
|
80
|
+
exit 1
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
done
|
|
84
|
+
|
|
85
|
+
# Validate
|
|
86
|
+
validate_project
|
|
87
|
+
|
|
88
|
+
if [[ -z "$CHANGE_ID" ]]; then
|
|
89
|
+
error "Debe proporcionar CHANGE-ID"
|
|
90
|
+
usage
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Find change directory
|
|
95
|
+
CHANGE_DIR=$(find "$PROJECT_ROOT/openspec/changes" -maxdepth 1 -type d -name "${CHANGE_ID}-*" | head -n1)
|
|
96
|
+
|
|
97
|
+
if [[ -z "$CHANGE_DIR" ]] || [[ ! -d "$CHANGE_DIR" ]]; then
|
|
98
|
+
error "Propuesta no encontrada: $CHANGE_ID"
|
|
99
|
+
info "Use: openspec new $CHANGE_ID <título>"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
info "Generando propuesta completa para: $CHANGE_ID"
|
|
104
|
+
info "Directorio: $CHANGE_DIR"
|
|
105
|
+
|
|
106
|
+
# Read current proposal for context
|
|
107
|
+
PROPOSAL_FILE="$CHANGE_DIR/proposal.md"
|
|
108
|
+
if [[ ! -f "$PROPOSAL_FILE" ]]; then
|
|
109
|
+
error "proposal.md no encontrado en $CHANGE_DIR"
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
PROPOSAL_CONTENT=$(cat "$PROPOSAL_FILE")
|
|
114
|
+
|
|
115
|
+
# Detect AI CLI
|
|
116
|
+
AI_CMD=""
|
|
117
|
+
if command -v oracle &> /dev/null; then
|
|
118
|
+
AI_CMD="oracle"
|
|
119
|
+
elif command -v ai-cli &> /dev/null; then
|
|
120
|
+
AI_CMD="ai-cli"
|
|
121
|
+
else
|
|
122
|
+
error "No se encontró CLI de AI (oracle, ai-cli)"
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# Generate design.md
|
|
127
|
+
if [[ "$SKIP_DESIGN" == false ]]; then
|
|
128
|
+
step "Generando design.md con AI..."
|
|
129
|
+
|
|
130
|
+
DESIGN_PROMPT=$(cat <<EOF
|
|
131
|
+
Eres un arquitecto de software experto.
|
|
132
|
+
|
|
133
|
+
Basándote en esta PROPUESTA:
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
$PROPOSAL_CONTENT
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
Genera un DISEÑO TÉCNICO completo siguiendo este formato:
|
|
140
|
+
|
|
141
|
+
# [$CHANGE_ID] Diseño Técnico: [Título]
|
|
142
|
+
|
|
143
|
+
## Resumen del Diseño
|
|
144
|
+
Descripción técnica de alto nivel.
|
|
145
|
+
|
|
146
|
+
## Arquitectura
|
|
147
|
+
|
|
148
|
+
### Diagrama de Componentes
|
|
149
|
+
\`\`\`
|
|
150
|
+
[Diagrama ASCII de componentes y flujo]
|
|
151
|
+
\`\`\`
|
|
152
|
+
|
|
153
|
+
### Componentes Afectados
|
|
154
|
+
| Componente | Tipo de Cambio | Descripción |
|
|
155
|
+
|------------|----------------|-------------|
|
|
156
|
+
| ... | ... | ... |
|
|
157
|
+
|
|
158
|
+
## Modelo de Datos
|
|
159
|
+
|
|
160
|
+
### Nuevas Entidades
|
|
161
|
+
\`\`\`typescript
|
|
162
|
+
interface NuevaEntidad {
|
|
163
|
+
// ...
|
|
164
|
+
}
|
|
165
|
+
\`\`\`
|
|
166
|
+
|
|
167
|
+
### Migraciones de Base de Datos
|
|
168
|
+
\`\`\`sql
|
|
169
|
+
-- Migration: ...
|
|
170
|
+
\`\`\`
|
|
171
|
+
|
|
172
|
+
## API / Interfaces
|
|
173
|
+
|
|
174
|
+
### Nuevos Endpoints
|
|
175
|
+
\`\`\`
|
|
176
|
+
POST /api/v1/...
|
|
177
|
+
GET /api/v1/...
|
|
178
|
+
\`\`\`
|
|
179
|
+
|
|
180
|
+
### Contratos de API
|
|
181
|
+
\`\`\`typescript
|
|
182
|
+
interface Request { ... }
|
|
183
|
+
interface Response { ... }
|
|
184
|
+
\`\`\`
|
|
185
|
+
|
|
186
|
+
## Seguridad
|
|
187
|
+
- Autenticación/autorización
|
|
188
|
+
- Validación de inputs
|
|
189
|
+
- Consideraciones de seguridad
|
|
190
|
+
|
|
191
|
+
## Performance
|
|
192
|
+
- Estimaciones de carga
|
|
193
|
+
- Optimizaciones necesarias
|
|
194
|
+
|
|
195
|
+
## Testing Strategy
|
|
196
|
+
- Unit tests
|
|
197
|
+
- Integration tests
|
|
198
|
+
- E2E tests (si aplica)
|
|
199
|
+
|
|
200
|
+
Usa español técnico. Sé específico y pragmático.
|
|
201
|
+
EOF
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
DESIGN_CONTENT=""
|
|
205
|
+
case $AI_CMD in
|
|
206
|
+
oracle)
|
|
207
|
+
DESIGN_CONTENT=$(echo "$DESIGN_PROMPT" | oracle --model "$MODEL" --no-stream)
|
|
208
|
+
;;
|
|
209
|
+
ai-cli)
|
|
210
|
+
DESIGN_CONTENT=$(echo "$DESIGN_PROMPT" | ai-cli prompt --model "$MODEL")
|
|
211
|
+
;;
|
|
212
|
+
esac
|
|
213
|
+
|
|
214
|
+
if [[ -n "$DESIGN_CONTENT" ]]; then
|
|
215
|
+
echo "$DESIGN_CONTENT" > "$CHANGE_DIR/design.md"
|
|
216
|
+
success "design.md generado"
|
|
217
|
+
else
|
|
218
|
+
warning "No se pudo generar design.md"
|
|
219
|
+
fi
|
|
220
|
+
fi
|
|
221
|
+
|
|
222
|
+
# Generate tasks.md
|
|
223
|
+
if [[ "$SKIP_TASKS" == false ]]; then
|
|
224
|
+
step "Generando tasks.md con AI..."
|
|
225
|
+
|
|
226
|
+
# Read design for context
|
|
227
|
+
DESIGN_CONTENT=""
|
|
228
|
+
if [[ -f "$CHANGE_DIR/design.md" ]]; then
|
|
229
|
+
DESIGN_CONTENT=$(cat "$CHANGE_DIR/design.md")
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
TASKS_PROMPT=$(cat <<EOF
|
|
233
|
+
Eres un Tech Lead experto en planificación de desarrollo.
|
|
234
|
+
|
|
235
|
+
Basándote en:
|
|
236
|
+
|
|
237
|
+
PROPUESTA:
|
|
238
|
+
---
|
|
239
|
+
$PROPOSAL_CONTENT
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
DISEÑO:
|
|
243
|
+
---
|
|
244
|
+
$DESIGN_CONTENT
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
Genera un DESGLOSE DE TAREAS completo siguiendo este formato:
|
|
248
|
+
|
|
249
|
+
# [$CHANGE_ID] Tareas: [Título]
|
|
250
|
+
|
|
251
|
+
## Resumen
|
|
252
|
+
Total de tareas: X
|
|
253
|
+
Estimación total: X story points
|
|
254
|
+
|
|
255
|
+
## Tareas
|
|
256
|
+
|
|
257
|
+
### 🏗️ Setup & Scaffolding
|
|
258
|
+
|
|
259
|
+
#### TASK-001: [Título de tarea]
|
|
260
|
+
- **Estimación:** X SP
|
|
261
|
+
- **Estado:** ⬜ Pendiente
|
|
262
|
+
- **Branch:** \`feat/$CHANGE_ID-...\`
|
|
263
|
+
|
|
264
|
+
**Subtareas:**
|
|
265
|
+
- [ ] Subtarea 1
|
|
266
|
+
- [ ] Subtarea 2
|
|
267
|
+
|
|
268
|
+
**Criterios de aceptación:**
|
|
269
|
+
- [ ] Criterio 1
|
|
270
|
+
- [ ] Criterio 2
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
### 📊 Backend / API
|
|
275
|
+
[Tareas de backend]
|
|
276
|
+
|
|
277
|
+
### 🎨 Frontend / UI
|
|
278
|
+
[Tareas de frontend]
|
|
279
|
+
|
|
280
|
+
### 🧪 Testing
|
|
281
|
+
[Tareas de testing]
|
|
282
|
+
|
|
283
|
+
### 📚 Documentación
|
|
284
|
+
[Tareas de documentación]
|
|
285
|
+
|
|
286
|
+
## Dependencias entre Tareas
|
|
287
|
+
\`\`\`
|
|
288
|
+
TASK-001 → TASK-002 → TASK-003
|
|
289
|
+
\`\`\`
|
|
290
|
+
|
|
291
|
+
## Testing Report (Template)
|
|
292
|
+
| Suite | Tests | Passed | Failed | Coverage |
|
|
293
|
+
|-------|-------|--------|--------|----------|
|
|
294
|
+
| Unit | 0 | 0 | 0 | 0% |
|
|
295
|
+
|
|
296
|
+
Usa español. Estima realísticamente (1-5 SP por tarea).
|
|
297
|
+
EOF
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
TASKS_CONTENT=""
|
|
301
|
+
case $AI_CMD in
|
|
302
|
+
oracle)
|
|
303
|
+
TASKS_CONTENT=$(echo "$TASKS_PROMPT" | oracle --model "$MODEL" --no-stream)
|
|
304
|
+
;;
|
|
305
|
+
ai-cli)
|
|
306
|
+
TASKS_CONTENT=$(echo "$TASKS_PROMPT" | ai-cli prompt --model "$MODEL")
|
|
307
|
+
;;
|
|
308
|
+
esac
|
|
309
|
+
|
|
310
|
+
if [[ -n "$TASKS_CONTENT" ]]; then
|
|
311
|
+
echo "$TASKS_CONTENT" > "$CHANGE_DIR/tasks.md"
|
|
312
|
+
success "tasks.md generado"
|
|
313
|
+
else
|
|
314
|
+
warning "No se pudo generar tasks.md"
|
|
315
|
+
fi
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
success "Fast-forward completado para $CHANGE_ID"
|
|
319
|
+
info ""
|
|
320
|
+
info "IMPORTANTE: Revisa y ajusta los archivos generados antes de continuar"
|
|
321
|
+
info ""
|
|
322
|
+
info "Archivos actualizados:"
|
|
323
|
+
[[ "$SKIP_DESIGN" == false ]] && info " - design.md"
|
|
324
|
+
[[ "$SKIP_TASKS" == false ]] && info " - tasks.md"
|
|
325
|
+
info ""
|
|
326
|
+
info "Próximos pasos:"
|
|
327
|
+
info " 1. Revisar y ajustar diseño/tareas"
|
|
328
|
+
info " 2. openspec verify $CHANGE_ID"
|
|
329
|
+
info " 3. openspec apply $CHANGE_ID"
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# openspec new — Crear nueva propuesta de cambio
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
7
|
+
|
|
8
|
+
source "$SCRIPT_DIR/common.sh"
|
|
9
|
+
|
|
10
|
+
usage() {
|
|
11
|
+
cat <<EOF
|
|
12
|
+
openspec new — Crear nueva propuesta de cambio
|
|
13
|
+
|
|
14
|
+
USAGE:
|
|
15
|
+
openspec new [CHANGE-ID] <título> [options]
|
|
16
|
+
openspec new --auto <título>
|
|
17
|
+
|
|
18
|
+
OPTIONS:
|
|
19
|
+
--auto Generar ID automáticamente
|
|
20
|
+
--from <file> Crear desde user story refinada
|
|
21
|
+
--ticket <id> Asociar con un ID de ticket (ej: app-tienda-23)
|
|
22
|
+
--priority <level> Prioridad (critical/high/medium/low)
|
|
23
|
+
--author <name> Autor (default: git user)
|
|
24
|
+
-h, --help Mostrar ayuda
|
|
25
|
+
|
|
26
|
+
DESCRIPTION:
|
|
27
|
+
Crea una nueva propuesta de cambio con estructura completa:
|
|
28
|
+
- proposal.md (QUÉ y POR QUÉ)
|
|
29
|
+
- design.md (CÓMO técnico)
|
|
30
|
+
- tasks.md (Tareas y Testing Report)
|
|
31
|
+
- specs/ (Delta specs si aplica)
|
|
32
|
+
|
|
33
|
+
EXAMPLES:
|
|
34
|
+
openspec new CHANGE-001 "Implementar autenticación JWT"
|
|
35
|
+
openspec new --auto "Sistema de notificaciones" --ticket app-tienda-23
|
|
36
|
+
openspec new CHANGE-002 --from stories/auth-refined.md
|
|
37
|
+
|
|
38
|
+
OUTPUT:
|
|
39
|
+
openspec/changes/CHANGE-XXX-nombre/
|
|
40
|
+
├── proposal.md
|
|
41
|
+
├── design.md
|
|
42
|
+
├── tasks.md
|
|
43
|
+
└── specs/ (si aplica)
|
|
44
|
+
|
|
45
|
+
EOF
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Parse arguments
|
|
49
|
+
CHANGE_ID=""
|
|
50
|
+
TITLE=""
|
|
51
|
+
AUTO_ID=false
|
|
52
|
+
FROM_FILE=""
|
|
53
|
+
TICKET_ID=""
|
|
54
|
+
PRIORITY="medium"
|
|
55
|
+
AUTHOR=$(git config user.name 2>/dev/null || echo "Unknown")
|
|
56
|
+
|
|
57
|
+
while [[ $# -gt 0 ]]; do
|
|
58
|
+
case $1 in
|
|
59
|
+
-h|--help)
|
|
60
|
+
usage
|
|
61
|
+
exit 0
|
|
62
|
+
;;
|
|
63
|
+
--auto)
|
|
64
|
+
AUTO_ID=true
|
|
65
|
+
shift
|
|
66
|
+
;;
|
|
67
|
+
--from)
|
|
68
|
+
FROM_FILE="$2"
|
|
69
|
+
shift 2
|
|
70
|
+
;;
|
|
71
|
+
--ticket)
|
|
72
|
+
TICKET_ID="$2"
|
|
73
|
+
shift 2
|
|
74
|
+
;;
|
|
75
|
+
--priority)
|
|
76
|
+
PRIORITY="$2"
|
|
77
|
+
shift 2
|
|
78
|
+
;;
|
|
79
|
+
--author)
|
|
80
|
+
AUTHOR="$2"
|
|
81
|
+
shift 2
|
|
82
|
+
;;
|
|
83
|
+
CHANGE-*)
|
|
84
|
+
CHANGE_ID="$1"
|
|
85
|
+
shift
|
|
86
|
+
;;
|
|
87
|
+
*)
|
|
88
|
+
if [[ -z "$TITLE" ]]; then
|
|
89
|
+
TITLE="$1"
|
|
90
|
+
else
|
|
91
|
+
error "Argumento inesperado: $1"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
shift
|
|
95
|
+
;;
|
|
96
|
+
esac
|
|
97
|
+
done
|
|
98
|
+
|
|
99
|
+
# Validate inputs
|
|
100
|
+
validate_project
|
|
101
|
+
|
|
102
|
+
if [[ -z "$TITLE" ]]; then
|
|
103
|
+
error "Debe proporcionar un título para la propuesta"
|
|
104
|
+
usage
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Generate or validate ID
|
|
109
|
+
if [[ "$AUTO_ID" == true ]]; then
|
|
110
|
+
CHANGE_NUM=$(get_next_id "change")
|
|
111
|
+
CHANGE_ID="CHANGE-$CHANGE_NUM"
|
|
112
|
+
info "ID generado automáticamente: $CHANGE_ID"
|
|
113
|
+
elif [[ -z "$CHANGE_ID" ]]; then
|
|
114
|
+
error "Debe proporcionar CHANGE-ID o usar --auto"
|
|
115
|
+
usage
|
|
116
|
+
exit 1
|
|
117
|
+
elif [[ ! $CHANGE_ID =~ ^CHANGE-[0-9]{4}$ ]]; then
|
|
118
|
+
error "Formato de ID inválido. Use: CHANGE-XXXX (ej: CHANGE-0001)"
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Create slug from title
|
|
123
|
+
SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//')
|
|
124
|
+
CHANGE_DIR="$PROJECT_ROOT/openspec/changes/${CHANGE_ID}-${SLUG}"
|
|
125
|
+
|
|
126
|
+
# Check if already exists
|
|
127
|
+
if [[ -d "$CHANGE_DIR" ]]; then
|
|
128
|
+
error "La propuesta ya existe: $CHANGE_DIR"
|
|
129
|
+
exit 1
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
info "Creando propuesta: $CHANGE_ID — $TITLE"
|
|
133
|
+
|
|
134
|
+
# Create directory structure
|
|
135
|
+
ensure_dir "$CHANGE_DIR"
|
|
136
|
+
ensure_dir "$CHANGE_DIR/specs"
|
|
137
|
+
|
|
138
|
+
# Get current date
|
|
139
|
+
DATE=$(current_date)
|
|
140
|
+
|
|
141
|
+
# Create proposal.md from template
|
|
142
|
+
step "Creando proposal.md..."
|
|
143
|
+
TEMPLATE_PROPOSAL="$PROJECT_ROOT/openspec/templates/proposal.md"
|
|
144
|
+
cp "$TEMPLATE_PROPOSAL" "$CHANGE_DIR/proposal.md"
|
|
145
|
+
|
|
146
|
+
# Replace placeholders
|
|
147
|
+
sed -i.bak \
|
|
148
|
+
-e "s/CHANGE-XXX/$CHANGE_ID/g" \
|
|
149
|
+
-e "s/Título del Cambio/$TITLE/g" \
|
|
150
|
+
-e "s/YYYY-MM-DD/$DATE/g" \
|
|
151
|
+
-e "s/nombre/$AUTHOR/g" \
|
|
152
|
+
-e "s/TICKET-XXX/${TICKET_ID:-TICKET-XXX}/g" \
|
|
153
|
+
-e "s/medium/$PRIORITY/g" \
|
|
154
|
+
"$CHANGE_DIR/proposal.md"
|
|
155
|
+
rm "$CHANGE_DIR/proposal.md.bak"
|
|
156
|
+
|
|
157
|
+
# Create design.md from template
|
|
158
|
+
step "Creando design.md..."
|
|
159
|
+
TEMPLATE_DESIGN="$PROJECT_ROOT/openspec/templates/design.md"
|
|
160
|
+
cp "$TEMPLATE_DESIGN" "$CHANGE_DIR/design.md"
|
|
161
|
+
|
|
162
|
+
sed -i.bak \
|
|
163
|
+
-e "s/CHANGE-XXX/$CHANGE_ID/g" \
|
|
164
|
+
-e "s/Título del Cambio/$TITLE/g" \
|
|
165
|
+
-e "s/YYYY-MM-DD/$DATE/g" \
|
|
166
|
+
-e "s/nombre/$AUTHOR/g" \
|
|
167
|
+
"$CHANGE_DIR/design.md"
|
|
168
|
+
rm "$CHANGE_DIR/design.md.bak"
|
|
169
|
+
|
|
170
|
+
# Create tasks.md from template
|
|
171
|
+
step "Creando tasks.md..."
|
|
172
|
+
TEMPLATE_TASKS="$PROJECT_ROOT/openspec/templates/tasks.md"
|
|
173
|
+
cp "$TEMPLATE_TASKS" "$CHANGE_DIR/tasks.md"
|
|
174
|
+
|
|
175
|
+
sed -i.bak \
|
|
176
|
+
-e "s/CHANGE-XXX/$CHANGE_ID/g" \
|
|
177
|
+
-e "s/Título del Cambio/$TITLE/g" \
|
|
178
|
+
-e "s/YYYY-MM-DD/$DATE/g" \
|
|
179
|
+
-e "s/TICKET-XXX/${TICKET_ID:-TICKET-XXX}/g" \
|
|
180
|
+
"$CHANGE_DIR/tasks.md"
|
|
181
|
+
rm "$CHANGE_DIR/tasks.md.bak"
|
|
182
|
+
|
|
183
|
+
# If created from refined user story, populate proposal
|
|
184
|
+
if [[ -n "$FROM_FILE" ]]; then
|
|
185
|
+
if [[ -f "$FROM_FILE" ]]; then
|
|
186
|
+
step "Importando user story refinada desde $FROM_FILE..."
|
|
187
|
+
# Append refined content to proposal
|
|
188
|
+
echo -e "\n## User Story Refinada (Importada)\n" >> "$CHANGE_DIR/proposal.md"
|
|
189
|
+
cat "$FROM_FILE" >> "$CHANGE_DIR/proposal.md"
|
|
190
|
+
else
|
|
191
|
+
warning "Archivo no encontrado: $FROM_FILE"
|
|
192
|
+
fi
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Create README in change folder
|
|
196
|
+
cat > "$CHANGE_DIR/README.md" <<EOF
|
|
197
|
+
# $CHANGE_ID — $TITLE
|
|
198
|
+
|
|
199
|
+
| Campo | Valor |
|
|
200
|
+
|-------|-------|
|
|
201
|
+
| ID | $CHANGE_ID |
|
|
202
|
+
| Título | $TITLE |
|
|
203
|
+
| Estado | draft |
|
|
204
|
+
| Autor | $AUTHOR |
|
|
205
|
+
| Fecha | $DATE |
|
|
206
|
+
| Prioridad | $PRIORITY |
|
|
207
|
+
| Ticket | ${TICKET_ID:-N/A} |
|
|
208
|
+
|
|
209
|
+
## Archivos
|
|
210
|
+
|
|
211
|
+
- [proposal.md](./proposal.md) — QUÉ y POR QUÉ
|
|
212
|
+
- [design.md](./design.md) — CÓMO (diseño técnico)
|
|
213
|
+
- [tasks.md](./tasks.md) — Tareas y Testing Report
|
|
214
|
+
- specs/ — Delta specs (si aplica)
|
|
215
|
+
|
|
216
|
+
## Próximos Pasos
|
|
217
|
+
|
|
218
|
+
1. Completar \`proposal.md\` (contexto, problema, solución, alcance)
|
|
219
|
+
2. Completar \`design.md\` (arquitectura, API, datos, seguridad)
|
|
220
|
+
3. Desglosar tareas en \`tasks.md\`
|
|
221
|
+
4. Crear delta specs si modifica specs existentes
|
|
222
|
+
5. Solicitar aprobación: \`openspec verify $CHANGE_ID\`
|
|
223
|
+
6. Implementar: \`openspec apply $CHANGE_ID\`
|
|
224
|
+
|
|
225
|
+
## Comandos
|
|
226
|
+
|
|
227
|
+
\`\`\`bash
|
|
228
|
+
# Fast-forward: generar propuesta completa con AI
|
|
229
|
+
openspec ff $CHANGE_ID
|
|
230
|
+
|
|
231
|
+
# Aplicar propuesta (crear branch, implementar)
|
|
232
|
+
openspec apply $CHANGE_ID
|
|
233
|
+
|
|
234
|
+
# Verificar tests y specs
|
|
235
|
+
openspec verify $CHANGE_ID
|
|
236
|
+
|
|
237
|
+
# Code review
|
|
238
|
+
openspec code-review $CHANGE_ID
|
|
239
|
+
|
|
240
|
+
# Archivar al completar
|
|
241
|
+
openspec archive $CHANGE_ID
|
|
242
|
+
\`\`\`
|
|
243
|
+
EOF
|
|
244
|
+
|
|
245
|
+
success "Propuesta creada exitosamente: $CHANGE_DIR"
|
|
246
|
+
info ""
|
|
247
|
+
info "Archivos creados:"
|
|
248
|
+
info " - proposal.md"
|
|
249
|
+
info " - design.md"
|
|
250
|
+
info " - tasks.md"
|
|
251
|
+
info " - README.md"
|
|
252
|
+
info ""
|
|
253
|
+
info "Próximos pasos:"
|
|
254
|
+
info " 1. Editar proposal.md (QUÉ y POR QUÉ)"
|
|
255
|
+
info " 2. Editar design.md (CÓMO)"
|
|
256
|
+
info " 3. Desglosar tareas en tasks.md"
|
|
257
|
+
info " 4. (Opcional) openspec ff $CHANGE_ID para generar rápido con AI"
|
|
258
|
+
info ""
|
|
259
|
+
info "Cuando esté listo:"
|
|
260
|
+
info " openspec apply $CHANGE_ID"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# OpenSpec CLI — Spec-Driven Development
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
7
|
+
|
|
8
|
+
# Colors
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
BLUE='\033[0;34m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# Helper functions
|
|
16
|
+
info() { echo -e "${BLUE}ℹ${NC} $*"; }
|
|
17
|
+
success() { echo -e "${GREEN}✓${NC} $*"; }
|
|
18
|
+
warning() { echo -e "${YELLOW}⚠${NC} $*"; }
|
|
19
|
+
error() { echo -e "${RED}✗${NC} $*" >&2; }
|
|
20
|
+
|
|
21
|
+
usage() {
|
|
22
|
+
cat <<EOF
|
|
23
|
+
OpenSpec CLI — Spec-Driven Development
|
|
24
|
+
|
|
25
|
+
USAGE:
|
|
26
|
+
openspec <command> [options]
|
|
27
|
+
|
|
28
|
+
COMMANDS:
|
|
29
|
+
enrich Refinar user story con AI
|
|
30
|
+
new Crear nueva propuesta de cambio
|
|
31
|
+
ff Fast-forward: generar propuesta completa
|
|
32
|
+
apply Implementar propuesta aprobada
|
|
33
|
+
verify Verificar tests y specs
|
|
34
|
+
implement Aplicar cambios de code review
|
|
35
|
+
code-review Solicitar review de CodeRabbit
|
|
36
|
+
archive Archivar propuesta completada
|
|
37
|
+
report Generar testing report
|
|
38
|
+
status Ver estado de propuestas activas
|
|
39
|
+
|
|
40
|
+
OPTIONS:
|
|
41
|
+
-h, --help Mostrar esta ayuda
|
|
42
|
+
-v, --version Mostrar versión
|
|
43
|
+
|
|
44
|
+
EXAMPLES:
|
|
45
|
+
openspec enrich "Como usuario quiero login"
|
|
46
|
+
openspec new CHANGE-001 "Implementar autenticación"
|
|
47
|
+
openspec ff CHANGE-001
|
|
48
|
+
openspec apply CHANGE-001
|
|
49
|
+
openspec verify CHANGE-001
|
|
50
|
+
openspec code-review CHANGE-001
|
|
51
|
+
openspec archive CHANGE-001
|
|
52
|
+
|
|
53
|
+
DOCS:
|
|
54
|
+
openspec/README.md
|
|
55
|
+
https://github.com/ConceptualCreative/specleap-framework
|
|
56
|
+
|
|
57
|
+
EOF
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Parse command
|
|
61
|
+
COMMAND="${1:-}"
|
|
62
|
+
if [[ -z "$COMMAND" ]] || [[ "$COMMAND" == "-h" ]] || [[ "$COMMAND" == "--help" ]]; then
|
|
63
|
+
usage
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if [[ "$COMMAND" == "-v" ]] || [[ "$COMMAND" == "--version" ]]; then
|
|
68
|
+
echo "OpenSpec CLI v1.0.0"
|
|
69
|
+
exit 0
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Dispatch to subcommand
|
|
73
|
+
SUBCOMMAND_SCRIPT="$SCRIPT_DIR/$COMMAND.sh"
|
|
74
|
+
if [[ ! -f "$SUBCOMMAND_SCRIPT" ]]; then
|
|
75
|
+
error "Comando desconocido: $COMMAND"
|
|
76
|
+
echo ""
|
|
77
|
+
usage
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
shift
|
|
82
|
+
exec "$SUBCOMMAND_SCRIPT" "$@"
|