sdd-es 2.0.0 → 2.6.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 (127) hide show
  1. package/.claude/settings.json +29 -29
  2. package/.claude/settings.local.json +10 -0
  3. package/.claude-plugin/marketplace.json +10 -7
  4. package/.claude-plugin/plugin.json +59 -37
  5. package/.gitignore +20 -0
  6. package/.mcp.json +8 -0
  7. package/LICENSE +21 -0
  8. package/README.md +77 -40
  9. package/agents/architecture-designer.md +211 -0
  10. package/agents/arquitecto.md +16 -1
  11. package/agents/asesor-datos.md +15 -1
  12. package/agents/critico.md +37 -1
  13. package/agents/desarrollador-backend.md +3 -1
  14. package/agents/desarrollador-frontend.md +11 -16
  15. package/agents/disenador-api.md +13 -1
  16. package/agents/documentador.md +3 -1
  17. package/agents/investigador.md +3 -1
  18. package/agents/operaciones.md +3 -1
  19. package/agents/product-designer.md +268 -0
  20. package/agents/revisor.md +25 -1
  21. package/agents/seguridad.md +5 -1
  22. package/agents/tester.md +3 -1
  23. package/claude-hooks/agent-memory.js +288 -0
  24. package/claude-hooks/pre-tool-guard.js +61 -9
  25. package/cli/index.js +1 -2
  26. package/commands/sdd.adr.md +196 -0
  27. package/commands/sdd.analizar.md +23 -2
  28. package/commands/sdd.ayuda.md +13 -0
  29. package/commands/sdd.compliance.md +521 -0
  30. package/commands/sdd.configurar.md +34 -1
  31. package/commands/sdd.constitucion.md +198 -23
  32. package/commands/sdd.construir.md +210 -0
  33. package/commands/sdd.crear-mcp.md +2 -0
  34. package/commands/sdd.defect-report.md +134 -0
  35. package/commands/sdd.descubrir.md +19 -0
  36. package/commands/sdd.dise/303/261ar.md +188 -0
  37. package/commands/sdd.estado.md +120 -3
  38. package/commands/sdd.exportar.md +344 -0
  39. package/commands/sdd.implementar.md +272 -52
  40. package/commands/sdd.interpretar.md +239 -0
  41. package/commands/sdd.md +93 -4
  42. package/commands/sdd.optimizar-memoria.md +47 -0
  43. package/commands/sdd.optimizar.md +164 -0
  44. package/commands/sdd.planificar.md +64 -0
  45. package/commands/sdd.retro.md +74 -0
  46. package/commands/sdd.verificar.md +81 -0
  47. package/configuracion-ejemplo/.claude/CLAUDE.md +106 -0
  48. package/configuracion-ejemplo/sdd.config.yaml +10 -0
  49. package/craft/accessibility-baseline.md +216 -0
  50. package/craft/anti-ai-slop.md +158 -0
  51. package/craft/color.md +160 -0
  52. package/craft/typography.md +121 -0
  53. package/design-systems/bold-brutalist/DESIGN.md +239 -0
  54. package/design-systems/editorial-minimal/DESIGN.md +205 -0
  55. package/design-systems/neutral-modern/DESIGN.md +227 -0
  56. package/design-systems/vibrant-consumer/DESIGN.md +257 -0
  57. package/design-systems/warm-editorial/DESIGN.md +221 -0
  58. package/docs/AGENTES.md +4 -1
  59. package/docs/CASO-COMPLETO.md +206 -0
  60. package/docs/EJEMPLOS.md +61 -185
  61. package/docs/FABRICA.md +163 -115
  62. package/docs/INICIO-RAPIDO.md +27 -79
  63. package/docs/MEMORIA-Y-OBSERVABILIDAD.md +239 -0
  64. package/docs/MODELOS.md +3 -0
  65. package/docs/QUE-PASA-SI-FALLA.md +404 -0
  66. package/docs/README.md +43 -0
  67. package/docs/RELACION-CON-CLAUDE-CODE.md +38 -0
  68. package/docs/SEGURIDAD-PARA-NOTECNICOS.md +280 -0
  69. package/package.json +15 -10
  70. package/plantillas/job-story-mejorar-prompt.md +107 -0
  71. package/presets/enterprise.yaml +6 -0
  72. package/presets/lean.yaml +4 -0
  73. package/presets/startup.yaml +6 -0
  74. package/skills/adr-indexer/SKILL.md +181 -0
  75. package/skills/cache-audit/SKILL.md +163 -0
  76. package/skills/critica-diseno/SKILL.md +193 -0
  77. package/skills/descubrir-idea/SKILL.md +133 -0
  78. package/skills/effort-router/SKILL.md +128 -0
  79. package/skills/elegir-direccion/SKILL.md +184 -0
  80. package/skills/github-connect/IMPLEMENTATION-CHECKLIST.md +297 -0
  81. package/skills/github-connect/INDEX.md +223 -0
  82. package/skills/github-connect/INTEGRATION.md +361 -0
  83. package/skills/github-connect/QUICK-START.md +168 -0
  84. package/skills/github-connect/README.md +414 -0
  85. package/skills/github-connect/RESUMEN_IMPLEMENTACION.txt +374 -0
  86. package/skills/github-connect/SKILL.md +343 -0
  87. package/skills/github-connect/STRUCTURE.txt +252 -0
  88. package/skills/github-connect/example-config.yaml +41 -0
  89. package/skills/github-connect/github-connect.sh +419 -0
  90. package/skills/interpretar-idea/SKILL.md +254 -0
  91. package/skills/mejorar-prompt/SKILL.md +237 -0
  92. package/skills/memory-compactor/SKILL.md +68 -0
  93. package/skills/modo-guiado/SKILL.md +12 -2
  94. package/skills/mutation-detector/SKILL.md +134 -0
  95. package/skills/observabilidad-consumo/SKILL.md +164 -0
  96. package/skills/token-budget/SKILL.md +177 -0
  97. package/skills/vercel-deploy/00-START-HERE.txt +364 -0
  98. package/skills/vercel-deploy/CHECKLIST.md +205 -0
  99. package/skills/vercel-deploy/EXEC-SUMMARY.txt +322 -0
  100. package/skills/vercel-deploy/FLOW.txt +334 -0
  101. package/skills/vercel-deploy/INDEX.md +276 -0
  102. package/skills/vercel-deploy/INTEGRATION.md +328 -0
  103. package/skills/vercel-deploy/MANIFEST.md +310 -0
  104. package/skills/vercel-deploy/README.md +65 -0
  105. package/skills/vercel-deploy/SKILL.md +356 -0
  106. package/skills/vercel-deploy/deploy.sh +298 -0
  107. package/skills/vercel-deploy/estado.json.example +205 -0
  108. package/skills/vercel-deploy/skill.yaml +323 -0
  109. package/skills/vercel-deploy/vercel-deploy.sh +216 -0
  110. package/skills/wireframe-mvp/SKILL.md +157 -0
  111. package/docs/EJEMPLO-PRACTICA.md +0 -383
  112. package/mcp-figma/README.md +0 -158
  113. package/mcp-figma/package.json +0 -7
  114. package/mcp-figma/src/component-generator.js +0 -162
  115. package/mcp-figma/src/design-system-analyzer.js +0 -247
  116. package/mcp-figma/src/figma-client.js +0 -75
  117. package/mcp-figma/src/index.js +0 -114
  118. package/mcp-figma/src/mcp.js +0 -97
  119. package/mcp-figma/src/style-mapper.js +0 -85
  120. /package/skills/{compresion-tokens.md → compresion-tokens/SKILL.md} +0 -0
  121. /package/skills/{constitucion-constraint.md → constitucion-constraint/SKILL.md} +0 -0
  122. /package/skills/{deteccion-stack.md → deteccion-stack/SKILL.md} +0 -0
  123. /package/skills/{enrutador-agentes.md → enrutador-agentes/SKILL.md} +0 -0
  124. /package/skills/{gestion-estado.md → gestion-estado/SKILL.md} +0 -0
  125. /package/skills/{indexador.md → indexador/SKILL.md} +0 -0
  126. /package/skills/{validacion-spec.md → validacion-spec/SKILL.md} +0 -0
  127. /package/skills/{verificador-implementacion.md → verificador-implementacion/SKILL.md} +0 -0
