@saulwade/swl-ses 2.2.4 → 2.3.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/CLAUDE.md CHANGED
@@ -1,4 +1,4 @@
1
- # CLAUDE.md — @saulwade/swl-ses v2.2.4
1
+ # CLAUDE.md — @saulwade/swl-ses v2.3.0
2
2
 
3
3
  ## Reglas de máxima prioridad (aplican SIEMPRE, sin excepción)
4
4
 
@@ -99,7 +99,7 @@ NUNCA asumir, sugerir como hecho consumado, ni escribir en ADRs/manifiestos/CHAN
99
99
  ## Qué es este repositorio
100
100
 
101
101
  Sistema de ingeniería de software auto-evolutivo multi-runtime polyglot (SDLC completo).
102
- 11 lenguajes, 7 runtimes (Claude, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot), 60 agentes, 182 skills, 44 comandos, 77 reglas, 48 hooks.
102
+ 11 lenguajes, 7 runtimes (Claude, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot), 60 agentes, 182 skills, 44 comandos, 77 reglas, 50 hooks.
103
103
 
104
104
  ## Estructura del repositorio
105
105
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # swl-ses v2.2.4
1
+ # swl-ses v2.3.0
2
2
 
3
3
  > El paquete anterior `@saulwadeleon/swl-software-engineering-system` está deprecado. Migrar a `@saulwade/swl-ses` (npmjs.org canónico) o `@saul-wade/swl-ses` (mirror en GitHub Packages) — el CLI `swl-ses` no cambia.
4
4
 
@@ -213,7 +213,7 @@ Correr solo uno deja el otro plano en una versión anterior.
213
213
  | `mobile` | Android + iOS + React Native/Flutter + UX |
214
214
  | `devops` | CI/CD + cloud + observabilidad + releases + seguridad |
215
215
  | `polyglot` | Todos los lenguajes: 11 lenguajes + revisores + build resolvers |
216
- | `completo` | Todo: 60 agentes + 182 habilidades + 44 comandos + 77 reglas + 48 hooks |
216
+ | `completo` | Todo: 60 agentes + 182 habilidades + 44 comandos + 77 reglas + 50 hooks |
217
217
 
218
218
  ### Targets soportados
219
219
 
@@ -518,7 +518,7 @@ swl-ses/
518
518
  habilidades/ # 160 habilidades modulares
519
519
  comandos/swl/ # 44 comandos slash
520
520
  reglas/ # 28 reglas base + 40 por lenguaje
521
- hooks/ # 48 hooks + 76 librerías en hooks/lib/
521
+ hooks/ # 50 hooks + 77 librerías en hooks/lib/
522
522
  schemas/ # 15 JSON Schemas
523
523
  contextos/ # 3 modos de desarrollo
524
524
  instintos/ # Instintos YAML con confianza
