@dforce2055/dai 0.14.0 → 0.15.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.
@@ -0,0 +1,156 @@
1
+ # Guía de releases — por qué versionar, y cómo hacerlo sin ceremonia inútil
2
+
3
+ > En una frase: **desplegar tiene que ser desplegar algo que ya existía y que ya se probó,
4
+ > no armarlo en el momento.** Todo lo demás de esta guía sale de ahí.
5
+
6
+ Esta guía es el *porqué*. Si ya lo tienes claro y solo quieres los comandos, ve al
7
+ [tutorial del ciclo completo](../tutoriales/ciclo-de-release).
8
+
9
+ ## El problema, tal como se ve por dentro
10
+
11
+ Hay equipos que no arman ramas de release ni etiquetan versiones. Cuando llega el momento
12
+ de subir a producción, alguien se sienta a recordar qué ramas componen la funcionalidad y
13
+ las va mergeando a la rama de producción, una por una.
14
+
15
+ Eso falla de tres formas distintas, y las tres duelen:
16
+
17
+ 1. **Se despliega algo que nunca se probó.** Cada orden de merge produce un árbol distinto.
18
+ El que llega a producción no existió en ningún ambiente antes de ese momento.
19
+ 2. **Nadie puede decir qué hay en producción.** Ni qué funcionalidades comprende. Y cuando
20
+ algo se rompe de noche, no hay un punto conocido al que volver.
21
+ 3. **Se cuelan cosas que no estaban listas**, porque la selección se hace rama por rama, a
22
+ mano y con prisa.
23
+
24
+ Si te suena, el resto de la guía es para ti.
25
+
26
+ ## Lo que hay que separar, porque no es lo mismo
27
+
28
+ La trampa habitual es intentar resolver los tres problemas con un solo mecanismo —
29
+ normalmente "armemos una rama de release". En realidad son tres:
30
+
31
+ | Problema | Se resuelve con |
32
+ |---|---|
33
+ | **Trazabilidad** — qué código hay en cada ambiente | identidad inmutable: un **tag** y un artefacto |
34
+ | **Selección** — qué funcionalidades van | lo que está integrado, más *feature flags* |
35
+ | **Estabilización** — arreglar sin frenar el desarrollo | **la rama de release**, y solo esto |
36
+
37
+ La rama de release resuelve el tercero. Si tu equipo no necesita una ventana de
38
+ estabilización, es ceremonia sin beneficio.
39
+
40
+ ## Las dos reglas que valen más que cualquier estrategia de ramas
41
+
42
+ ### 1. Construye una vez, promueve el artefacto
43
+
44
+ Promover a producción es **desplegar el mismo binario/imagen/paquete** que ya pasó por
45
+ test, con otra configuración. No es reconstruir desde otra rama.
46
+
47
+ Si en cada ambiente vuelves a construir, probaste una cosa y desplegaste otra. Es el fallo
48
+ más profundo del modelo "una rama por ambiente": el mismo commit produce artefactos
49
+ distintos, y las ramas divergen en silencio cuando alguien olvida un *back-merge*.
50
+
51
+ ### 2. Desplegar no es lanzar
52
+
53
+ Que el código esté en producción no obliga a que la funcionalidad esté visible. Un *feature
54
+ flag* separa las dos cosas, y con eso desaparece el motivo real por el que se cuelan cosas a
55
+ medias: ya no hace falta retener el código para retener la funcionalidad.
56
+
57
+ Si algo llega a la rama de integración a medio hacer, ninguna rama de release lo va a
58
+ salvar: vas a terminar sacando cosas *de* la release, que es la misma enfermedad al revés y
59
+ más difícil de revertir. El control real es doble: **nada se integra si no es desplegable**
60
+ (el gate de `dai check --ci`) y lo desplegable-pero-no-lanzable va detrás de un flag.
61
+
62
+ ## Los dos modelos, y la pregunta que elige
63
+
64
+ **Modelo A — tronco y tag.** Una sola rama de vida larga. Ramas cortas (uno o dos días) con
65
+ PR y gate de CI. Cada integración produce un artefacto; promover a producción es desplegar
66
+ ese artefacto y etiquetar el commit exacto. Los *hotfix* salen del tag que está en
67
+ producción, se etiquetan y se reintegran.
68
+
69
+ **Modelo B — tronco y rama de release.** Igual que A, pero al cortar se crea
70
+ `release/X.Y.Z` desde integración. Solo entran correcciones, y siempre **arregladas primero
71
+ en integración y llevadas a la release** — nunca al revés, que es como se pierde el
72
+ *back-merge*. Se etiqueta, se despliega, y **la rama se borra**: una rama de release que
73
+ sobrevive a su release es un fork. (`dai release done` la borra solo; `dai release status`
74
+ avisa de las que quedaron de antes.)
75
+
76
+ > **La pregunta que decide:** ¿cuántos días pasan entre "dejamos de agregar" y "está en
77
+ > producción"? Menos de un día → modelo A, la rama sería ceremonia. Varios días con
78
+ > desarrollo en paralelo (QA de regresión, comité de cambios, ventana fija de despliegue) →
79
+ > modelo B, y ahí la rama se gana su lugar.
80
+
81
+ Nota incómoda pero honesta: la investigación de entrega de software encuentra que los
82
+ equipos de alto desempeño tienen **ramas de vida corta y pocas ramas de larga vida**. Una
83
+ rama de release que vive semanas correlaciona con peor desempeño, no mejor. Si tu ventana se
84
+ alarga, conviene preguntarse si es porque hay menos que entregar o porque cada release
85
+ duele — la segunda es un síntoma a atacar, no una razón para espaciar más.
86
+
87
+ ## Qué versión poner
88
+
89
+ Depende de quién consume tu software:
90
+
91
+ - **Una librería, un SDK, un paquete**: **semver**. El número comunica compatibilidad a
92
+ quien depende de ti, y eso es un contrato.
93
+ - **Una aplicación interna** que nadie consume como dependencia: semver puede volverse
94
+ teatro — vas a discutir en reunión si algo es *minor* o *patch* para un número que no le
95
+ comunica nada a nadie. Ahí lo que necesitas es identidad **inequívoca y ordenada**
96
+ (`2026.09.1`, o un secuencial) más un manifiesto de qué contiene. El valor está en el
97
+ manifiesto, no en el número.
98
+
99
+ Sea cual sea el esquema, **la decisión es de una persona**. dai propone un piso mirando los
100
+ tipos de commit y lo dice; la regla que manda mira el **comportamiento observable**. Un
101
+ cambio que mueve un valor por omisión es *minor* aunque todos los commits digan `fix:`.
102
+
103
+ ## Qué aporta dai
104
+
105
+ dai no elige tu estrategia de ramas: eso es tuyo. Lo que aporta es el eslabón que falta en
106
+ la trazabilidad.
107
+
108
+ ```
109
+ User Story → implements.yaml → commit → PR → VERSIÓN → AMBIENTE
110
+ └── esto es lo que agrega ──┘
111
+ ```
112
+
113
+ Con eso, preguntas que hoy requieren una reunión se contestan desde el ticket:
114
+
115
+ - **¿Qué entra en la próxima versión?** → `dai release plan`, que además muestra las US
116
+ cuyos criterios cambiaron después de implementarlas y lo que se coló sin declarar US.
117
+ - **¿Esto ya está en producción?** → el comentario en la propia User Story, con versión,
118
+ aplicación, ambiente y fecha.
119
+ - **¿Dónde estamos en el ciclo?** → `dai release status`, que también avisa si quedó un
120
+ *back-merge* pendiente.
121
+
122
+ Y dos límites deliberados: **dai no despliega** (llega hasta el tag y vuelve a aparecer
123
+ después, estampando) y **no mergea ni publica** — esas son firmas humanas.
124
+
125
+ ## Cómo lo adopta un equipo sin que se abandone en dos sprints
126
+
127
+ 1. **Declara tus dos ramas de vida larga** en el `.env.dai` y deja de discutirlo:
128
+ `DAI_BRANCH_DEV` (la que integra) y `DAI_BRANCH_PROD` (la que va a producción). Con eso,
129
+ `dai pr` deduce la base del tipo de rama y avisa cuando apuntas a producción.
130
+ 2. **Etiqueta la próxima versión aunque el proceso todavía sea manual.** El tag es lo que te
131
+ da el punto de retorno; todo lo demás se puede agregar después.
132
+ 3. **Corre `dai release plan` antes de cada corte, y léelo en voz alta en la reunión.** Es
133
+ donde aparecen las sorpresas mientras todavía se pueden arreglar.
134
+ 4. **Empieza a estampar solo en producción.** Si estampar en todos los ambientes hace
135
+ demasiado ruido, con producción alcanza para contestar la pregunta que más se hace.
136
+ 5. **Deja el aviso al canal para el final.** Es lo que hace visible el cambio para el resto
137
+ de la organización, y conviene encenderlo cuando el ciclo ya funciona.
138
+
139
+ ## Preguntas frecuentes
140
+
141
+ **No usamos npm y no tenemos `package.json`. ¿Sirve igual?**
142
+ Sí. El tag es la versión; los archivos son espejos opcionales. dai actualiza los que
143
+ reconoce, dice cuáles tocó, y no se detiene si no hay ninguno.
144
+
145
+ **Nuestra rama principal despliega a producción.**
146
+ Decláralo en `DAI_BRANCH_PROD`. dai marcará esa base en el previo de la PR y pedirá una
147
+ confirmación explícita antes de proponer un merge hacia ahí.
148
+
149
+ **¿Y si no queremos llenar los tickets de comentarios?**
150
+ No estampes. La versión ya está hecha cuando llegas a ese paso: `dai release stamp` es
151
+ opcional y decir que no no rompe nada. Muchos equipos prefieren avisar solo al canal.
152
+
153
+ **¿Cada cuánto conviene sacar una versión?**
154
+ Tan seguido como el equipo tolere sin dolor. Si la respuesta a "¿por qué no más seguido?" es
155
+ *"no hay tanto que entregar"*, está bien. Si es *"porque cada release cuesta"*, eso es lo que
156
+ hay que arreglar — y espaciar los releases lo empeora, porque agranda el lote.
@@ -0,0 +1,266 @@
1
+ # Ciclo de release, paso a paso
2
+
3
+ De "hay cosas para sacar" a "producción sabe qué versión tiene y cada User Story lo dice".
4
+ Unos 15 minutos la primera vez.
5
+
6
+ El *porqué* de todo esto está en la [guía de releases](../guias/releases). Acá van los
7
+ comandos.
8
+
9
+ > **Lo hace la persona, no el agente.** dai prepara, muestra y confirma; mergear, publicar y
10
+ > desplegar los firmas tú. Si prefieres que un asistente te acompañe paso a paso, invoca la
11
+ > skill `/dai-release` — usa exactamente estos comandos y frena en las mismas firmas.
12
+
13
+ ## Antes de empezar
14
+
15
+ Declara las dos ramas de vida larga de tu repositorio en el `.env.dai`. Es lo único que
16
+ tienes que configurar, y se hace una sola vez:
17
+
18
+ ```bash
19
+ # .env.dai (no se versiona)
20
+ DAI_BRANCH_DEV=develop # la rama que integra el desarrollo
21
+ DAI_BRANCH_PROD=main # la rama que despliega a producción
22
+ ```
23
+
24
+ Comprueba que dai las ve:
25
+
26
+ ```bash
27
+ dai release status
28
+ ```
29
+
30
+ ```
31
+ › versión declarada: 0.4.2 (VERSION)
32
+ › último tag: v0.4.2
33
+ ⚠ 'develop' tiene 6 commit(s) sin promover · 3 US · bump propuesto: minor.
34
+ Ver el detalle: dai release plan
35
+ ```
36
+
37
+ Si dice que falta un *back-merge* de la versión anterior, resuélvelo antes de seguir: cortar
38
+ una versión sobre otra a medio cerrar arrastra el problema.
39
+
40
+ ## Paso 1 · Qué entra — `dai release plan`
41
+
42
+ ```bash
43
+ dai release plan
44
+ ```
45
+
46
+ ```
47
+ ── Release a preparar ────────────────────────────────
48
+ desde: v0.4.2
49
+ hasta: develop
50
+ cambios: 6 commit(s) · 5 merge(s)
51
+ versión: 0.4.2 → 0.5.0 (minor)
52
+ ─────────────────────────────────────────────────────
53
+ User Stories que entran (3):
54
+ ✅ ACME-482 v2 Checkout sin duplicado
55
+ ⚠️ ACME-491 v1 Alta de póliza sin duplicar cliente
56
+ ATRASADA
57
+ ✅ ACME-503 v3 Recordar medio de pago
58
+
59
+ ⚠ 1 US ATRASADA(S): el QUÉ cambió después de implementarlo.
60
+ Esta release las llevaría sin cubrir el criterio nuevo. Revisalas antes de cortar.
61
+
62
+ Sin US, por tipo de branch (1): chore/deps
63
+
64
+ ⚠ 1 branch(es) sin US y sin prefijo exento:
65
+ arreglo-rapido
66
+ ```
67
+
68
+ **Esta es la pantalla importante del ciclo.** Léela entera antes de seguir:
69
+
70
+ - **US atrasadas** — alguien cambió los criterios de aceptación después de que se
71
+ implementaran. Puedes cortar igual (a veces el criterio nuevo va en la próxima versión),
72
+ pero que sea una decisión y no un descuido.
73
+ - **Ramas sin US y sin prefijo exento** — entró trabajo que nadie va a poder rastrear a una
74
+ historia. Es la última oportunidad de verlo.
75
+
76
+ Con `--json` sale el mismo manifiesto estructurado, para scripts o para un asistente.
77
+
78
+ ## Paso 2 · La versión — la firmas tú
79
+
80
+ dai **propone** un piso mirando los tipos de commit y lo dice:
81
+
82
+ ```
83
+ minor: 3 commit(s) feat: agregan funcionalidad
84
+ propuesta a partir de los TIPOS de commit — la regla del repo mira el COMPORTAMIENTO.
85
+ ```
86
+
87
+ La regla que manda mira el **comportamiento observable**: si algo mueve un valor por
88
+ omisión, agrega una opción o cambia lo que ve quien no configura nada, es *minor* aunque
89
+ todos los commits digan `fix:`. Esa decisión es tuya.
90
+
91
+ ## Paso 3 · Cortar — `dai release cut`
92
+
93
+ ```bash
94
+ dai release cut 0.5.0
95
+ ```
96
+
97
+ Crea la rama `release/0.5.0`, sube el número en los archivos que tu repositorio espeja,
98
+ escribe la entrada del CHANGELOG y hace el commit. **No habla hacia afuera**: no hay *push*,
99
+ ni tag, ni PR.
100
+
101
+ ```
102
+ ✓ branch release/0.5.0
103
+ ✓ VERSION: 0.4.2 → 0.5.0
104
+ ✓ package.json: 0.4.2 → 0.5.0
105
+ ✓ CHANGELOG.md: entrada para 0.5.0
106
+ ✓ commit chore(release): v0.5.0
107
+ ```
108
+
109
+ > ¿Tu repositorio no tiene `VERSION` ni `package.json`? No pasa nada: el tag es la versión y
110
+ > dai te lo dice. ¿Trabajas sin rama de release, etiquetando directamente desde integración?
111
+ > Usa `--no-branch`.
112
+
113
+ ## Paso 4 · El CHANGELOG — lo escribes tú
114
+
115
+ dai deja el material y las secciones vacías:
116
+
117
+ ```markdown
118
+ ## [0.5.0] — 2026-09-09
119
+
120
+ <!-- dai:manifiesto · el material de esta versión. Repartilo abajo y contá el porqué:
121
+ dai sabe qué entró; por qué importa lo sabés vos.
122
+ ACME-482 Checkout sin duplicado
123
+ ACME-491 Alta de póliza sin duplicar cliente
124
+ -->
125
+
126
+ ### Agregado
127
+ ### Cambiado
128
+ ### Corregido
129
+ ### Interno
130
+ ```
131
+
132
+ Reparte las historias en las secciones que correspondan, **explica por qué importaba cada
133
+ una** y borra el comentario. Un changelog que solo lista lo que entró no lo lee nadie; uno
134
+ que cuenta qué estaba mal se lee seis meses después.
135
+
136
+ Luego, el commit y la PR:
137
+
138
+ ```bash
139
+ git add CHANGELOG.md && git commit -m "docs(changelog): reparte el manifiesto de la 0.5.0"
140
+ dai pr --description-file notas.md
141
+ ```
142
+
143
+ La base sale sola: una rama `release/` va contra tu rama de producción, y dai te lo marca y
144
+ te pide que escribas el nombre de la rama para confirmar.
145
+
146
+ ## Paso 5 · Merge y publicación — tu firma
147
+
148
+ Apruebas y mergeas la PR, y ejecutas lo que tu repositorio use para publicar (`npm publish`,
149
+ un despliegue, lo que sea). **El ciclo no terminó acá**: faltan el tag, la nota de release y
150
+ el *back-merge* — los tres pasos que más se olvidan cuando esto se hace de memoria.
151
+
152
+ ## Paso 6 · Cerrar — `dai release done`
153
+
154
+ ```bash
155
+ dai release done 0.5.0
156
+ ```
157
+
158
+ ```
159
+ ── Cerrar la versión 0.5.0 ──────────────────────────
160
+ tag: v0.5.0 → main @ 177719f3
161
+ release: nota en el forge
162
+ back-merge: main → develop
163
+ aviso: webex · webexapis.com
164
+ ─────────────────────────────────────────────────────
165
+ ✓ tag v0.5.0 creado y publicado
166
+ ✓ release note publicada
167
+ ✓ back-merge main → develop
168
+ ```
169
+
170
+ Y borra la rama `release/0.5.0` (local y remota): ya está mergeada, etiquetada y con el
171
+ back-merge hecho, así que no tiene más razón de existir — una rama de release que sobrevive
172
+ a su release es un fork. Si quieres conservarla, `--keep-branch`. Si git se niega a
173
+ borrarla, es porque tiene commits que no llegaron a producción: revísala.
174
+
175
+ Cada paso se reporta por separado a propósito: **una vez creado el tag, la versión existe**.
176
+ Si falla la nota de release, dai te lo dice y aclara que el tag ya está publicado, para que
177
+ completes solo lo que falta.
178
+
179
+ ## Paso 7 · Estampar el despliegue — opcional
180
+
181
+ Cuando la versión llega a un ambiente:
182
+
183
+ ```bash
184
+ dai release stamp 0.5.0 --env prod --app acme-backend
185
+ ```
186
+
187
+ ```
188
+ ── Estampar despliegue ───────────────────────────────
189
+ versión: v0.5.0 app: acme-backend ambiente: PROD
190
+ tracker: jira · 3 User Storie(s) en el release
191
+ ─────────────────────────────────────────────────────
192
+ ACME-482 Checkout sin duplicado
193
+ ACME-491 Alta de póliza sin duplicar cliente
194
+ ACME-503 Recordar medio de pago
195
+ ─────────────────────────────────────────────────────
196
+ ⚠ esto escribe 3 comentario(s) en el tracker de todo el equipo. No se deshace.
197
+ ¿Estampo 3 comentario(s)? (s/N)
198
+ ```
199
+
200
+ Cada User Story recibe un comentario con versión, aplicación, ambiente y fecha. Desde ese
201
+ momento, el funcional abre el ticket y sabe dónde está su historia sin preguntar. Si una US
202
+ se implementa en varios repositorios, el ticket va acumulando la matriz: *backend en
203
+ producción, frontend en pre*.
204
+
205
+ **Es opcional.** Decir que no sale con código 0 y no rompe nada: la versión ya está hecha.
206
+ Si tu equipo prefiere no llenar los tickets, avisa solo al canal.
207
+
208
+ Volver a ejecutarlo **no duplica**: dai reconoce sus propios comentarios por
209
+ `(aplicación, versión, ambiente)` y saltea los que ya están. La misma versión en otro
210
+ ambiente sí es un evento nuevo y se estampa.
211
+
212
+ ## Paso 8 · El aviso al equipo — opcional
213
+
214
+ Si declaras un canal, `done` y `stamp` avisan solos:
215
+
216
+ ```bash
217
+ # .env.dai
218
+ DAI_NOTIFY=webex # discord | slack | webex | telegram | webhook | none
219
+ DAI_NOTIFY_WEBHOOK=https://… # SECRETO: quien lo tiene, puede publicar
220
+ ```
221
+
222
+ Antes de depender de él, pruébalo:
223
+
224
+ ```bash
225
+ dai release notify --test
226
+ ```
227
+
228
+ El mensaje que sale es siempre el mismo, en cualquier canal:
229
+
230
+ ```
231
+ 🚀 Release desplegada · acme-backend v0.5.0 → PROD
232
+ Autor: Ada Lovelace · Fecha: 09/09/2026 09:15
233
+
234
+ Cambios principales:
235
+ • ACME-482 Checkout sin duplicado
236
+ • ACME-491 Alta de póliza sin duplicar cliente
237
+ • ACME-503 Recordar medio de pago
238
+
239
+ Ver release: https://…/releases/v0.5.0
240
+ ```
241
+
242
+ Las viñetas son las **User Stories**, no los commits: lo que el equipo quiere leer es qué
243
+ valor salió, no qué archivos se tocaron.
244
+
245
+ ## El ciclo entero, resumido
246
+
247
+ ```bash
248
+ dai release status # ¿dónde estoy?
249
+ dai release plan # ¿qué entra? ← la pantalla importante
250
+ dai release cut 0.5.0 # rama + número + CHANGELOG + commit
251
+ # … escribes el CHANGELOG …
252
+ dai pr # PR a producción (te pide confirmación)
253
+ # … mergeas y publicas: tu firma …
254
+ dai release done 0.5.0 # tag + nota + back-merge + aviso
255
+ dai release stamp 0.5.0 --env prod # opcional: avisar a cada US
256
+ ```
257
+
258
+ ## Si algo sale mal
259
+
260
+ | Síntoma | Qué hacer |
261
+ |---|---|
262
+ | `no existe el tag vX.Y.Z` al estampar | Cierra la versión primero (`dai release done`), o trae los tags con `git fetch --tags`. |
263
+ | `done` creó el tag pero falló la nota | El tag ya está: la versión existe. Publica la nota a mano con el comando que dai te deja impreso. |
264
+ | El manifiesto no muestra ninguna US | ¿Las ramas tenían `implements.yaml`? Sin link no hay trazabilidad que reportar. |
265
+ | El tracker no responde | `dai release plan --no-network` sale igual, avisando que no pudo verificar. |
266
+ | Salieron comentarios repetidos | dai no pudo leer los comentarios previos y lo avisó. Revisa el token del tracker. |
@@ -11,6 +11,12 @@ Guías de **setup operativo** — lo que haces una vez por máquina para trabaja
11
11
  + `glab`, las skills en Copilot, OpenSpec y el ciclo completo sobre una US real
