@dforce2055/dai 0.9.0 → 0.11.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 (63) hide show
  1. package/{.env.example → .env.dai.example} +3 -3
  2. package/CHANGELOG.md +148 -0
  3. package/README.md +47 -26
  4. package/VERSION +1 -1
  5. package/cli/dai.mjs +528 -61
  6. package/cli/lib/bootstrap.mjs +44 -9
  7. package/cli/lib/branch-scope.mjs +144 -0
  8. package/cli/lib/env.mjs +12 -0
  9. package/cli/lib/forge-api.mjs +57 -0
  10. package/cli/lib/pm-adapter.mjs +16 -2
  11. package/cli/lib/pm-clickup.mjs +18 -3
  12. package/cli/lib/pm-jira.mjs +23 -3
  13. package/cli/lib/skills-source.mjs +8 -0
  14. package/cli/lib/us-format.mjs +147 -0
  15. package/docs/EJEMPLO-END-TO-END.md +78 -46
  16. package/docs/MANIFIESTO.md +2 -2
  17. package/docs/METODOLOGIA.md +25 -15
  18. package/docs/PROBAR.md +25 -15
  19. package/docs/SCRUM-CON-IA.md +11 -11
  20. package/docs/adr/0003-deteccion-y-estampado-son-comandos.md +1 -1
  21. package/docs/adr/0006-distribucion-y-licencia.md +1 -1
  22. package/docs/adr/0013-skills-externas-install-from.md +11 -4
  23. package/docs/adr/0015-jira-corporativo.md +1 -1
  24. package/docs/adr/0017-env-dai.md +64 -0
  25. package/docs/adr/0018-alcance-de-stamp-y-gate-de-ci.md +183 -0
  26. package/docs/adr/README.md +2 -0
  27. package/docs/detalle/01-refinamiento.md +20 -5
  28. package/docs/detalle/03-ramas.md +2 -2
  29. package/docs/detalle/04-tdd.md +15 -9
  30. package/docs/detalle/06-code-review.md +8 -5
  31. package/docs/detalle/07-merge-trazabilidad.md +13 -2
  32. package/docs/detalle/08-daily.md +1 -1
  33. package/docs/detalle/README.md +1 -1
  34. package/docs/glosario.md +3 -3
  35. package/docs/guias/dev.md +31 -7
  36. package/docs/guias/index.md +12 -0
  37. package/docs/guias/lead.md +1 -1
  38. package/docs/guias/po.md +53 -8
  39. package/docs/index.md +35 -0
  40. package/docs/public/favicon.svg +12 -0
  41. package/docs/public/logo-link.svg +12 -0
  42. package/docs/public/logo.svg +12 -0
  43. package/docs/public/tutoriales/clickup-1-settings.png +0 -0
  44. package/docs/public/tutoriales/clickup-2-api.png +0 -0
  45. package/docs/public/tutoriales/clickup-3-generate-copy.png +0 -0
  46. package/docs/public/tutoriales/jira-1-avatar.png +0 -0
  47. package/docs/public/tutoriales/jira-2-seguridad-tokens.png +0 -0
  48. package/docs/public/tutoriales/jira-3-crear-token.png +0 -0
  49. package/docs/public/tutoriales/jira-4-nombre-vencimiento.png +0 -0
  50. package/docs/public/tutoriales/jira-5-copiar.png +0 -0
  51. package/docs/tutoriales/claves-ssh.md +93 -0
  52. package/docs/tutoriales/configurar-git.md +53 -0
  53. package/docs/tutoriales/index.md +18 -0
  54. package/docs/tutoriales/instalar-glab.md +74 -0
  55. package/docs/tutoriales/token-clickup.md +73 -0
  56. package/docs/tutoriales/token-jira.md +74 -0
  57. package/governance/ci-rules.md +47 -8
  58. package/package.json +9 -3
  59. package/skills/dai-review/SKILL.md +1 -1
  60. package/skills/grill-epic/SKILL.md +2 -2
  61. package/skills/grill-intent/SKILL.md +1 -1
  62. package/skills/grill-user-story/SKILL.md +58 -10
  63. package/templates/ci-dai-gate.yml +50 -0
@@ -12,10 +12,10 @@
12
12
 
13
13
  | Paso | Skill / evento | Artefacto que produce |
14
14
  |---|---|---|
15
- | 1 Refinamiento | `grill-intent` → `grill-user-story` | `intent.md` + la **US** (`ABC-482`) |
15
+ | 1 Refinamiento | `grill-user-story` → `grill-intent` (Gate 0) | la **US** (`ABC-482`) + `intent.md` |
16
16
  | 2 Planning | `opsx:propose` | `proposal.md` + `design.md` + `tasks.md` + `specs/` |
17
17
  | 3 Rama | `link-us` | branch + `implements.yaml` |
18
- | 4 TDD | `tdd` | test (RED) → código (GREEN) |
18
+ | 4 Implementación | `opsx:apply` (con TDD) | test (RED) → código (GREEN), por el agente |
19
19
  | 5 Smoke | skill de smoke | escenario end-to-end verde |
20
20
  | 6 Code review | review propio del dev → `dai pr` → partner (con `/dai-review`) | PR (código + spec) + aprobación |
21
21
  | 7 Merge | `dai stamp` | cobertura estampada en el tracker |
@@ -37,34 +37,9 @@ ABC-482 · "Arreglar lo del carrito que a veces deja comprar de más"
37
37
 
38
38
  Impresentable para implementar. Acá entra la IA.
39
39
 
40
- ### 1b · Gate 0 — `grill-intent` desafía el problema
40
+ ### 1b · `grill-user-story` produce la US
41
41
 
