@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
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <defs><radialGradient id="favc" cx="0.5" cy="0.5" r="0.5">
3
+ <stop offset="0.35" stop-color="#F4B41A"/><stop offset="1" stop-color="#D98E04"/>
4
+ </radialGradient></defs>
5
+ <g fill="url(#favc)"><path d="M50.00 4.00 L52.00 29.00 L48.00 29.00 Z"/><path d="M67.60 7.50 L59.88 31.36 L56.19 29.83 Z"/><path d="M82.53 17.47 L66.26 36.56 L63.44 33.74 Z"/><path d="M92.50 32.40 L70.17 43.81 L68.64 40.12 Z"/><path d="M96.00 50.00 L71.00 52.00 L71.00 48.00 Z"/><path d="M92.50 67.60 L68.64 59.88 L70.17 56.19 Z"/><path d="M82.53 82.53 L63.44 66.26 L66.26 63.44 Z"/><path d="M67.60 92.50 L56.19 70.17 L59.88 68.64 Z"/><path d="M50.00 96.00 L48.00 71.00 L52.00 71.00 Z"/><path d="M32.40 92.50 L40.12 68.64 L43.81 70.17 Z"/><path d="M17.47 82.53 L33.74 63.44 L36.56 66.26 Z"/><path d="M7.50 67.60 L29.83 56.19 L31.36 59.88 Z"/><path d="M4.00 50.00 L29.00 48.00 L29.00 52.00 Z"/><path d="M7.50 32.40 L31.36 40.12 L29.83 43.81 Z"/><path d="M17.47 17.47 L36.56 33.74 L33.74 36.56 Z"/><path d="M32.40 7.50 L43.81 29.83 L40.12 31.36 Z"/></g>
6
+
7
+ <circle cx="50" cy="50" r="19" fill="none" stroke="#74ACDF" stroke-width="2.3"/>
8
+ <circle cx="50" cy="50" r="15" fill="#14305C"/><path d="M43.5 44.9 L39.5 50 L43.5 55.1
9
+ M56.5 44.9 L60.5 50 L56.5 55.1
10
+ M51.8 44.4 L48.2 55.6"
11
+ fill="none" stroke="#EAF4FB" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <defs><radialGradient id="sol-link" cx="0.5" cy="0.5" r="0.5">
3
+ <stop offset="0.35" stop-color="#F4B41A"/><stop offset="1" stop-color="#D98E04"/>
4
+ </radialGradient></defs>
5
+ <g fill="url(#sol-link)"><path d="M50.00 6.00 L51.12 32.00 L48.88 32.00 Z"/><path d="M57.61 11.75 L54.61 32.56 L52.41 32.13 Z"/><path d="M66.84 9.35 L57.92 33.80 L55.85 32.94 Z"/><path d="M71.67 17.57 L60.93 35.66 L59.07 34.41 Z"/><path d="M81.11 18.89 L63.52 38.06 L61.94 36.48 Z"/><path d="M82.43 28.33 L65.59 40.93 L64.34 39.07 Z"/><path d="M90.65 33.16 L67.06 44.15 L66.20 42.08 Z"/><path d="M88.25 42.39 L67.87 47.59 L67.44 45.39 Z"/><path d="M94.00 50.00 L68.00 51.12 L68.00 48.88 Z"/><path d="M88.25 57.61 L67.44 54.61 L67.87 52.41 Z"/><path d="M90.65 66.84 L66.20 57.92 L67.06 55.85 Z"/><path d="M82.43 71.67 L64.34 60.93 L65.59 59.07 Z"/><path d="M81.11 81.11 L61.94 63.52 L63.52 61.94 Z"/><path d="M71.67 82.43 L59.07 65.59 L60.93 64.34 Z"/><path d="M66.84 90.65 L55.85 67.06 L57.92 66.20 Z"/><path d="M57.61 88.25 L52.41 67.87 L54.61 67.44 Z"/><path d="M50.00 94.00 L48.88 68.00 L51.12 68.00 Z"/><path d="M42.39 88.25 L45.39 67.44 L47.59 67.87 Z"/><path d="M33.16 90.65 L42.08 66.20 L44.15 67.06 Z"/><path d="M28.33 82.43 L39.07 64.34 L40.93 65.59 Z"/><path d="M18.89 81.11 L36.48 61.94 L38.06 63.52 Z"/><path d="M17.57 71.67 L34.41 59.07 L35.66 60.93 Z"/><path d="M9.35 66.84 L32.94 55.85 L33.80 57.92 Z"/><path d="M11.75 57.61 L32.13 52.41 L32.56 54.61 Z"/><path d="M6.00 50.00 L32.00 48.88 L32.00 51.12 Z"/><path d="M11.75 42.39 L32.56 45.39 L32.13 47.59 Z"/><path d="M9.35 33.16 L33.80 42.08 L32.94 44.15 Z"/><path d="M17.57 28.33 L35.66 39.07 L34.41 40.93 Z"/><path d="M18.89 18.89 L38.06 36.48 L36.48 38.06 Z"/><path d="M28.33 17.57 L40.93 34.41 L39.07 35.66 Z"/><path d="M33.16 9.35 L44.15 32.94 L42.08 33.80 Z"/><path d="M42.39 11.75 L47.59 32.13 L45.39 32.56 Z"/></g>
6
+
7
+ <circle cx="50" cy="50" r="15.5" fill="none" stroke="#74ACDF" stroke-width="2.3"/>
8
+ <circle cx="50" cy="50" r="12" fill="#14305C"/>
9
+ <line x1="45" y1="50" x2="55" y2="50" stroke="#EAF4FB" stroke-width="2.2" stroke-linecap="round"/>
10
+ <circle cx="45" cy="50" r="2.5" fill="#EAF4FB"/>
11
+ <circle cx="55" cy="50" r="2.5" fill="#EAF4FB"/>
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <defs><radialGradient id="sol-code" cx="0.5" cy="0.5" r="0.5">
3
+ <stop offset="0.35" stop-color="#F4B41A"/><stop offset="1" stop-color="#D98E04"/>
4
+ </radialGradient></defs>
5
+ <g fill="url(#sol-code)"><path d="M50.00 6.00 L51.12 32.00 L48.88 32.00 Z"/><path d="M57.61 11.75 L54.61 32.56 L52.41 32.13 Z"/><path d="M66.84 9.35 L57.92 33.80 L55.85 32.94 Z"/><path d="M71.67 17.57 L60.93 35.66 L59.07 34.41 Z"/><path d="M81.11 18.89 L63.52 38.06 L61.94 36.48 Z"/><path d="M82.43 28.33 L65.59 40.93 L64.34 39.07 Z"/><path d="M90.65 33.16 L67.06 44.15 L66.20 42.08 Z"/><path d="M88.25 42.39 L67.87 47.59 L67.44 45.39 Z"/><path d="M94.00 50.00 L68.00 51.12 L68.00 48.88 Z"/><path d="M88.25 57.61 L67.44 54.61 L67.87 52.41 Z"/><path d="M90.65 66.84 L66.20 57.92 L67.06 55.85 Z"/><path d="M82.43 71.67 L64.34 60.93 L65.59 59.07 Z"/><path d="M81.11 81.11 L61.94 63.52 L63.52 61.94 Z"/><path d="M71.67 82.43 L59.07 65.59 L60.93 64.34 Z"/><path d="M66.84 90.65 L55.85 67.06 L57.92 66.20 Z"/><path d="M57.61 88.25 L52.41 67.87 L54.61 67.44 Z"/><path d="M50.00 94.00 L48.88 68.00 L51.12 68.00 Z"/><path d="M42.39 88.25 L45.39 67.44 L47.59 67.87 Z"/><path d="M33.16 90.65 L42.08 66.20 L44.15 67.06 Z"/><path d="M28.33 82.43 L39.07 64.34 L40.93 65.59 Z"/><path d="M18.89 81.11 L36.48 61.94 L38.06 63.52 Z"/><path d="M17.57 71.67 L34.41 59.07 L35.66 60.93 Z"/><path d="M9.35 66.84 L32.94 55.85 L33.80 57.92 Z"/><path d="M11.75 57.61 L32.13 52.41 L32.56 54.61 Z"/><path d="M6.00 50.00 L32.00 48.88 L32.00 51.12 Z"/><path d="M11.75 42.39 L32.56 45.39 L32.13 47.59 Z"/><path d="M9.35 33.16 L33.80 42.08 L32.94 44.15 Z"/><path d="M17.57 28.33 L35.66 39.07 L34.41 40.93 Z"/><path d="M18.89 18.89 L38.06 36.48 L36.48 38.06 Z"/><path d="M28.33 17.57 L40.93 34.41 L39.07 35.66 Z"/><path d="M33.16 9.35 L44.15 32.94 L42.08 33.80 Z"/><path d="M42.39 11.75 L47.59 32.13 L45.39 32.56 Z"/></g>
6
+
7
+ <circle cx="50" cy="50" r="16" fill="none" stroke="#74ACDF" stroke-width="2.3"/>
8
+ <circle cx="50" cy="50" r="12.8" fill="#14305C"/><path d="M44.5 46.43 L40.5 50 L44.5 53.57
9
+ M55.5 46.43 L59.5 50 L55.5 53.57
10
+ M51.8 45.93 L48.2 54.07"
11
+ fill="none" stroke="#EAF4FB" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"/>
12
+ </svg>
@@ -0,0 +1,93 @@
1
+ # Claves SSH para GitHub y GitLab
2
+
3
+ Guía para generar tu **clave SSH** y registrarla en GitHub y/o GitLab. En dai, **git usa
4
+ SSH** (clonar, `push`, `pull`); los tokens son solo para el forge y el tracker, y **nunca**
5
+ se usa la contraseña ([ADR-0007](../adr/0007-modelo-de-autenticacion.md)). Con la clave
6
+ configurada, `dai pr` puede pushear la rama sin pedirte credenciales.
7
+
8
+ > **Una vez por máquina.** La misma clave sirve para GitHub y GitLab (y para todos tus
9
+ > repos). No necesitas una por proyecto.
10
+
11
+ ---
12
+
13
+ ## Paso 1 — ¿Ya tienes una clave?
14
+
15
+ ```bash
16
+ ls ~/.ssh/id_ed25519.pub
17
+ ```
18
+
19
+ Si el archivo existe, ya tienes clave: salta al **Paso 4**. Si dice *"No such file"*, sigue
20
+ con el paso 2.
21
+
22
+ ---
23
+
24
+ ## Paso 2 — Genera la clave
25
+
26
+ ```bash
27
+ ssh-keygen -t ed25519 -C "tu-correo@ejemplo.com"
28
+ ```
29
+
30
+ - Usa el correo de tu cuenta de GitHub/GitLab.
31
+ - Cuando pregunte la ubicación, acepta la default (Enter).
32
+ - La *passphrase* es opcional pero recomendada (una contraseña que protege la clave).
33
+
34
+ > Si tu sistema es viejo y no soporta `ed25519`, usa `-t rsa -b 4096`.
35
+
36
+ ---
37
+
38
+ ## Paso 3 — Carga la clave en el agente SSH
39
+
40
+ ```bash
41
+ eval "$(ssh-agent -s)" # inicia el agente
42
+ ssh-add ~/.ssh/id_ed25519 # carga tu clave (pide la passphrase si pusiste una)
43
+ ```
44
+
45
+ > **Windows:** usa **Git Bash** para estos comandos, o habilita el servicio *OpenSSH
46
+ > Authentication Agent* de Windows.
47
+
48
+ ---
49
+
50
+ ## Paso 4 — Copia la clave **pública**
51
+
52
+ Nunca compartas la privada (`id_ed25519`). Copia solo la **pública** (`.pub`):
53
+
54
+ ```bash
55
+ cat ~/.ssh/id_ed25519.pub # muestra la clave; copiala entera (empieza con "ssh-ed25519")
56
+ # atajos: macOS → | pbcopy · Windows (Git Bash) → | clip · Linux → | xclip -sel clip
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Paso 5 — Pégala en GitHub y/o GitLab
62
+
63
+ - **GitHub:** *Settings → SSH and GPG keys → New SSH key*. Pega la clave, ponle un título
64
+ (ej. `laptop-trabajo`) y guarda.
65
+ Acceso directo: **https://github.com/settings/ssh/new**
66
+ - **GitLab:** *Preferences → SSH Keys → Add new key*. Pega la clave y guarda. En un GitLab
67
+ **self-hosted/corporativo** entra por la URL de tu instancia
68
+ (`https://gitlab.tu-empresa.com/-/user_settings/ssh_keys`).
69
+
70
+ ---
71
+
72
+ ## Paso 6 — Prueba la conexión
73
+
74
+ ```bash
75
+ ssh -T git@github.com
76
+ # → "Hi <usuario>! You've successfully authenticated..."
77
+
78
+ ssh -T git@gitlab.com
79
+ # (self-hosted: ssh -T git@gitlab.tu-empresa.com)
80
+ ```
81
+
82
+ La primera vez te pregunta si confías en el host: escribí `yes`. Si ves el saludo con tu
83
+ usuario, quedó lista.
84
+
85
+ ---
86
+
87
+ ## Reglas de seguridad
88
+
89
+ - 🔒 **La clave privada nunca sale de tu máquina.** No la pegues en ningún lado, no la
90
+ commitees, no la mandes por chat. Solo se registra la **pública** (`.pub`).
91
+ - 🧯 **Si se compromete tu máquina**, borra la clave pública de GitHub/GitLab (misma
92
+ pantalla del paso 5) y generá una nueva.
93
+ - 👤 Es **por máquina y por persona**: cada dev tiene la suya.
@@ -0,0 +1,53 @@
1
+ # Configurar tu identidad de git
2
+
3
+ Antes de tu primer commit, git necesita saber **quién sos**: cada commit lleva un nombre y
4
+ un correo de autor. Sin configurarlo, los commits salen con un autor vacío o incorrecto, y
5
+ en dai la **autoría siempre es de una persona** — nunca de un bot.
6
+
7
+ > **Una vez por máquina.** Con `--global` queda para todos tus repos.
8
+
9
+ ---
10
+
11
+ ## Paso 1 — Nombre y correo
12
+
13
+ ```bash
14
+ git config --global user.name "Nombre Completo"
15
+ git config --global user.email "tu-correo@ejemplo.com"
16
+ ```
17
+
18
+ > **Usa el mismo correo que tu cuenta de GitHub/GitLab.** Así el forge te **atribuye** los
19
+ > commits (aparecen con tu avatar y cuentan en tu actividad). Si el correo no coincide, los
20
+ > commits quedan "huérfanos", sin vincularse a tu cuenta.
21
+
22
+ ---
23
+
24
+ ## Paso 2 — Verifica
25
+
26
+ ```bash
27
+ git config --global user.name # → Nombre Completo
28
+ git config --global user.email # → tu-correo@ejemplo.com
29
+ git config --global --list # ve toda la config global
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Un correo distinto para un repo puntual
35
+
36
+ Si en un repo específico quieres usar otra identidad (ej. trabajo vs. personal), configúralo
37
+ **sin** `--global`, dentro de ese repo:
38
+
39
+ ```bash
40
+ cd mi-repo
41
+ git config user.email "correo-de-este-repo@ejemplo.com"
42
+ ```
43
+
44
+ La config del repo **gana** sobre la global, solo ahí.
45
+
46
+ ---
47
+
48
+ ## Por qué importa en dai
49
+
50
+ - **Trazabilidad de autoría:** dai ata el QUÉ al CÓMO, y el CÓMO lo firma una persona. Un
51
+ commit con autor mal seteado rompe esa cadena.
52
+ - **El review sale a tu nombre:** cuando `dai-review` postea con tu token, el forge lo
53
+ atribuye a **ti** — tener bien tu identidad es parte de responder por lo que firmas.
@@ -0,0 +1,18 @@
1
+ # Tutoriales
2
+
3
+ Guías de **setup operativo** — lo que haces una vez por máquina para trabajar con dai.
4
+
5
+ ## Preparar el entorno
6
+
7
+ - [**Configurar git**](./configurar-git) — tu identidad (nombre + correo) para que los
8
+ commits te atribuyan.
9
+ - [**Claves SSH**](./claves-ssh) — generar y registrar tu clave en GitHub / GitLab. En dai,
10
+ git usa SSH ([ADR-0007](../adr/0007-modelo-de-autenticacion.md)).
11
+ - [**Instalar gh / glab**](./instalar-glab) — el CLI del forge, para que `dai pr` cree la
12
+ PR/MR.
13
+
14
+ ## Conectar el tracker
15
+
16
+ - [**Token de Jira**](./token-jira) — generar tu token de API de Atlassian (`DAI_PM=jira`).
17
+ - [**Token de ClickUp**](./token-clickup) — generar tu token personal de ClickUp
18
+ (`DAI_PM=clickup`).
@@ -0,0 +1,74 @@
1
+ # Instalar el CLI del forge (`gh` / `glab`) para `dai pr`
2
+
3
+ `dai pr` crea la Pull/Merge Request usando el **CLI del forge**: `gh` para GitHub, `glab`
4
+ para GitLab. dai pushea la rama por **SSH** igual (necesitas las [claves SSH](claves-ssh)),
5
+ pero para **crear la PR/MR** hace falta el CLI autenticado.
6
+
7
+ > **Una vez por máquina.** Instalás el que use tu equipo (o los dos, si trabajás con ambos
8
+ > forges). Sin el CLI, `dai pr` **igual pushea la rama** y te dice qué instalar — después
9
+ > creás la PR a mano desde la web.
10
+
11
+ ---
12
+
13
+ ## GitHub → `gh`
14
+
15
+ ### Instalar
16
+
17
+ ```bash
18
+ brew install gh # macOS
19
+ winget install GitHub.cli # Windows
20
+ sudo apt install gh # Debian/Ubuntu (o ver cli.github.com para tu distro)
21
+ ```
22
+
23
+ ### Autenticar
24
+
25
+ ```bash
26
+ gh auth login
27
+ ```
28
+
29
+ Elige **GitHub.com**, protocolo **SSH** (o HTTPS), y sigue los pasos. Verifica:
30
+
31
+ ```bash
32
+ gh --version
33
+ ```
34
+
35
+ ---
36
+
37
+ ## GitLab → `glab`
38
+
39
+ ### Instalar
40
+
41
+ ```bash
42
+ brew install glab # macOS · o Linux con Homebrew
43
+ winget install GitLab.GLab # Windows (alternativa: scoop install glab)
44
+ sudo pacman -S glab # Arch / Manjaro
45
+ # Debian/Ubuntu y otras distros: el .deb o el binario de https://gitlab.com/gitlab-org/cli/-/releases
46
+ ```
47
+
48
+ ### Autenticar
49
+
50
+ ```bash
51
+ # GitLab.com:
52
+ glab auth login
53
+
54
+ # GitLab self-hosted / corporativo (el --hostname es OBLIGATORIO):
55
+ glab auth login --hostname gitlab.tu-empresa.com
56
+ ```
57
+
58
+ Te va a pedir un **token con scope `api`** (lo generás en *GitLab → Preferences → Access
59
+ Tokens*). Verifica:
60
+
61
+ ```bash
62
+ glab --version
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Notas
68
+
69
+ - 🪟 **Windows:** después de instalar con `winget`/`scoop`, **abre una terminal nueva** para
70
+ que tome el PATH; si no, `glab`/`gh` "no se encuentra".
71
+ - 🔑 **El CLI usa un token del forge** (no la contraseña, no la clave SSH). Git sigue usando
72
+ SSH; el CLI, token — cada uno lo suyo ([ADR-0007](../adr/0007-modelo-de-autenticacion.md)).
73
+ - Con el CLI instalado y autenticado, `dai pr` (o `dai mr` en GitLab) crea la PR/MR
74
+ precargada con la US, el estado de `dai check` y los enlaces.
@@ -0,0 +1,73 @@
1
+ # Cómo obtener el token de API de ClickUp
2
+
3
+ Guía paso a paso para generar tu **token de API personal de ClickUp**, necesario para que
4
+ `dai` (o cualquier script) se autentique contra la REST API de **ClickUp** cuando el tracker
5
+ del repo es ClickUp (`DAI_PM=clickup`).
6
+
7
+ > **¿Por qué un token y no la contraseña?** ClickUp no permite autenticar la API con la
8
+ > contraseña de la cuenta (menos aún con SSO / verificación en dos pasos). El **token
9
+ > personal** cumple ese rol: es una credencial que representa a tu usuario y que tratas
10
+ > **igual que una contraseña**. Empieza siempre con `pk_`.
11
+
12
+ **Atajo:** si quieres saltar los pasos 1 y 2, entra directo a
13
+ 👉 **https://app.clickup.com/settings/apps** (te lleva al paso 3).
14
+
15
+ ---
16
+
17
+ ## Paso 1 — Abre la configuración de tu cuenta
18
+
19
+ En ClickUp, haz clic en tu **avatar** (arriba a la derecha) y elige **Settings**
20
+ (Configuración).
21
+
22
+ ![Menú del avatar → Settings](/tutoriales/clickup-1-settings.png)
23
+
24
+ ---
25
+
26
+ ## Paso 2 — Ve a "API de ClickUp"
27
+
28
+ En la barra lateral de configuración, bajo tu cuenta, entra a la sección **API de ClickUp**.
29
+ Ahí, arriba de todo, verás el bloque **API Token**.
30
+
31
+ ![Barra lateral de Settings → Apps](/tutoriales/clickup-2-api.png)
32
+
33
+ ---
34
+
35
+ ## Paso 3 — Genera o copia el token
36
+
37
+ En **API Token**:
38
+
39
+ - Si es la primera vez, haz clic en **Generate** para crearlo.
40
+ - Si ya tenías uno, aparece oculto con un botón **Copy** (y un **Regenerate** al lado).
41
+
42
+ El token empieza con `pk_` (ej. `pk_1234567_ABCDEFG…`). Haz clic en **Copy** para copiarlo.
43
+
44
+ ![Bloque API Token → Generate / Copy](/tutoriales/clickup-3-generate-copy.png)
45
+
46
+ ---
47
+
48
+ ## Paso 4 — Guárdalo en tu `.env.dai`
49
+
50
+ Pega el token en el `.env.dai` del repo (que **no se versiona**; el `.env` del equipo no se
51
+ toca — [ADR-0017](../adr/0017-env-dai.md)), en la variable que espera dai:
52
+
53
+ ```bash
54
+ DAI_PM=clickup
55
+ DAI_CLICKUP_TOKEN=pk_... # ← tu token, solo el token (sin comillas ni comentarios al lado)
56
+ # DAI_CLICKUP_LIST_ID= # solo hace falta para `dai publish` (crear tareas)
57
+ ```
58
+
59
+ Verifica con `dai doctor` → debería decir **"token de ClickUp presente"**.
60
+
61
+ ---
62
+
63
+ ## Reglas de seguridad (importante)
64
+
65
+ - 🔒 **Trátalo como una contraseña.** Nunca lo pegues en el código, en un commit, en un chat
66
+ ni en el `implements.yaml`. Solo va en `.env.dai` (no versionado).
67
+ - ♻️ **No vence por sí solo** (a diferencia de Jira): queda válido hasta que lo **regeneres**.
68
+ Regenerar crea uno nuevo e **invalida el anterior al instante** — así lo rotas y así cortas
69
+ el acceso de uno filtrado.
70
+ - 👤 **Es personal:** representa a tu usuario, con tus permisos. Cada dev usa el suyo, nunca
71
+ uno compartido.
72
+ - 🧯 **Si se filtra**, entra a la misma pantalla (paso 3) y haz **Regenerate** de inmediato;
73
+ el viejo deja de funcionar y actualizas el `.env.dai` con el nuevo.
@@ -0,0 +1,74 @@
1
+ # Cómo obtener el token de API de Jira (Atlassian)
2
+
3
+ Guía paso a paso para generar un **token de API de Atlassian**, necesario para que `dai`
4
+ (o cualquier script) se autentique contra la REST API de **Jira Cloud** cuando el tracker
5
+ del repo es Jira (`DAI_PM=jira`).
6
+
7
+ > **¿Por qué un token y no la contraseña?** Jira Cloud no permite autenticar la API con la
8
+ > contraseña de la cuenta (menos aún con SSO / verificación en dos pasos). El token cumple
9
+ > ese rol: es una credencial revocable, con vencimiento, que tratas **igual que una
10
+ > contraseña**.
11
+
12
+ **Atajo:** si quieres saltar los pasos 1 y 2, entra directo a
13
+ 👉 **https://id.atlassian.com/manage-profile/security/api-tokens** (te lleva al paso 3).
14
+
15
+ ---
16
+
17
+ ## Paso 1 — Abre la configuración de tu cuenta
18
+
19
+ En Jira, haz clic en tu **avatar** (arriba a la derecha) y elige **Configuración de la cuenta**.
20
+
21
+ ![Menú del avatar → Configuración de la cuenta](/tutoriales/jira-1-avatar.png)
22
+
23
+ ---
24
+
25
+ ## Paso 2 — Ve a Seguridad → Tokens de API
26
+
27
+ En la barra superior, entra a la pestaña **Seguridad**. Baja hasta la sección
28
+ **Tokens de API** y haz clic en **Crear y gestionar tokens de API**.
29
+
30
+ ![Pestaña Seguridad → Crear y gestionar tokens de API](/tutoriales/jira-2-seguridad-tokens.png)
31
+
32
+ ---
33
+
34
+ ## Paso 3 — Crea el token
35
+
36
+ Haz clic en **Crear token de API** (el botón simple, no el de "con alcances").
37
+ Acceso directo => https://id.atlassian.com/manage-profile/security/api-tokens
38
+
39
+ ![Botón Crear token de API](/tutoriales/jira-3-crear-token.png)
40
+
41
+ ---
42
+
43
+ ## Paso 4 — Nombre y vencimiento
44
+
45
+ - **Name:** un nombre que describa para qué es (ej. `dai-frontend`, `dai-backend`).
46
+ - **Caduca el:** una fecha de vencimiento. Por seguridad, Atlassian **no permite más de un
47
+ año**. Pon la fecha máxima si no quieres renovarlo seguido, o una más corta para rotarlo
48
+ antes.
49
+
50
+ Haz clic en **Crear**.
51
+
52
+ ![Formulario: Name + fecha de caducidad](/tutoriales/jira-4-nombre-vencimiento.png)
53
+
54
+ ---
55
+
56
+ ## Paso 5 — Cópialo AHORA (no se recupera después)
57
+
58
+ Atlassian te muestra el token **una sola vez**. Haz clic en **Copiar** y guárdalo en un
59
+ lugar seguro. **Si cierras esta ventana sin copiarlo, no hay forma de recuperarlo** —
60
+ tendrías que crear uno nuevo.
61
+
62
+ ![Ventana Copia tu token de API](/tutoriales/jira-5-copiar.png)
63
+
64
+ ---
65
+
66
+ ## Reglas de seguridad (importante)
67
+
68
+ - 🔒 **Trátalo como una contraseña.** Nunca lo pegues en el código, en un commit, en un chat
69
+ ni en el `implements.yaml`. Solo va en `.env.dai`, que **no se versiona** (el `.env` del
70
+ equipo no se toca; ver [ADR-0017](../adr/0017-env-dai.md)).
71
+ - ♻️ **Rótalo** periódicamente y **revoca** los que no uses (misma pantalla del paso 3, columna
72
+ *Acción → Revocar*).
73
+ - ⏱️ **Vencimiento:** el token deja de funcionar en la fecha que pusiste; anota cuándo renovarlo.
74
+ - 🧯 **Si se filtra**, revócalo de inmediato y crea uno nuevo.
@@ -12,15 +12,45 @@
12
12
 
