@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.
- package/{.env.example → .env.dai.example} +3 -3
- package/CHANGELOG.md +148 -0
- package/README.md +47 -26
- package/VERSION +1 -1
- package/cli/dai.mjs +528 -61
- package/cli/lib/bootstrap.mjs +44 -9
- package/cli/lib/branch-scope.mjs +144 -0
- package/cli/lib/env.mjs +12 -0
- package/cli/lib/forge-api.mjs +57 -0
- package/cli/lib/pm-adapter.mjs +16 -2
- package/cli/lib/pm-clickup.mjs +18 -3
- package/cli/lib/pm-jira.mjs +23 -3
- package/cli/lib/skills-source.mjs +8 -0
- package/cli/lib/us-format.mjs +147 -0
- package/docs/EJEMPLO-END-TO-END.md +78 -46
- package/docs/MANIFIESTO.md +2 -2
- package/docs/METODOLOGIA.md +25 -15
- package/docs/PROBAR.md +25 -15
- package/docs/SCRUM-CON-IA.md +11 -11
- package/docs/adr/0003-deteccion-y-estampado-son-comandos.md +1 -1
- package/docs/adr/0006-distribucion-y-licencia.md +1 -1
- package/docs/adr/0013-skills-externas-install-from.md +11 -4
- package/docs/adr/0015-jira-corporativo.md +1 -1
- package/docs/adr/0017-env-dai.md +64 -0
- package/docs/adr/0018-alcance-de-stamp-y-gate-de-ci.md +183 -0
- package/docs/adr/README.md +2 -0
- package/docs/detalle/01-refinamiento.md +20 -5
- package/docs/detalle/03-ramas.md +2 -2
- package/docs/detalle/04-tdd.md +15 -9
- package/docs/detalle/06-code-review.md +8 -5
- package/docs/detalle/07-merge-trazabilidad.md +13 -2
- package/docs/detalle/08-daily.md +1 -1
- package/docs/detalle/README.md +1 -1
- package/docs/glosario.md +3 -3
- package/docs/guias/dev.md +31 -7
- package/docs/guias/index.md +12 -0
- package/docs/guias/lead.md +1 -1
- package/docs/guias/po.md +53 -8
- package/docs/index.md +35 -0
- package/docs/public/favicon.svg +12 -0
- package/docs/public/logo-link.svg +12 -0
- package/docs/public/logo.svg +12 -0
- package/docs/public/tutoriales/clickup-1-settings.png +0 -0
- package/docs/public/tutoriales/clickup-2-api.png +0 -0
- package/docs/public/tutoriales/clickup-3-generate-copy.png +0 -0
- package/docs/public/tutoriales/jira-1-avatar.png +0 -0
- package/docs/public/tutoriales/jira-2-seguridad-tokens.png +0 -0
- package/docs/public/tutoriales/jira-3-crear-token.png +0 -0
- package/docs/public/tutoriales/jira-4-nombre-vencimiento.png +0 -0
- package/docs/public/tutoriales/jira-5-copiar.png +0 -0
- package/docs/tutoriales/claves-ssh.md +93 -0
- package/docs/tutoriales/configurar-git.md +53 -0
- package/docs/tutoriales/index.md +18 -0
- package/docs/tutoriales/instalar-glab.md +74 -0
- package/docs/tutoriales/token-clickup.md +73 -0
- package/docs/tutoriales/token-jira.md +74 -0
- package/governance/ci-rules.md +47 -8
- package/package.json +9 -3
- package/skills/dai-review/SKILL.md +1 -1
- package/skills/grill-epic/SKILL.md +2 -2
- package/skills/grill-intent/SKILL.md +1 -1
- package/skills/grill-user-story/SKILL.md +58 -10
- 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>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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.
|
package/governance/ci-rules.md
CHANGED
|
@@ -12,15 +12,45 @@
|
|
|
12
12
|
|
|
13
13
|
## Qué valida el CI en cada PR/MR
|
|
14
14
|
|
|
15
|
-
|
|
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
|
-
|
|
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.
|
|
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`
|
|
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`
|
|
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
|
|