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,189 @@
|
|
|
1
|
+
# OpenSpec CLI — Spec-Driven Development
|
|
2
|
+
|
|
3
|
+
CLI para implementar el workflow completo de SpecLeap.
|
|
4
|
+
|
|
5
|
+
## Instalación
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Desde la raíz del proyecto
|
|
9
|
+
export PATH="$PATH:$(pwd)/openspec/cli"
|
|
10
|
+
|
|
11
|
+
# O crear symlink en /usr/local/bin
|
|
12
|
+
ln -s $(pwd)/openspec/cli/openspec /usr/local/bin/openspec
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Comandos
|
|
16
|
+
|
|
17
|
+
| Comando | Descripción |
|
|
18
|
+
|---------|-------------|
|
|
19
|
+
| `openspec enrich` | Refinar user story con AI |
|
|
20
|
+
| `openspec new` | Crear nueva propuesta de cambio |
|
|
21
|
+
| `openspec ff` | Fast-forward: generar propuesta completa |
|
|
22
|
+
| `openspec apply` | Implementar propuesta aprobada |
|
|
23
|
+
| `openspec verify` | Verificar tests y specs |
|
|
24
|
+
| `openspec code-review` | Solicitar review de CodeRabbit |
|
|
25
|
+
| `openspec archive` | Archivar propuesta completada |
|
|
26
|
+
| `openspec report` | Generar testing report |
|
|
27
|
+
| `openspec status` | Ver estado de propuestas activas |
|
|
28
|
+
|
|
29
|
+
**📖 Referencia completa:** Ver [COMMAND_REFERENCE.md](./COMMAND_REFERENCE.md) para documentación detallada de cada comando con todas las opciones, ejemplos, y exit codes.
|
|
30
|
+
|
|
31
|
+
## Ciclo Completo de Desarrollo
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# 1. Refinar user story
|
|
35
|
+
openspec enrich "Como usuario quiero hacer login" --output us-refined.md
|
|
36
|
+
|
|
37
|
+
# 2. Crear propuesta
|
|
38
|
+
openspec new --auto "Implementar autenticación JWT" --from us-refined.md --ticket app-tienda-23
|
|
39
|
+
|
|
40
|
+
# 3. (Opcional) Generar propuesta completa con AI
|
|
41
|
+
openspec ff CHANGE-001
|
|
42
|
+
|
|
43
|
+
# 4. Revisar y ajustar manualmente proposal.md, design.md, tasks.md
|
|
44
|
+
|
|
45
|
+
# 5. Aplicar propuesta (crear branch, scaffolding)
|
|
46
|
+
openspec apply CHANGE-001
|
|
47
|
+
|
|
48
|
+
# 6. Implementar código (manual o con AI assistant)
|
|
49
|
+
# ... usar Continue.dev, Copilot, Cursor según specs ...
|
|
50
|
+
|
|
51
|
+
# 7. Verificar tests y specs
|
|
52
|
+
openspec verify CHANGE-001
|
|
53
|
+
|
|
54
|
+
# 8. Solicitar code review
|
|
55
|
+
openspec code-review CHANGE-001 --create-pr
|
|
56
|
+
|
|
57
|
+
# 9. (AI review automático por CodeRabbit)
|
|
58
|
+
# ... revisar comentarios y aplicar cambios ...
|
|
59
|
+
|
|
60
|
+
# 10. Archivar al completar
|
|
61
|
+
openspec archive CHANGE-001
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Ejemplos de Uso
|
|
65
|
+
|
|
66
|
+
### Crear propuesta rápida con AI
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Generar todo automáticamente
|
|
70
|
+
openspec enrich "Sistema de notificaciones push" | \
|
|
71
|
+
openspec new --auto --from - --ticket app-tienda-24
|
|
72
|
+
openspec ff CHANGE-002
|
|
73
|
+
openspec apply CHANGE-002
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Ver estado de propuestas
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
openspec status
|
|
80
|
+
openspec status --all
|
|
81
|
+
openspec status --state in_progress --format json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Generar testing report
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
openspec report CHANGE-001
|
|
88
|
+
openspec report --format json --output report.json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Prerequisitos
|
|
92
|
+
|
|
93
|
+
- **Git:** Para branch management
|
|
94
|
+
- **AI CLI:** oracle, gh copilot, o ai-cli (para `/enrich` y `/ff`)
|
|
95
|
+
- **GitHub CLI (gh):** Para crear PRs y verificar merges
|
|
96
|
+
- **Test frameworks:** PHPUnit, Jest, etc. (según proyecto)
|
|
97
|
+
|
|
98
|
+
## Configuración
|
|
99
|
+
|
|
100
|
+
Edita `openspec/config.yaml` para personalizar:
|
|
101
|
+
|
|
102
|
+
- Estados de specs y changes
|
|
103
|
+
- Integración con ticket tracker (Asana recomendado en SpecLeap; el CLI es agnóstico al backend)
|
|
104
|
+
- Umbrales de testing
|
|
105
|
+
- Formato de IDs
|
|
106
|
+
|
|
107
|
+
## Integración con AI Assistants
|
|
108
|
+
|
|
109
|
+
Los scripts CLI están diseñados para trabajar con:
|
|
110
|
+
|
|
111
|
+
- **Continue.dev:** Lee `.continue/rules/*.md` para seguir metodología
|
|
112
|
+
- **Copilot:** Usa `codex.md`
|
|
113
|
+
- **Cursor:** Sigue `.cursorrules`
|
|
114
|
+
- **Cline:** Usa `.clinerules`
|
|
115
|
+
- **Claude Code:** Sigue `AGENTS.md`
|
|
116
|
+
|
|
117
|
+
Todos los AI assistants tienen acceso a las specs en `openspec/specs/` y las propuestas en `openspec/changes/`.
|
|
118
|
+
|
|
119
|
+
## Testing Report Automation
|
|
120
|
+
|
|
121
|
+
El comando `openspec report` detecta automáticamente:
|
|
122
|
+
|
|
123
|
+
- **PHPUnit:** `phpunit.xml` o `phpunit.xml.dist`
|
|
124
|
+
- **Jest:** `package.json` con jest configurado
|
|
125
|
+
- **Otros:** Puedes extender `report.sh`
|
|
126
|
+
|
|
127
|
+
## Code Review con CodeRabbit
|
|
128
|
+
|
|
129
|
+
CodeRabbit se activa automáticamente en PRs si está configurado en el repo.
|
|
130
|
+
|
|
131
|
+
Configuración en `.coderabbit.yaml`:
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
language: es
|
|
135
|
+
early_access: true
|
|
136
|
+
enable_free_tier: true
|
|
137
|
+
reviews:
|
|
138
|
+
profile: assertive
|
|
139
|
+
request_changes_workflow: true
|
|
140
|
+
high_level_summary: true
|
|
141
|
+
poem: false
|
|
142
|
+
collapse_walkthrough: false
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Troubleshooting
|
|
146
|
+
|
|
147
|
+
### "Comando no encontrado: openspec"
|
|
148
|
+
|
|
149
|
+
Asegúrate de que `openspec/cli` esté en tu `$PATH`:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
export PATH="$PATH:$(pwd)/openspec/cli"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### "No se encontró CLI de AI"
|
|
156
|
+
|
|
157
|
+
Instala uno de estos:
|
|
158
|
+
|
|
159
|
+
- **oracle:** https://github.com/djmango/oracle
|
|
160
|
+
- **gh copilot:** `gh extension install github/gh-copilot`
|
|
161
|
+
- **ai-cli:** https://ai-cli.ai
|
|
162
|
+
|
|
163
|
+
### "PHPUnit/Jest no encontrado"
|
|
164
|
+
|
|
165
|
+
Instala las dependencias del proyecto:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# PHP
|
|
169
|
+
composer install
|
|
170
|
+
|
|
171
|
+
# Node
|
|
172
|
+
npm install
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Contribuir
|
|
176
|
+
|
|
177
|
+
Para añadir nuevos comandos o mejorar existentes:
|
|
178
|
+
|
|
179
|
+
1. Crear `openspec/cli/mi-comando.sh`
|
|
180
|
+
2. Seguir estructura de scripts existentes
|
|
181
|
+
3. Usar funciones de `common.sh`
|
|
182
|
+
4. Documentar en esta README
|
|
183
|
+
|
|
184
|
+
## Referencias
|
|
185
|
+
|
|
186
|
+
- Metodología: `../.continue/rules/01-sdd-methodology.md`
|
|
187
|
+
- Templates: `../templates/`
|
|
188
|
+
- Config: `../config.yaml`
|
|
189
|
+
- Docs: `../README.md`
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# openspec apply — Implementar propuesta aprobada
|
|
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 apply — Implementar propuesta aprobada
|
|
13
|
+
|
|
14
|
+
USAGE:
|
|
15
|
+
openspec apply <CHANGE-ID> [options]
|
|
16
|
+
|
|
17
|
+
OPTIONS:
|
|
18
|
+
--no-branch No crear branch de Git
|
|
19
|
+
--base <branch> Branch base (default: develop)
|
|
20
|
+
--dry-run Simular sin hacer cambios
|
|
21
|
+
-h, --help Mostrar ayuda
|
|
22
|
+
|
|
23
|
+
DESCRIPTION:
|
|
24
|
+
Implementa una propuesta aprobada:
|
|
25
|
+
1. Crea branch de Git (feat/CHANGE-ID-nombre)
|
|
26
|
+
2. Aplica delta specs (si existen)
|
|
27
|
+
3. Genera scaffolding según design.md
|
|
28
|
+
4. Actualiza estado a "in_progress"
|
|
29
|
+
|
|
30
|
+
NOTA: No genera código automáticamente.
|
|
31
|
+
Use AI assistant (Continue, Copilot) para implementar según specs.
|
|
32
|
+
|
|
33
|
+
EXAMPLES:
|
|
34
|
+
openspec apply CHANGE-001
|
|
35
|
+
openspec apply CHANGE-002 --base main
|
|
36
|
+
openspec apply CHANGE-003 --dry-run
|
|
37
|
+
|
|
38
|
+
PREREQUISITES:
|
|
39
|
+
- Propuesta completada y revisada
|
|
40
|
+
- Git repositorio inicializado
|
|
41
|
+
- Base branch existente
|
|
42
|
+
|
|
43
|
+
EOF
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Parse arguments
|
|
47
|
+
CHANGE_ID=""
|
|
48
|
+
NO_BRANCH=false
|
|
49
|
+
BASE_BRANCH="develop"
|
|
50
|
+
DRY_RUN=false
|
|
51
|
+
|
|
52
|
+
while [[ $# -gt 0 ]]; do
|
|
53
|
+
case $1 in
|
|
54
|
+
-h|--help)
|
|
55
|
+
usage
|
|
56
|
+
exit 0
|
|
57
|
+
;;
|
|
58
|
+
--no-branch)
|
|
59
|
+
NO_BRANCH=true
|
|
60
|
+
shift
|
|
61
|
+
;;
|
|
62
|
+
--base)
|
|
63
|
+
BASE_BRANCH="$2"
|
|
64
|
+
shift 2
|
|
65
|
+
;;
|
|
66
|
+
--dry-run)
|
|
67
|
+
DRY_RUN=true
|
|
68
|
+
shift
|
|
69
|
+
;;
|
|
70
|
+
CHANGE-*)
|
|
71
|
+
CHANGE_ID="$1"
|
|
72
|
+
shift
|
|
73
|
+
;;
|
|
74
|
+
*)
|
|
75
|
+
error "Argumento desconocido: $1"
|
|
76
|
+
usage
|
|
77
|
+
exit 1
|
|
78
|
+
;;
|
|
79
|
+
esac
|
|
80
|
+
done
|
|
81
|
+
|
|
82
|
+
# Validate
|
|
83
|
+
validate_project
|
|
84
|
+
|
|
85
|
+
if [[ -z "$CHANGE_ID" ]]; then
|
|
86
|
+
error "Debe proporcionar CHANGE-ID"
|
|
87
|
+
usage
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Find change directory
|
|
92
|
+
CHANGE_DIR=$(find "$PROJECT_ROOT/openspec/changes" -maxdepth 1 -type d -name "${CHANGE_ID}-*" | head -n1)
|
|
93
|
+
|
|
94
|
+
if [[ -z "$CHANGE_DIR" ]] || [[ ! -d "$CHANGE_DIR" ]]; then
|
|
95
|
+
error "Propuesta no encontrada: $CHANGE_ID"
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
CHANGE_NAME=$(basename "$CHANGE_DIR" | sed "s/^${CHANGE_ID}-//")
|
|
100
|
+
|
|
101
|
+
info "Aplicando propuesta: $CHANGE_ID — $CHANGE_NAME"
|
|
102
|
+
|
|
103
|
+
# Verify required files exist
|
|
104
|
+
for file in proposal.md design.md tasks.md; do
|
|
105
|
+
if [[ ! -f "$CHANGE_DIR/$file" ]]; then
|
|
106
|
+
error "Archivo requerido no encontrado: $file"
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
|
|
111
|
+
# Check Git status
|
|
112
|
+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
113
|
+
error "No estás en un repositorio Git"
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
if git_has_changes && [[ "$DRY_RUN" == false ]]; then
|
|
118
|
+
warning "Hay cambios sin commitear en el working directory"
|
|
119
|
+
read -p "¿Continuar de todos modos? (y/N) " -n 1 -r
|
|
120
|
+
echo
|
|
121
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
122
|
+
info "Operación cancelada"
|
|
123
|
+
exit 0
|
|
124
|
+
fi
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Create feature branch
|
|
128
|
+
if [[ "$NO_BRANCH" == false ]]; then
|
|
129
|
+
BRANCH_NAME="feat/${CHANGE_ID}-${CHANGE_NAME}"
|
|
130
|
+
|
|
131
|
+
step "Creando branch: $BRANCH_NAME desde $BASE_BRANCH"
|
|
132
|
+
|
|
133
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
134
|
+
# Check if base branch exists
|
|
135
|
+
if ! git show-ref --verify --quiet "refs/heads/$BASE_BRANCH"; then
|
|
136
|
+
error "Branch base no existe: $BASE_BRANCH"
|
|
137
|
+
exit 1
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# Create and checkout new branch
|
|
141
|
+
git checkout -b "$BRANCH_NAME" "$BASE_BRANCH" || {
|
|
142
|
+
error "No se pudo crear branch. Puede que ya exista."
|
|
143
|
+
exit 1
|
|
144
|
+
}
|
|
145
|
+
success "Branch creado: $BRANCH_NAME"
|
|
146
|
+
else
|
|
147
|
+
info "[DRY RUN] Crearía branch: $BRANCH_NAME"
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Apply delta specs if they exist
|
|
152
|
+
if [[ -d "$CHANGE_DIR/specs" ]] && [[ -n "$(ls -A "$CHANGE_DIR/specs" 2>/dev/null)" ]]; then
|
|
153
|
+
step "Aplicando delta specs..."
|
|
154
|
+
|
|
155
|
+
for delta_spec in "$CHANGE_DIR/specs"/**/*.spec.md; do
|
|
156
|
+
if [[ -f "$delta_spec" ]]; then
|
|
157
|
+
# Extract relative path
|
|
158
|
+
rel_path="${delta_spec#$CHANGE_DIR/specs/}"
|
|
159
|
+
target_spec="$PROJECT_ROOT/openspec/specs/$rel_path"
|
|
160
|
+
|
|
161
|
+
info " Delta: $rel_path"
|
|
162
|
+
|
|
163
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
164
|
+
# Create target directory if needed
|
|
165
|
+
target_dir=$(dirname "$target_spec")
|
|
166
|
+
ensure_dir "$target_dir"
|
|
167
|
+
|
|
168
|
+
# Apply delta (simple: copy for now, later implement merge)
|
|
169
|
+
if [[ -f "$target_spec" ]]; then
|
|
170
|
+
warning " Spec existente será actualizada: $target_spec"
|
|
171
|
+
# TODO: Implement proper delta merge
|
|
172
|
+
cp "$delta_spec" "$target_spec"
|
|
173
|
+
else
|
|
174
|
+
cp "$delta_spec" "$target_spec"
|
|
175
|
+
fi
|
|
176
|
+
success " Aplicada: $target_spec"
|
|
177
|
+
else
|
|
178
|
+
info "[DRY RUN] Aplicaría delta a: $target_spec"
|
|
179
|
+
fi
|
|
180
|
+
fi
|
|
181
|
+
done
|
|
182
|
+
else
|
|
183
|
+
info "No hay delta specs para aplicar"
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# Update proposal state
|
|
187
|
+
step "Actualizando estado de propuesta a: in_progress"
|
|
188
|
+
|
|
189
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
190
|
+
# Update state in proposal.md
|
|
191
|
+
sed -i.bak 's/Estado | draft/Estado | in_progress/' "$CHANGE_DIR/proposal.md"
|
|
192
|
+
sed -i.bak 's/Estado | review/Estado | in_progress/' "$CHANGE_DIR/proposal.md"
|
|
193
|
+
sed -i.bak 's/Estado | approved/Estado | in_progress/' "$CHANGE_DIR/proposal.md"
|
|
194
|
+
rm -f "$CHANGE_DIR/proposal.md.bak"
|
|
195
|
+
|
|
196
|
+
# Commit the state change
|
|
197
|
+
git add "$CHANGE_DIR/proposal.md"
|
|
198
|
+
git commit -m "chore(openspec): iniciar implementación de $CHANGE_ID
|
|
199
|
+
|
|
200
|
+
## Qué se hizo
|
|
201
|
+
- Cambiar estado de propuesta a in_progress
|
|
202
|
+
- Aplicar delta specs
|
|
203
|
+
|
|
204
|
+
## Refs
|
|
205
|
+
- Propuesta: openspec/changes/$CHANGE_ID-$CHANGE_NAME/
|
|
206
|
+
" || true
|
|
207
|
+
|
|
208
|
+
success "Estado actualizado"
|
|
209
|
+
else
|
|
210
|
+
info "[DRY RUN] Actualizaría estado a: in_progress"
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# Show next steps
|
|
214
|
+
success "Propuesta aplicada exitosamente"
|
|
215
|
+
info ""
|
|
216
|
+
info "Branch activo: $(git_current_branch)"
|
|
217
|
+
info "Propuesta: $CHANGE_DIR"
|
|
218
|
+
info ""
|
|
219
|
+
info "Próximos pasos:"
|
|
220
|
+
info " 1. Implementar según design.md y tasks.md"
|
|
221
|
+
info " 2. Usar AI assistant (Continue, Copilot) con las specs"
|
|
222
|
+
info " 3. Escribir tests según Testing Strategy"
|
|
223
|
+
info " 4. openspec verify $CHANGE_ID (verificar tests)"
|
|
224
|
+
info " 5. openspec code-review $CHANGE_ID (solicitar review)"
|
|
225
|
+
info ""
|
|
226
|
+
info "Archivos clave:"
|
|
227
|
+
info " - $(basename "$CHANGE_DIR")/design.md — Diseño técnico"
|
|
228
|
+
info " - $(basename "$CHANGE_DIR")/tasks.md — Tareas y criterios"
|
|
229
|
+
info " - openspec/specs/ — Especificaciones source of truth"
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# openspec archive — Archivar propuesta completada
|
|
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 archive — Archivar propuesta completada
|
|
13
|
+
|
|
14
|
+
USAGE:
|
|
15
|
+
openspec archive <CHANGE-ID> [options]
|
|
16
|
+
|
|
17
|
+
OPTIONS:
|
|
18
|
+
--keep-branch No eliminar branch feature
|
|
19
|
+
--no-merge No verificar merge (útil si ya mergeado manualmente)
|
|
20
|
+
-h, --help Mostrar ayuda
|
|
21
|
+
|
|
22
|
+
DESCRIPTION:
|
|
23
|
+
Archiva una propuesta completada y mergeada:
|
|
24
|
+
1. Verifica que PR esté mergeado
|
|
25
|
+
2. Actualiza estado a "completed"
|
|
26
|
+
3. Elimina branch feature (opcional)
|
|
27
|
+
4. Genera reporte final
|
|
28
|
+
|
|
29
|
+
EXAMPLES:
|
|
30
|
+
openspec archive CHANGE-001
|
|
31
|
+
openspec archive CHANGE-002 --keep-branch
|
|
32
|
+
openspec archive CHANGE-003 --no-merge
|
|
33
|
+
|
|
34
|
+
PREREQUISITES:
|
|
35
|
+
- PR mergeado a base branch
|
|
36
|
+
- Code review aprobado
|
|
37
|
+
|
|
38
|
+
EOF
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Parse arguments
|
|
42
|
+
CHANGE_ID=""
|
|
43
|
+
KEEP_BRANCH=false
|
|
44
|
+
NO_MERGE_CHECK=false
|
|
45
|
+
|
|
46
|
+
while [[ $# -gt 0 ]]; do
|
|
47
|
+
case $1 in
|
|
48
|
+
-h|--help)
|
|
49
|
+
usage
|
|
50
|
+
exit 0
|
|
51
|
+
;;
|
|
52
|
+
--keep-branch)
|
|
53
|
+
KEEP_BRANCH=true
|
|
54
|
+
shift
|
|
55
|
+
;;
|
|
56
|
+
--no-merge)
|
|
57
|
+
NO_MERGE_CHECK=true
|
|
58
|
+
shift
|
|
59
|
+
;;
|
|
60
|
+
CHANGE-*)
|
|
61
|
+
CHANGE_ID="$1"
|
|
62
|
+
shift
|
|
63
|
+
;;
|
|
64
|
+
*)
|
|
65
|
+
error "Argumento desconocido: $1"
|
|
66
|
+
usage
|
|
67
|
+
exit 1
|
|
68
|
+
;;
|
|
69
|
+
esac
|
|
70
|
+
done
|
|
71
|
+
|
|
72
|
+
# Validate
|
|
73
|
+
validate_project
|
|
74
|
+
|
|
75
|
+
if [[ -z "$CHANGE_ID" ]]; then
|
|
76
|
+
error "Debe proporcionar CHANGE-ID"
|
|
77
|
+
usage
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Find change directory
|
|
82
|
+
CHANGE_DIR=$(find "$PROJECT_ROOT/openspec/changes" -maxdepth 1 -type d -name "${CHANGE_ID}-*" | head -n1)
|
|
83
|
+
|
|
84
|
+
if [[ -z "$CHANGE_DIR" ]] || [[ ! -d "$CHANGE_DIR" ]]; then
|
|
85
|
+
error "Propuesta no encontrada: $CHANGE_ID"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
CHANGE_NAME=$(basename "$CHANGE_DIR" | sed "s/^${CHANGE_ID}-//")
|
|
90
|
+
|
|
91
|
+
info "Archivando propuesta: $CHANGE_ID — $CHANGE_NAME"
|
|
92
|
+
|
|
93
|
+
# Check if PR is merged (if gh is available)
|
|
94
|
+
if [[ "$NO_MERGE_CHECK" == false ]] && command -v gh &> /dev/null; then
|
|
95
|
+
step "Verificando estado de PR..."
|
|
96
|
+
|
|
97
|
+
# Find PR for this change
|
|
98
|
+
FEATURE_BRANCH="feat/${CHANGE_ID}-${CHANGE_NAME}"
|
|
99
|
+
PR_STATE=$(gh pr list --head "$FEATURE_BRANCH" --state all --json state --jq '.[0].state' 2>/dev/null || echo "")
|
|
100
|
+
|
|
101
|
+
if [[ "$PR_STATE" != "MERGED" ]]; then
|
|
102
|
+
warning "PR no parece estar mergeado (estado: ${PR_STATE:-desconocido})"
|
|
103
|
+
read -p "¿Continuar de todos modos? (y/N) " -n 1 -r
|
|
104
|
+
echo
|
|
105
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
106
|
+
info "Operación cancelada"
|
|
107
|
+
exit 0
|
|
108
|
+
fi
|
|
109
|
+
else
|
|
110
|
+
success "PR verificado como mergeado"
|
|
111
|
+
fi
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Update proposal state
|
|
115
|
+
step "Actualizando estado a: completed"
|
|
116
|
+
|
|
117
|
+
sed -i.bak 's/Estado | .*/Estado | completed/' "$CHANGE_DIR/proposal.md"
|
|
118
|
+
rm -f "$CHANGE_DIR/proposal.md.bak"
|
|
119
|
+
|
|
120
|
+
# Add completion date
|
|
121
|
+
COMPLETION_DATE=$(current_date)
|
|
122
|
+
echo -e "\n## Completada\n- Fecha: $COMPLETION_DATE" >> "$CHANGE_DIR/proposal.md"
|
|
123
|
+
|
|
124
|
+
# Update spec states if delta specs were applied
|
|
125
|
+
if [[ -d "$CHANGE_DIR/specs" ]]; then
|
|
126
|
+
for delta_spec in "$CHANGE_DIR/specs"/**/*.spec.md; do
|
|
127
|
+
if [[ -f "$delta_spec" ]]; then
|
|
128
|
+
rel_path="${delta_spec#$CHANGE_DIR/specs/}"
|
|
129
|
+
target_spec="$PROJECT_ROOT/openspec/specs/$rel_path"
|
|
130
|
+
|
|
131
|
+
if [[ -f "$target_spec" ]]; then
|
|
132
|
+
# Update state to implemented
|
|
133
|
+
sed -i.bak 's/Estado: draft/Estado: implemented/' "$target_spec"
|
|
134
|
+
sed -i.bak 's/Estado: review/Estado: implemented/' "$target_spec"
|
|
135
|
+
sed -i.bak 's/Estado: approved/Estado: implemented/' "$target_spec"
|
|
136
|
+
rm -f "$target_spec.bak"
|
|
137
|
+
|
|
138
|
+
success "Spec marcada como implemented: $rel_path"
|
|
139
|
+
fi
|
|
140
|
+
fi
|
|
141
|
+
done
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# Commit archive changes
|
|
145
|
+
git add "$CHANGE_DIR/proposal.md"
|
|
146
|
+
if [[ -d "$PROJECT_ROOT/openspec/specs" ]]; then
|
|
147
|
+
git add "$PROJECT_ROOT/openspec/specs"
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
git commit -m "chore(openspec): archivar $CHANGE_ID como completed
|
|
151
|
+
|
|
152
|
+
## Qué se hizo
|
|
153
|
+
- Marcar propuesta como completed
|
|
154
|
+
- Actualizar specs a implemented
|
|
155
|
+
|
|
156
|
+
## Refs
|
|
157
|
+
- Propuesta: openspec/changes/$CHANGE_ID-$CHANGE_NAME/
|
|
158
|
+
" || true
|
|
159
|
+
|
|
160
|
+
success "Propuesta archivada"
|
|
161
|
+
|
|
162
|
+
# Delete feature branch if requested
|
|
163
|
+
if [[ "$KEEP_BRANCH" == false ]]; then
|
|
164
|
+
FEATURE_BRANCH="feat/${CHANGE_ID}-${CHANGE_NAME}"
|
|
165
|
+
|
|
166
|
+
step "Eliminando branch feature: $FEATURE_BRANCH"
|
|
167
|
+
|
|
168
|
+
# Switch to base branch first
|
|
169
|
+
BASE_BRANCH="develop"
|
|
170
|
+
if git show-ref --verify --quiet "refs/heads/$BASE_BRANCH"; then
|
|
171
|
+
git checkout "$BASE_BRANCH" || true
|
|
172
|
+
elif git show-ref --verify --quiet "refs/heads/main"; then
|
|
173
|
+
git checkout main || true
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Delete local branch
|
|
177
|
+
git branch -d "$FEATURE_BRANCH" 2>/dev/null || warning "Branch local no encontrado"
|
|
178
|
+
|
|
179
|
+
# Delete remote branch
|
|
180
|
+
git push origin --delete "$FEATURE_BRANCH" 2>/dev/null || warning "Branch remoto no encontrado o ya eliminado"
|
|
181
|
+
|
|
182
|
+
success "Branch eliminado"
|
|
183
|
+
else
|
|
184
|
+
info "Branch feature conservado (--keep-branch)"
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# Generate final report
|
|
188
|
+
step "Generando reporte final..."
|
|
189
|
+
|
|
190
|
+
REPORT_FILE="$CHANGE_DIR/COMPLETION_REPORT.md"
|
|
191
|
+
|
|
192
|
+
cat > "$REPORT_FILE" <<EOF
|
|
193
|
+
# Reporte de Completación: $CHANGE_ID
|
|
194
|
+
|
|
195
|
+
| Campo | Valor |
|
|
196
|
+
|-------|-------|
|
|
197
|
+
| ID | $CHANGE_ID |
|
|
198
|
+
| Título | $CHANGE_NAME |
|
|
199
|
+
| Completada | $COMPLETION_DATE |
|
|
200
|
+
|
|
201
|
+
## Archivos Generados
|
|
202
|
+
|
|
203
|
+
- proposal.md
|
|
204
|
+
- design.md
|
|
205
|
+
- tasks.md
|
|
206
|
+
- $(find "$CHANGE_DIR/specs" -name "*.spec.md" 2>/dev/null | wc -l) delta specs
|
|
207
|
+
|
|
208
|
+
## Specs Actualizadas
|
|
209
|
+
|
|
210
|
+
$(if [[ -d "$CHANGE_DIR/specs" ]]; then
|
|
211
|
+
find "$CHANGE_DIR/specs" -name "*.spec.md" -exec basename {} \; 2>/dev/null | sed 's/^/- /'
|
|
212
|
+
else
|
|
213
|
+
echo "Ninguna"
|
|
214
|
+
fi)
|
|
215
|
+
|
|
216
|
+
## Commits
|
|
217
|
+
|
|
218
|
+
\`\`\`bash
|
|
219
|
+
$(git log --oneline --grep="$CHANGE_ID" 2>/dev/null || echo "No commits found")
|
|
220
|
+
\`\`\`
|
|
221
|
+
|
|
222
|
+
## Estado Final
|
|
223
|
+
|
|
224
|
+
✅ Propuesta completada y archivada
|
|
225
|
+
✅ Specs actualizadas a "implemented"
|
|
226
|
+
$(if [[ "$KEEP_BRANCH" == false ]]; then echo "✅ Branch feature eliminado"; else echo "⚠️ Branch feature conservado"; fi)
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
Generado: $(current_datetime)
|
|
230
|
+
EOF
|
|
231
|
+
|
|
232
|
+
success "Reporte generado: $REPORT_FILE"
|
|
233
|
+
|
|
234
|
+
# Final message
|
|
235
|
+
success "✅ $CHANGE_ID archivado exitosamente"
|
|
236
|
+
info ""
|
|
237
|
+
info "Reporte final: $REPORT_FILE"
|
|
238
|
+
info ""
|
|
239
|
+
info "La propuesta está completada y puede consultarse en:"
|
|
240
|
+
info " openspec/changes/$CHANGE_ID-$CHANGE_NAME/"
|