@@ -1,141 +1,146 @@
1
- ---
2
- name: swl:aprobar-plan
3
- description: Aprueba el PLAN.md de una fase y lo firma con un lock SHA256 (gate G1 de SDD). Transiciona el frontmatter de estado borrador a aprobado y escribe .planning/locks/<plan>.lock. Es la única vía válida de aprobación — ejecutar-fase verifica este lock antes de implementar y detiene la ejecución si el plan fue mutado tras la firma.
4
- allowed_tools: ["Read", "Write", "Edit", "Bash", "Glob"]
5
- ---
6
-
7
- # /swl:aprobar-plan <n> — Aprobar y firmar el plan de una fase (Gate G1)
8
-
9
- Eres el guardián del gate G1 del enforcement SDD. Tu trabajo es transicionar un
10
- PLAN de `borrador` a `aprobado` Y firmarlo con un lock SHA256, de modo que
11
- cualquier mutación posterior del plan sea detectable por `/swl:ejecutar-fase`.
12
-
13
- Este comando es la **única vía documentada de aprobación**. Editar el frontmatter
14
- a mano (`estado: aprobado`) deja el plan en modo legacy (cláusula de gracia D-05):
15
- se ejecuta con advertencia pero sin protección de integridad. Usar este comando
16
- es lo que activa el gate real.
17
-
18
- > **Invocación cross-scope** (ver `@docs/invocacion-cli-cross-scope.md`): las
19
- > partes deterministas del gate viven en subcomandos del CLI. Resuélvelos así:
20
- > si existe `./scripts/cli/<sub>.js` (repo madre) usa `node scripts/cli/<sub>.js`;
21
- > si `command -v swl-ses` responde usa `swl-ses <sub>`; si no,
22
- > `npx -y @saulwade/swl-ses@latest <sub>`. Abajo escribo la forma `swl-ses <sub>`
23
- > como canónica. NUNCA uses `node -e "require('./scripts/lib/...')"` — esa ruta no
24
- > existe en proyectos downstream.
25
-
26
- ## Uso
27
-
28
- ```
29
- /swl:aprobar-plan 9
30
- ```
31
-
32
- El argumento `<n>` es el número de la fase cuyo PLAN se aprueba.
33
-
34
- ## Paso 1 — Localizar el PLAN
35
-
36
- Resuelve la ruta `.planning/fases/0N-PLAN.md` (N con cero a la izquierda si N < 10).
37
-
38
- - Si no existe: detente con "No existe el PLAN de la fase N. Ejecuta `/swl:planear-fase N` primero."
39
- - Lee el archivo completo.
40
-
41
- ## Paso 2 — Validar el estado actual del frontmatter
42
-
43
- Lee el campo `estado:` del frontmatter:
44
-
45
- - Si `estado: borrador` → continúa al Paso 3 (caso normal).
46
- - Si `estado: aprobado` → ya está aprobado. Verifica si existe el lock:
47
- ```bash
48
- swl-ses verificar-plan --fase=N
49
- ```
50
- - Si `modo: "firmado"` → informa "El plan ya está aprobado y firmado." y termina.
51
- - Si `modo: "legacy"` (aprobado sin lock) → pregunta al usuario: "El plan está
52
- aprobado pero sin firmar (modo legacy). ¿Lo firmo ahora para activar el gate
53
- G1?" Si confirma, salta al Paso 4 (firmar sin re-transicionar).
54
- - Si `modo: "mutado"` → el plan cambió tras una firma previa. Informa el
55
- `hashEsperado` vs `hashActual` y pregunta si re-aprobar (re-firmar el estado
56
- actual). Procede solo con confirmación explícita.
57
- - Si no hay campo `estado` → detente: "El PLAN no tiene campo `estado` en el
58
- frontmatter. Revisa que sea un plan válido generado por `/swl:planear-fase`."
59
-
60
- ## Paso 2.5 — Validar la matriz REQ×T (trazabilidad G4)
61
-
62
- Lee `.planning/fases/0N-CONTEXTO.md` y extrae los IDs `REQ-NN:` (fases 01-11) o
63
- `REQ-<fase>-NN:` (namespaceados, fases ≥12) de la sección de criterios de
64
- aceptación. `verificar-trazabilidad.js` reconoce ambos formatos.
65
-
66
- - **CONTEXTO sin REQ-IDs** (fases legacy 01-09): advertencia informativa
67
- ("CONTEXTO sin REQ-IDs — trazabilidad no exigible, gracia legacy") y continúa.
68
- - **CONTEXTO con REQ-IDs**: verifica que el PLAN cubra TODOS:
69
- ```bash
70
- swl-ses verificar-trazabilidad --fase=N --solo-plan
71
- ```
72
- - Exit 0 → continúa al Paso 3.
73
- - Exit 1 (REQ huérfanos) → **RECHAZA la aprobación**. Lista los REQ sin tarea y
74
- remite a `/swl:planear-fase N` para cubrirlos (o a retirar el REQ del CONTEXTO
75
- con marca "RETIRADO — razón"). NO firmes un plan con REQ huérfanos.
76
-
77
- ## Paso 3Confirmar con el usuario antes de aprobar
78
-
79
- NUNCA apruebes sin confirmación explícita. Presenta un resumen breve del plan
80
- (número de slices, tareas, slices HITL) y pregunta:
81
-
82
- ```
83
- El plan de la fase N tiene [X] slices y [Y] tareas ([Z] HITL).
84
- ¿Confirmas la aprobación? Al aprobar se firma con SHA256 y queda inmutable:
85
- cualquier edición posterior detendrá /swl:ejecutar-fase.
86
- ```
87
-
88
- Espera respuesta afirmativa. Si el usuario pide cambios, NO apruebes remítelo
89
- a `/swl:planear-fase N` para refinar.
90
-
91
- ## Paso 4 — Transicionar y firmar
92
-
93
- 1. **Transicionar** (omitir si el plan ya estaba `aprobado` en modo legacy):
94
- edita el frontmatter `estado: borrador` `estado: aprobado` y agrega
95
- `aprobadoPor: usuario (<nombre>) — <fecha>, via /swl:aprobar-plan`.
96
-
97
- 2. **Firmar y marcar la fase activa** — un solo subcomando hace las tres
98
- operaciones deterministas: firma SHA256 `.planning/locks/0N-PLAN.md.lock`,
99
- verifica la firma, y escribe `.planning/locks/fase-activa.json` (gate G0 que
100
- consume `hooks/spec-gate.js`):
101
- ```bash
102
- swl-ses aprobar-plan --fase=N
103
- ```
104
- Verifica en la salida JSON que `ok: true` y `modo: "firmado"`. Si reporta
105
- error de firma, **NO continúes** — revisa el `motivo`.
106
-
107
- El `.lock` SÍ se versiona en git (evidencia de aprobación, parte del audit
108
- trail SDD). El `fase-activa.json` es runtime local (gitignored);
109
- `/swl:ejecutar-fase` lo elimina al cerrar la fase. Re-ejecutar
110
- `swl-ses aprobar-plan --fase=N` tras una re-aprobación (plan mutado) realinea
111
- lock y fase-activa automáticamente.
112
-
113
- ## Paso 5 Reporte
114
-
115
- ```
116
- Plan de la fase N aprobado y firmado (gate G1 activo).
117
-
118
- estado: borrador -> aprobado
119
- lock: .planning/locks/0N-PLAN.md.lock
120
- fase activa: .planning/locks/fase-activa.json (gate G0 cubierto)
121
- sha256: <hash corto>
122
-
123
- Cualquier edición del PLAN tras esta firma detendrá /swl:ejecutar-fase con un
124
- mensaje de "plan mutado tras aprobación". Para cambiar el plan: edítalo y vuelve
125
- a ejecutar /swl:aprobar-plan N.
126
-
127
- Próximo paso: /swl:ejecutar-fase N
128
- ```
129
-
130
- ## Reglas de comportamiento
131
-
132
- - NUNCA apruebes un plan sin confirmación explícita del usuario.
133
- - NUNCA modifiques el contenido del plan al aprobarlo — solo el campo `estado`
134
- del frontmatter y la línea `aprobadoPor`. El cuerpo es lo que se firma.
135
- - El lock vive en `.planning/locks/` y SÍ se versiona en git (es evidencia de
136
- aprobación, parte del audit trail de SDD).
137
- - Si el usuario quiere cambiar el plan después de aprobado, el flujo correcto es
138
- editar el PLAN y re-ejecutar `/swl:aprobar-plan N` (re-firma). NUNCA editar el
139
- lock a mano.
140
- - El número de versión del release que publique esta fase lo decide el usuario
141
- (regla CLAUDE.md) este comando no toca versiones.
1
+ ---
2
+ name: swl:aprobar-plan
3
+ description: Aprueba el PLAN.md de una fase y lo firma con un lock SHA256 (gate G1 de SDD). Transiciona el frontmatter de estado borrador a aprobado y escribe .planning/locks/<plan>.lock. Es la única vía válida de aprobación — ejecutar-fase verifica este lock antes de implementar y detiene la ejecución si el plan fue mutado tras la firma.
4
+ allowed_tools: ["Read", "Write", "Edit", "Bash", "Glob"]
5
+ ---
6
+
7
+ # /swl:aprobar-plan <n> — Aprobar y firmar el plan de una fase (Gate G1)
8
+
9
+ Eres el guardián del gate G1 del enforcement SDD. Tu trabajo es transicionar un
10
+ PLAN de `borrador` a `aprobado` Y firmarlo con un lock SHA256, de modo que
11
+ cualquier mutación posterior del plan sea detectable por `/swl:ejecutar-fase`.
12
+
13
+ Este comando es la **única vía documentada de aprobación**. Editar el frontmatter
14
+ a mano (`estado: aprobado`) deja el plan en modo legacy (cláusula de gracia D-05):
15
+ se ejecuta con advertencia pero sin protección de integridad. Usar este comando
16
+ es lo que activa el gate real.
17
+
18
+ > **Invocación cross-scope** (ver `@docs/invocacion-cli-cross-scope.md`): las
19
+ > partes deterministas del gate viven en subcomandos del CLI. Resuélvelos así:
20
+ > si existe `./scripts/cli/<sub>.js` (repo madre) usa `node scripts/cli/<sub>.js`;
21
+ > si `command -v swl-ses` responde usa `swl-ses <sub>`; si no,
22
+ > `npx -y @saulwade/swl-ses@latest <sub>`. Abajo escribo la forma `swl-ses <sub>`
23
+ > como canónica. NUNCA uses `node -e "require('./scripts/lib/...')"` — esa ruta no
24
+ > existe en proyectos downstream.
25
+
26
+ ## Uso
27
+
28
+ ```
29
+ /swl:aprobar-plan 9
30
+ ```
31
+
32
+ El argumento `<n>` es el número de la fase cuyo PLAN se aprueba.
33
+
34
+ ## Paso 1 — Localizar el PLAN
35
+
36
+ Resuelve la ruta `.planning/fases/0N-PLAN.md` (N con cero a la izquierda si N < 10).
37
+
38
+ - Si no existe: detente con "No existe el PLAN de la fase N. Ejecuta `/swl:planear-fase N` primero."
39
+ - Lee el archivo completo.
40
+
41
+ ## Paso 2 — Validar el estado actual del frontmatter
42
+
43
+ Lee el campo `estado:` del frontmatter:
44
+
45
+ - Si `estado: borrador` → continúa al Paso 3 (caso normal).
46
+ - Si `estado: aprobado` → ya está aprobado. Verifica si existe el lock:
47
+ ```bash
48
+ swl-ses verificar-plan --fase=N
49
+ ```
50
+ - Si `modo: "firmado"` → informa "El plan ya está aprobado y firmado." y termina.
51
+ - Si `modo: "legacy"` (aprobado sin lock) → pregunta al usuario: "El plan está
52
+ aprobado pero sin firmar (modo legacy). ¿Lo firmo ahora para activar el gate
53
+ G1?" Si confirma, salta al Paso 4 (firmar sin re-transicionar).
54
+ - Si `modo: "mutado"` → el plan cambió tras una firma previa. Informa el
55
+ `hashEsperado` vs `hashActual` y pregunta si re-aprobar (re-firmar el estado
56
+ actual). Procede solo con confirmación explícita.
57
+ - Si no hay campo `estado` → detente: "El PLAN no tiene campo `estado` en el
58
+ frontmatter. Revisa que sea un plan válido generado por `/swl:planear-fase`."
59
+
60
+ ## Paso 2.5 — Validar la matriz REQ×T (trazabilidad G4)
61
+
62
+ Lee `.planning/fases/0N-CONTEXTO.md` y extrae los IDs `REQ-NN:` (fases 01-11) o
63
+ `REQ-<fase>-NN:` (namespaceados, fases ≥12) de la sección de criterios de
64
+ aceptación. `verificar-trazabilidad.js` reconoce ambos formatos.
65
+
66
+ - **CONTEXTO sin REQ-IDs** (fases legacy 01-09): advertencia informativa
67
+ ("CONTEXTO sin REQ-IDs — trazabilidad no exigible, gracia legacy") y continúa.
68
+ - **CONTEXTO con REQ-IDs**: verifica que el PLAN cubra TODOS:
69
+ ```bash
70
+ swl-ses verificar-trazabilidad --fase=N --solo-plan
71
+ ```
72
+ - Exit 0 → continúa al Paso 3.
73
+ - Exit 1 (REQ huérfanos) → **RECHAZA la aprobación**. Lista los REQ sin tarea y
74
+ remite a `/swl:planear-fase N` para cubrirlos (o a retirar el REQ del CONTEXTO
75
+ con marca "RETIRADO — razón"). NO firmes un plan con REQ huérfanos.
76
+ - **WARN "headers de tarea malformados"** (warn-only, no cambia el exit): si el
77
+ reporte lista headers como `#### T-01 ...`, son la **causa silenciosa** de
78
+ REQ huérfanos. El parser de la matriz exige `### T-NN:` (2-4 `#`, dos puntos
79
+ tras el ID; nunca em-dash). Corrige el separador en el PLAN y re-ejecuta antes
80
+ de aprobar un header con `—` deja la tarea invisible aunque declare su REQ.
81
+
82
+ ## Paso 3 — Confirmar con el usuario antes de aprobar
83
+
84
+ NUNCA apruebes sin confirmación explícita. Presenta un resumen breve del plan
85
+ (número de slices, tareas, slices HITL) y pregunta:
86
+
87
+ ```
88
+ El plan de la fase N tiene [X] slices y [Y] tareas ([Z] HITL).
89
+ ¿Confirmas la aprobación? Al aprobar se firma con SHA256 y queda inmutable:
90
+ cualquier edición posterior detendrá /swl:ejecutar-fase.
91
+ ```
92
+
93
+ Espera respuesta afirmativa. Si el usuario pide cambios, NO apruebes remítelo
94
+ a `/swl:planear-fase N` para refinar.
95
+
96
+ ## Paso 4 — Transicionar y firmar
97
+
98
+ 1. **Transicionar** (omitir si el plan ya estaba `aprobado` en modo legacy):
99
+ edita el frontmatter `estado: borrador` `estado: aprobado` y agrega
100
+ `aprobadoPor: usuario (<nombre>) — <fecha>, via /swl:aprobar-plan`.
101
+
102
+ 2. **Firmar y marcar la fase activa** — un solo subcomando hace las tres
103
+ operaciones deterministas: firma SHA256 → `.planning/locks/0N-PLAN.md.lock`,
104
+ verifica la firma, y escribe `.planning/locks/fase-activa.json` (gate G0 que
105
+ consume `hooks/spec-gate.js`):
106
+ ```bash
107
+ swl-ses aprobar-plan --fase=N
108
+ ```
109
+ Verifica en la salida JSON que `ok: true` y `modo: "firmado"`. Si reporta
110
+ error de firma, **NO continúes** revisa el `motivo`.
111
+
112
+ El `.lock` SÍ se versiona en git (evidencia de aprobación, parte del audit
113
+ trail SDD). El `fase-activa.json` es runtime local (gitignored);
114
+ `/swl:ejecutar-fase` lo elimina al cerrar la fase. Re-ejecutar
115
+ `swl-ses aprobar-plan --fase=N` tras una re-aprobación (plan mutado) realinea
116
+ lock y fase-activa automáticamente.
117
+
118
+ ## Paso 5 — Reporte
119
+
120
+ ```
121
+ Plan de la fase N aprobado y firmado (gate G1 activo).
122
+
123
+ estado: borrador -> aprobado
124
+ lock: .planning/locks/0N-PLAN.md.lock
125
+ fase activa: .planning/locks/fase-activa.json (gate G0 cubierto)
126
+ sha256: <hash corto>
127
+
128
+ Cualquier edición del PLAN tras esta firma detendrá /swl:ejecutar-fase con un
129
+ mensaje de "plan mutado tras aprobación". Para cambiar el plan: edítalo y vuelve
130
+ a ejecutar /swl:aprobar-plan N.
131
+
132
+ Próximo paso: /swl:ejecutar-fase N
133
+ ```
134
+
135
+ ## Reglas de comportamiento
136
+
137
+ - NUNCA apruebes un plan sin confirmación explícita del usuario.
138
+ - NUNCA modifiques el contenido del plan al aprobarlo solo el campo `estado`
139
+ del frontmatter y la línea `aprobadoPor`. El cuerpo es lo que se firma.
140
+ - El lock vive en `.planning/locks/` y se versiona en git (es evidencia de
141
+ aprobación, parte del audit trail de SDD).
142
+ - Si el usuario quiere cambiar el plan después de aprobado, el flujo correcto es
143
+ editar el PLAN y re-ejecutar `/swl:aprobar-plan N` (re-firma). NUNCA editar el
144
+ lock a mano.
145
+ - El número de versión del release que publique esta fase lo decide el usuario
146
+ (regla CLAUDE.md) — este comando no toca versiones.
@@ -266,7 +266,19 @@ Usar tags anotados siempre (regla del skill).
266
266
 