@@ -0,0 +1,356 @@
1
+ ---
2
+ name: vercel-deploy
3
+ description: Despliega automáticamente a Vercel. Pre-checks, build, health checks, rollback si falla.
4
+ tools: ["Bash"]
5
+ ---
6
+
7
+ # Skill: Despliegue Automático en Vercel
8
+
9
+ ## Propósito
10
+
11
+ Cerrar el ciclo idea→producción sin salir del flujo. Diferenciador vs Bolt/v0: verificación independiente PRE-deploy, no post-deploy.
12
+
13
+ Ejecución **sincrónica bloqueante**: el usuario ve al instante si funcionó o no.
14
+
15
+ ---
16
+
17
+ ## Entrada requerida
18
+
19
+ - **`VERCEL_TOKEN`** (variable de entorno) — token de autenticación
20
+ - **`VERCEL_PROJECT_ID`** (variable de entorno, opcional) — si el proyecto ya existe en Vercel
21
+ - **`deploy.framework`** (detectado automáticamente: nextjs, react, vue, astro, flask, fastapi, etc.)
22
+
23
+ ---
24
+
25
+ ## Flujo de 6 pasos
26
+
27
+ ### PASO 1: Pre-checks (bloquea si alguno falla)
28
+
29
+ Validaciones preliminares que impiden proseguir con deploy si hay problemas:
30
+
31
+ ```bash
32
+ #!/bin/bash
33
+ set -e # Detener en cualquier error
34
+
35
+ echo "🔍 PASO 1: Pre-checks"
36
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
37
+
38
+ # Check 1: VERCEL_TOKEN presente
39
+ if [ -z "$VERCEL_TOKEN" ]; then
40
+ echo "❌ Error: VERCEL_TOKEN no configurado"
41
+ echo ""
42
+ echo "Instrucciones para generar:"
43
+ echo " 1. Ve a https://vercel.com/account/tokens"
44
+ echo " 2. Crea un nuevo token con scope 'full'"
45
+ echo " 3. Guárdalo:"
46
+ echo " export VERCEL_TOKEN='xxx_tu_token_aqui_xxx'"
47
+ echo " # O en .env:"
48
+ echo " echo 'VERCEL_TOKEN=xxx_tu_token_aqui_xxx' >> .env.local"
49
+ exit 1
50
+ fi
51
+ echo "✅ VERCEL_TOKEN presente"
52
+
53
+ # Check 2: Rama limpia (sin cambios sin stagear)
54
+ if ! git diff-files --quiet; then
55
+ echo "❌ Error: Cambios sin stagear detectados"
56
+ echo ""
57
+ echo "Acción requerida:"
58
+ echo " git add ."
59
+ echo " git commit -m 'descripción de cambios'"
60
+ exit 1
61
+ fi
62
+ echo "✅ Rama limpia (sin cambios sin stagear)"
63
+
64
+ # Check 3: Sin secretos en código
65
+ echo "🔐 Escaneando por secretos en src/..."
66
+ SECRETOS=$(grep -r "VERCEL_TOKEN\|API_KEY\|SECRET" src/ 2>/dev/null || true)
67
+ if [ ! -z "$SECRETOS" ]; then
68
+ echo "❌ Error: Secretos detectados en código:"
69
+ echo "$SECRETOS"
70
+ echo ""
71
+ echo "Acción: Mueve secretos a .env.local o variables de entorno en Vercel"
72
+ exit 1
73
+ fi
74
+ echo "✅ Sin secretos hardcodeados en src/"
75
+
76
+ # Check 4: Tests verdes
77
+ echo "🧪 Ejecutando tests..."
78
+ if ! npm test -- --passWithNoTests 2>/dev/null; then
79
+ echo "❌ Error: Tests fallando"
80
+ echo ""
81
+ echo "Acción: Ejecuta `/sdd.implementar` nuevamente para arreglar issues"
82
+ exit 1
83
+ fi
84
+ echo "✅ Tests pasando"
85
+
86
+ echo ""
87
+ ```
88
+
89
+ ---
90
+
91
+ ### PASO 2: Auto-generar vercel.json si no existe
92
+
93
+ Detección automática del framework e inyección de configuración mínima válida:
94
+
95
+ ```bash
96
+ echo "⚙️ PASO 2: Configurar vercel.json"
97
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
98
+
99
+ # Detectar framework leyendo package.json
100
+ if [ -f package.json ]; then
101
+ FRAMEWORK="unknown"
102
+
103
+ if grep -q '"next"' package.json; then
104
+ FRAMEWORK="nextjs"
105
+ BUILD_CMD="npm run build"
106
+ OUTPUT_DIR=".next"
107
+ elif grep -q '"react"' package.json && ! grep -q '"next"' package.json; then
108
+ FRAMEWORK="react"
109
+ BUILD_CMD="npm run build"
110
+ OUTPUT_DIR="build"
111
+ elif grep -q '"vue"' package.json; then
112
+ FRAMEWORK="vue"
113
+ BUILD_CMD="npm run build"
114
+ OUTPUT_DIR="dist"
115
+ elif grep -q '"astro"' package.json; then
116
+ FRAMEWORK="astro"
117
+ BUILD_CMD="npm run build"
118
+ OUTPUT_DIR="dist"
119
+ elif grep -q '"fastapi\|flask"' package.json; then
120
+ FRAMEWORK="python"
121
+ BUILD_CMD="pip install -r requirements.txt"
122
+ OUTPUT_DIR="."
123
+ fi
124
+
125
+ echo "📦 Framework detectado: $FRAMEWORK"
126
+
127
+ # Si vercel.json no existe, crearlo
128
+ if [ ! -f vercel.json ]; then
129
+ echo "Generando vercel.json..."
130
+ cat > vercel.json << EOF
131
+ {
132
+ "buildCommand": "$BUILD_CMD",
133
+ "outputDirectory": "$OUTPUT_DIR",
134
+ "framework": "$FRAMEWORK"
135
+ }
136
+ EOF
137
+ echo "✅ vercel.json creado automáticamente"
138
+ else
139
+ echo "✅ vercel.json ya existe"
140
+ fi
141
+ else
142
+ echo "⚠️ No se encontró package.json"
143
+ fi
144
+
145
+ echo ""
146
+ ```
147
+
148
+ ---
149
+
150
+ ### PASO 3: Build y Deploy a Vercel (bloqueante)
151
+
152
+ Ejecución del build local y envío a Vercel:
153
+
154
+ ```bash
155
+ echo "🚀 PASO 3: Deploy a Vercel"
156
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
157
+
158
+ # Ejecutar build local
159
+ echo "🔨 Compilando localmente..."
160
+ if ! npm run build 2>&1; then
161
+ echo "❌ Error: Build local falló"
162
+ echo ""
163
+ echo "Acción: Revisa los errores arriba y ejecuta `/sdd.implementar`"
164
+ exit 1
165
+ fi
166
+ echo "✅ Build local exitoso"
167
+
168
+ # Deploy a Vercel
169
+ echo "📤 Enviando a Vercel..."
170
+ DEPLOY_OUTPUT=$(vercel deploy --prod --token="$VERCEL_TOKEN" 2>&1)
171
+ DEPLOY_URL=$(echo "$DEPLOY_OUTPUT" | grep -oP 'https://[^\s]+' | head -1)
172
+
173
+ if [ -z "$DEPLOY_URL" ]; then
174
+ echo "❌ Error: No se pudo obtener URL de despliegue"
175
+ echo "Salida de Vercel:"
176
+ echo "$DEPLOY_OUTPUT"
177
+ exit 1
178
+ fi
179
+
180
+ echo "✅ Deploy enviado a Vercel"
181
+ echo " URL: $DEPLOY_URL"
182
+
183
+ echo ""
184
+ ```
185
+
186
+ ---
187
+
188
+ ### PASO 4: Health Check (retry con backoff)
189
+
190
+ Validación de que la URL está respondiendo correctamente:
191
+
192
+ ```bash
193
+ echo "🏥 PASO 4: Health Check"
194
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
195
+
196
+ HEALTH_CHECK_PASSED=0
197
+ MAX_RETRIES=3
198
+ RETRY_DELAY=5
199
+
200
+ for i in $(seq 1 $MAX_RETRIES); do
201
+ echo "Intento $i/$MAX_RETRIES: GET $DEPLOY_URL"
202
+
203
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$DEPLOY_URL" --max-time 10)
204
+
205
+ if [ "$HTTP_CODE" = "200" ]; then
206
+ echo "✅ Health check exitoso (HTTP $HTTP_CODE)"
207
+ HEALTH_CHECK_PASSED=1
208
+ break
209
+ else
210
+ echo "⚠️ HTTP $HTTP_CODE — esperando ${RETRY_DELAY}s antes de reintentar..."
211
+ if [ $i -lt $MAX_RETRIES ]; then
212
+ sleep $RETRY_DELAY
213
+ fi
214
+ fi
215
+ done
216
+
217
+ if [ $HEALTH_CHECK_PASSED -eq 0 ]; then
218
+ echo "❌ Health check falló después de $MAX_RETRIES intentos"
219
+ HEALTH_STATUS="FAILED"
220
+ else
221
+ HEALTH_STATUS="OK"
222
+ fi
223
+
224
+ echo ""
225
+ ```
226
+
227
+ ---
228
+
229
+ ### PASO 5: Rollback automático si health check falla
230
+
231
+ Reversión al despliegue anterior si la app no responde:
232
+
233
+ ```bash
234
+ echo "⏮️ PASO 5: Rollback (si es necesario)"
235
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
236
+
237
+ if [ "$HEALTH_STATUS" != "OK" ]; then
238
+ echo "🔄 Ejecutando rollback..."
239
+
240
+ if vercel rollback --token="$VERCEL_TOKEN" --yes 2>&1; then
241
+ echo "✅ Rollback completado — versión anterior está en vivo"
242
+ echo ""
243
+ echo "⚠️ ACCIÓN REQUERIDA:"
244
+ echo " • Revisa los logs de Vercel para diagnosticar el error"
245
+ echo " • Corrije el problema y ejecuta /sdd.desplegar nuevamente"
246
+ else
247
+ echo "❌ Rollback falló — contacta al equipo de DevOps"
248
+ exit 1
249
+ fi
250
+ else
251
+ echo "✅ Health check OK — sin rollback necesario"
252
+ fi
253
+
254
+ echo ""
255
+ ```
256
+
257
+ ---
258
+
259
+ ### PASO 6: Registrar resultado
260
+
261
+ Guardar metadatos del despliegue para auditoría y monitoring:
262
+
263
+ ```bash
264
+ echo "📊 PASO 6: Registrar Resultado"
265
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
266
+
267
+ # Crear directorio .sdd si no existe
268
+ mkdir -p .sdd
269
+
270
+ # Generar timestamp ISO 8601
271
+ TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
272
+
273
+ # Escribir a estado.json
274
+ cat > .sdd/estado.json << EOF
275
+ {
276
+ "ultimo_despliegue": {
277
+ "timestamp": "$TIMESTAMP",
278
+ "url": "$DEPLOY_URL",
279
+ "status": "$([ "$HEALTH_STATUS" = "OK" ] && echo "OK" || echo "ROLLED_BACK")",
280
+ "health_check": "$([ "$HEALTH_CHECK_PASSED" -eq 1 ] && echo "200 OK" || echo "FAILED")",
281
+ "framework": "$FRAMEWORK"
282
+ }
283
+ }
284
+ EOF
285
+
286
+ echo "✅ Estado registrado en .sdd/estado.json"
287
+ echo ""
288
+ ```
289
+
290
+ ---
291
+
292
+ ## Output final para el usuario
293
+
294
+ Una vez completados todos los pasos exitosamente:
295
+
296
+ ```
297
+ 🚀 DESPLIEGUE A VERCEL — COMPLETADO
298
+
299
+ ✅ Pre-checks completados
300
+ ✅ Build exitoso
301
+ ✅ Vercel deployment: https://mi-proyecto.vercel.app
302
+ ✅ Health check: HTTP 200
303
+
304
+ Tu app está en vivo: https://mi-proyecto.vercel.app
305
+ Timestamp: 2026-06-13T14:30:00Z
306
+ Tiempo total: 3m 42s
307
+
308
+ Próximos pasos:
309
+ • Comparte la URL con testers y stakeholders
310
+ • Monitorea por anomalías en los próximos 15 minutos
311
+ • Ejecuta /sdd.snapshot para actualizar el estado del producto
312
+ • En caso de issues, /sdd.revertir ejecutará rollback manual
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Manejo de errores
318
+
319
+ | Error | Causa probable | Acción |
320
+ |-------|-----------------|--------|
321
+ | `VERCEL_TOKEN` ausente | No configurado en env | Mostrar instrucciones de generación (ver PASO 1) |
322
+ | Tests fallando | Código tiene issues | Usuario debe ejecutar `/sdd.implementar` nuevamente |
323
+ | Health check 502/503 | Cold start, env var faltante, o timeout | Reintenta 3 veces; si persiste, rollback automático |
324
+ | Build local falla | Dependencias rotas o código inválido | Usuario debe revisar errores y corregir |
325
+ | Cambios sin stagear | Usuario modificó código manualmente | Error: "Ejecuta `git add . && git commit` primero" |
326
+ | Rollback falla | Problemas con Vercel API | Contactar equipo de DevOps; escalar al SRE |
327
+
328
+ ---
329
+
330
+ ## Cuándo se invoca
331
+
332
+ 1. **Automáticamente** en el PASO final de `sdd.implementar.md` si `deploy.plataforma: vercel` está configurado
333
+ - Con gate humano ANTES de ejecutar: "¿Despliego en Vercel?" [sí/no/después]
334
+
335
+ 2. **Manualmente** ejecutando:
336
+ ```bash
337
+ /sdd.desplegar
338
+ ```
339
+
340
+ 3. **Con promoción de entorno**:
341
+ ```bash
342
+ /sdd.desplegar --environment staging
343
+ # o
344
+ /sdd.desplegar --environment production
345
+ ```
346
+
347
+ ---
348
+
349
+ ## Notas de implementación
350
+
351
+ - **Atomicidad**: O todo se despliega y pasa health check, o se revierte. Sin estados intermedios.
352
+ - **Idempotencia**: Ejecutar dos veces seguidas produce el mismo resultado (si no hay cambios de código).
353
+ - **Observabilidad**: Cada run deja trazas en `.sdd/estado.json` para auditoría y debugging.
354
+ - **Seguridad**: VERCEL_TOKEN nunca se loguea; los secretos se detectan antes de deploy.
355
+ - **UX**: Output visual con emojis, colores, y pasos claramente numerados.
356
+
@@ -0,0 +1,298 @@
1
+ #!/bin/bash
2
+ # Skill: vercel-deploy
3
+ # Despliegue automático en Vercel con 6 pasos
4
+
5
+ set -e
6
+
7
+ # Colores
8
+ RED='\033[0;31m'
9
+ GREEN='\033[0;32m'
10
+ YELLOW='\033[1;33m'
11
+ BLUE='\033[0;34m'
12
+ NC='\033[0m' # No Color
13
+
14
+ # Funciones de utilidad
15
+ log_step() {
16
+ echo -e "${BLUE}📍 $1${NC}"
17
+ }
18
+
19
+ log_success() {
20
+ echo -e "${GREEN}✅ $1${NC}"
21
+ }
22
+
23
+ log_error() {
24
+ echo -e "${RED}❌ $1${NC}"
25
+ }
26
+
27
+ log_warning() {
28
+ echo -e "${YELLOW}⚠️ $1${NC}"
29
+ }
30
+
31
+ # ============================================================================
32
+ # PASO 1: Pre-checks
33
+ # ============================================================================
34
+
35
+ paso_1_prechecks() {
36
+ log_step "PASO 1: Pre-checks"
37
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
38
+
39
+ # Check 1: VERCEL_TOKEN
40
+ if [ -z "$VERCEL_TOKEN" ]; then
41
+ log_error "VERCEL_TOKEN no configurado"
42
+ echo ""
43
+ echo "Instrucciones para generar:"
44
+ echo " 1. Ve a https://vercel.com/account/tokens"
45
+ echo " 2. Crea un nuevo token con scope 'full'"
46
+ echo " 3. Guárdalo:"
47
+ echo " export VERCEL_TOKEN='vercel_xxx_...'"
48
+ exit 1
49
+ fi
50
+ log_success "VERCEL_TOKEN presente"
51
+
52
+ # Check 2: Rama limpia
53
+ if ! git diff-files --quiet; then
54
+ log_error "Cambios sin stagear detectados"
55
+ echo ""
56
+ echo "Acción requerida:"
57
+ echo " git add ."
58
+ echo " git commit -m 'Descripción de cambios'"
59
+ exit 1
60
+ fi
61
+ log_success "Rama limpia (sin cambios sin stagear)"
62
+
63
+ # Check 3: Sin secretos
64
+ log_warning "Escaneando por secretos en src/..."
65
+ SECRETOS=$(grep -r "VERCEL_TOKEN\|API_KEY\|SECRET\|password" src/ 2>/dev/null || true)
66
+ if [ ! -z "$SECRETOS" ]; then
67
+ log_error "Secretos detectados en código:"
68
+ echo "$SECRETOS"
69
+ exit 1
70
+ fi
71
+ log_success "Sin secretos hardcodeados"
72
+
73
+ # Check 4: Tests verdes
74
+ log_warning "Ejecutando tests..."
75
+ if ! npm test -- --passWithNoTests 2>/dev/null; then
76
+ log_error "Tests fallando"
77
+ echo ""
78
+ echo "Acción: Ejecuta /sdd.implementar para arreglar"
79
+ exit 1
80
+ fi
81
+ log_success "Tests pasando"
82
+ echo ""
83
+ }
84
+
85
+ # ============================================================================
86
+ # PASO 2: Auto-generar vercel.json
87
+ # ============================================================================
88
+
89
+ paso_2_vercel_config() {
90
+ log_step "PASO 2: Configurar vercel.json"
91
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
92
+
93
+ FRAMEWORK="unknown"
94
+ BUILD_CMD=""
95
+ OUTPUT_DIR=""
96
+
97
+ if [ -f package.json ]; then
98
+ if grep -q '"next"' package.json; then
99
+ FRAMEWORK="nextjs"
100
+ BUILD_CMD="npm run build"
101
+ OUTPUT_DIR=".next"
102
+ elif grep -q '"react"' package.json && ! grep -q '"next"' package.json; then
103
+ FRAMEWORK="react"
104
+ BUILD_CMD="npm run build"
105
+ OUTPUT_DIR="build"
106
+ elif grep -q '"vue"' package.json; then
107
+ FRAMEWORK="vue"
108
+ BUILD_CMD="npm run build"
109
+ OUTPUT_DIR="dist"
110
+ elif grep -q '"astro"' package.json; then
111
+ FRAMEWORK="astro"
112
+ BUILD_CMD="npm run build"
113
+ OUTPUT_DIR="dist"
114
+ elif grep -q '"fastapi\|flask"' package.json; then
115
+ FRAMEWORK="python"
116
+ BUILD_CMD="pip install -r requirements.txt"
117
+ OUTPUT_DIR="."
118
+ fi
119
+
120
+ echo "📦 Framework detectado: $FRAMEWORK"
121
+
122
+ if [ ! -f vercel.json ]; then
123
+ cat > vercel.json << EOF
124
+ {
125
+ "buildCommand": "$BUILD_CMD",
126
+ "outputDirectory": "$OUTPUT_DIR",
127
+ "framework": "$FRAMEWORK"
128
+ }
129
+ EOF
130
+ log_success "vercel.json creado automáticamente"
131
+ else
132
+ log_success "vercel.json ya existe"
133
+ fi
134
+ else
135
+ log_warning "No se encontró package.json"
136
+ fi
137
+
138
+ echo ""
139
+ }
140
+
141
+ # ============================================================================
142
+ # PASO 3: Build y Deploy
143
+ # ============================================================================
144
+
145
+ paso_3_deploy() {
146
+ log_step "PASO 3: Build y Deploy a Vercel"
147
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
148
+
149
+ log_warning "Compilando localmente..."
150
+ if ! npm run build 2>&1; then
151
+ log_error "Build local falló"
152
+ exit 1
153
+ fi
154
+ log_success "Build local exitoso"
155
+
156
+ log_warning "Enviando a Vercel..."
157
+ DEPLOY_OUTPUT=$(vercel deploy --prod --token="$VERCEL_TOKEN" 2>&1)
158
+ DEPLOY_URL=$(echo "$DEPLOY_OUTPUT" | grep -oP 'https://[^\s]+' | head -1)
159
+
160
+ if [ -z "$DEPLOY_URL" ]; then
161
+ log_error "No se pudo obtener URL de despliegue"
162
+ echo "Salida de Vercel:"
163
+ echo "$DEPLOY_OUTPUT"
164
+ exit 1
165
+ fi
166
+
167
+ log_success "Deploy enviado a Vercel"
168
+ echo " URL: $DEPLOY_URL"
169
+ echo ""
170
+ }
171
+
172
+ # ============================================================================
173
+ # PASO 4: Health Check
174
+ # ============================================================================
175
+
176
+ paso_4_health_check() {
177
+ log_step "PASO 4: Health Check"
178
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
179
+
180
+ HEALTH_CHECK_PASSED=0
181
+ MAX_RETRIES=3
182
+ RETRY_DELAY=5
183
+
184
+ for i in $(seq 1 $MAX_RETRIES); do
185
+ echo "Intento $i/$MAX_RETRIES: GET $DEPLOY_URL"
186
+
187
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$DEPLOY_URL" --max-time 10)
188
+
189
+ if [ "$HTTP_CODE" = "200" ]; then
190
+ log_success "Health check exitoso (HTTP $HTTP_CODE)"
191
+ HEALTH_CHECK_PASSED=1
192
+ break
193
+ else
194
+ log_warning "HTTP $HTTP_CODE — esperando ${RETRY_DELAY}s..."
195
+ if [ $i -lt $MAX_RETRIES ]; then
196
+ sleep $RETRY_DELAY
197
+ fi
198
+ fi
199
+ done
200
+
201
+ if [ $HEALTH_CHECK_PASSED -eq 0 ]; then
202
+ log_error "Health check falló después de $MAX_RETRIES intentos"
203
+ HEALTH_STATUS="FAILED"
204
+ else
205
+ HEALTH_STATUS="OK"
206
+ fi
207
+
208
+ echo ""
209
+ }
210
+
211
+ # ============================================================================
212
+ # PASO 5: Rollback (si es necesario)
213
+ # ============================================================================
214
+
215
+ paso_5_rollback() {
216
+ log_step "PASO 5: Rollback (si es necesario)"
217
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
218
+
219
+ if [ "$HEALTH_STATUS" != "OK" ]; then
220
+ log_warning "Ejecutando rollback..."
221
+
222
+ if vercel rollback --token="$VERCEL_TOKEN" --yes 2>&1; then
223
+ log_success "Rollback completado"
224
+ echo ""
225
+ log_error "Deployment was rolled back"
226
+ echo " • Revisa los logs de Vercel para diagnosticar"
227
+ echo " • Corrije el problema y ejecuta /sdd.desplegar nuevamente"
228
+ exit 1
229
+ else
230
+ log_error "Rollback falló"
231
+ exit 1
232
+ fi
233
+ else
234
+ log_success "Health check OK — sin rollback necesario"
235
+ fi
236
+
237
+ echo ""
238
+ }
239
+
240
+ # ============================================================================
241
+ # PASO 6: Registrar resultado
242
+ # ============================================================================
243
+
244
+ paso_6_register() {
245
+ log_step "PASO 6: Registrar Resultado"
246
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
247
+
248
+ mkdir -p .sdd
249
+
250
+ TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
251
+
252
+ cat > .sdd/estado.json << EOF
253
+ {
254
+ "ultimo_despliegue": {
255
+ "timestamp": "$TIMESTAMP",
256
+ "url": "$DEPLOY_URL",
257
+ "status": "$([ "$HEALTH_STATUS" = "OK" ] && echo "OK" || echo "ROLLED_BACK")",
258
+ "health_check": "$([ "$HEALTH_CHECK_PASSED" -eq 1 ] && echo "200 OK" || echo "FAILED")",
259
+ "framework": "$FRAMEWORK"
260
+ }
261
+ }
262
+ EOF
263
+
264
+ log_success "Estado registrado en .sdd/estado.json"
265
+ echo ""
266
+ }
267
+
268
+ # ============================================================================
269
+ # Main: Ejecutar todos los pasos
270
+ # ============================================================================
271
+
272
+ main() {
273
+ echo ""
274
+ echo "🚀 DESPLIEGUE A VERCEL"
275
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
276
+ echo ""
277
+
278
+ paso_1_prechecks
279
+ paso_2_vercel_config
280
+ paso_3_deploy
281
+ paso_4_health_check
282
+ paso_5_rollback
283
+ paso_6_register
284
+
285
+ # Output final
286
+ echo "✅ DESPLIEGUE COMPLETADO"
287
+ echo ""
288
+ echo "Tu app está en vivo:"
289
+ echo " 🌐 $DEPLOY_URL"
290
+ echo ""
291
+ echo "Próximos pasos:"
292
+ echo " • Comparte la URL con testers"
293
+ echo " • Monitorea por anomalías (15 minutos)"
294
+ echo " • Ejecuta /sdd.snapshot para actualizar estado del producto"
295
+ echo ""
296
+ }
297
+
298
+ main "$@"