@dforce2055/dai 0.1.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 +30 -0
- package/CHANGELOG.md +46 -0
- package/CODE_OF_CONDUCT.md +37 -0
- package/CONTRIBUTING.md +66 -0
- package/LICENSE +674 -0
- package/README.md +288 -0
- package/SECURITY.md +37 -0
- package/VERSION +1 -0
- package/cli/dai.mjs +692 -0
- package/cli/lib/ac-hash.mjs +74 -0
- package/cli/lib/args.mjs +23 -0
- package/cli/lib/bootstrap.mjs +74 -0
- package/cli/lib/env.mjs +23 -0
- package/cli/lib/forge-api.mjs +96 -0
- package/cli/lib/forge-url.mjs +61 -0
- package/cli/lib/fsutil.mjs +24 -0
- package/cli/lib/implements.mjs +94 -0
- package/cli/lib/link-us.mjs +59 -0
- package/cli/lib/pm-adapter.mjs +59 -0
- package/cli/lib/pm-clickup.mjs +54 -0
- package/cli/lib/pm-jira.mjs +123 -0
- package/cli/lib/pr.mjs +53 -0
- package/cli/lib/us.mjs +36 -0
- package/docs/EJEMPLO-END-TO-END.md +330 -0
- package/docs/MANIFIESTO.md +114 -0
- package/docs/METODOLOGIA.md +254 -0
- package/docs/PROBAR.md +91 -0
- package/docs/SCRUM-CON-IA.md +190 -0
- package/docs/adr/0001-contrato-ac-hash.md +86 -0
- package/docs/adr/0002-agnostico-del-asistente.md +87 -0
- package/docs/adr/0003-deteccion-y-estampado-son-comandos.md +73 -0
- package/docs/adr/0004-ubicacion-y-schema-implements.md +94 -0
- package/docs/adr/0005-superficie-comandos-y-stamp.md +65 -0
- package/docs/adr/0006-distribucion-y-licencia.md +59 -0
- package/docs/adr/0007-modelo-de-autenticacion.md +63 -0
- package/docs/adr/README.md +19 -0
- package/docs/detalle/01-refinamiento.md +33 -0
- package/docs/detalle/02-planning.md +27 -0
- package/docs/detalle/03-ramas.md +32 -0
- package/docs/detalle/04-tdd.md +35 -0
- package/docs/detalle/05-smoke.md +32 -0
- package/docs/detalle/06-code-review.md +34 -0
- package/docs/detalle/07-merge-trazabilidad.md +33 -0
- package/docs/detalle/08-daily.md +29 -0
- package/docs/detalle/09-review.md +25 -0
- package/docs/detalle/10-retro.md +27 -0
- package/docs/detalle/README.md +20 -0
- package/docs/glosario.md +79 -0
- package/docs/guias/dev.md +66 -0
- package/docs/guias/lead.md +53 -0
- package/docs/guias/po.md +50 -0
- package/governance/branch-naming.md +36 -0
- package/governance/ci-rules.md +57 -0
- package/governance/commit-convention.md +76 -0
- package/index.html +479 -0
- package/install.sh +19 -0
- package/manifest.yaml +76 -0
- package/package.json +55 -0
- package/skills/dai-review/SKILL.md +78 -0
- package/skills/doc-to-backlog/SKILL.md +70 -0
- package/skills/doc-to-backlog/templates/backlog-candidato.md +49 -0
- package/skills/grill-epic/SKILL.md +76 -0
- package/skills/grill-intent/SKILL.md +43 -0
- package/skills/grill-intent/templates/intent.md +36 -0
- package/skills/grill-user-story/SKILL.md +76 -0
- package/skills/grill-user-story/templates/user-story.md +61 -0
- package/skills/link-us/SKILL.md +42 -0
- package/skills/link-us/templates/implements.yaml +16 -0
- package/skills/tdd/SKILL.md +109 -0
- package/skills/tdd/deep-modules.md +33 -0
- package/skills/tdd/interface-design.md +31 -0
- package/skills/tdd/mocking.md +59 -0
- package/skills/tdd/refactoring.md +10 -0
- package/skills/tdd/tests.md +61 -0
- package/templates/adr.md +43 -0
- package/templates/commit-msg +48 -0
- package/templates/definition-of-done.md +50 -0
- package/templates/definition-of-ready.md +51 -0
- package/templates/epica.md +62 -0
- package/templates/formato-us.md +129 -0
- package/templates/pull-request.md +62 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# ADR-0002 — La metodología es agnóstica del asistente de IA
|
|
2
|
+
|
|
3
|
+
- **Estado:** aceptado
|
|
4
|
+
- **Fecha:** 2026-07-03
|
|
5
|
+
- **Decide:** lead / arquitecto de la metodología
|
|
6
|
+
|
|
7
|
+
## Contexto
|
|
8
|
+
|
|
9
|
+
Las skills están hoy empaquetadas como **skills de Claude Code** (`SKILL.md` en
|
|
10
|
+
`.claude/skills/`). Pero los equipos usan asistentes distintos: una organización usa
|
|
11
|
+
**GitHub Copilot** (nadie usa Claude), otra usa **Claude Code**. Si atamos la
|
|
12
|
+
metodología a un asistente, dejamos afuera a media empresa — y contradecimos el
|
|
13
|
+
principio rector "sin importar la herramienta de abajo" ([Art. 2](../MANIFIESTO.md#art-2)), que ya aplicamos a
|
|
14
|
+
las herramientas de spec (OpenSpec/Swagger/yml). Falta aplicarlo **una capa más
|
|
15
|
+
arriba**: el asistente de IA.
|
|
16
|
+
|
|
17
|
+
## Decisión
|
|
18
|
+
|
|
19
|
+
Aplicamos el mismo principio al asistente. Una "skill" se separa en tres capas:
|
|
20
|
+
|
|
21
|
+
1. **Contenido portable** — la lógica de interrogación, el formato, los cortes. Se
|
|
22
|
+
escribe **una sola vez**, neutral al asistente. Es la fuente de verdad.
|
|
23
|
+
2. **Acciones deterministas = CLI `dai`** — todo lo mecánico (crear rama,
|
|
24
|
+
generar `implements.yaml`, calcular `ac_hash`, indexar cobertura) vive en el
|
|
25
|
+
**CLI**, no en la inteligencia del asistente. `dai link-us ABC-###` anda igual
|
|
26
|
+
con Claude, con Copilot, o sin ningún asistente. Es la forma más agnóstica de
|
|
27
|
+
garantizar comportamiento determinista: el asistente solo lo **invoca**.
|
|
28
|
+
3. **Adaptadores por asistente (delgados, generados)** — de la Capa 1 se emiten los
|
|
29
|
+
wrappers finos de cada asistente:
|
|
30
|
+
- **Claude Code** → `SKILL.md` en `.claude/skills/`.
|
|
31
|
+
- **Copilot** → `.github/prompts/*.prompt.md` + `.github/copilot-instructions.md`
|
|
32
|
+
(este último auto-inyecta el manifiesto en cada chat del repo).
|
|
33
|
+
|
|
34
|
+
El instalador elige el target: `dai init --for claude` | `--for copilot` | `--for both`.
|
|
35
|
+
Mismo método, misma CLI, distinto wrapper. **`--for` es aditivo, no destructivo**: los
|
|
36
|
+
adaptadores coexisten en el mismo repo (viven en carpetas distintas —
|
|
37
|
+
`.claude/skills/` y `.github/prompts/`— y no se pisan). Un equipo mixto (unos con
|
|
38
|
+
Copilot, otros con Claude) versiona los dos y cada quien usa el suyo. Como lo mecánico
|
|
39
|
+
vive en el CLI, el **output es idéntico** sin importar qué asistente lo disparó: misma
|
|
40
|
+
rama, mismo `implements.yaml`, mismo `ac_hash`. El repo queda consistente aunque el
|
|
41
|
+
equipo esté mezclado.
|
|
42
|
+
|
|
43
|
+
| Capacidad | Naturaleza | Claude Code | Copilot |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `grill-intent`, `grill-user-story` | interrogación (prompt puro) | `SKILL.md` | `*.prompt.md` |
|
|
46
|
+
| `link-us`, `ac-hash`, `coverage` | acción mecánica | wrapper → `dai <cmd>` | prompt/CLI → `dai <cmd>` |
|
|
47
|
+
| el manifiesto y las reglas | contexto siempre presente | `CLAUDE.md` / `project.md` | `.github/copilot-instructions.md` |
|
|
48
|
+
|
|
49
|
+
## Consecuencias
|
|
50
|
+
|
|
51
|
+
- ✅ La misma metodología corre en una organización con Copilot y en una factory con
|
|
52
|
+
Claude — "un protocolo, distinta plomería" aplicado al asistente.
|
|
53
|
+
- ✅ Lo mecánico se vuelve **más confiable**: un CLI determinista no alucina.
|
|
54
|
+
- ✅ Los docs (`MANIFIESTO`, `METODOLOGIA`, guías, glosario) ya eran 100% agnósticos:
|
|
55
|
+
la dualidad solo toca la capa `skills/`.
|
|
56
|
+
- ⚠️ Hay que **construir el CLI `dai`** con los subcomandos mecánicos (hoy esa lógica
|
|
57
|
+
está descrita dentro de las skills de Claude). Es trabajo nuevo.
|
|
58
|
+
- ⚠️ Las capacidades de agente difieren: los prompts puros portan limpio; las
|
|
59
|
+
acciones se apoyan en el CLI. Copilot en modo agente puede correr el CLI; en modo
|
|
60
|
+
chat, el dev lo corre a mano.
|
|
61
|
+
- ⚠️ **Límite de superficie de Copilot (verificado):** los `.github/prompts/*.prompt.md`
|
|
62
|
+
se invocan **solo en VS Code / Visual Studio / JetBrains** (o, como custom agents, en
|
|
63
|
+
el **Copilot CLI**). **No** en la app standalone de Copilot ni en el chat de
|
|
64
|
+
github.com. Claude, en cambio, lee `~/.claude/skills/` tanto en **Claude Code** como
|
|
65
|
+
en **Claude Desktop**. Consecuencia: el analista funcional "sin IDE" cierra con Claude
|
|
66
|
+
Desktop; con Copilot necesita VS Code o el Copilot CLI. Es un límite de Copilot, no de
|
|
67
|
+
dai — el CLI `dai` corre igual en cualquier terminal.
|
|
68
|
+
- ⚠️ Los wrappers se **generan**, no se mantienen a mano — si no, se desincronizan (la misma
|
|
69
|
+
regla de oro del link).
|
|
70
|
+
|
|
71
|
+
**Estado de implementación:** `dai init` es un **scaffolder interactivo** (estilo
|
|
72
|
+
`create-vue`): pregunta asistente (`--for claude|copilot|both`) y gestor
|
|
73
|
+
(`--pm md|clickup|jira`), genera los adaptadores (`.claude/skills/` + `CLAUDE.md`;
|
|
74
|
+
`.github/prompts/*.prompt.md` + `.github/copilot-instructions.md`, transformando los
|
|
75
|
+
`SKILL.md` con `cli/lib/bootstrap.mjs`), deja un `.env` configurado, y cierra con
|
|
76
|
+
próximos pasos. **OpenSpec:** se detecta; si falta, se **ofrece instalarlo**
|
|
77
|
+
(`npm i -g @fission-ai/openspec@latest` + `openspec init`) — no se bundlea (Art. 2).
|
|
78
|
+
Con flags o sin TTY corre no-interactivo (defaults `both`/`md`, OpenSpec solo con `--openspec`).
|
|
79
|
+
|
|
80
|
+
## Alternativas consideradas
|
|
81
|
+
|
|
82
|
+
- **Mantener skills separadas por asistente a mano** — descartado: desincronización garantizada
|
|
83
|
+
al primer cambio (viola Art. 9/Art. 10 aplicados al propio paquete).
|
|
84
|
+
- **Atarse solo a Claude** — descartado: deja afuera a la organización que usa
|
|
85
|
+
Copilot, que es justo uno de los dos casos que el método debe soportar.
|
|
86
|
+
- **Meter toda la lógica mecánica en el asistente (sin CLI)** — descartado: no es
|
|
87
|
+
portable y es menos confiable (el asistente puede alucinar un paso determinista).
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# ADR-0003 — La detección y el estampado son comandos, no infraestructura
|
|
2
|
+
|
|
3
|
+
- **Estado:** aceptado
|
|
4
|
+
- **Fecha:** 2026-07-03
|
|
5
|
+
- **Decide:** lead / arquitecto de la metodología
|
|
6
|
+
|
|
7
|
+
## Contexto
|
|
8
|
+
|
|
9
|
+
El ADR-0001 dice que la **autoridad** de la detección de atrasos es "el CI, que
|
|
10
|
+
re-deriva el `ac_hash` de la US viva y compara". Leído literal, suena a que hace
|
|
11
|
+
falta **montar un CI que corra del lado de Jira/ClickUp** antes de poder usar la
|
|
12
|
+
metodología — infraestructura pesada, y una barrera de entrada que contradice el
|
|
13
|
+
[Art. 14](../MANIFIESTO.md#art-14) (*no adelantar complejidad*).
|
|
14
|
+
|
|
15
|
+
Además, un equipo que ya está en escala N3 (organización grande federada; los niveles
|
|
16
|
+
N1/N2/N3 están en el [glosario](../glosario.md)) puede **no tener** todavía esa
|
|
17
|
+
automatización. La trazabilidad federada tiene que funcionar igual, de forma
|
|
18
|
+
**distribuida**, sin depender de que exista un pipeline corriendo.
|
|
19
|
+
|
|
20
|
+
El malentendido está en la palabra "CI". Jira/ClickUp **no ejecutan** nada: solo
|
|
21
|
+
**guardan** la US. La detección es comparar dos hashes — eso es un **comando**, no
|
|
22
|
+
un servidor.
|
|
23
|
+
|
|
24
|
+
## Decisión
|
|
25
|
+
|
|
26
|
+
La trazabilidad se expone como **comandos del CLI `dai`**, invocables por un humano
|
|
27
|
+
o por un CI indistintamente (mismo binario, mismo output — ADR-0002):
|
|
28
|
+
|
|
29
|
+
| Comando | Naturaleza | Qué hace |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `dai ac-hash <us>` | puro | calcula el hash de los criterios (ADR-0001). |
|
|
32
|
+
| `dai check` | **read-only** | lee el `implements.yaml` del repo + la US viva, re-deriva el hash y **compara**. Reporta al día / ⚠️ atrasado. Exit code ≠ 0 si hay atraso → sirve de **gate de PR**. **No escribe nada.** |
|
|
33
|
+
| `dai stamp` | **write** | calcula la cobertura derivada y la **escribe en el tracker** (la trazabilidad inversa del Art. 10: "`<repo>` @ `<version>` ✅/⚠️"). Requiere token de escritura. |
|
|
34
|
+
|
|
35
|
+
**El tracker solo almacena y sirve la US.** La lógica corre donde se invoca el
|
|
36
|
+
comando: la máquina del dev, un git-hook, o un pipeline.
|
|
37
|
+
|
|
38
|
+
### Modo distribuido (sin infraestructura) vs automático
|
|
39
|
+
|
|
40
|
+
- **Distribuido (default, N1–N2 y N3 sin CI):** el dev corre `dai check` cuando
|
|
41
|
+
quiere saber si está atrasado, y `dai stamp` después de mergear para publicar su
|
|
42
|
+
cobertura. **Cero infraestructura nueva.** Depende de disciplina (alguien tiene
|
|
43
|
+
que correr `dai stamp`), mitigable con un git-hook local.
|
|
44
|
+
- **Automático (N3 maduro):** el CI que la organización **ya tiene** corre
|
|
45
|
+
`dai check` como gate y `dai stamp` al mergear. La automatización es, literalmente,
|
|
46
|
+
*"correr los mismos comandos en un hook"* — no hay un código distinto.
|
|
47
|
+
|
|
48
|
+
Pasar de distribuido a automático es mover la invocación, no reescribir nada.
|
|
49
|
+
|
|
50
|
+
## Consecuencias
|
|
51
|
+
|
|
52
|
+
- ✅ **No hace falta ningún CI para empezar.** La metodología arranca con un dev
|
|
53
|
+
tipeando `dai check` / `dai stamp`. El [Art. 14](../MANIFIESTO.md#art-14) queda respetado.
|
|
54
|
+
- ✅ **Rampa de adopción continua:** manual → git-hook → CI, siempre el mismo comando.
|
|
55
|
+
- ✅ **Honra el [Art. 10](../MANIFIESTO.md#art-10):** el humano *dispara* la derivación; no *escribe a mano* el
|
|
56
|
+
contenido (eso sigue prohibido). Un `dai stamp` corrido por una persona escribe lo
|
|
57
|
+
mismo que uno corrido por el CI.
|
|
58
|
+
- ✅ Un equipo N3 sin pipeline tiene trazabilidad federada **distribuida** ya mismo.
|
|
59
|
+
- ⚠️ En modo distribuido, `dai stamp` depende de que alguien lo corra. `dai check`
|
|
60
|
+
como git-hook o gate de PR reduce el riesgo de olvido.
|
|
61
|
+
- ⚠️ Ambos comandos necesitan **leer** la US viva (y `dai stamp`, escribir): eso es el
|
|
62
|
+
adaptador de PM (Jira/ClickUp/`.md`), ya implementado en `getAdapter`. Es un token +
|
|
63
|
+
llamadas HTTP, **no** un CI.
|
|
64
|
+
|
|
65
|
+
## Alternativas consideradas
|
|
66
|
+
|
|
67
|
+
- **Exigir un CI corriendo en Jira/ClickUp** — descartado: barrera de entrada que
|
|
68
|
+
contradice el [Art. 14](../MANIFIESTO.md#art-14) y que además es un fantasma (el tracker no ejecuta nada).
|
|
69
|
+
- **Estampar la cobertura a mano en el tracker** — descartado: viola el [Art. 10](../MANIFIESTO.md#art-10) (el
|
|
70
|
+
contenido debe derivarse, no escribirse a mano) y se desincroniza.
|
|
71
|
+
- **Un solo comando que compare y escriba a la vez** — descartado: separar `check`
|
|
72
|
+
(read-only, gate) de `stamp` (write) permite usar `check` como gate de PR sin
|
|
73
|
+
permisos de escritura, y correr `stamp` solo cuando corresponde.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# ADR-0004 — Ubicación y schema del `implements.yaml`
|
|
2
|
+
|
|
3
|
+
- **Estado:** aceptado
|
|
4
|
+
- **Fecha:** 2026-07-03
|
|
5
|
+
- **Decide:** lead / arquitecto de la metodología
|
|
6
|
+
|
|
7
|
+
## Contexto
|
|
8
|
+
|
|
9
|
+
El `implements.yaml` es el **único registro autorado** del link QUÉ↔CÓMO ([Art. 9](../MANIFIESTO.md#art-9)).
|
|
10
|
+
Para que `link-us` lo scaffoldee y `dai check`/`stamp` lo parseen, hay que congelar
|
|
11
|
+
**dónde vive** y **qué campos tiene**. Cierra la decisión abierta de METODOLOGIA §7 sobre el formato del link.
|
|
12
|
+
|
|
13
|
+
Dos requisitos duros (Art. 9): vive **en el repo de código** y está **versionado por
|
|
14
|
+
git** — así el `ac_hash` estampado viaja con el commit y el link es revisable en el PR.
|
|
15
|
+
|
|
16
|
+
## Decisión
|
|
17
|
+
|
|
18
|
+
### Ubicación
|
|
19
|
+
|
|
20
|
+
- **Co-localizado con la unidad de trabajo** (una US = una capacidad entera = un
|
|
21
|
+
`implements.yaml`). Default usando OpenSpec: `openspec/changes/<change-id>/implements.yaml`.
|
|
22
|
+
|
|
23
|
+
El `implements.yaml` vive **junto a los artefactos de OpenSpec** del change, no aparte:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
openspec/
|
|
27
|
+
└── changes/
|
|
28
|
+
└── finalizar-compra/ # el change = el CÓMO (una US = una capacidad entera)
|
|
29
|
+
├── proposal.md # opsx:propose · qué se propone y por qué
|
|
30
|
+
├── design.md # opsx:propose · el diseño técnico
|
|
31
|
+
├── tasks.md # opsx:propose · las tareas (se implementan con TDD)
|
|
32
|
+
├── specs/ # opsx:propose · las deltas de spec
|
|
33
|
+
│ └── carrito/
|
|
34
|
+
│ └── spec.md
|
|
35
|
+
└── implements.yaml # ★ dai link-us · el link QUÉ↔CÓMO (id + @version + ac_hash)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Los tres primeros los genera **OpenSpec** (`opsx:propose`); el `implements.yaml` lo agrega
|
|
39
|
+
**dai** (`link-us`) en la misma carpeta. Al archivar, el change entero (incluido el
|
|
40
|
+
`implements.yaml`) se mueve a `openspec/changes/archive/` y **sigue contando** para la cobertura.
|
|
41
|
+
|
|
42
|
+
- **Tool-agnóstico por descubrimiento (Art. 2):** `dai` **no** hardcodea la ruta de
|
|
43
|
+
OpenSpec. Hace un glob de `**/implements.yaml` (excluyendo `node_modules`, `dist`,
|
|
44
|
+
etc.). Un equipo con Swagger u otra herramienta lo pone donde quiera y `dai` lo
|
|
45
|
+
encuentra.
|
|
46
|
+
- **Incluye archivados:** el glob abarca `openspec/changes/archive/**` — un change
|
|
47
|
+
archivado sigue vivo en el código, así que **cuenta** para la cobertura.
|
|
48
|
+
- **La lista de "qué implementa el repo" es derivada**, no un manifiesto a mano: se
|
|
49
|
+
arma escaneando los `implements.yaml` co-localizados (Art. 10).
|
|
50
|
+
|
|
51
|
+
### Schema
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
change: finalizar-compra # identidad del CÓMO (nombre local del change/spec).
|
|
55
|
+
# Explícito, NO derivado del path → sobrevive al archivado.
|
|
56
|
+
repo: frontend # repo donde vive.
|
|
57
|
+
|
|
58
|
+
implements: # FORWARD: qué QUÉ cumple este change (capacidad entera).
|
|
59
|
+
- id: ABC-482 # ticket de Jira/ClickUp (identidad del QUÉ). No se tipea: lo pone link-us.
|
|
60
|
+
version: v1 # spec_version de la US al implementar (nº legible).
|
|
61
|
+
ac_hash: 7f3a9c2e # snapshot del hash de criterios (lo calcula `dai ac-hash`).
|
|
62
|
+
|
|
63
|
+
introduces: # specs técnicas nuevas que crea este change (opcional).
|
|
64
|
+
- guard-carrito-vacio
|
|
65
|
+
|
|
66
|
+
autor: D. Force (dev) # quién implementa.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `change` y `repo` son obligatorios y hacen el registro **auto-contenido**: `dai stamp`
|
|
70
|
+
puede reportar "ABC-482 ← frontend/finalizar-compra @v1" sin parsear rutas.
|
|
71
|
+
- `implements` es una lista (un change podría cumplir más de un QUÉ, aunque el default
|
|
72
|
+
es uno — capacidad entera, §2.6).
|
|
73
|
+
- El link es **dirigido CÓMO→QUÉ**; la inversa (QUÉ→CÓMO en Jira) la deriva `dai stamp`.
|
|
74
|
+
|
|
75
|
+
## Consecuencias
|
|
76
|
+
|
|
77
|
+
- ✅ `link-us` tiene molde exacto para generar; `check`/`stamp` tienen contrato para
|
|
78
|
+
parsear.
|
|
79
|
+
- ✅ Registro auto-contenido → robusto al archivado y a mover carpetas.
|
|
80
|
+
- ✅ Independiente de OpenSpec: la ubicación es convención, el descubrimiento es glob.
|
|
81
|
+
- ⚠️ El glob debe excluir directorios ruidosos (`node_modules`, `dist`, `vendor`) para no
|
|
82
|
+
escanear de más.
|
|
83
|
+
- ⚠️ Si un repo tuviera dos `implements.yaml` con el mismo `change`, es un error a
|
|
84
|
+
detectar (identidad duplicada).
|
|
85
|
+
|
|
86
|
+
## Alternativas consideradas
|
|
87
|
+
|
|
88
|
+
- **Un manifiesto único en la raíz (`.dai/implements.yaml`)** — descartado: archivo
|
|
89
|
+
compartido que todos editan (conflictos de merge), y pierde la co-localización que
|
|
90
|
+
hace el diff del PR revisable.
|
|
91
|
+
- **Derivar la identidad del CÓMO del path de la carpeta** — descartado: se rompe al
|
|
92
|
+
archivar/mover; mejor un campo `change` explícito.
|
|
93
|
+
- **Registrar el mapping también a mano en Jira** — descartado: sería un tercer
|
|
94
|
+
registro que se desincroniza; la inversa se deriva (Art. 10).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# ADR-0005 — Superficie de comandos del CLI y contenido del stamp
|
|
2
|
+
|
|
3
|
+
- **Estado:** aceptado
|
|
4
|
+
- **Fecha:** 2026-07-03
|
|
5
|
+
- **Decide:** lead / arquitecto de la metodología
|
|
6
|
+
|
|
7
|
+
## Contexto
|
|
8
|
+
|
|
9
|
+
Los ADR-0001/0003/0004 definieron el hash, el modelo de detección y el schema del
|
|
10
|
+
`implements.yaml`. Falta congelar **qué comandos** expone `dai` para la trazabilidad
|
|
11
|
+
y **qué estampa** exactamente `dai stamp` en el tracker (que es el router de Nivel-1,
|
|
12
|
+
§2.5, y por lo tanto debe llevar links a la implementación).
|
|
13
|
+
|
|
14
|
+
## Decisión
|
|
15
|
+
|
|
16
|
+
### Superficie de comandos de trazabilidad
|
|
17
|
+
|
|
18
|
+
| Comando | Acceso | Qué hace |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `dai ac-hash <us>` | local | calcula el hash de criterios (ADR-0001). |
|
|
21
|
+
| `dai ls [--json]` | **local, offline** | escanea `**/implements.yaml`, lista las US que implementa el repo + su link al tracker. Base de los otros dos. |
|
|
22
|
+
| `dai check` | lee la US viva | `ls` + trae la US + compara hashes → al día / ⚠️ atrasado. Exit ≠ 0 si atraso (gate de PR). |
|
|
23
|
+
| `dai stamp` | escribe al tracker | `ls` + trae la US + **escribe la cobertura** (inversa, [Art. 10](../MANIFIESTO.md#art-10)). |
|
|
24
|
+
|
|
25
|
+
`check` y `stamp` se construyen sobre `ls` (un solo lugar descubre y parsea).
|
|
26
|
+
|
|
27
|
+
### Contenido del stamp (el router necesita links)
|
|
28
|
+
|
|
29
|
+
`dai stamp` escribe en el ticket, por cada repo/change que lo implementa:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
repo: <nombre> → <repo web url>
|
|
33
|
+
branch: <branch> → <branch url> ← link principal (legible)
|
|
34
|
+
commit: <sha> → <commit url> ← ANCLA durable (sobrevive al borrado de branch)
|
|
35
|
+
version: <v> (<ac_hash>) → ✅ al día | ⚠️ atrasado
|
|
36
|
+
autor: <dev>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Los links se derivan de git, sin API del forge ni `--pr`:**
|
|
40
|
+
- repo/branch/commit salen de `git remote get-url origin` + `git rev-parse`.
|
|
41
|
+
- La URL web es **específica del forge** (GitHub `/tree/` `/commit/`; GitLab `/-/tree/`
|
|
42
|
+
`/-/commit/`; Bitbucket `/src/` `/commits/`): `dai` mapea forge→esquema por el host
|
|
43
|
+
del remoto.
|
|
44
|
+
|
|
45
|
+
**Branch + commit-ancla:** la branch es el link legible, pero se borra al mergear; el
|
|
46
|
+
commit es permanente. Guardar los dos evita que el router quede en 404.
|
|
47
|
+
|
|
48
|
+
## Consecuencias
|
|
49
|
+
|
|
50
|
+
- ✅ Trazabilidad completa sin API del forge ni flags manuales: todo se deriva de git.
|
|
51
|
+
- ✅ El router (§2.5) siempre tiene un link vivo (el commit) → nunca dead-link.
|
|
52
|
+
- ✅ `dai ls` es offline y read-only → sirve de base barata para todo lo demás.
|
|
53
|
+
- ⚠️ Construir la URL web es forge-específico → lógica a testear (SSH/HTTPS, 3 forges).
|
|
54
|
+
- ⚠️ `dai stamp` (write) y `dai check` (read US viva) dependen del **adaptador de PM**
|
|
55
|
+
(`getAdapter`, ya implementado). Para el backend `md`, `stamp --format md` emite el bloque para
|
|
56
|
+
pegar a mano (mismo fallback que `grill-user-story`).
|
|
57
|
+
|
|
58
|
+
## Alternativas consideradas
|
|
59
|
+
|
|
60
|
+
- **Link a la PR/MR** — descartado: no es derivable localmente sin API del forge, y en
|
|
61
|
+
modo distribuido genera fricción (`--pr`). La branch+commit se derivan de git solo.
|
|
62
|
+
- **Solo la branch** — descartado: la branch se borra al mergear → 404. El commit es la
|
|
63
|
+
ancla durable.
|
|
64
|
+
- **Solo el commit** — viable pero menos legible; la branch le da contexto humano.
|
|
65
|
+
Guardamos los dos.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ADR-0006 — Distribución y licencia
|
|
2
|
+
|
|
3
|
+
- **Estado:** aceptado
|
|
4
|
+
- **Fecha:** 2026-07-03
|
|
5
|
+
- **Decide:** autor / mantenedor
|
|
6
|
+
|
|
7
|
+
## Contexto
|
|
8
|
+
|
|
9
|
+
`dai` va a distribuirse para que **la comunidad lo use y lo mejore**. Hay que fijar
|
|
10
|
+
dos cosas: bajo qué **licencia** se libera, y por qué **canales** se distribuye. El
|
|
11
|
+
CLI es Node **cero dependencias**, lo que abre canales que no todos los proyectos
|
|
12
|
+
tienen (correr sin `npm install`).
|
|
13
|
+
|
|
14
|
+
## Decisión
|
|
15
|
+
|
|
16
|
+
### Licencia: GPLv3 (`GPL-3.0-or-later`)
|
|
17
|
+
|
|
18
|
+
El objetivo es *libre + que la comunidad ayude a mejorarla*. La garantía **legal**
|
|
19
|
+
más fuerte de eso es el **copyleft**: quien distribuya un `dai` modificado debe
|
|
20
|
+
publicar sus cambios bajo la misma licencia. La GPL convierte "las mejoras vuelven"
|
|
21
|
+
en cláusula, no en deseo.
|
|
22
|
+
|
|
23
|
+
El downside típico de la GPL **no aplica** acá: `dai` es un **CLI que se ejecuta**,
|
|
24
|
+
no una librería que se embebe. Usar `dai` sobre tu código —aunque sea propietario y
|
|
25
|
+
comercial— **no genera ninguna obligación**; el copyleft solo se activa si alguien
|
|
26
|
+
**forkea y redistribuye** una versión modificada. Y *libre ≠ gratis*: se puede
|
|
27
|
+
cobrar por uso, soporte o desarrollo sobre `dai`.
|
|
28
|
+
|
|
29
|
+
- SPDX: **`GPL-3.0-or-later`** (recomendación FSF: "v3 o posterior"). Si se prefiere
|
|
30
|
+
fijar solo v3, cambiar a `GPL-3.0-only`.
|
|
31
|
+
- El texto íntegro va en `LICENSE` (copia verbatim de gnu.org).
|
|
32
|
+
- Los **docs/metodología** quedan cubiertos por la misma licencia por ahora; a
|
|
33
|
+
futuro podrían migrar a **CC BY-SA** (el copyleft equivalente para texto).
|
|
34
|
+
|
|
35
|
+
### Distribución
|
|
36
|
+
|
|
37
|
+
- **npm público** como canal principal (el CLI es cero-dep → `npx dai …` anda sin
|
|
38
|
+
instalar nada).
|
|
39
|
+
- **git-clone + `install.sh`** y **tarball** como fallback para **redes corporativas
|
|
40
|
+
cerradas** (proxy/firewall que bloquea el registry).
|
|
41
|
+
- Se saca `"private": true` del `package.json` para habilitar la publicación.
|
|
42
|
+
|
|
43
|
+
## Consecuencias
|
|
44
|
+
|
|
45
|
+
- ✅ Los forks públicos de `dai` quedan abiertos para siempre → el commons crece.
|
|
46
|
+
- ✅ Cualquier empresa puede *usar* `dai` sin obligaciones (es un CLI).
|
|
47
|
+
- ✅ El canal cero-dep + fallback cubre tanto factories abiertas como orgs cerradas.
|
|
48
|
+
- ⚠️ `dai` no se podrá **embeber** como librería dentro de software propietario. Si
|
|
49
|
+
alguna vez hace falta eso, se evaluaría relicenciar una parte como LGPL/MIT.
|
|
50
|
+
- ⚠️ Publicar en npm hace el código **público** — nada de secretos en el repo (ya lo
|
|
51
|
+
cubre `.gitignore` + `.env`).
|
|
52
|
+
|
|
53
|
+
## Alternativas consideradas
|
|
54
|
+
|
|
55
|
+
- **MIT / Apache-2.0 (permisivas)** — máxima adopción y fricción cero, pero **no**
|
|
56
|
+
obligan a devolver mejoras: se depende de la buena voluntad. Descartadas frente al
|
|
57
|
+
objetivo explícito de "que la comunidad ayude a mejorarla".
|
|
58
|
+
- **AGPLv3** — extiende el copyleft al uso como servicio en red. Overkill para un CLI
|
|
59
|
+
local; se descarta salvo que aparezca un caso SaaS.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# ADR-0007 — Modelo de autenticación
|
|
2
|
+
|
|
3
|
+
- **Estado:** aceptado
|
|
4
|
+
- **Fecha:** 2026-07-03
|
|
5
|
+
- **Decide:** lead / arquitecto + mantenedor
|
|
6
|
+
|
|
7
|
+
## Contexto
|
|
8
|
+
|
|
9
|
+
`dai` y sus skills tocan **tres** sistemas externos: los repos de código (git), el
|
|
10
|
+
forge (GitHub/GitLab, para comentar PRs), y el tracker (Jira/ClickUp). Cada uno se
|
|
11
|
+
autentica distinto. Ahora que hay tokens en juego (`dai forge`, adaptador de PM),
|
|
12
|
+
hay que fijar un modelo de auth **antes** de seguir sumando credenciales — para no
|
|
13
|
+
terminar con contraseñas hardcodeadas o secretos en un commit.
|
|
14
|
+
|
|
15
|
+
Principio rector: **least privilege, sin contraseñas, secretos nunca versionados.**
|
|
16
|
+
|
|
17
|
+
## Decisión
|
|
18
|
+
|
|
19
|
+
### Tres credenciales, tres mecanismos (no se mezclan)
|
|
20
|
+
|
|
21
|
+
| Sistema | Acción | Credencial | Dónde vive |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| **git** | clone / fetch / push | **SSH key** (ssh-agent) | `~/.ssh` — **nunca** en `.env` ni en el repo |
|
|
24
|
+
| **forge** | leer/comentar PR/MR | **token scopeado** (`GITHUB_TOKEN` / `GITLAB_TOKEN`) | `.env` (gitignored) o secret store del CI |
|
|
25
|
+
| **tracker** | leer/escribir US y cobertura | **api_key** (`DAI_JIRA_TOKEN` / `DAI_CLICKUP_TOKEN`) | `.env` o secret store del CI |
|
|
26
|
+
|
|
27
|
+
### Reglas
|
|
28
|
+
|
|
29
|
+
1. **Nada de contraseñas.** Ni para git (SSH), ni para las APIs (tokens scopeados y
|
|
30
|
+
revocables). Prohibido el patrón `https://user:password@host`.
|
|
31
|
+
2. **git es SSH.** El transporte de git (incluido lo que haga un agente o el CLI)
|
|
32
|
+
usa SSH. Comentar una PR **no** se hace por SSH (SSH solo mueve objetos git): eso
|
|
33
|
+
es API del forge → token.
|
|
34
|
+
3. **Least privilege.** El token del forge se limita al scope mínimo (PRs/notes), no
|
|
35
|
+
un PAT con acceso total. Igual para el tracker.
|
|
36
|
+
4. **Secretos fuera del repo.** Solo en `.env` (gitignored) o el secret store del CI.
|
|
37
|
+
Nunca en el código, ni en `implements.yaml`, ni en un commit. `.env.example`
|
|
38
|
+
documenta los **nombres** de las variables, jamás los valores.
|
|
39
|
+
5. **Dos caras (ADR-0002).** Las **skills** usan el **MCP** del asistente (que guarda
|
|
40
|
+
sus propias credenciales); el **CLI** usa los **tokens del `.env`**. Nunca se
|
|
41
|
+
comparten ni se filtra uno al otro.
|
|
42
|
+
6. **Variables de entorno ganan.** Un token exportado en la shell/CI pisa al `.env`
|
|
43
|
+
(para que el CI inyecte secretos sin escribir archivos).
|
|
44
|
+
|
|
45
|
+
## Consecuencias
|
|
46
|
+
|
|
47
|
+
- ✅ Superficie de secretos mínima y auditable: SSH keys + tokens scopeados, cero
|
|
48
|
+
contraseñas.
|
|
49
|
+
- ✅ `.gitignore` + `.env.example` ya hacen cumplir "secretos fuera del repo".
|
|
50
|
+
- ✅ Rotar/revocar es trivial: son tokens, no contraseñas de cuenta.
|
|
51
|
+
- ⚠️ Requiere que cada dev tenga su SSH key configurada (ssh-agent) — es el costo de
|
|
52
|
+
no usar contraseñas. Se documenta en el onboarding.
|
|
53
|
+
- ⚠️ En el CI hay que cargar los tokens desde su secret store, no desde un `.env`
|
|
54
|
+
commiteado (que no existe).
|
|
55
|
+
|
|
56
|
+
## Alternativas consideradas
|
|
57
|
+
|
|
58
|
+
- **Contraseña / PAT embebido en la URL de git** — descartado: viola "sin
|
|
59
|
+
contraseñas", y termina en el `~/.git-credentials` o en un remoto commiteado.
|
|
60
|
+
- **Un único super-token para todo** — descartado: rompe least privilege; si se
|
|
61
|
+
filtra, se filtra todo. Un token por sistema y por scope.
|
|
62
|
+
- **Que el CLI use el MCP del asistente** — imposible: el CLI corre standalone, no
|
|
63
|
+
tiene acceso al MCP. Por eso el CLI usa tokens propios (dos caras).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# ADRs — decisiones de fondo de la metodología
|
|
2
|
+
|
|
3
|
+
Registro de las decisiones estructurales de `dai`. Cada ADR es **inmutable**: si una
|
|
4
|
+
decisión cambia, se escribe un ADR nuevo que supersede al viejo. Molde en
|
|
5
|
+
[`templates/adr.md`](../../templates/adr.md).
|
|
6
|
+
|
|
7
|
+
| # | Decisión | Estado |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| [0001](0001-contrato-ac-hash.md) | El contrato del `ac_hash` (normalización + SHA-256, tres momentos) | aceptado |
|
|
10
|
+
| [0002](0002-agnostico-del-asistente.md) | La metodología es agnóstica del asistente (Claude / Copilot) | aceptado |
|
|
11
|
+
| [0003](0003-deteccion-y-estampado-son-comandos.md) | La detección y el estampado son comandos (`dai check` / `dai stamp`), no infraestructura | aceptado |
|
|
12
|
+
| [0004](0004-ubicacion-y-schema-implements.md) | Ubicación (co-localizado + glob) y schema del `implements.yaml` | aceptado |
|
|
13
|
+
| [0005](0005-superficie-comandos-y-stamp.md) | Superficie de comandos (`ls`/`check`/`stamp`) y contenido del stamp (branch + commit-ancla) | aceptado |
|
|
14
|
+
| [0006](0006-distribucion-y-licencia.md) | Distribución (npm + fallback) y licencia (GPLv3) | aceptado |
|
|
15
|
+
| [0007](0007-modelo-de-autenticacion.md) | Modelo de auth: SSH para git, tokens scopeados para forge/tracker, sin contraseñas | aceptado |
|
|
16
|
+
|
|
17
|
+
> Estas son las decisiones que cierran las "Decisiones abiertas" de
|
|
18
|
+
> [`METODOLOGIA.md §7`](../METODOLOGIA.md) y las enmiendas al
|
|
19
|
+
> [`MANIFIESTO.md`](../MANIFIESTO.md).
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Paso 1 — Refinamiento: de la idea vaga a la US testeable
|
|
2
|
+
|
|
3
|
+
← vuelve a [`SCRUM-CON-IA.md`](../SCRUM-CON-IA.md)
|
|
4
|
+
|
|
5
|
+
## En qué consiste en detalle
|
|
6
|
+
|
|
7
|
+
El PO llega con una idea (a veces un ticket de una línea). Antes de escribir specs,
|
|
8
|
+
la IA hace dos cosas, en orden:
|
|
9
|
+
|
|
10
|
+
1. **Gate 0** (`grill-intent`) — desafía el *problema*, no la solución. Veredicto:
|
|
11
|
+
`a-spec` (seguir), `reframe` (el problema real es otro) o `descartar` (no vale la
|
|
12
|
+
pena ahora). Un "no lo construyas" es un éxito del gate, no una falla.
|
|
13
|
+
2. **Pulido** (`grill-user-story`) — interroga hasta que la US es **testeable por
|
|
14
|
+
construcción** (INVEST + Gherkin) y la publica en el tracker.
|
|
15
|
+
|
|
16
|
+
## Herramientas
|
|
17
|
+
|
|
18
|
+
- `/grill-intent` → `openspec/intents/<fecha-slug>/intent.md`
|
|
19
|
+
- `/grill-user-story` → US en formato [`formato-us.md`](../../templates/formato-us.md),
|
|
20
|
+
publicada en Jira/ClickUp (o `.md` de fallback).
|
|
21
|
+
- Gate de entrada: [`definition-of-ready.md`](../../templates/definition-of-ready.md).
|
|
22
|
+
|
|
23
|
+
## Qué firma el humano
|
|
24
|
+
|
|
25
|
+
El PO **responde y decide**. La IA no inventa requerimientos: los saca a preguntas
|
|
26
|
+
([Art. 4](../MANIFIESTO.md#art-4)). El PO es dueño del contenido funcional.
|
|
27
|
+
|
|
28
|
+
## Antipatrones
|
|
29
|
+
|
|
30
|
+
- **US vaga** ("como usuario quiero un botón") → no pasa el pulido.
|
|
31
|
+
- **Criterio no testeable** ("buena experiencia") → se rechaza (Art. 3).
|
|
32
|
+
- **Solución prefijada** en la US (endpoints, tablas) → eso es CÓMO, va después (Art. 1).
|
|
33
|
+
- **Saltearse el Gate 0** → se construye lo que no había que construir.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Paso 2 — Planning: derivar el CÓMO desde la US
|
|
2
|
+
|
|
3
|
+
← vuelve a [`SCRUM-CON-IA.md`](../SCRUM-CON-IA.md)
|
|
4
|
+
|
|
5
|
+
## En qué consiste en detalle
|
|
6
|
+
|
|
7
|
+
El equipo elige qué US entran al sprint (prioridad + capacidad). Para cada una, el
|
|
8
|
+
dev corre OpenSpec sobre la US: `opsx:explore` (entiende specs + código) y luego
|
|
9
|
+
`opsx:propose`, que **genera** el `design.md`, el `tasks.md` y las deltas de
|
|
10
|
+
`specs/`. El dev valida y ajusta — no acepta a ciegas.
|
|
11
|
+
|
|
12
|
+
## Herramientas
|
|
13
|
+
|
|
14
|
+
- `opsx:explore` → mapa de specs y código relevante.
|
|
15
|
+
- `opsx:propose` → `proposal.md` + `design.md` + `tasks.md` + `specs/`.
|
|
16
|
+
|
|
17
|
+
## Qué firma el humano
|
|
18
|
+
|
|
19
|
+
El **equipo** decide capacidad y prioridad. El **dev** valida el design y las tareas
|
|
20
|
+
propuestas — son suyas, nacen del CÓMO ([Art. 1](../MANIFIESTO.md#art-1)), no bajadas desde arriba.
|
|
21
|
+
|
|
22
|
+
## Antipatrones
|
|
23
|
+
|
|
24
|
+
- **Tareas inventadas por fuera del que implementa** → pierden sentido técnico.
|
|
25
|
+
- **Estimar a ciegas** una US que no cumple el DoR → primero se pule (paso 1).
|
|
26
|
+
- **US demasiado grande** que no entra en el sprint → se parte (INVEST), no se fuerza.
|
|
27
|
+
- **Aceptar el design generado sin leerlo** → el dev es responsable del CÓMO.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Paso 3 — Rama: atar el código al QUÉ desde el commit uno
|
|
2
|
+
|
|
3
|
+
← vuelve a [`SCRUM-CON-IA.md`](../SCRUM-CON-IA.md)
|
|
4
|
+
|
|
5
|
+
## En qué consiste en detalle
|
|
6
|
+
|
|
7
|
+
El dev arranca la implementación **atándola al QUÉ**: la branch y el `implements.yaml`
|
|
8
|
+
salen del mismo ID del tracker, así el link no puede quedar mal tipeado.
|
|
9
|
+
|
|
10
|
+
## Herramientas
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
dai link-us ABC-482 --us us.md
|
|
14
|
+
# → branch feature/ABC-482-<slug>
|
|
15
|
+
# → openspec/changes/<change>/implements.yaml (con el ac_hash ya calculado)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- Convención de rama: [`branch-naming.md`](../../governance/branch-naming.md).
|
|
19
|
+
- Schema del link: [ADR-0004](../adr/0004-ubicacion-y-schema-implements.md).
|
|
20
|
+
- El `ac_hash` lo calcula `dai ac-hash` ([ADR-0001](../adr/0001-contrato-ac-hash.md)).
|
|
21
|
+
|
|
22
|
+
## Qué firma el humano
|
|
23
|
+
|
|
24
|
+
El dev **elige qué US agarra**. El resto es mecánico y determinista (el CLI), no
|
|
25
|
+
criterio humano — por eso el key **no se tipea a mano** ([Art. 8](../MANIFIESTO.md#art-8), Art. 9).
|
|
26
|
+
|
|
27
|
+
## Antipatrones
|
|
28
|
+
|
|
29
|
+
- **Tipear el key en la branch o el yaml a mano** → error que rompe la trazabilidad.
|
|
30
|
+
- **Branch sin `implements.yaml`** en trabajo de producto → no hay link.
|
|
31
|
+
- **Escribir la cobertura inversa a mano** → se deriva con `dai stamp` (Art. 10).
|
|
32
|
+
- **Una branch para varias US** → una US = una capacidad = un `implements.yaml`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Paso 4 — TDD: test primero, en vertical slices
|
|
2
|
+
|
|
3
|
+
← vuelve a [`SCRUM-CON-IA.md`](../SCRUM-CON-IA.md)
|
|
4
|
+
|
|
5
|
+
## En qué consiste en detalle
|
|
6
|
+
|
|
7
|
+
El CÓMO se construye con **test primero**, un comportamiento a la vez:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
RED → escribes UN test que falla (un criterio de aceptación)
|
|
11
|
+
GREEN → el código mínimo para que pase
|
|
12
|
+
REFACTOR → limpias, con los tests en verde
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
*Vertical slices* (un test → una implementación → repetir), **no** horizontal
|
|
16
|
+
(todos los tests, después todo el código).
|
|
17
|
+
|
|
18
|
+
## Herramientas
|
|
19
|
+
|
|
20
|
+
- Skill [`tdd`](../../skills/tdd/SKILL.md) — el loop red-green-refactor y qué es un
|
|
21
|
+
buen test.
|
|
22
|
+
|
|
23
|
+
## Qué firma el humano
|
|
24
|
+
|
|
25
|
+
El dev **decide qué comportamientos importa testear** (no se testea todo) y revisa
|
|
26
|
+
cada slice. La IA escribe el test como spec ejecutable, el dev valida.
|
|
27
|
+
|
|
28
|
+
## Antipatrones
|
|
29
|
+
|
|
30
|
+
- **Horizontal slicing** (todos los tests juntos) → tests de la *forma imaginada*, no
|
|
31
|
+
del comportamiento real.
|
|
32
|
+
- **Testear lo interno** (mocks de colaboradores, métodos privados) → el test se rompe
|
|
33
|
+
al refactorizar aunque el comportamiento no cambió. Testea por la **interfaz pública**.
|
|
34
|
+
- **Codear primero, testear "si queda tiempo"** → vibe coding ([Art. 7](../MANIFIESTO.md#art-7)).
|
|
35
|
+
- **Refactorizar en rojo** → primero llega a verde.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Paso 5 — Smoke: el flujo entero, verde
|
|
2
|
+
|
|
3
|
+
← vuelve a [`SCRUM-CON-IA.md`](../SCRUM-CON-IA.md)
|
|
4
|
+
|
|
5
|
+
## En qué consiste en detalle
|
|
6
|
+
|
|
7
|
+
Antes de cerrar la US, se corre un **smoke end-to-end**: ejercita el flujo completo
|
|
8
|
+
—happy path + los guards principales— para confirmar que no se rompió nada grueso.
|
|
9
|
+
No reemplaza a los tests unitarios (paso 4); los complementa a nivel sistema.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
✓ happy path → resultado esperado
|
|
13
|
+
✓ guard 1 → rechazado como corresponde
|
|
14
|
+
✓ guard 2 → rechazado como corresponde
|
|
15
|
+
SMOKE OK
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Herramientas
|
|
19
|
+
|
|
20
|
+
- Skills de smoke por dominio (p. ej. `smoke-<módulo>`), armadas por el equipo.
|
|
21
|
+
|
|
22
|
+
## Qué firma el humano
|
|
23
|
+
|
|
24
|
+
El dev **confirma que el escenario refleja el uso real**. Un smoke que no toca el
|
|
25
|
+
flujo que importa da falsa confianza.
|
|
26
|
+
|
|
27
|
+
## Antipatrones
|
|
28
|
+
|
|
29
|
+
- **Smoke manual** que se olvida o se saltea bajo presión → automatizarlo (idealmente
|
|
30
|
+
en el pipeline, ver retro).
|
|
31
|
+
- **Smoke que no ejercita los guards** → pasa en verde y esconde el bug.
|
|
32
|
+
- **Confundir smoke con suite completa** → el smoke es grueso y rápido, a propósito.
|