13
13
  ## Qué valida el CI en cada PR/MR
14
14
 
15
- | Check | Regla | Si falla |
16
- |---|---|---|
17
- | **Link presente** | Toda rama de producto (`feature/ABC-###-*`) tiene `implements.yaml`. | ❌ bloquea el PR |
18
- | **ID válido** | El `id` matchea el formato del gestor (`ABC-\d+`) y el ID existe. | ❌ bloquea |
19
- | **`ac_hash` calculado** | El CI (re)calcula el hash de los criterios de la US y lo compara. | ⚠️ marca atrasado si no coincide |
20
- | **Tests verdes** | La suite de la US pasa. | ❌ bloquea |
21
- | **Estándares** | Lint + tipos + convenciones del repo. | ❌ bloquea |
15
+ Las dos primeras filas **las ejecuta un comando**, no la buena voluntad:
22
16
 
23
- > Ramas `chore/`/`fix/` sin US no requieren `implements.yaml` (ver `branch-naming.md`).
17
+ ```bash
18
+ dai check --ci # salidas: 0 pasa · 1 falta el link · 2 el QUÉ cambió
19
+ ```
20
+
21
+ Hay un workflow listo para copiar en [`templates/ci-dai-gate.yml`](../templates/ci-dai-gate.yml).
22
+ Si tu CI no es GitHub Actions, el contrato es el mismo: un comando y su código de salida.
23
+
24
+ | Check | Regla | Quién lo hace | Si falla |
25
+ |---|---|---|---|
26
+ | **Link presente** | Toda rama de producto (`feature/`) tiene `implements.yaml`. | `dai check --ci` | ❌ bloquea (exit 1) |
27
+ | **`ac_hash` al día** | Recalcula el hash de los criterios de la US viva y lo compara. | `dai check --ci` | ❌ bloquea (exit 2) |
28
+ | **ID resoluble** | El `id` del link existe en el gestor. | `dai check --ci` | ❌ bloquea (exit 2) |
29
+ | **Tests verdes** | La suite de la US pasa. | el CI del repo | ❌ bloquea |
30
+ | **Estándares** | Lint + tipos + convenciones del repo. | el CI del repo | ❌ bloquea |
31
+
32
+ ### Qué ramas quedan exentas
33
+
34
+ Un gate que le exige US a todo se desactiva a la semana, y entonces no protege nada.
35
+ Por eso `dai check --ci` decide **leyendo el nombre de la rama** (`branch-naming.md`):
36
+
37
+ | Prefijo | ¿Exige `implements.yaml`? |
38
+ |---|---|
39
+ | `feature/`, `feat/` | **Sí, siempre** — es trabajo de producto |
40
+ | `chore/`, `docs/`, `ci/`, `build/`, `test/`, `refactor/`, `style/`, `release/`, `hotfix/`, `revert/` | **No** — trabajo sin US |
41
+ | `fix/` y cualquier otro prefijo | **Solo si el nombre trae un ID** (`fix/ABC-482-…`). Sin ID, no |
42
+ | `main`, `develop` (sin prefijo) | No — no es una rama de trabajo |
43
+
44
+ > Si tu PR es una corrección o un chore y el gate te lo bloquea, la respuesta **no** es
45
+ > inventarle una US: es renombrar la rama con el prefijo que corresponde. El nombre de la
46
+ > rama es la declaración de qué tipo de trabajo es.
47
+
48
+ ### Sin credenciales del tracker
49
+
50
+ `dai check --ci --no-network` valida el link y **no** compara contra la US viva. Es el
51
+ default del template: un gate que falla porque un token venció o porque el CI no tiene
52
+ salida a internet enseña al equipo a ignorarlo. Con los secrets cargados, sacá el flag y
53
+ el gate detecta además las US atrasadas.
24
54
 