42
- La skill no acepta el ticket: interroga el *problema* detrás (contra el
43
- [`MANIFIESTO.md`](MANIFIESTO.md)).
44
-
45
- ```
46
- IA: ¿Qué duele HOY, concretamente? "Comprar de más" es un síntoma.
47
- PO: Un cliente finalizó la compra de un producto que ya no tenía stock, y quedó
48
- una orden que no podemos cumplir. También pasa que finalizan con el carrito
49
- vacío y se genera una orden fantasma.
50
- IA: ¿Quién siente el dolor? "El sistema" no es un usuario.
51
- PO: El comprador (recibe un error después de comprar) y depósito, que recibe
52
- órdenes que no puede despachar.
53
- IA: ¿Y si no lo hacemos? (costo de no actuar)
54
- PO: Órdenes que se cancelan a mano, clientes enojados. Pasó bastante el último mes.
55
- IA: La solución implícita es "validar el carrito al finalizar". ¿Es el salto correcto,
56
- o el problema real es que el stock que muestra el carrito no es confiable?
57
- PO: No, validar al finalizar es lo correcto: el stock ya existe, falta chequearlo
58
- en el momento de la compra.
59
-
60
- Veredicto: a-spec ✅ (problema real, usuario concreto, costo claro, sin solution-lock)
61
- ```
62
-
63
- → produce `openspec/intents/20260703-checkout-invalido/intent.md` con ese veredicto.
64
-
65
- ### 1c · `grill-user-story` produce la US
66
-
67
- Con el problema validado, la skill interroga hasta que la US es **testeable por
42
+ Acá entra la IA: `grill-user-story` interroga al PO hasta que la US es **testeable por
68
43
  construcción** ([`formato-us.md`](../templates/formato-us.md)) y la publica en el gestor:
69
44
 
70
45
  ```markdown
@@ -113,6 +88,33 @@ para **recibir los productos que elijo sin sorpresas**.
113
88
  > Nota que la US **no dice** tablas, endpoints ni framework — solo el QUÉ. Y cada
114
89
  > AC es un test en potencia ([Art. 3](./MANIFIESTO.md#art-3) del manifiesto).
115
90
 
91
+ ### 1c · Gate 0 — `grill-intent` desafía el problema
92
+
93
+ Con la US ya formada, **antes** de invertir en el spec, el Gate 0 cuestiona el *problema*
94
+ detrás (contra el [`MANIFIESTO.md`](MANIFIESTO.md)):
95
+
96
+ ```
97
+ IA: ¿Qué duele HOY, concretamente? "Comprar de más" es un síntoma.
98
+ PO: Un cliente finalizó la compra de un producto que ya no tenía stock, y quedó
99
+ una orden que no podemos cumplir. También pasa que finalizan con el carrito
100
+ vacío y se genera una orden fantasma.
101
+ IA: ¿Quién siente el dolor? "El sistema" no es un usuario.
102
+ PO: El comprador (recibe un error después de comprar) y depósito, que recibe
103
+ órdenes que no puede despachar.
104
+ IA: ¿Y si no lo hacemos? (costo de no actuar)
105
+ PO: Órdenes que se cancelan a mano, clientes enojados. Pasó bastante el último mes.
106
+ IA: La solución implícita es "validar el carrito al finalizar". ¿Es el salto correcto,
107
+ o el problema real es que el stock que muestra el carrito no es confiable?
108
+ PO: No, validar al finalizar es lo correcto: el stock ya existe, falta chequearlo
109
+ en el momento de la compra.
110
+
111
+ Veredicto: a-spec ✅ (problema real, usuario concreto, costo claro, sin solution-lock)
112
+ ```
113
+
114
+ → produce `openspec/intents/20260703-checkout-invalido/intent.md` con ese veredicto. Si
115
+ hubiera dado *reframe* o *don't build*, la US volvería al PO **antes** de gastar un solo
116
+ artefacto de spec — ese es el punto del Gate 0.
117
+
116
118
  ---
117
119
 
118
120
  ## Paso 2 — Planning: `opsx:propose` deriva el CÓMO
@@ -175,9 +177,10 @@ autor: D. Force (dev)
175
177
 
176
178
  ---
177
179
 
178
- ## Paso 4 — TDD: un test a la vez (RED → GREEN)
180
+ ## Paso 4 — Implementación: el agente construye con TDD (`/opsx:apply`)
179
181
 
180
- Vertical slice del AC-2 (el guard del carrito vacío). **Primero el test (RED):**
182
+ `/opsx:apply` implementa las tareas del change, un test a la vez. Vertical slice del AC-2
183
+ (el guard del carrito vacío). **Primero el test (RED):**
181
184
 
182
185
  ```typescript
