| name | engine-release |
| description | Audits, cleans, and releases a new SpecBox Engine version. Checks for residual code, updates ENGINE_VERSION.yaml, CLAUDE.md, changelog, and pushes to remote. Use when the user says "release", "bump version", "new version", "cut release", "audit and release", "sube version", "prepara release".
|
| context | direct |
| allowed-tools | Read, Grep, Glob, Bash(*), Write, Edit, Agent |
/release — SpecBox Engine Release Pipeline
Audita residuos, actualiza version, CLAUDE.md, changelog, y sube a remoto.
Uso
/release [version] [codename]
Ejemplos:
/release 5.9.0 — Release con version explicita
/release 5.9.0 "Pipeline Guards" — Con codename
/release — Auto-detecta: bump minor desde version actual
/release patch — Bump patch (5.8.0 → 5.8.1)
/release major — Bump major (5.8.0 → 6.0.0)
Paso 0: Resolver Version
0.1 Leer version actual
grep "^version:" ENGINE_VERSION.yaml | head -1
0.2 Calcular nueva version
¿Que recibi?
├── X.Y.Z explicito → Usar directamente
├── "patch" → Bump patch (X.Y.Z → X.Y.Z+1)
├── "minor" o sin argumento → Bump minor (X.Y.Z → X.Y+1.0)
├── "major" → Bump major (X.Y.Z → X+1.0.0)
└── Codename → Segundo argumento o preguntar
Si no se proporciona codename, preguntar al usuario:
"Version {X.Y.Z} — ¿Con que codename? (ej: 'Pipeline Guards', 'FreeForm', etc.)"
0.3 Verificar estado git
git status --short
git branch --show-current
- Si hay cambios sin commitear → WARNING: "Hay cambios pendientes. Los incluire en el release commit."
- Si no esta en
main → WARNING: "No estas en main. ¿Continuar en rama {branch}?"
0.4 Pre-flight: VSCode extension version sync (v6.2.0+)
Gate INVIOLABLE introducido por US-VSCODE-MARKETPLACE (UC-635).
Si vscode-extension/package.json:version no coincide con ENGINE_VERSION.yaml:version,
el publish CI fallará con drift. NO se permite tagear con drift.
Ejecutar:
bash scripts/sync-extension-version.sh --check
Interpretar el exit code:
| Exit | Significado | Acción |
|---|
| 0 | Versions sincronizadas | Continuar a Paso 1 |
| 1 | Drift detectado entre engine y extensión | Presentar las dos opciones de abajo |
| 2 | Error de ejecución (script ausente, YAML inválido) | Abortar release, investigar |
Si exit == 1, presentar al usuario EXACTAMENTE estas dos opciones (NO añadir una tercera "ignorar"):
✗ Drift detectado entre ENGINE_VERSION.yaml y vscode-extension/package.json
Opciones:
[a] Auto-fix + commit
Ejecuta sync-extension-version.sh --write, hace commit
"chore(vscode-ext): sync version to v{nueva_version}" y continúa el release.
El commit de sync va ANTES del commit de release notes y del tag.
[b] Abortar release
Termina el skill. Resuelve el drift manualmente y vuelve a lanzar /release.
¿Qué prefieres? [a/b]
Si el usuario elige [a]:
bash scripts/sync-extension-version.sh --write
git add vscode-extension/package.json vscode-extension/package-lock.json
git commit -m "chore(vscode-ext): sync version to v{nueva_version}"
Después de este commit, continuar normalmente a Paso 1. El orden final de commits en el release será:
HEAD <tag v{nueva_version}>
HEAD~1 release: v{nueva_version} - <codename>
HEAD~2 chore(vscode-ext): sync version to v{nueva_version}
Verificable post-release con git log --oneline -3.
Test manual del gate
Para verificar que el gate dispara correctamente sin lanzar un release real:
python3 -c "import json; p=json.load(open('vscode-extension/package.json')); p['version']='0.0.1'; json.dump(p, open('vscode-extension/package.json','w'), indent=2)"
bash scripts/sync-extension-version.sh --check
git checkout vscode-extension/package.json
Si el script sale exit 0 con drift artificial, el gate está roto — investigar antes de lanzar /release real.
Paso 1: Auditoria de Residuos
Lanzar 3 auditorias en paralelo usando Agent tool (subagent_type=Explore):
1.1 Codigo residual
Buscar en todo el proyecto:
TODO, FIXME, HACK, XXX en archivos de codigo (.py, .ts, .tsx, .sh, .dart)
console.log, print( en archivos de produccion (no tests, no scripts)
- Archivos
.bak, .orig, .tmp, archivos vacios
- Imports no usados (buscar patrones comunes)
- Archivos en
server/ que no esten referenciados desde server.py o tools/
1.2 Consistencia de documentacion
- Version en
ENGINE_VERSION.yaml vs CLAUDE.md header vs pyproject.toml
- Features listadas en ENGINE_VERSION.yaml que no estan en CLAUDE.md
- Skills listadas en CLAUDE.md que no existen en
.claude/skills/
- Hooks listados en CLAUDE.md que no existen en
.claude/hooks/
- Agents listados en CLAUDE.md que no existen en
agents/
- Tools count en CLAUDE.md vs archivos reales en
server/tools/
1.3 Integridad estructural
__init__.py en cada directorio de server/ y server/backends/ y server/tools/
- Todos los backends en
server/backends/ importados en auth_gateway.py
- Archivos en
commands/ tienen correspondencia con skills/
install.sh copia todas las skills que existen
1.4 Reporte de auditoria
Presentar resultados al usuario como tabla:
## Auditoria de Release v{X.Y.Z}
| Categoria | Estado | Hallazgos |
|-----------|--------|-----------|
| Codigo residual | OK/WARN | N TODOs, N console.logs, N archivos tmp |
| Documentacion | OK/WARN | N inconsistencias |
| Estructura | OK/WARN | N problemas |
Si hay hallazgos WARN:
- Listar cada uno con ubicacion (archivo:linea)
- Preguntar: "¿Corrijo estos N problemas antes de continuar con el release?"
Si el usuario dice si: Corregir automaticamente lo que sea safe:
- Eliminar archivos
.bak, .orig, .tmp
- Corregir version inconsistente en docs
- NO eliminar TODOs (pueden ser intencionales)
- NO eliminar console.log/print (pueden ser logging real)
Si el usuario dice no o no hay hallazgos: Continuar al Paso 2.
Paso 2: Recolectar Cambios para Changelog
2.1 Obtener commits desde ultima version
git log --oneline $(git log --oneline --all --grep="feat: v" | head -2 | tail -1 | cut -d' ' -f1)..HEAD
Si no hay tags, comparar con el commit del changelog anterior:
git log --oneline --since="$(grep -A1 'date:' ENGINE_VERSION.yaml | tail -1 | sed 's/.*date: //')" 2>/dev/null || git log --oneline -20
2.2 Categorizar cambios
Agrupar commits por tipo:
feat: → Nuevas funcionalidades
fix: → Correcciones
refactor: → Refactorizaciones
docs: → Documentacion
test: → Tests
2.3 Generar changelog entries
Para cada cambio significativo, crear entrada con formato:
- "tipo: descripcion clara y concisa"
Reglas:
- Maximo 15 entries (agrupar cambios menores)
- Cada entry empieza con
feat:, fix:, refactor:, docs:, o test:
- Descripcion en ingles (consistente con changelog existente)
- No incluir merges, bumps, ni commits de infraestructura triviales
Paso 3: Actualizar ENGINE_VERSION.yaml
3.1 Actualizar campos base
version: {nueva_version}
codename: "{codename}"
release_date: {YYYY-MM-DD de hoy}
3.2 Agregar nuevas features
Revisar los cambios del Paso 2 y determinar que features nuevas se agregan a la lista.
Agregar bajo comentario # New (v{X.Y.Z}).
3.3 Agregar changelog entry
Agregar al inicio de la seccion changelog::
{nueva_version}:
date: {YYYY-MM-DD}
changes:
- "feat: ..."
- "fix: ..."
Paso 4: Actualizar CLAUDE.md
4.1 Version en header
# SpecBox Engine v{nueva_version}
4.2 Secciones afectadas
Revisar cada seccion de CLAUDE.md y actualizar si los cambios del release la afectan:
- "Que es este repositorio" — Si se anaden nuevas capacidades top-level
- "Stack soportado" — Si se anade nuevo stack
- "Gestores de proyecto" — Si se anade nuevo backend
- "Estructura del repositorio" — Si hay nuevos directorios/archivos clave
- "Available Skills" — Si se anade nueva skill
- "Hooks" — Si se anade nuevo hook
- "Agents" — Si se anade nuevo agente
- "Engine Version" — Siempre: actualizar
Current: v{X.Y.Z} "{codename}"
- Tools count — Si cambia el numero de tools MCP
4.3 Consistencia
- Todos los archivos referenciados en CLAUDE.md deben existir
- Tablas deben reflejar el estado actual del codigo
- Counts (108+ tools, etc.) deben ser precisos
Paso 4.5: Actualizar README.md (OBLIGATORIO — v5.32.1+)
Regla: el README se bumpea en TODA release (major, minor o patch).
Ningun /release puede pasar al Paso 6 (commit) sin haber tocado este
archivo. El validador del Paso 7 abortara la release si la version del
README no coincide con ENGINE_VERSION.yaml.
El README tiene 4 ubicaciones que deben actualizarse en CADA release. Ningun
bloque historico ("Lo nuevo en vX" / "What's new in vX" anteriores) se borra
— se preservan para contexto historico segun el protocolo establecido en
v5.31.1.
4.5.1 Subtitulo en espanol (linea ~9)
v{nueva_version} — "{codename}" (sobre vX.Y "{codename anterior}")
4.5.2 Bloque "Lo nuevo en vX.Y" (espanol, arriba de la primera "Por que vX.X" existente)
Insertar (NO reemplazar) un nuevo bloque:
## Lo nuevo en v{nueva_version_minor_or_major}
**v{nueva_version} — "{codename}"** {1-2 frases del cambio principal}:
- **{cambio 1}** — {1 linea}
- **{cambio 2}** — {1 linea}
- ...
100% backwards-compatible. {nota sobre defaults o migracion si aplica}.
---
Si la version es un patch (X.Y.Z con Z>0) y ya existe un bloque
"Lo nuevo en vX.Y" del minor previo, NO se anade un nuevo bloque
"Lo nuevo en vX.Y.Z". En su lugar, se actualiza el subtitulo del bloque
existente con una linea adicional al final:
**v{X.Y.Z}** {1 frase resumen del patch}.
4.5.3 Subtitulo en ingles (busqueda: # SpecBox Engine — English version)
> v{nueva_version} — "{codename}" (over vX.Y "{codename anterior}")
4.5.4 Bloque "What's new in vX.Y" (ingles, simetrico al espanol)
Mismo patron que 4.5.2 pero traducido al ingles.
4.5.5 Verificacion
Tras editar:
grep -n "v{nueva_version}" README.md | head
Paso 5: Actualizar pyproject.toml
version = "{nueva_version}"
Paso 5.5: Actualizar CHANGELOG.md (OBLIGATORIO — v5.32.1+)
Regla: el CHANGELOG.md tambien se bumpea en TODA release. La entrada
nueva va al inicio (debajo del header), arriba de la entrada anterior —
NO se reemplaza ni se borra ninguna entrada historica.
5.5.1 Insertar nueva entrada al inicio
## [{nueva_version}] - {YYYY-MM-DD} — "{codename}"
{1 parrafo de contexto: que problema cierra y como}.
### Added
- **{componente 1}** — {descripcion}
- **{componente 2}** — {descripcion}
### Changed
- {cambios sobre archivos existentes}
### Decisions
- {decisiones de diseno tomadas en la release}
### Compatibility
- {nota sobre backwards-compatibility, defaults, migracion}
### Tests
- N nuevos tests, todos verdes:
- {breakdown por archivo}
- Pre-existing failures on `main` documentados en releases previas
permanecen.
## [version_anterior] - ...
5.5.2 Verificacion
head -10 CHANGELOG.md | grep -E "^## \[{nueva_version}\]"
Paso 6: Commit y Push
6.1 Verificar cambios
git diff --stat
git status --short
Mostrar resumen al usuario de todos los archivos que se van a commitear.
6.2 Commit
git add ENGINE_VERSION.yaml CLAUDE.md pyproject.toml CHANGELOG.md README.md \
[otros archivos corregidos en auditoria]
git commit -m "feat: v{nueva_version} {codename} — {resumen de 1 linea}
{lista de cambios principales, max 5 lineas}
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
README.md y CHANGELOG.md SON OBLIGATORIOS en el git add. Si el
validador del Paso 7 detecta que faltan, la release se aborta.
6.3 Push
git push
6.4 Confirmacion final
## Release v{nueva_version} "{codename}" completado
- Commit: {hash corto}
- Archivos modificados: N
- Changelog: N entries
- Auditoria: {resultado}
- Pushed to: {remote}/{branch}
Paso 6.5: Publicar estado del engine al site (US-16 + US-20 — v6.11.0+)
Qué: tras bumpear ENGINE_VERSION.yaml + CHANGELOG.md (Pasos 3 y 5.5) y
commitear (Paso 6), publica al schema público de Supabase SpecBox-Cloud, en una sola
invocación, dos cosas: (1) el estado del engine —release actual, features, changelog
curado (US-16)— y (2) el inventario de capacidades —agentes, MCP tools, skills y la
extensión VSCode (US-20)— extraído del propio código del engine (agents/*.md, decoradores
@*.tool en server/, .claude/skills/*/SKILL.md, vscode-extension/package.json). El site
specbox.embed.build (satélite site) lee esas tablas y refleja la versión y el inventario
recién liberados sin editar .astro a mano.
Por qué aquí: la única vía de liberar (/release) es también la única vía de
publicar → el changelog Y el inventario del site nunca divergen del engine.
6.5.1 Ejecutar el publicador
El paso es no bloqueante: el release ya está consumado (commit + push hechos). Si la
publicación falla, se reporta como WARNING accionable, NO se revierte el release.
SUPABASE_URL="https://nywjsvumsvxlpflpbord.supabase.co" \
SUPABASE_SERVICE_ROLE_KEY="<service-role-key>" \
uv run python -m server.site_publish
Exit codes:
| Exit | Significado | Acción |
|---|
| 0 | Publicado OK | Reportar en el resumen del release: "Estado + inventario publicados al site (N features, M versiones; A agentes, T tools, S skills, ext vX.Y.Z)" |
| 2 | Faltan credenciales | WARNING accionable: "No se publicó al site — define SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY y re-ejecuta uv run python -m server.site_publish". El release NO se aborta. |
| 3 | Fallo de red / HTTP | WARNING accionable con el mismo comando de re-ejecución. El release NO se aborta. |
6.5.2 Idempotencia
El publicador hace UPSERT (resolution=merge-duplicates): re-ejecutarlo es seguro y deja
la BD en el mismo estado. Por eso el comando de recuperación de 6.5.1 puede correrse las
veces que haga falta hasta exit 0, incluso días después del release.
6.5.3 Reflejar en el reporte final
Añadir una línea al bloque "Release completado" del Paso 6.4:
- Estado + inventario publicados al site: {OK (N features, M versiones; A agentes, T tools, S skills, ext vX.Y.Z) | WARNING: no publicado — re-ejecutar `uv run python -m server.site_publish`}
Paso 7: Pre-commit Consistency Check (BLOQUEANTE — v5.32.1+)
Regla: ANTES del git commit del Paso 6, correr el validador automatico
que verifica que los 5 archivos de version estan alineados. Si falla,
abortar la release y reportar al usuario los archivos desincronizados.
7.1 Ejecutar validador
node .quality/scripts/version-consistency-check.mjs
El script lee la version canonica de ENGINE_VERSION.yaml y verifica que
aparezca en:
pyproject.toml (campo version = "...")
CLAUDE.md (header # SpecBox Engine vX.Y.Z + footer Current: vX.Y.Z)
CHANGELOG.md (entrada ## [X.Y.Z] - ... al inicio)
README.md (subtitulo ES + subtitulo EN)
7.2 Interpretacion del resultado
| Exit code | Significado | Accion |
|---|
| 0 | Todas las versiones alineadas | Continuar a Paso 6 (commit) |
| 1 | Al menos un archivo desincronizado | ABORTAR release. Stderr lista los archivos y la version detectada en cada uno |
7.3 Si falla
- Volver a los Pasos 3, 4, 4.5, 5, 5.5 y corregir el archivo desincronizado.
- Re-ejecutar el validador.
- Solo cuando devuelva exit 0, proceder al Paso 6.
NUNCA bypasear este check. Si el validador tiene un falso positivo, repor
tarlo como bug en lugar de saltarse el bloqueo.
Reglas de Seguridad
- NUNCA hacer release si hay tests fallando (verificar con
pytest o equivalente si hay tests)
- NUNCA eliminar codigo sin confirmar con el usuario
- NUNCA modificar archivos de
server/tools/ o server/backends/ durante release — solo docs y config
- Si la auditoria encuentra problemas criticos → BLOQUEAR release y reportar
- El codename es obligatorio — si no se proporciona, preguntar
- Siempre mostrar diff completo antes de commitear para que el usuario revise