12
12
  (`link-us` → `check` → `mr` → `stamp`).
13
13
 
14
+ ## El día a día
15
+
16
+ - [**Ciclo de release**](./ciclo-de-release) — de "hay cosas para sacar" a "producción sabe
17
+ qué versión tiene y cada User Story lo dice": manifiesto, corte, tag, nota de release y el
18
+ aviso a cada historia. El *porqué* está en la [guía de releases](../guias/releases).
19
+
14
20
  ## Preparar el entorno
15
21
 
16
22
  - [**Configurar git**](./configurar-git) — tu identidad (nombre + correo) para que los
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dforce2055/dai",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Metodología de desarrollo asistido por IA — CLI de acciones deterministas (trazabilidad QUÉ↔CÓMO).",
5
5
  "repository": { "type": "git", "url": "git+https://github.com/dforce2055/dai.git" },
6
6
  "homepage": "https://dforce2055.github.io/dai/",
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: dai-release
3
+ description: "Conduce el ciclo de versión de un repo con dai, paso a paso y confirmando cada uno: el manifiesto de qué entra (qué User Stories, cuáles atrasadas, qué se coló sin US), la versión que corresponde, el corte de la release, la redacción del CHANGELOG, el cierre con tag + release note + back-merge, y —opcional— el aviso a cada US de en qué versión y ambiente salió más la notificación al canal del equipo. Se apoya en `dai release plan/cut/done/stamp/status`: NO recalcula nada por su cuenta, narra lo que el CLI dice. Frena en las dos firmas humanas (aprobar la versión; mergear y publicar) y nunca las salta. Invocar como /dai-release, opcionalmente con la versión. Usar cuando alguien dice 'cortemos una versión', 'hay que sacar release', 'promover a producción' o 'qué entra en la próxima'."
4
+ ---
5
+
6
+ # dai-release — conducir el ciclo de versión
7
+
8
+ Un release tiene doce pasos, dos de ellos son firmas humanas, y los dos que más se olvidan
9
+ están **después** de la firma — el release note y el back-merge. Nadie los recuerda todos, y
10
+ por eso se hacen mal. Esta skill los conduce.
11
+
12
+ ## El reparto: el CLI sabe, tú contás
13
+
14
+ No calculás el manifiesto ni derivás la versión. Los comandos ya lo hacen, igual con
15
+ Claude, con Copilot o sin ningún asistente ([ADR-0002](../../docs/adr/0002-agnostico-del-asistente.md)):
16
+
17
+ ```
18
+ dai release plan --json → vos → la persona decide
19
+ qué entró, en qué estado lo contás firma o corrige
20
+ ```
21
+
22
+ **Nunca inventes el contenido del manifiesto.** Si `dai release plan` no lista una US, esa
23
+ US no entró — aunque la recuerdes del chat. Si el CLI y tu memoria no coinciden, gana el CLI
24
+ y lo decís en voz alta.
25
+
26
+ Lo que sí es tuyo, porque ningún comando puede hacerlo:
27
+
28
+ 1. **Proponer el bump mirando el comportamiento.** El CLI lo deriva de los tipos de commit
29
+ y lo dice: es un piso, no un veredicto. Vos leés el diff. Si algo mueve un default,
30
+ agrega un flag o cambia lo que ve quien no configura nada, **es minor aunque todo sea
31
+ `fix:`** — le pasó a este mismo repo en la 0.14.0, cuatro commits `fix:` que eran minor.
32
+ 2. **Escribir el CHANGELOG.** El CLI deja el material (las US) y las secciones vacías. La
33
+ prosa la escribís vos: dai sabe *qué* entró, no *por qué importa*.
34
+ 3. **Ver lo que falta.** Una US atrasada en el manifiesto, una branch que entró sin link,
35
+ el back-merge de la release anterior que nunca se hizo.
36
+ 4. **Frenar en las firmas.** Y saber que después de la firma quedan pasos pendientes.
37
+
38
+ ## Antes de empezar
39
+
40
+ Corré `dai release status`. Te dice dónde está el repo en el ciclo y evita el error más
41
+ común: cortar una versión cuando la anterior quedó a medio cerrar.
42
+
43
+ ## El ciclo
44
+
45
+ ```
46
+ plan ──▶ [FIRMA 1: la versión] ──▶ cut ──▶ CHANGELOG ──▶ dai pr
47
+
48
+ [FIRMA 2: merge + publicar] ◀──┘
49
+
50
+
51
+ done ──▶ stamp (opcional) ──▶ aviso (opcional)
52
+ ```
53
+
54
+ ### 1 · El manifiesto — `dai release plan`
55
+
56
+ Corré `dai release plan` y **contá lo que dice**, no lo que esperabas que dijera:
57
+
58
+ - cuántas US entran y cuáles;
59
+ - **cuáles están ATRASADAS** — el QUÉ cambió después de implementarlas, así que esta
60
+ versión las llevaría sin cubrir el criterio nuevo. Nombralas una por una;
61
+ - **qué branches entraron sin US y sin prefijo exento** — es la última pantalla donde eso
62
+ se puede ver antes de que quede adentro de una versión;
63
+ - el bump propuesto y su justificación.
64
+
65
+ Si hay US atrasadas o branches huérfanas, **preguntá antes de seguir**: *"¿cortamos igual,
66
+ o querés resolver esto primero?"* No decidas vos. Cortar con una US atrasada es legítimo
67
+ —a veces el criterio nuevo va en la próxima— pero tiene que ser una decisión, no un
68
+ descuido.
69
+
70
+ ### 2 · La versión — FIRMA HUMANA
71
+
72
+ Proponé la versión **con tu propio análisis del comportamiento**, no repitiendo el bump del
73
+ CLI. Decí explícitamente si coincidís con él o no, y por qué:
74
+
75
+ > El CLI propone `patch` (solo hay commits `fix:`). Yo propongo **minor**: el default de
76
+ > `dai pr` cambió, y quien actualice sin leer el changelog lo va a notar. ¿Vamos con 0.15.0?
77
+
78
+ **Esperá el sí.** Sin confirmación explícita en este turno, no sigas. Un "dale" de un
79
+ release anterior no cuenta.
80
+
81
+ ### 3 · Cortar — `dai release cut <X.Y.Z>`
82
+
83
+ Mostrá el preview del comando y confirmá antes de correrlo con `--yes` (o dejá que pregunte
84
+ él). Crea la branch de release, sube el número en los archivos que el repo espeja, escribe
85
+ la entrada del CHANGELOG y commitea. **No habla hacia afuera:** ni push, ni tag, ni PR.
86
+
87
+ Si el repo trabaja sin branch de release (todo sale de la rama de integración), es
88
+ `--no-branch`. Preguntá cuál es el flujo si no está claro; no lo asumas.
89
+
90
+ ### 4 · El CHANGELOG — tu parte
91
+
92
+ `cut` deja la entrada con el material en un comentario y las secciones vacías. **Escribila.**
93
+ Mirá cómo están escritas las entradas anteriores del repo y seguí esa voz. Si el repo no
94
+ tiene ninguna, el estándar es:
95
+
96
+ - abrí con **qué estaba mal o qué cambia**, en una o dos frases, para alguien que no siguió
97
+ el desarrollo;
98
+ - cada ítem explica **por qué importaba**, no qué archivos se tocaron;
99
+ - repartí las US del comentario en las secciones que correspondan y **borrá el comentario**.
100
+
101
+ Un changelog que solo lista commits no lo lee nadie. Si no sabés por qué un cambio importa,
102
+ **preguntá** — es exactamente la información que solo tiene una persona.
103
+
104
+ Después, commiteá el CHANGELOG y abrí la PR con `dai pr`. La base sale sola del mapa de
105
+ ramas: una branch `release/` va contra la rama de producción y pide confirmación explícita.
106
+
107
+ ### 5 · Merge y publicación — FIRMA HUMANA
108
+
109
+ **Acá parás.** Mergear la PR y publicar (npm, un deploy, lo que este repo use) lo hace una
110
+ persona. Si el repo tiene un `RELEASING.md`, leelo y decí los pasos exactos que le tocan.
111
+
112
+ Decí claramente que **el ciclo no terminó**: falta el tag, el release note y el back-merge.
113
+ Es justo acá donde se abandonan los releases hechos a mano.
114
+
115
+ ### 6 · Cerrar — `dai release done <X.Y.Z>`
116
+
117
+ Después del merge. Tag anotado, release note en el forge, back-merge a integración y aviso
118
+ al canal. Cada paso reporta por separado: **si falla la release note, el tag ya existe** —
119
+ decilo, no lo tapes.
120
+
121
+ También **borra la rama de release** que cerró: ya está mergeada, etiquetada y con el
122
+ back-merge hecho. Si git se niega, es porque tiene commits que no llegaron a producción —
123
+ decilo, no lo tapes con `--keep-branch`.
124
+
125
+ ### 7 · Estampar — `dai release stamp <X.Y.Z> --env <ambiente>` · OPCIONAL
126
+
127
+ Cuando la versión llega a un ambiente. Le deja a **cada US del release** un comentario
128
+ diciendo en qué versión y ambiente salió, y con eso el funcional lee el ticket en vez de
129
+ preguntar.
130
+
131
+ **Antes de correrlo, avisá el alcance en voz alta**: *"esto va a escribir N comentarios en
132
+ N tickets, que puede tocar a varias personas del equipo, y no se deshace"*. El comando
133
+ muestra el detalle y confirma; tu trabajo es que nadie llegue a esa pantalla sin saber qué
134
+ va a pasar.
135
+
136
+ **Si dicen que no, seguí adelante.** No es un error ni hay que insistir: la versión ya está
137
+ hecha. Decí una vez qué se pierde (el ticket no va a registrar en qué versión salió) y
138
+ ofrecé la alternativa: *"¿preferís que solo avise al canal?"*. Muchos equipos no quieren
139
+ hacer ruido en veinte tickets, y es una decisión legítima.
140
+
141
+ ### 8 · El aviso al canal · OPCIONAL
142
+
143
+ Sale solo con `done` y con `stamp` si el repo declaró `DAI_NOTIFY`. Mostrá el mensaje
144
+ exacto antes de mandarlo. Si el repo no lo declaró y el equipo quiere avisar, `dai release
145
+ notify --test` prueba el canal antes de depender de él.
146
+
147
+ ## Reglas que no se negocian
148
+
149
+ - **No mergeás, no publicás, no desplegás.** Esas son firmas humanas
150
+ ([Art. 5](../../docs/MANIFIESTO.md#art-5) del manifiesto).
151
+ - **No inventás el manifiesto ni la versión.** El manifiesto sale del CLI; la versión la
152
+ firma una persona.
153
+ - **No escribís un CHANGELOG que no entendés.** Preguntá.
154
+ - **No estampás sin avisar el alcance**, y un "no" se acepta sin insistir.
155
+ - **No cierres el ciclo sin el release note y el back-merge.** Son los dos que se olvidan.
156
+ - **Nada de datos de terceros** en el CHANGELOG, el release note ni el aviso: ni nombres de
157
+ empresas, ni de personas ajenas al repo, ni URLs corporativas. Si el material que tenés a
158
+ mano los trae, traducilos.
159
+
160
+ ## Cuando algo no cierra
161
+
162
+ - **El tracker no responde** → el manifiesto sale igual con `--no-network`, diciendo que no
163
+ pudo verificar. Es preferible a no tener manifiesto; decilo al contarlo.
164
+ - **`done` falla a mitad de camino** → mirá qué reportó cada paso. Si el tag salió, la
165
+ versión existe: lo que falta es la nota o el back-merge, y se completan a mano.
166
+ - **El repo no tiene VERSION ni package.json** → normal. El tag es la versión; `cut` lo dice.
167
+ - **No hay tags todavía** → el manifiesto arranca desde el principio del repo. Es correcto.