183
186
  test("un carrito vacío no se puede finalizar", async () => {
@@ -205,8 +208,9 @@ export async function finalizarCompra(id: CarritoId) {
205
208
  // ▶ VERDE. Repetir el ciclo para AC-1 y AC-3.
206
209
  ```
207
210
 
208
- > El test verifica por la **interfaz pública** (`finalizarCompra`, `ordenesDe`), no
209
- > espía lo interno. Sobrevive a un refactor (Art. 7 + skill `tdd`).
211
+ > El test (que escribió el agente) verifica por la **interfaz pública**
212
+ > (`finalizarCompra`, `ordenesDe`), no espía lo interno. Sobrevive a un refactor
213
+ > (Art. 7 + skill `tdd`). El dev revisa cada slice: es responsable del código.
210
214
 
211
215
  ---
212
216
 
@@ -239,29 +243,34 @@ $ dai pr --assignee mgomez
239
243
  ✓ PR #123 creada → …/pull/123 (base: main · US: ABC-482 @ v1 · dai check ✅)
240
244
  ```
241
245
 
242
- El **partner** revisa la PR. Se apoya en la skill `/dai-review` para un primer pase con
243
- comentario estándar, y **firma** aprobación o rechazo:
246
+ El **partner** revisa la PR. Se apoya en la skill `/dai-review` para un primer pase: deja
247
+ un **review inline** (resumen + un comentario anclado por línea, low/medium/high). La skill
248
+ le muestra el preview y **espera su OK antes de postear**; después el partner **firma**
249
+ aprobación o rechazo:
244
250
 
245
251
  ```
246
- 🤖 /dai-review (primer pase, ayuda al partner)
247
- · AC-2 cubierto y verificado (no se crea orden con carrito vacío).
248
- · Sugerencia: CarritoVacioError y SinStockError deberían extender un DomainError
249
- común, como el resto del módulo.
250
- · Sin problemas de correctitud.
252
+ 🤖 /dai-review resumen
253
+ US: ABC-482 @ v1 · dai check: al día · DoD: 5/5
254
+ 1 comentario en línea: 1 🔵 Low.
251
255
 
252
- 👤 M. Gómez (partner): de acuerdo con el DomainError. Aprobado tras el ajuste.
256
+ 🔵 Low src/checkout/errors.ts:12
257
+ CarritoVacioError y SinStockError podrían extender un DomainError común,
258
+ como el resto del módulo.
259
+
260
+ 👤 M. Gómez (partner): reviso el preview, lo posteo, y apruebo tras el ajuste.
253
261
  ```
254
262
 
255
263
  > El dev revisa su propio código; un partner distinto revisa la PR y **firma** (Art. 5).
256
- > La skill `/dai-review` le saca el ruido al partner, pero la aprobación la firma la persona.
264
+ > El review sale con el nombre y el token del partner (nunca `APPROVE` automático): la
265
+ > skill asiste, la persona firma.
257
266
 
258
267
  ---
259
268
 
260
269
  ## Paso 7 — Merge: la trazabilidad se estampa sola
261
270
 
262
271
  Al mergear, se corre `dai stamp` (el dev, o el CI si está automatizado — ADR-0003).
263
- Lee el `implements.yaml` y **estampa la cobertura inversa** en el ticket `ABC-482`,
264
- con links a la implementación:
272
+ Deduce que la US de esta rama es `ABC-482`, lee el `implements.yaml` y **estampa la
273
+ cobertura inversa** en el ticket, con links a la implementación:
265
274
 
266
275
  ```
267
276
  ABC-482 · implementado por (lo estampó dai stamp)
@@ -282,7 +291,7 @@ ABC-482 · implementado por (lo estampó dai stamp)
282
291
  ## Paso 8 — Daily *(humano, a propósito)*
283
292
 
284
293
  > *"Ayer cerré ABC-482, la validación del checkout con el guard de carrito. Hoy
285
- > agarro ABC-490. Sin trabas."* — La IA no genera esto; el equipo se sincroniza (Art. 6).
294
+ > tomo ABC-490. Sin trabas."* — La IA no genera esto; el equipo se sincroniza (Art. 6).
286
295
 
287
296
  ## Paso 9 — Review / Demo
288
297
 
@@ -303,7 +312,30 @@ AC-3 verdes → **US aceptada**. Cero sorpresas: si el QUÉ hubiera cambiado, el
303
312
 
304
313
  Dos sprints después, el PO agrega un criterio a `ABC-482` (ahora exige **avisar al
305
314
  comprador qué productos quedaron sin stock, sin cancelar el resto del carrito**).
306
- Sube la US a **v2** → cambia el `ac_hash`.
315
+
316
+ Lo hace con `dai edit-us ABC-482`: la baja del tracker, la abre en su editor, valida el
317
+ formato cuando guarda, y le pregunta si el cambio es material o editorial.
318
+
319
+ ```
320
+ ── formato de la US (.dai/us/ABC-482.md) ────────────
321
+ ✓ formato válido — 4 criterio(s), 4 en Gherkin completo
322
+
323
+ Cambiaron los criterios (ac_hash 7f3a9c2e → b81d40f5).
324
+ s = cambio material: subo spec_version a v2 y los repos con v1 se marcan ATRASADOS
325
+ n = cambio editorial (typo, redacción): se queda en v1
326
+ ¿Subo spec_version a v2? (S/n) s
327
+
328
+ ── ABC-482 · qué cambia en jira ────────────
329
+ título: Finalizar la compra del carrito (sin cambios)
330
+ criterios: 4
331
+ version: v1 → v2
332
+ ac_hash: 7f3a9c2e → b81d40f5
333
+ ──────────────────────────────────────
334
+ Esto PISA la US ABC-482 en jira. ¿Guardo? (s/N) s
335
+ ✓ ABC-482 actualizada en jira → https://acme.atlassian.net/browse/ABC-482
336
+ ```
337
+
338
+ La US sube a **v2** → cambia el `ac_hash`.
307
339
 
308
340
  ```
309
341
  ABC-482 · implementado por
@@ -3,7 +3,7 @@
3
3
  > **Qué es esto.** La *constitución* de la metodología: los principios inmutables
4
4
  > contra los que se mide toda decisión. Cuando `grill-intent` desafía un problema,
5
5
  > lo hace contra estos artículos. Cuando dudas si algo "va con el método", la
6
- > respuesta está acá. Es corto a propósito — un manifiesto que no se puede citar de
6
+ > respuesta está aquí. Es corto a propósito — un manifiesto que no se puede citar de
7
7
  > memoria no gobierna nada.
8
8
  >
9
9
  > **Cómo se usa.** Es el input de constitución que las skills asumen (junto con
@@ -56,7 +56,7 @@ El *daily* y la *retro* se hacen a mano, a propósito. Son donde el equipo se
56
56
  apropia del proceso y lo entiende. La IA puede darles datos; no los reemplaza.
57
57
 
58
58
  <a id="art-7"></a>**Art. 7 — No vibe coding.**
59
- No se improvisa código sobre una idea vaga. Toda implementación arranca de una US
59
+ No se improvisa código sobre una idea vaga. Toda implementación parte de una US
60
60
  bien definida, pasa por un design, y se construye con tests. La disciplina no es
61
61
  opcional: es lo que separa este método de "pedirle cosas a un chat".
62
62
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Fuente de verdad única.** Este documento es el maestro. Los dos HTML
4
4
  > (`desarrollo-asistido-por-ia.html` federado y `-equipos-compactos.html`) son
5
- > **vistas de presentación** derivadas de acá — si algo contradice a este `.md`,
5
+ > **vistas de presentación** derivadas de aquí — si algo contradice a este `.md`,
6
6
  > gana este `.md`. Versionado por git para que no driftee.
7
7
 
8
8
  Una sola metodología para dos escalas opuestas:
@@ -57,9 +57,9 @@ identidad el día que se crea el ticket/change.
57
57
  ### 2.2 Formato linkeable garantizado
58
58
 
59
59
  El QUÉ se produce con una forma mínima **testeable**: `id · spec_version · autor ·
60
- criterios de aceptación en Gherkin`. Es exactamente lo que aseguran las skills
61
- `grill-intent` → `grill-user-story` (ver `formato-us.md`). Sin esa forma, no hay
62
- a qué linkear.
60
+ criterios de aceptación en Gherkin`. Es exactamente lo que asegura la skill
61
+ `grill-user-story` (y después el Gate 0 de `grill-intent` desafía el problema; ver
62
+ `formato-us.md`). Sin esa forma, no hay a qué linkear.
63
63
 
64
64
  ### 2.3 El link se autora una sola vez, del lado del CÓMO
65
65
 
@@ -83,6 +83,11 @@ cambio.
83
83
  - **`ac_hash`** lo calcula la máquina para **detectar**. Es el hash del bloque de
84
84
  *Criterios de aceptación* normalizado (whitespace colapsado, orden estable).
85
85
 
86
+ > El reparto no es decorativo: la máquina sabe **que** algo cambió, la persona sabe **si
87
+ > importa**. Un typo corregido mueve el hash igual que un criterio nuevo, y solo un humano
88
+ > distingue el uno del otro. Por eso `dai edit-us` / `dai update-us` **proponen** subir el
89
+ > `spec_version` cuando el hash se mueve, y esperan un sí o un no — nunca lo deciden solos.
90
+
86
91
  Cuando el QUÉ evoluciona, cambia el `ac_hash`; todos los CÓMO que declaran el hash
87
92
  viejo quedan marcados **atrasados** solos. El funcional ve "el backend todavía no
88
93
  tomó mi cambio"; el dev ve "el QUÉ que implementé cambió". Nadie avisa a nadie — el
@@ -122,8 +127,10 @@ federación.**
122
127
 
123
128
  El CÓMO se construye con **test primero**, en *vertical slices* (un test → una
124
129
  implementación → repetir), verificando por la **interfaz pública**, no espiando lo
125
- interno. Un buen test lee como una spec y sobrevive a un refactor. Ver
126
- `skills/tdd/`.
130
+ interno. Un buen test lee como una spec y sobrevive a un refactor. **Quien lo ejecuta
131
+ es el agente**, dentro de `/opsx:apply` (la disciplina la encapsula la skill `tdd`); el
132
+ dev decide qué comportamientos importa testear y es responsable de revisar el resultado
133
+ ([Art. 7](MANIFIESTO.md#art-7)). Ver `skills/tdd/`.
127
134
 
128
135
  ---
129
136
 
@@ -134,7 +141,7 @@ duele, no antes.**
134
141
 
135
142
  | | **N1 · Solo / 1 repo** | **N2 · Equipo compacto** | **N3 · Federado** |
136
143
  |---|---|---|---|
137
- | Caso típico | equipo chico arrancando, un dev | equipo chico | organización grande |
144
+ | Caso típico | equipo chico empezando, un dev | equipo chico | organización grande |
138
145
  | El QUÉ vive en | `proposal.md` de OpenSpec | ClickUp (US) → el change la referencia | Jira (`ABC-###`, hub) |
139
146
  | El link vive en | la carpeta del change (co-localizado) | `implements.yaml` en el repo | `implements.yaml` versionado |
140
147
  | Inversa la genera | un comando local | comando / CI liviano | CI estampa cobertura + CD reporta ambiente |
@@ -178,13 +185,13 @@ El artefacto no desaparece; se aligera la ceremonia alrededor.
178
185
 
179
186
  ```
180
187
  ① Nace la idea → ticket vago en el PM (o intención suelta en N1)
181
- Gate 0: ¿problema OK? → /grill-intent → veredicto: a-spec / reframe / descartar
182
- ③ Se pule el QUÉ → /grill-user-story → US testeable (formato-us.md),
188
+ Se pule el QUÉ → /grill-user-story US testeable (formato-us.md),
183
189
  publicada en Jira/ClickUp (o .md si no hay MCP)
190
+ ③ Gate 0: ¿problema OK? → /grill-intent → veredicto: a-spec / reframe / descartar
184
191
  ④ Se abre el CÓMO → /link-us ABC-### → branch + implements.yaml ligados al ID
185
192
  ⑤ Se arma el change → opsx:explore → opsx:propose (proposal/design/tasks + specs)
186
- ⑥ Se implementa → TDD (red green refactor), vertical slices
187
- ⑦ Se promueve → opsx:apply → opsx:archive; el CI estampa cobertura en el PM
193
+ ⑥ Se implementa → opsx:apply → el agente aplica las tareas con TDD (red→green→refactor)
194
+ ⑦ Se promueve → opsx:archive; el CI estampa cobertura en el PM
188
195
  ⑧ Se despliega → el CD reporta a qué ambiente (dev/test/pre/prod) fue la versión
189
196
  ```
190
197
 
@@ -203,11 +210,14 @@ El artefacto no desaparece; se aligera la ceremonia alrededor.
203
210
 
204
211
  | Skill | Lado | Qué hace |
205
212
  |---|---|---|
206
- | `grill-intent` | QUÉ | Gate 0: desafía el *problema* antes de escribir spec. Veredicto: a-spec / reframe / descartar. |
213
+ | `doc-to-backlog` | QUÉ | Un documento (PDF/Word) backlog candidato de épicas + US para priorizar. |
214
+ | `grill-epic` | QUÉ | Algo grande → una épica partida en varias US. |
207
215
  | `grill-user-story` | QUÉ | Interroga hasta producir una US testeable (INVEST + Gherkin). Publica en Jira/ClickUp o deja `.md`. |
216
+ | `grill-intent` | QUÉ | Gate 0: con la US ya formada, desafía el *problema* antes de escribir spec. Veredicto: a-spec / reframe / descartar. |
208
217
  | `link-us` | CÓMO | Crea branch + `implements.yaml` desde el ID del PM. El link, correcto por construcción. |
209
- | `tdd` | CÓMO | Red-green-refactor en vertical slices, tests por interfaz pública. |
210
- | `opsx:*` | CÓMO | OpenSpec: explore propose apply archive. Lo provee OpenSpec. |
218
+ | `opsx:*` | CÓMO | OpenSpec: explore propose apply (el agente implementa con TDD) → archive. Lo provee OpenSpec. |
219
+ | `tdd` | CÓMO | La disciplina red-green-refactor (vertical slices, tests por interfaz pública) que aplica `opsx:apply`. |
220
+ | `dai-review` | CÓMO | Review inline de una PR/MR ajena: resumen + un comentario por línea, con gate humano de OK antes de postear. |
211
221
 
212
222
  El **adaptador de PM** es un seam único: las skills del QUÉ publican en Jira **o**
213
223
  ClickUp **o** dejan un `.md` según qué MCP/token haya. Es la **misma** skill con
@@ -228,7 +238,7 @@ de N3 queda **una** decisión sin resolver; el resto se cerró al construir la h
228
238
 
229
239
  **Ya resueltas** (al construir dai):
230
240
  - **Adaptador de PM configurable** → `getAdapter` (backends `md`/`jira`/`clickup`, token del
231
- `.env`); modelo de auth en [ADR-0007](adr/0007-modelo-de-autenticacion.md).
241
+ `.env.dai` no versionado — [ADR-0017](adr/0017-env-dai.md)); modelo de auth en [ADR-0007](adr/0007-modelo-de-autenticacion.md).
232
242
  - **Formato de `implements.yaml`** → congelado en [ADR-0004](adr/0004-ubicacion-y-schema-implements.md)
233
243
  (schema + ubicación + descubrimiento por glob).
234
244
  - **Escritura multi-repo en el tracker** → `dai stamp` deja un **comentario por repo** (no se
package/docs/PROBAR.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Probar dai
2
2
 
3
- No hace falta publicar en npm para probarlo. Se prueba local. Recomendado: hacer la
4
- **Fase 0** (backend `md`, sin credenciales) para validar el flujo, y después la
5
- **Fase 1** (ClickUp real).
3
+ La forma más rápida de conocer dai: instala el CLI y corre el ciclo completo en tu
4
+ máquina. Empieza **sin credenciales** (backend `md`) para ver el flujo entero en un par de
5
+ minutos, y después pruébalo **contra tu tracker real** (ClickUp o Jira).
6
6
 
7
7
  > Esto es la guía para **usar** dai por primera vez. Para verlo funcionando sobre una
8
8
  > US real (narrado), mira [`EJEMPLO-END-TO-END.md`](EJEMPLO-END-TO-END.md).
@@ -10,19 +10,17 @@ No hace falta publicar en npm para probarlo. Se prueba local. Recomendado: hacer
10
10
  ## Instalar el CLI
11
11
 
12
12
  ```bash
13
- npm i -g @dforce2055/dai # desde npm
14
- # — o, si clonaste el repo —
15
- git clone https://github.com/dforce2055/dai && cd dai && npm link
16
-
13
+ npm i -g @dforce2055/dai
17
14
  dai --version
18
15
  ```
19
16
 
20
- ## Fase 0 — sin credenciales (backend `md`)
17
+ ## Paso 1 — sin credenciales (backend `md`)
21
18
 
22
- Valida el loop completo `link-us → check → stamp` sin depender de red ni tokens.
19
+ Recorre el loop completo `link-us → check → stamp` sin red ni tokens: todo local. Perfecto
20
+ para ver cómo funciona antes de conectar nada.
23
21
 
24
22
  ```bash
25
- # 1. Repo de prueba + bootstrap (dai init deja el .env; elige "md" cuando pregunte)
23
+ # 1. Repo de prueba + bootstrap (dai init deja el .env.dai; elige "md" cuando pregunte)
26
24
  mkdir /tmp/dai-test && cd /tmp/dai-test
27
25
  git init && git commit --allow-empty -m init
28
26
  git remote add origin git@github.com:TU-USUARIO/dai-test.git # para los links de branch/commit
@@ -43,14 +41,21 @@ dai link-us finalizar-la-compra-del-carrito # branch + implements.yaml
43
41
  git add -A && git commit -m "feat: guard carrito vacío"
44
42
  dai check # ✅ al día
45
43
 
46
- # 4. La demo del ⚠️: edita el criterio en .dai/us/<slug>.md y vuelve a chequear
44
+ # 4. La demo del ⚠️: cambia el QUÉ y mira cómo se detecta solo
45
+ dai edit-us finalizar-la-compra-del-carrito # la trae, la abres, valida, pregunta si sube spec_version
47
46
  dai check # ⚠️ ATRASADO (exit 1) → sugiere: dai link-us <id> --resync
47
+
48
+ # 5. Estampa la cobertura
48
49
  dai stamp # con md, deja .dai/us/<slug>.coverage.md
49
50
  ```
50
51
 
51
- Si esto anda, el flujo está bien. Pasa al tracker real.
52
+ > En el paso 4, `dai edit-us` abre tu `$EDITOR`. Si no tienes uno configurado te pide
53
+ > editar el archivo y volver, así que también funciona con el archivo abierto en tu IDE.
54
+ > Agrega un criterio, guarda, y responde `s` a "¿subo spec_version?" para ver el ⚠️.
52
55
 
53
- ## Fase 1 ClickUp real
56
+ Con esto ya viste el ciclo entero. Ahora conéctalo a tu tracker real.
57
+
58
+ ## Paso 2 — contra tu tracker real (ClickUp)
54
59
 
55
60
  **Preparar ClickUp:**
56
61
 
@@ -62,7 +67,7 @@ Si esto anda, el flujo está bien. Pasa al tracker real.
62
67
  **Config y flujo:**
63
68
 
64
69
  ```bash
65
- cat > .env <<'EOF'
70
+ cat > .env.dai <<'EOF'
66
71
  DAI_PM=clickup
67
72
  DAI_CLICKUP_TOKEN=pk_XXXXXXXX
68
73
  EOF
@@ -77,9 +82,13 @@ dai check # ✅ al día
77
82
  # → edita un criterio de la tarea en ClickUp (en el navegador). Después:
78
83
  dai check # ⚠️ ATRASADO (lo detectó solo)
79
84
  dai stamp # deja un COMENTARIO en la tarea con la cobertura
85
+
86
+ # ¿Editar la US sin salir de la terminal? La trae, la abres, valida y la devuelve:
87
+ dai edit-us 86cxyz --dry-run # el preview completo, sin escribir en ClickUp
80
88
  ```
81
89
 
82
- > El `.env` está gitignored: el token no se commitea (ADR-0007).
90
+ > El `.env.dai` **no se versiona**: el token no se commitea, y el `.env` del equipo no se
91
+ > toca ([ADR-0017](adr/0017-env-dai.md); modelo de auth en [ADR-0007](adr/0007-modelo-de-autenticacion.md)).
83
92
 
84
93
  ## Troubleshooting
85
94
 
@@ -87,6 +96,7 @@ dai stamp # deja un COMENTARIO en la tarea con la cobertu
87
96
  |---|---|
88
97
  | `no encontré la US <id>` | ID mal, o el token no ve esa tarea |
89
98
  | `clickup 401` | token inválido o expirado |
99
+ | `edit-us` dice que la US no tiene el formato mínimo | le falta el `# Título` o la sección `## Criterios de aceptación`. Sin criterios no hay `ac_hash` y no hay link |
90
100
  | `check` siempre da ⚠️ | editaste la US entre `link-us` y `check` (esperado), **o** los criterios no están bajo el heading `Criterios de aceptación` |
91
101
  | `sin US` en `check` | la tarea no tiene el bloque de criterios en la descripción |
92
102
  | branch/commit vacíos en el stamp | falta el remoto git (`git remote add origin …`) |
@@ -49,9 +49,9 @@
49
49
  |---|---|
50
50
  | **Clásico** | El PO parte épicas en Historias de Usuario y les pone criterios de aceptación. |
51
51
  | **Dolor** | US vagas, no testeables ("el usuario quiere un botón"). El malentendido se descubre tarde, ya implementado. |
52
- | **Con IA** | `grill-intent` (Gate 0: ¿es el problema correcto? veredicto a-spec / reframe / descartar) y luego `grill-user-story` **interrogan** al PO hasta que la US es testeable por construcción (INVEST + Gherkin). La IA no *escribe* la US: la *saca a preguntas*. La US nace con ID estable y criterios hasheables. |
53
- | **Humano (HITL)** | El PO responde y decide. La IA no inventa requerimientos: los pule. |
54
- | **Herramienta** | `grill-intent`, `grill-user-story`, `formato-us.md` |
52
+ | **Con IA** | `grill-user-story` **interroga** al PO hasta que la US es testeable por construcción (INVEST + Gherkin); y después el Gate 0 de `grill-intent` desafía el *problema* detrás (veredicto: a-spec / reframe / descartar). La IA no *escribe* la US: la *saca a preguntas*. La US nace con ID estable y criterios hasheables. |
53
+ | **Humano (HITL)** | El PO responde y decide. La IA no inventa requerimientos: los pule. Si la US ya existe y hay que retocarla, `dai edit-us <ID>` la baja del tracker, valida el formato al guardar y **pregunta** si el cambio es material (sube `spec_version`) o editorial. |
54
+ | **Herramienta** | `grill-user-story`, `grill-intent`, `formato-us.md`, `dai edit-us` |
55
55
  | **Detalle →** | [`detalle/01-refinamiento.md`](detalle/01-refinamiento.md) |
56
56
 
57
57
  #### 2. Sprint Planning: comprometer US y derivar tareas
@@ -76,19 +76,19 @@
76
76
  | **Clásico** | El dev crea una rama para trabajar la US. |
77
77
  | **Dolor** | Nombres inconsistentes, ramas que no se sabe a qué US pertenecen → trazabilidad rota desde el commit uno. |
78
78
  | **Con IA** | `link-us ABC-###` crea la rama **desde el ID de la US, sin tipearlo a mano**, y genera el `implements.yaml`. La rama *es* el link: correcto por construcción. |
79
- | **Humano (HITL)** | El dev elige qué US agarra. |
79
+ | **Humano (HITL)** | El dev elige qué US toma. |
80
80
  | **Herramienta** | `link-us` |
81
81
  | **Detalle →** | [`detalle/03-ramas.md`](detalle/03-ramas.md) |
82
82
 
83
- #### 4. Implementación con TDD
83
+ #### 4. Implementación (`/opsx:apply`, con TDD)
84
84
 
85
85
  | | |
86
86
  |---|---|
87
87
  | **Clásico** | El dev codea. Idealmente con tests. |
88
88
  | **Dolor** | Se codea primero y se testea "si queda tiempo" (nunca queda). Vibe coding. |
89
- | **Con IA** | La skill `tdd` fuerza test→código en *vertical slices* (un test → una implementación → repetir). La IA escribe el test como spec ejecutable **antes** del código, verificando por la interfaz pública. Anti vibe-coding real. |
90
- | **Humano (HITL)** | El dev decide qué comportamientos importa testear y revisa cada slice. |
91
- | **Herramienta** | `tdd` |
89
+ | **Con IA** | El **agente implementa** con `/opsx:apply`: aplica las tareas de `opsx:propose` en *vertical slices* (un test → el código mínimo → repetir), escribiendo el test como spec ejecutable **antes** del código y verificando por la interfaz pública (la disciplina TDD la encapsula la skill `tdd`). Anti vibe-coding real. |
90
+ | **Humano (HITL)** | El dev decide qué comportamientos importa testear, valida cada slice y **es responsable del código** (no la IA) — lo revisa en el paso 6. |
91
+ | **Herramienta** | `opsx:apply` (con la disciplina de `tdd`) |
92
92
  | **Detalle →** | [`detalle/04-tdd.md`](detalle/04-tdd.md) |
93
93
 
94
94
  #### 5. Smoke test de la US
@@ -108,9 +108,9 @@
108
108
  |---|---|
109
109
  | **Clásico** | Un compañero revisa el PR/MR antes de mergear. |
110
110
  | **Dolor** | Depende de que el partner tenga tiempo y ganas; reviews superficiales que dejan pasar lo importante. |
111
- | **Con IA** | La IA hace el **primer pase** (correctitud + estándares del repo) antes del humano. El partner revisa lo que importa, no el ruido. |
111
+ | **Con IA** | La IA hace el **primer pase**: un **review inline** (corre `dai check` + valida el DoD, y deja un resumen + **un comentario por línea**, low/medium/high). Muestra el preview y **espera el OK del partner antes de postear**; el partner revisa lo que importa, no el ruido. |
112
112
  | **Humano (HITL)** | El partner aprueba o rechaza. La IA sugiere; la persona decide y firma. |
113
- | **Herramienta** | `dai-review` |
113
+ | **Herramienta** | `dai-review` (`dai forge review`) |
114
114
  | **Detalle →** | [`detalle/06-code-review.md`](detalle/06-code-review.md) |
115
115
 
116
116
  #### 7. Merge + trazabilidad automática
@@ -170,7 +170,7 @@
170
170
  | 1 Refinamiento | ●●● | La US testeable es la base de todo. |
171
171
  | 2 Planning | ●● | El design y las tareas se derivan de la US. |
172
172
  | 3 Rama | ●●● | El link correcto por construcción. |
173
- | 4 TDD | ●●● | El corazón del anti vibe-coding. |
173
+ | 4 Implementación | ●●● | El agente construye con TDD; el corazón del anti vibe-coding. |
174
174
  | 5 Smoke | ●● | Cierre verificable de la US. |
175
175
  | 6 Code review | ●● | Primer pase automático, humano decide. |
176
176
  | 7 Merge + trazabilidad | ●●● | La matriz se deriva sola. |
@@ -49,7 +49,7 @@ Pasar de distribuido a automático es mover la invocación, no reescribir nada.
49
49
 
50
50
  ## Consecuencias
51
51
 
52
- - ✅ **No hace falta ningún CI para empezar.** La metodología arranca con un dev
52
+ - ✅ **No hace falta ningún CI para empezar.** La metodología empieza con un dev
53
53
  tipeando `dai check` / `dai stamp`. El [Art. 14](../MANIFIESTO.md#art-14) queda respetado.
54
54
  - ✅ **Rampa de adopción continua:** manual → git-hook → CI, siempre el mismo comando.
55
55
  - ✅ **Honra el [Art. 10](../MANIFIESTO.md#art-10):** el humano *dispara* la derivación; no *escribe a mano* el
@@ -20,7 +20,7 @@ más fuerte de eso es el **copyleft**: quien distribuya un `dai` modificado debe
20
20
  publicar sus cambios bajo la misma licencia. La GPL convierte "las mejoras vuelven"
21
21
  en cláusula, no en deseo.
22
22
 
23
- El downside típico de la GPL **no aplica** acá: `dai` es un **CLI que se ejecuta**,
23
+ El downside típico de la GPL **no aplica** aquí: `dai` es un **CLI que se ejecuta**,
24
24
  no una librería que se embebe. Usar `dai` sobre tu código —aunque sea propietario y
25
25
  comercial— **no genera ninguna obligación**; el copyleft solo se activa si alguien
26
26
  **forkea y redistribuye** una versión modificada. Y *libre ≠ gratis*: se puede
@@ -18,11 +18,17 @@ dueño ni gatekeeper de ellas.
18
18
 
19
19
  ## Decisión
20
20
 
21
- Agregamos **`dai skills install --from <git-url|path>[#ref]`**: instala skills
22
- **externas** desde un repo/dir (con estructura `skills/<nombre>/SKILL.md`, la misma
21
+ Agregamos **`dai skills install --from <git-url|npm:pkg|path>[#ref]`**: instala skills
22
+ **externas** desde un repo/dir/paquete (con estructura `skills/<nombre>/SKILL.md`, la misma
23
23
  de dai), **convertidas para los 3 asistentes** (Claude copia · Cursor `skillToCursor`
24
24
  · Copilot `skillToPrompt` → `.github/prompts/`).
25
25
 
26
+ - **Tres fuentes:** un **git URL** (`github.com/org/skills[#ref]` → clone), un **path
27
+ local**, o un **paquete npm** (`npm:@scope/pkg[@version]` → `npm pack` a un temp,
28
+ respetando el `.npmrc` del cwd, así resuelve registries privados con scope). Es común
29
+ distribuir skills como paquete npm (una org publica sus componentes + skills juntas);
30
+ materializarlo a mano era fricción de más.
31
+
26
32
  - **`dai skills` es el namespace canónico** de las operaciones de skills, consistente
27
33
  con `dai forge <verb>`. `dai skills install` (sin `--from`) instala las de dai;
28
34
  **`dai install` queda como alias** silencioso (backward-compatible).
@@ -42,8 +48,9 @@ de dai), **convertidas para los 3 asistentes** (Claude copia · Cursor `skillToC
42
48
  - **Se acepta pagar:** es **one-off** (dai no mantiene esas skills al día; re-corrés
43
49
  `--from`). **Sin registro** → dai no sabe qué repos tienen skills externas, a
44
50
  propósito: cero gatekeeping, bajo riesgo del equipo. Las fuentes remotas dependen de
45
- git/red, y la **auth se delega en git** (público sin más; privado por SSH o credential
46
- helper — dai no autentica): *si podés `git clone` la fuente, dai instala desde ahí*.
51
+ git/red/npm, y la **auth se delega en la herramienta** (git: SSH o credential helper;
52
+ npm: el `.npmrc` del repo — dai no autentica): *si puedes `git clone` o `npm pack` la
53
+ fuente, dai instala desde ahí*.
47
54
 
48
55
  ## Alternativas consideradas
49
56
 
@@ -89,7 +89,7 @@ error de config más común. El mensaje da los dos caminos: `DAI_JIRA_PROJECT=PR
89
89
  - **`dai doctor`** valida la clave de proyecto y que el archivo de campos parsee. Sigue
90
90
  **sin** verificar que el token sirva — eso es red, y lo dice `dai publish`. El chequeo
91
91
  ahora lo admite en voz alta en vez de dar un ✓ engañoso.
92
- - **ClickUp queda con el mismo hueco de TLS.** `daiFetch` está listo para adoptarse allá
92
+ - **ClickUp queda con el mismo hueco de TLS.** `daiFetch` está listo para adoptarse allí
93
93
  con un import; no lo hicimos ahora por alcance.
94
94
 
95
95
  ## Alternativas descartadas
@@ -0,0 +1,64 @@
1
+ # ADR-0017 — La config de dai vive en `.env.dai`, no en el `.env` del equipo
2
+
3
+ - **Estado:** aceptado
4
+ - **Fecha:** 2026-07-18
5
+ - **Decide:** lead / arquitecto de la metodología
6
+
7
+ ## Contexto
8
+
9
+ dai guarda su config y sus secretos (token del tracker, email, plantilla de URL) en
10
+ variables de entorno, y hasta ahora las escribía en el `.env` del repo, con la premisa de
11
+ que ese `.env` está **gitignored** (por eso `dai init` lo agregaba al `.gitignore` y el
12
+ loader avisaba "NUNCA commitees tokens").
13
+
14
+ Esa premisa se rompe en muchas empresas: **versionan el `.env`** como política (mismas
15
+ variables públicas para todo el equipo y el CI). Pasó de verdad en un repo de frontend
16
+ corporativo: el `.env` estaba trackeado con `VITE_*` públicas, y `dai init`
17
+
18
+ 1. le **inyectaba** sus claves `DAI_*` a un archivo compartido del equipo, y
19
+ 2. le agregaba `.env` al `.gitignore` — inútil, porque git no ignora un archivo ya
20
+ trackeado, y encima confuso (parece que lo protege y no lo hace).
21
+
22
+ El día que un dev completara `DAI_JIRA_TOKEN` en ese `.env` versionado, git lo marcaba
23
+ para commit: **un secreto a un empujón de filtrarse** al historial del repo corporativo.
24
+
25
+ ## Decisión
26
+
27
+ dai deja de tocar el `.env` del equipo. Toda su config vive en archivos **propios**:
28
+
29
+ | Archivo | Versionado | Quién lo maneja | Contenido |
30
+ |---|---|---|---|
31
+ | `.env` | según el equipo | el equipo | dai **no lo escribe**; solo lo **lee** (compat) |
32
+ | `.env.dai` | **no** (gitignored) | cada dev | config + secretos de dai (token, email) |
33
+ | `.env.dai.example` | sí | dai / el equipo | plantilla: mismas claves, valores vacíos |
34
+
35
+ - **`dai init`** crea `.env.dai` (real, ignorado) y `.env.dai.example` (plantilla
36
+ versionada), de forma aditiva, y **nunca** modifica `.env`/`.env.example`.
37
+ - **`reconcileGitignore`** ignora `.env.dai` (su archivo), **no** `.env`: el `.env` del
38
+ equipo es del equipo, y muchas orgs lo versionan a propósito. `.env.dai.example` no
39
+ matchea el patrón exacto `.env.dai`, así que se versiona sin negación extra.
40
+ - **El loader** (`loadDaiEnv`) lee `.env.dai` **y** `.env`. Precedencia:
41
+ **entorno (shell/CI) > `.env.dai` > `.env`**. Se logra cargando `.env.dai` primero,
42
+ porque el loader es "primero-gana". Seguir leyendo `.env` mantiene compatibilidad con
43
+ repos previos que tienen los `DAI_*` ahí — no se rompe nada.
44
+
45
+ ## Consecuencias
46
+
47
+ - **A favor:** dai no ensucia ni pone en riesgo un archivo compartido del equipo. El
48
+ secreto vive en un archivo que git ignora de verdad (no trackeado). Funciona igual en
49
+ equipos que versionan el `.env` y en los que no. Los repos viejos siguen andando (se
50
+ lee `.env`).
51
+ - **En contra:** una convención más de archivos (`.env.dai`, `.env.dai.example`) que
52
+ documentar. Un repo que ya tenía `DAI_*` en un `.env` gitignored puede migrarlos a
53
+ `.env.dai` cuando quiera; no es urgente, porque el loader sigue leyendo `.env`.
54
+ - **Vite:** el nombre `.env.dai` solo lo cargaría Vite con `vite --mode dai` (raro), y
55
+ las claves de dai no llevan prefijo `VITE_`, así que nunca van al bundle del cliente.
56
+
57
+ ## Alternativas descartadas
58
+
59
+ - **Destrackear el `.env`** (`git rm --cached`): rompe la convención del equipo y les saca
60
+ del control de versiones las `VITE_*` públicas que comparten a propósito.
61
+ - **Secreto solo por variable de shell:** anda hoy (el loader no pisa el entorno), pero
62
+ obliga a `source` en cada sesión: fricción para todo el equipo, sin plantilla que guíe.
63
+ - **Seguir usando `.env` y forzar el `.gitignore`:** es justo lo que fallaba — inerte
64
+ sobre un archivo ya trackeado, y peligroso el día que alguien escribe el token.