@dforce2055/dai 0.11.0 → 0.13.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,480 @@
1
+ # Setup para analistas funcionales y PMs (Windows)
2
+
3
+ Guía paso a paso para dejar tu entorno listo y empezar a producir **épicas y User Stories**
4
+ con las skills de `dai` desde **GitHub Copilot**, publicándolas directo en **Jira**.
5
+
6
+ **No necesitas saber programar, ni usar git, ni clonar ningún repositorio.** Vas a usar la
7
+ terminal unas pocas veces, todas en esta guía, y después nunca más.
8
+
9
+ > **¿Qué son las skills?** Son los comandos que te **interrogan** hasta que la historia queda
10
+ > bien: `/doc-to-backlog` (un documento → un backlog candidato), `/grill-epic` (una épica),
11
+ > `/grill-user-story` (una US testeable). **No inventan requerimientos: te los sacan a
12
+ > preguntas.** Tú respondes y tú decides.
13
+ >
14
+ > Se escriben **en el chat de Copilot**, no en PowerShell: las ejecuta un agente, no la
15
+ > terminal. Más abajo está la tabla de qué va dónde.
16
+
17
+ **Atajo:** si ya tienes Node y `dai` instalados, salta al **Paso 3** — es el que te habilita
18
+ todo.
19
+
20
+ Los ejemplos usan `acme.atlassian.net` y el proyecto `PROJ`: reemplázalos por los de tu
21
+ empresa.
22
+
23
+ ---
24
+
25
+ ## Paso 1 — Instala Node
26
+
27
+ Descarga el instalador **LTS** desde 👉 **https://nodejs.org** y ejecútalo.
28
+ Siguiente → Siguiente → Instalar.
29
+
30
+ Para comprobar que quedó, abre **PowerShell** (tecla Windows → escribe `powershell` → Enter):
31
+
32
+ ```powershell
33
+ node --version
34
+ ```
35
+
36
+ Tiene que responder algo como `v20.11.0`. Cualquier número **18 o mayor** sirve.
37
+
38
+ > **Si dice que no reconoce el comando:** cierra PowerShell, ábrelo de nuevo y reintenta. El
39
+ > instalador no refresca las ventanas que ya estaban abiertas.
40
+
41
+ ---
42
+
43
+ ## Paso 2 — Instala dai
44
+
45
+ En la misma ventana:
46
+
47
+ ```powershell
48
+ npm i -g @dforce2055/dai
49
+ ```
50
+
51
+ Comprueba que quedó:
52
+
53
+ ```powershell
54
+ dai --version
55
+ ```
56
+
57
+ Si quieres ver todo lo que hace, `dai --help` te lista los comandos.
58
+
59
+ ---
60
+
61
+ ## Paso 3 — Instala las skills en Copilot (el comando clave)
62
+
63
+ **Este es el comando que te habilita todo:**
64
+
65
+ ```powershell
66
+ dai skills install --for copilot --global
67
+ ```
68
+
69
+ Te va a listar las skills instaladas. Comprueba que llegaron:
70
+
71
+ ```powershell
72
+ dir $env:USERPROFILE\.copilot\skills
73
+ ```
74
+
75
+ Tienes que ver 7 carpetas: `dai-review`, `doc-to-backlog`, `grill-epic`, `grill-intent`,
76
+ `grill-user-story`, `link-us`, `tdd`.
77
+
78
+ ![Las 7 skills instaladas en la carpeta del usuario](/tutoriales/funcional-1-skills-usuario.png)
79
+
80
+ > **¿Por qué `--global`?** Porque las deja en **tu usuario**, no en un proyecto. Eso significa
81
+ > que los comandos te van a aparecer **en cualquier carpeta**, sin preparar nada. Es lo que
82
+ > hace que no necesites un repositorio para trabajar
83
+ > ([ADR-0014](../adr/0014-copilot-agent-skills.md)).
84
+
85
+ ---
86
+
87
+ ## Paso 4 — Comprueba que Copilot las ve
88
+
89
+ Si todavía no iniciaste sesión en Copilot, hazlo ahora: VS Code te lo pide solo, con la cuenta
90
+ de GitHub que tiene tu licencia. Si tu empresa usa inicio de sesión único (SSO), sigue el flujo
91
+ que te muestre.
92
+
93
+ ![Iniciar sesión en GitHub Copilot](/tutoriales/funcional-2-copilot-signin.png)
94
+
95
+ Reinicia Copilot (cierra y abre la sesión) y escribe `/` en el chat, en modo **Agent**. Tienen
96
+ que aparecer las 7, marcadas **`User Data`** — esa etiqueta confirma que salen de tu usuario y
97
+ no de un proyecto.
98
+
99
+ > **Si no aparecen:** ejecuta `/skills` dentro de Copilot para refrescar el listado. Si sigue
100
+ > sin verlas, recarga la ventana: `Ctrl+Shift+P` → **Developer: Reload Window**.
101
+
102
+ ---
103
+
104
+ ## Paso 5 — Crea tu carpeta de trabajo
105
+
106
+ Las skills ya te funcionan en cualquier lado. **Pero para publicar en Jira hace falta una
107
+ carpeta con la configuración**: aquí van tus documentos y aquí vive el token.
108
+
109
+ ```powershell
110
+ mkdir $HOME\backlog
111
+ cd $HOME\backlog
112
+ dai init --for copilot --pm jira
113
+ ```
114
+
115
+ Te va a preguntar si quieres instalar **OpenSpec**: responde **`n`**. OpenSpec es el motor del
116
+ *cómo* (lo técnico) y un funcional no lo usa nunca.
117
+
118
+ ![La carpeta configurada: .dai/, .github/skills y .env.dai](/tutoriales/funcional-3-carpeta-configurada.png)
119
+
120
+ > **Importante:** de aquí en adelante trabaja siempre **parado en esta carpeta**
121
+ > (`cd $HOME\backlog`). Es donde dai busca tu configuración de Jira.
122
+
123
+ ---
124
+
125
+ ## Paso 6 — Conecta Jira
126
+
127
+ `dai init` te dejó un archivo `.env.dai` ([ADR-0017](../adr/0017-env-dai.md)). Hay que
128
+ completarlo.
129
+
130
+ Primero necesitas un **token de API de Atlassian**. Si no tienes, sigue el tutorial
131
+ 👉 **[Cómo obtener el token de API de Jira](./token-jira.md)** y vuelve con el token copiado.
132
+
133
+ Abre la carpeta en el editor:
134
+
135
+ ```powershell
136
+ code .
137
+ ```
138
+
139
+ Abre el `.env.dai` y complétalo:
140
+
141
+ ```bash
142
+ DAI_PM=jira
143
+ DAI_JIRA_BASE_URL=https://acme.atlassian.net
144
+ DAI_JIRA_EMAIL=tu.correo@acme.com
145
+ DAI_JIRA_TOKEN=el-token-que-copiaste
146
+ DAI_JIRA_PROJECT=PROJ
147
+ DAI_JIRA_ISSUETYPE=Story
148
+ DAI_JIRA_FIELDS_FILE=.dai/jira-fields.json
149
+ DAI_TRACKER_URL_TEMPLATE=https://acme.atlassian.net/browse/{id}
150
+ ```
151
+
152
+ Guarda con `Ctrl+S`.
153
+
154
+ ### Los dos que más se equivocan
155
+
156
+ | Variable | Qué va | El error típico |
157
+ |---|---|---|
158
+ | `DAI_JIRA_PROJECT` | La clave del **proyecto**: las letras antes del guion. Si tus tickets son `PROJ-123`, va **`PROJ`**. | Pegar la clave de un **ticket** (`PROJ-123`). Eso es un ticket, no un proyecto. |
159
+ | `DAI_TRACKER_URL_TEMPLATE` | Viene vacío, complétalo. Deja el `{id}` tal cual: es un marcador que dai reemplaza solo. | Reemplazar el `{id}` por un número. |
160
+
161
+ > **Si te equivocas en `DAI_JIRA_PROJECT`, dai te lo dice** y te da los dos caminos:
162
+ > ```
163
+ > dai: DAI_JIRA_PROJECT='PROJ-123' es la clave de un ticket, no la del proyecto.
164
+ > Usá solo la parte de adelante: DAI_JIRA_PROJECT=PROJ
165
+ > Si lo que querías era colgar la US de esa épica: dai publish <us.md> --parent PROJ-123
166
+ > ```
167
+
168
+ ---
169
+
170
+ ## Paso 7 — Verifica todo
171
+
172
+ ```powershell
173
+ dai doctor
174
+ ```
175
+
176
+ Lo que tienes que ver:
177
+
178
+ ```
179
+ ✓ DAI_PM=jira
180
+ ✓ token de Jira presente (no verificado: eso lo dice `dai publish`)
181
+ ✓ proyecto=PROJ (para dai publish)
182
+ ```
183
+
184
+ ![dai doctor con la configuración de Jira completa](/tutoriales/funcional-4-doctor.png)
185
+
186
+ > **Ojo:** `dai doctor` solo comprueba que el token **esté escrito**, no que funcione. Si está
187
+ > vencido o mal pegado, doctor te dice que está todo bien y el error recién aparece al
188
+ > publicar. La prueba de verdad es publicar una US — es el paso siguiente.
189
+
190
+ ---
191
+
192
+ ## Paso 8 — La prueba de fuego: publica una épica y una US
193
+
194
+ Vas a crear **dos issues de prueba** en Jira —una épica y una US colgada de ella— y después los
195
+ borras. De paso ves el flujo completo, que es exactamente lo que hacen las skills por ti.
196
+
197
+ ### 1. Una carpeta para tus US
198
+
199
+ ```powershell
200
+ cd $HOME\backlog
201
+ mkdir US
202
+ ```
203
+
204
+ ### 2. La épica (opcional)
205
+
206
+ Este paso es opcional: si en tu proyecto **ya existe** la épica, salta al punto 3 y usa su key.
207
+
208
+ ```powershell
209
+ code US\epica-prueba.md
210
+ ```
211
+
212
+ VS Code abre el archivo nuevo. Pega esto y guarda con `Ctrl+S`:
213
+
214
+ ```markdown
215
+ # Compra del carrito
216
+
217
+ ## Objetivo de negocio
218
+
219
+ Que un cliente pueda comprar lo que puso en el carrito sin depender de nadie del equipo.
220
+
221
+ ## Alcance
222
+
223
+ - **Dentro** — finalizar la compra y ver el detalle antes de confirmar.
224
+ - **Fuera** — nuevos medios de pago, facturación.
225
+
226
+ ## User Stories (partición)
227
+
228
+ - [ ] Finalizar la compra del carrito
229
+ ```
230
+
231
+ Publícala **como épica**:
232
+
233
+ ```powershell
234
+ dai publish US\epica-prueba.md --issuetype Epic
235
+ ```
236
+
237
+ Te responde con el key y el link:
238
+
239
+ ```
240
+ ✓ US publicada en jira: PROJ-124 → https://acme.atlassian.net/browse/PROJ-124
241
+ › Próximo paso (el dev abre el CÓMO): dai link-us PROJ-124
242
+ ```
243
+
244
+ La línea *Próximo paso* es para el dev (`dai link-us` es lo que abre el CÓMO): tú no la
245
+ necesitas.
246
+
247
+ **Anota ese key** (`PROJ-124` en el ejemplo): lo necesitas en el paso siguiente.
248
+
249
+ ### 3. La US, colgada de la épica
250
+
251
+ ```powershell
252
+ code US\us-prueba.md
253
+ ```
254
+
255
+ Pega esto y guarda con `Ctrl+S`:
256
+
257
+ ```markdown
258
+ # Finalizar la compra del carrito
259
+
260
+ ## Historia
261
+
262
+ Como **cliente con productos en el carrito**
263
+ quiero **finalizar la compra**
264
+ para **recibir lo que elegí sin tener que llamar a nadie**.
265
+
266
+ ## Criterios de aceptación
267
+
268
+ - [ ] **AC-1** —
269
+ - **Dado** un carrito con al menos un producto
270
+ - **Cuando** finalizo la compra
271
+ - **Entonces** se registra el pedido y recibo la confirmación.
272
+ - [ ] **AC-2** —
273
+ - **Dado** un carrito vacío
274
+ - **Cuando** intento finalizar la compra
275
+ - **Entonces** se rechaza y se me avisa que el carrito está vacío.
276
+ ```
277
+
278
+ Publícala colgada de la épica — cambia `PROJ-124` por **tu** key:
279
+
280
+ ```powershell
281
+ dai publish US\us-prueba.md --parent PROJ-124
282
+ ```
283
+
284
+ ```
285
+ ✓ US publicada en jira: PROJ-125 → https://acme.atlassian.net/browse/PROJ-125
286
+ › colgada de PROJ-124
287
+ › Próximo paso (el dev abre el CÓMO): dai link-us PROJ-125
288
+ ```
289
+
290
+ ![Publicar la US colgada de la épica](/tutoriales/funcional-5-publish-parent.png)
291
+
292
+ > **La épica no tiene que ser de dai.** `--parent` acepta cualquier épica que ya exista en el
293
+ > proyecto: la key se saca de la URL del navegador (`…/browse/PROJ-77` → `PROJ-77`). Dos
294
+ > límites: la épica tiene que estar en el proyecto de `DAI_JIRA_PROJECT` (si no, `--project`),
295
+ > y `dai publish` siempre **crea** — para mover una US que ya existe a una épica, se hace en
296
+ > Jira a mano.
297
+
298
+ > **Si tu Jira exige campos propios**, los dos comandos llevan además `--field alias=valor`
299
+ > (p. ej. `--field tipo=Mejora`). Está explicado abajo, en *Al publicar dice `jira 400` y
300
+ > nombra un `customfield_NNNNN`*.
301
+
302
+ ### 4. Comprueba en Jira
303
+
304
+ Abre el link de la US y mira **tres cosas**:
305
+
306
+ | Qué mirar | De dónde salió |
307
+ |---|---|
308
+ | El **título** del issue | el `# Título` del archivo (el primero que no sea *Metadata*) |
309
+ | La descripción con el bloque **Criterios de aceptación** | el archivo entero viaja como descripción |
310
+ | La US **dentro** de la épica `PROJ-124` | el `--parent` |
311
+
312
+ Si las tres están, tu entorno funciona de punta a punta. **Borra los dos issues de prueba**
313
+ desde Jira y sigue con tu backlog real.
314
+
315
+ > **Lo importante es el heading `## Criterios de aceptación`.** Es el bloque del que dai saca
316
+ > el `ac_hash` ([ADR-0001](../adr/0001-contrato-ac-hash.md)): lo que después le avisa al equipo
317
+ > técnico si cambiaste los criterios. Sin ese heading la US se publica igual, pero queda sin
318
+ > link con el código. Por eso las skills lo escriben siempre tal cual.
319
+
320
+ > **¿Todavía no tienes Jira?** El mismo ejemplo corre con `DAI_PM=md` en el `.env.dai`: en vez
321
+ > de crear el issue, `dai publish` te guarda la US en `.dai\us\` y devuelve un slug
322
+ > (`✓ US publicada en md: finalizar-la-compra-del-carrito`). Sirve para probar el formato sin
323
+ > token, pero `--parent` no hace nada: sin tracker no hay épica de la que colgar.
324
+
325
+ ---
326
+
327
+ ## Ya puedes trabajar
328
+
329
+ ```
330
+ tu documento → /doc-to-backlog → /grill-epic → /grill-user-story → Jira
331
+ (candidatos) (una épica) (cada US)
332
+ ```
333
+
334
+ De aquí en adelante no vas a escribir estos `.md` a mano: las skills te interrogan, arman la
335
+ épica y las US con el formato completo, y las publican con estos mismos comandos.
336
+
337
+ > ⚠️ **IMPORTANTE — las skills no se ejecutan en PowerShell.** Funcionan con un **agente**: son
338
+ > acciones que le pides **en el chat de Copilot** (modo *Agent*), escribiendo `/` adelante. Si
339
+ > pegas `/grill-epic` en PowerShell, te va a decir que no reconoce el comando.
340
+
341
+ | Qué | Dónde se escribe | Ejemplos |
342
+ |---|---|---|
343
+ | Los comandos de **dai** | **PowerShell**, parado en tu carpeta | `dai init` · `dai doctor` · `dai publish` |
344
+ | Las **skills** (empiezan con `/`) | El **chat de Copilot**, en modo *Agent* | `/doc-to-backlog` · `/grill-epic` · `/grill-user-story` |
345
+
346
+ PowerShell lo usaste en los pasos 1 a 8 para **preparar el entorno y publicar**. El trabajo de
347
+ todos los días —sacar el backlog de un documento, armar la épica, pulir cada US— pasa en el
348
+ chat. Y cuando la skill necesita publicar, **ella** ejecuta el `dai publish` por ti.
349
+
350
+ ---
351
+
352
+ ## Cuando algo falla
353
+
354
+ ### Al publicar dice `no pude extraer el título de la US`
355
+
356
+ dai toma el título del **primer `# ` del archivo** y no lo encontró. Dos causas, en orden de
357
+ frecuencia:
358
+
359
+ 1. **El `#` no está solo o no está al principio de la línea.** Tiene que ser `# Título`, con el
360
+ espacio, empezando en el borde izquierdo. `#Título` o ` # Título` no cuentan.
361
+ 2. **El archivo se guardó con BOM** (una marca invisible al inicio que agregan algunas
362
+ herramientas). El título está ahí y aun así dai no lo ve. Se arregla guardando desde
363
+ VS Code, que usa **UTF-8 sin BOM**: `Ctrl+Shift+P` → **Change File Encoding** → *Save with
364
+ Encoding* → **UTF-8**.
365
+
366
+ > Por eso la guía te hace crear los `.md` con `code archivo.md` y no con comandos de PowerShell
367
+ > tipo `Set-Content`: el editor los guarda bien de entrada.
368
+
369
+ ### Al publicar dice `jira 401`
370
+
371
+ El token no es válido o venció. Genera uno nuevo
372
+ ([tutorial](./token-jira.md)) y vuelve a pegarlo en el `.env.dai`. Comprueba también que
373
+ `DAI_JIRA_EMAIL` sea **exactamente** el correo de tu cuenta de Atlassian.
374
+
375
+ ### Al publicar dice `jira 400` y nombra el `project`
376
+
377
+ El mensaje dice que el proyecto no existe o que no tienes permiso para crear issues en él.
378
+ Tres causas, en orden:
379
+
380
+ 1. **`DAI_JIRA_PROJECT` no es la clave de ese proyecto.** Abre el proyecto en Jira: la clave
381
+ está en la URL (`…/browse/PROJ-1` → `PROJ`). `dai doctor` te dice cuál está usando.
382
+ 2. **La cuenta del token no puede crear issues ahí.** Entra a Jira con esa misma cuenta e
383
+ intenta crear un issue a mano en ese proyecto: si el proyecto no aparece en el selector, es
384
+ permisos y los da el administrador del proyecto.
385
+ 3. **`DAI_JIRA_BASE_URL` apunta a otro site** del que salió el token. Si el token es de otra
386
+ instancia, el proyecto "no existe" desde ahí.
387
+
388
+ > **El mensaje puede llegarte en otro idioma.** Jira responde los errores de la API en el
389
+ > idioma del perfil de Atlassian de la cuenta autenticada. Se cambia en Atlassian →
390
+ > *Configuración de la cuenta* → *Idioma*.
391
+
392
+ ### Al publicar dice `jira 400` y nombra un `customfield_NNNNN`
393
+
394
+ Tu proyecto **exige un campo propio** al crear un issue (muy común en Jira corporativo). No es
395
+ un error tuyo: hay que declararle ese campo a dai
396
+ ([ADR-0015](../adr/0015-jira-corporativo.md)).
397
+
398
+ Crea el archivo `.dai\jira-fields.json` en tu carpeta — el molde está en
399
+ `.dai\templates\jira-fields.example.json`. Por ejemplo, si tu Jira exige un desplegable:
400
+
401
+ ```json
402
+ {
403
+ "Story": {
404
+ "tipo": {
405
+ "field": "customfield_10042",
406
+ "shape": "select",
407
+ "options": ["Mejora", "Corrección"]
408
+ }
409
+ }
410
+ }
411
+ ```
412
+
413
+ - **`field`** es el `customfield_NNNNN` que te nombró el error.
414
+ - **`options`** son los valores válidos. dai los valida **antes** de llamar a Jira, así que un
415
+ error de tipeo te lo dice al instante en vez de un 400 críptico.
416
+ - **Sin `default`**, dai te va a pedir el valor en cada publicación (útil cuando cambia según la
417
+ historia).
418
+
419
+ Y publicas así:
420
+
421
+ ```powershell
422
+ dai publish us.md --field tipo=Mejora
423
+ ```
424
+
425
+ Comprueba que el archivo esté bien escrito con `dai doctor`.
426
+
427
+ ### Al publicar dice que no puede verificar el certificado
428
+
429
+ Es el **proxy de tu empresa**, que intercepta las conexiones con su propio certificado. dai te
430
+ va a decir qué hacer: pide a Sistemas el archivo `.pem` de la CA de la empresa y declárala:
431
+
432
+ ```powershell
433
+ $env:NODE_EXTRA_CA_CERTS="C:\ruta\ca-empresa.pem"
434
+ ```
435
+
436
+ > ⛔ **Nunca uses `NODE_TLS_REJECT_UNAUTHORIZED=0`**, aunque lo veas sugerido en internet o te
437
+ > lo proponga un asistente. Eso no arregla nada: **apaga la verificación entera**, y por esa
438
+ > conexión viaja tu token de Jira.
439
+
440
+ ---
441
+
442
+ ## Reglas de seguridad
443
+
444
+ - 🔒 **El `.env.dai` tiene tu token: es una contraseña.** Nunca lo pegues en un chat, en un
445
+ ticket ni en un documento compartido. `dai init` ya lo dejó fuera del control de versiones.
446
+ - 🙅 **No aceptes atajos que bajen la seguridad.** Si algo falla por un certificado, se declara
447
+ la CA; no se apaga la verificación.
448
+ - ♻️ **Rota el token** periódicamente y revoca los que no uses.
449
+ - 🧯 **Si se filtra**, revócalo de inmediato y crea uno nuevo.
450
+
451
+ ---
452
+
453
+ ## Lo que nunca tienes que hacer
454
+
455
+ - **No entres al código.** Tu trabajo termina en la US publicada. El *cómo* es del dev.
456
+ - **No escribas soluciones técnicas en las US.** Si te encuentras escribiendo "agregar una
457
+ columna a la tabla", frena: eso es el cómo. La US dice **qué** necesita el usuario y **por
458
+ qué**.
459
+ - **No aceptes un criterio que no puedas testear.** Si no sabes cómo comprobarlo, el dev
460
+ tampoco. Cuando la skill te insiste con eso, está trabajando bien.
461
+ - **No trates el documento como un mandato.** Es la materia prima: un menú, no una orden. Tú
462
+ decides qué entra.
463
+
464
+ ---
465
+
466
+ ## ¿Qué sigue?
467
+
468
+ El entorno ya está listo y probado. Lo que viene es tu día a día:
469
+
470
+ - 👉 [**Guía del PO / funcional**](../guias/po.md) — **empieza aquí.** Tu rol de punta a punta:
471
+ de qué eres dueño, qué no tocas, y el día a día paso por paso (nace la idea o llega un
472
+ documento → `/grill-user-story` te interroga → Gate 0 con `/grill-intent` → el dev
473
+ implementa el CÓMO → tú aceptas en la demo).
474
+ - [**Scrum con IA**](../SCRUM-CON-IA.md) — los 10 pasos del equipo completo, para ubicar dónde
475
+ entra y dónde termina tu parte.
476
+ - [**Glosario**](../glosario.md) — el vocabulario del método: el QUÉ y el CÓMO, `ac_hash`,
477
+ *atrasado*, el link.
478
+
479
+ > Tu trabajo termina en la **US publicada y aceptada**. Lo que pasa entre una y otra —ramas,
480
+ > tests, PRs— es del dev, y el link QUÉ↔CÓMO es lo que te deja verlo sin entrar al código.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dforce2055/dai",
3
- "version": "0.11.0",
3
+ "version": "0.13.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/",
@@ -25,7 +25,7 @@ Es la contraparte técnica de `grill-user-story`: donde esa produce el QUÉ (en
25
25
  - Nombre: `feature/ABC-###-<slug>` donde `<slug>` sale del título (minúsculas, sin acentos, `-` como separador).
26
26
  - Base según convención del repo (`main` o `develop`). Verificar que la branch no exista ya.
27
27
  - No permitir crear la branch si el key no fue validado en el paso 1.
28
- 4. **Generar el link.** Crear `openspec/changes/<change-id>/implements.yaml` a partir de [templates/implements.yaml](templates/implements.yaml), completando `id`, `version`, `ac_hash`, `repo` y `autor`. Dejar `introduces` para que el dev liste las capacidades técnicas nuevas.
28
+ 4. **Generar el link.** Crear `openspec/changes/<change-id>/implements.yaml` a partir de [templates/implements.yaml](templates/implements.yaml), completando `id`, `version`, `ac_hash`, `repo` y `autor`. Dejar `introduces` con el placeholder: **no se completa ahora**. Al arrancar no se sabe qué capacidades técnicas va a introducir el change — eso se sabe al terminar de implementarlo, y ahí lo completa quien implementó (agente o dev), con el dev revisándolo en la PR.
29
29
  5. **Hand-off.** Ofrecer seguir con `opsx:explore` → `opsx:propose` para armar el change (proposal/design/tasks) sobre la branch ya creada y linkeada.
30
30
 
31
31
  ## Guardrails (por qué esta skill existe)
@@ -1,5 +1,6 @@
1
1
  # Link QUÉ↔CÓMO · lo genera link-us / `dai link-us`, lo versiona git junto al código.
2
- # Es el ÚNICO link autorado a mano. La cobertura inversa la deriva `dai stamp`.
2
+ # Es el ÚNICO link AUTORADO (se escribe, no se deriva): lo scaffoldea `link-us` y se cierra
3
+ # al terminar de implementar. La cobertura inversa la deriva `dai stamp`.
3
4
  # Schema: docs/adr/0004-ubicacion-y-schema-implements.md
4
5
 
5
6
  change: <change-id> # ← identidad del CÓMO (nombre local del change/spec). Auto-contenido.
@@ -11,6 +12,7 @@ implements: # FORWARD: qué QUÉ del negocio cumple este ch
11
12
  ac_hash: <autogenerado> # ← lo calcula `dai ac-hash`. Dispara el ⚠️ si el QUÉ cambia.
12
13
 
13
14
  introduces: # capacidades TÉCNICAS nuevas que agrega este change (opcional)
14
- - <capacidad-tecnica> # p. ej. guard-carrito-vacio
15
+ - <capacidad-tecnica> # p. ej. guard-carrito-vacio. Se completa AL TERMINAR de
16
+ # implementar, no al crear el link: recién ahí se sabe.
15
17
 
16
18
  autor: <dev> # quién implementa
@@ -24,6 +24,9 @@
24
24
  - [ ] Existe `implements.yaml` con `id`, `version` y `ac_hash`. *(Art. 9)*
25
25
  - [ ] El **`ac_hash` coincide** con el de la US vigente (no se implementó una versión atrasada). *(Art. 11)*
26
26
  - [ ] La rama sigue la convención (`feature/ABC-###-<slug>`) → ver `governance/branch-naming.md`.
27
+ - [ ] **`introduces` está cerrado**: lista las capacidades técnicas que el change agregó, o el
28
+ bloque se borró porque no agregó ninguna. No queda el placeholder `<capacidad-tecnica>`:
29
+ es el único campo que se completa **al terminar**, y sin cerrarlo el link queda a medias.
27
30
 
28
31
  ### Revisión
29
32
  - [ ] Pasó el **primer pase de IA** (`dai-review`): sin problemas de correctitud.
@@ -31,7 +34,9 @@
31
34
  - [ ] Cumple los estándares del repo (lint, tipos, convenciones).
32
35
 
33
36
  ### Cierre
34
- - [ ] El change se promovió (`opsx:apply` → `opsx:archive`) si aplica.
37
+ - [ ] El change se promovió (los comandos `apply` → `archive` de OpenSpec) si aplica.
38
+ *(Se escriben `/opsx:apply` en Claude Code y `/opsx-apply` en Copilot y Cursor —
39
+ `dai doctor` te dice cuál usa este repo.)*
35
40
  - [ ] El **CI estampó la cobertura** en el gestor (no la escribió una persona). *(Art. 10)*
36
41
  - [ ] La US quedó en estado **implementada**.
37
42