267
267
  ## Paso 9 — Generar RELEASE-NOTES
268
268
 
269
- Crea `RELEASE-NOTES-v[nueva-versión].md` con: resumen, cambios, instrucciones de actualización y guía de migración si hay breaking changes.
269
+ Crea `releases/v[nueva-versión]/RELEASE-NOTES-v[nueva-versión].md` con: resumen,
270
+ cambios, instrucciones de actualización y guía de migración si hay breaking changes.
271
+
272
+ ```bash
273
+ mkdir -p releases/v[nueva-versión]
274
+ # escribir releases/v[nueva-versión]/RELEASE-NOTES-v[nueva-versión].md
275
+ ```
276
+
277
+ **NUNCA crear las RELEASE-NOTES en la raíz del repo.** La convención (todos los
278
+ releases previos en `releases/`) es que las RELEASE-NOTES viven SOLO en
279
+ `releases/vX.Y.Z/` — no se versiona ninguna copia en raíz. El directorio
280
+ `releases/v[nueva-versión]/` también lo crea `evidencia-release.js` (Paso 9.5);
281
+ si ese paso corre primero, el `mkdir -p` es no-op.
270
282
 
271
283
  ## Paso 9.5 — Evidencia de procedencia (cadena de suministro, ADR-0038)
272
284
 