25
55
  ## Qué hace el CI al mergear
26
56
 
@@ -28,6 +58,15 @@
28
58
  2. **Estampa la cobertura inversa** en el gestor: en el ticket `ABC-###`, deja
29
59
  "implementado por `<repo>` @ `<version>` (`ac_hash`) ✅". **Nadie lo escribe a
30
60
  mano** ([Art. 10](../docs/MANIFIESTO.md#art-10)).
61
+
62
+ ```bash
63
+ dai stamp ABC-482 # explícito: lo que corresponde en CI
64
+ dai stamp # local: deduce la US de la rama; si hay varias, pregunta
65
+ ```
66
+
67
+ > En CI **pasá el ID**. `dai stamp` sin argumentos es para el dev en su máquina:
68
+ > deduce la US del nombre de la rama y, si no puede, pregunta en vez de estampar de
69
+ > más. Un comentario en el tracker no se deshace.
31
70
  3. **Actualiza el índice/router central** de la federación: la fila `ABC-### → { repos }`.
32
71
 
33
72
  ## Qué hace el CD al desplegar (solo N3 · organización grande)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dforce2055/dai",
3
- "version": "0.9.0",
3
+ "version": "0.11.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/",
@@ -32,7 +32,7 @@
32
32
  "skills",
33
33
  "manifest.yaml",
34
34
  "install.sh",
35
- ".env.example",
35
+ ".env.dai.example",
36
36
  "VERSION",
37
37
  "LICENSE",
38
38
  "README.md",
@@ -43,7 +43,13 @@
43
43
  ],
44
44
  "scripts": {
45
45
  "test": "node --test cli/test/*.test.mjs",
46
- "prepublishOnly": "npm test"
46
+ "prepublishOnly": "npm test",
47
+ "docs:dev": "vitepress dev",
48
+ "docs:build": "vitepress build",
49
+ "docs:preview": "vitepress preview"
50
+ },
51
+ "devDependencies": {
52
+ "vitepress": "^1.6.3"
47
53
  },
48
54
  "engines": {
49
55
  "node": ">=18"
@@ -30,7 +30,7 @@ falló. El CLI lo caza antes.
30
30
  ### Cómo postear (elige la primera disponible)
31
31
 
32
32
  1. **`dai forge review <ref> --from <archivo> --yes`** — la forma. Review inline:
33
- resumen + un comentario por línea. Usa `GITHUB_TOKEN`/`GITLAB_TOKEN` del `.env`.
33
+ resumen + un comentario por línea. Usa `GITHUB_TOKEN`/`GITLAB_TOKEN` de `.env.dai` o `.env`.
34
34
  2. **MCP del forge / `dai forge comment`** — fallback si no hay token, o si necesitas
35
35
  dejar un comentario suelto sin anclar. Pierdes el inline y la validación.
36
36
 
@@ -60,11 +60,11 @@ la forma. Nunca reescribas el formato inline.
60
60
  1. **Armar la épica** con el formato de `templates/epica.md`: metadata (`ID`, autor,
61
61
  estado, US que la componen) + objetivo + alcance (in/out) + lista de US + métricas +
62
62
  dependencias.
63
- 2. **Publicar en el tracker.** **No asumas el tracker: lee `DAI_PM` del `.env` primero.**
63
+ 2. **Publicar en el tracker.** **No asumas el tracker: lee `DAI_PM` primero**, de `.env.dai` o `.env` (dai lee los dos; `.env.dai` gana clave por clave).
64
64
  Tres caminos, mismo contenido:
65
65
  - **Con MCP** (`jira` → MCP de Atlassian · `clickup` → MCP de ClickUp): crea el ticket
66
66
  de épica; las US hijas se crean como tickets vinculados (o quedan listadas).
67
- - **Sin MCP, con token** (`DAI_PM=jira` + token en `.env`): escribe la épica como `.md`
67
+ - **Sin MCP, con token** (`DAI_PM=jira` + token en `.env.dai` o `.env`): escribe la épica como `.md`
68
68
  y publícala con **`dai publish <epica.md> --issuetype Epic`**. Devuelve el key. Si el
69
69
  proyecto exige campos propios, van con `--field alias=valor` (los declarados en
70
70
  `.dai/jira-fields.json`; `dai doctor` te los lista). Después, cada US hija se cuelga
@@ -36,7 +36,7 @@ Pull *up* from the story's "I want Y" to the problem underneath, and pressure-te
36
36
  1. **Read** the user story and the constitution.
37
37
  2. **Challenge, one axis at a time.** grill-me discipline: ask, listen, push, move on. Don't dump the five questions at once.
38
38
  3. **Reach a verdict** — `a-spec` (problem survived, go to propose), `reframe` (the real problem is different, back to `grill-user-story`), or `descartar` (not worth solving now, stop and record why).
39
- 4. **Emit** the filled `intent.md` (default location `openspec/intents/<YYYYMMDD-slug>/intent.md`; adjust to where the manifesto puts intents). Embed the tracker ID (the issue/task key — Jira or ClickUp, per `DAI_PM` in the repo's `.env`) and the source story.
39
+ 4. **Emit** the filled `intent.md` (default location `openspec/intents/<YYYYMMDD-slug>/intent.md`; adjust to where the manifesto puts intents). Embed the tracker ID (the issue/task key — Jira or ClickUp, per `DAI_PM` in the repo's `.env.dai` or `.env` — dai reads both, `.env.dai` wins) and the source story.
40
40
 
41
41
  ## Hand-off
42
42