@@ -286,20 +298,21 @@ Esto escribe (vía `scripts/lib/evidencia-release.js`):
286
298
  Luego:
287
299
 
288
300
  1. **Insertar la sección "Integridad y verificación"** en
289
- `RELEASE-NOTES-v[nueva-versión].md`, justo después de la sección de
290
- correcciones. La genera `seccionVerificacionNotas` de la lib:
301
+ `releases/v[nueva-versión]/RELEASE-NOTES-v[nueva-versión].md`, justo después de
302
+ la sección de correcciones. La genera `seccionVerificacionNotas` de la lib:
291
303
 
292
304
  ```bash
293
305
  node -e "const {seccionVerificacionNotas}=require('./scripts/lib/evidencia-release');const fs=require('fs');const v='[nueva-versión]';const sums=fs.readFileSync('releases/v'+v+'/SHA256SUMS','utf8').trim().split(/\s+/);const md=seccionVerificacionNotas({version:v,hash:sums[0],tarball:sums[1]});console.log(md)"
294
306
  ```
295
307
 
296
- Copiar ese markdown a RELEASE-NOTES (tras "Correcciones").
308
+ Anexar ese markdown a `releases/v[nueva-versión]/RELEASE-NOTES-v[nueva-versión].md`
309
+ (tras "Correcciones").
297
310
 
298
- 2. **Copiar las RELEASE-NOTES** a la carpeta del release como evidencia
299
- versionada:
311
+ 2. **Versionar la evidencia** del release. Las RELEASE-NOTES ya viven en
312
+ `releases/v[nueva-versión]/` (Paso 9) — NO hacer `cp` desde la raíz (no debe
313
+ existir copia en raíz):
300
314
 
301
315
  ```bash
302
- cp RELEASE-NOTES-v[nueva-versión].md releases/v[nueva-versión]/
303
316
  git add releases/v[nueva-versión]/
304
317
  ```
305
318
 
@@ -397,7 +410,7 @@ Commits incluidos: [N] (feat: [N], fix: [N], otros: [N])
397
410
  Tests: [ejecutados OK | omitidos (--skip-tests)]
398
411
 
399
412
  Próximos pasos:
400
- 1. Revisar RELEASE-NOTES-v[nueva-versión].md
413
+ 1. Revisar releases/v[nueva-versión]/RELEASE-NOTES-v[nueva-versión].md
401
414
  2. git push origin v[nueva-versión]
402
415
  3. Publicar release en GitHub/GitLab si aplica
403
416
  4. Notificar al equipo
@@ -416,6 +429,15 @@ Próximos pasos:
416
429
  release ya creado pero aún-no-publicado obliga a mover el tag + regenerar la
417
430
  evidencia (el SHA del tarball cambia si el commit toca archivos de
418
431
  `package.json#files`) — churn evitable. Si hay que iterar, hacerlo antes de taggear.
432
+ - **Si el usuario alimenta archivos de forma incremental para la MISMA versión
433
+ ("faltan N archivos que agregar a esta versión, espera"), NO finalizar el
434
+ release** (no congelar tag, no regenerar evidencia final, no proponer push)
435
+ hasta que el usuario confirme que ya están TODOS los archivos. Mantener el
436
+ commit de release como HEAD entre tandas para que cada incorporación sea un
437
+ `amend` limpio + mover tag; regenerar la evidencia (SBOM/SHA256SUMS) SOLO en la
438
+ última tanda, porque el SHA del tarball cambia con cada archivo nuevo que entre
439
+ en `package.json#files`. Cerrar el release antes de tiempo obliga a rehacer
440
+ evidencia y tag por cada archivo tardío.
419
441
  - **El agente NUNCA corre `npm` (test/pack/build/publish) en paralelo a un
420
442
  `npm run publish:*` que está ejecutando el usuario.** `test:release` incluye
421
443
  `test:smoke` (install/uninstall a temp + lectura de estado global); dos suites