@saulwade/swl-ses 1.8.0 → 2.0.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 +8 -8
- package/README.md +13 -13
- package/agentes/accesibilidad-wcag-swl.md +3 -3
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/disenador-ui-swl.md +6 -5
- package/agentes/frontend-angular-swl.md +2 -2
- package/agentes/frontend-css-swl.md +2 -2
- package/agentes/frontend-react-swl.md +4 -4
- package/agentes/frontend-swl.md +6 -6
- package/agentes/investigador-ux-swl.md +5 -5
- package/agentes/orquestador-swl.md +96 -8
- package/agentes/perfilador-usuario-swl.md +308 -308
- package/agentes/producto-prd-swl.md +1 -1
- package/agentes/red-team-swl.md +218 -218
- package/agentes/revisor-codigo-swl.md +34 -10
- package/agentes/revisor-seguridad-swl.md +7 -0
- package/agentes/tdd-qa-swl.md +39 -2
- package/comandos/swl/actualizar.md +1 -1
- package/comandos/swl/aprender.md +2 -2
- package/comandos/swl/aprobar-plan.md +152 -0
- package/comandos/swl/autoresearch.md +102 -6
- package/comandos/swl/ayuda.md +3 -3
- package/comandos/swl/discutir-fase.md +20 -2
- package/comandos/swl/ejecutar-fase.md +53 -6
- package/comandos/swl/evolucionar.md +1 -1
- package/comandos/swl/inbox.md +1 -1
- package/comandos/swl/instalar.md +1 -1
- package/comandos/swl/nemesis.md +42 -1
- package/comandos/swl/planear-fase.md +25 -1
- package/comandos/swl/plugins.md +1 -1
- package/comandos/swl/predecir.md +139 -0
- package/comandos/swl/release.md +1 -1
- package/comandos/swl/status.md +279 -0
- package/comandos/swl/verificar.md +75 -7
- package/habilidades/ai-runtime-security/SKILL.md +1 -1
- package/habilidades/angular-moderno/SKILL.md +44 -1
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
- package/habilidades/autoresearch/SKILL.md +15 -1
- package/habilidades/benchmark-memoria/SKILL.md +1 -1
- package/habilidades/calidad-contract-testing/SKILL.md +165 -0
- package/habilidades/calidad-mutation-testing/SKILL.md +170 -0
- package/habilidades/changelog-generator/SKILL.md +9 -2
- package/habilidades/changelog-generator/scripts/parse-commits.js +12 -1
- package/habilidades/checklist-seguridad/SKILL.md +29 -1
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -0
- package/habilidades/css-moderno/SKILL.md +3 -1
- package/habilidades/diagrama-arquitectura/SKILL.md +1 -1
- package/habilidades/drift-detection/SKILL.md +179 -179
- package/habilidades/ejecutar-fase/SKILL.md +64 -14
- package/habilidades/estructura-proyecto-claude/SKILL.md +17 -14
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +34 -23
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +70 -53
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -77
- package/habilidades/extractor-de-aprendizajes/SKILL.md +9 -5
- package/habilidades/fastapi-experto/SKILL.md +56 -5
- package/habilidades/harness-claude-code/SKILL.md +10 -7
- package/{reglas/harness-claude-code.md → habilidades/harness-claude-code/recursos/disciplina-harness-regla.md} +2 -2
- package/habilidades/instalar-sistema/SKILL.md +3 -3
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +1 -1
- package/habilidades/patrones-python/SKILL.md +8 -5
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/planear-fase/SKILL.md +25 -4
- package/habilidades/proceso-ddia-fundamentos/SKILL.md +1 -1
- package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
- package/habilidades/proceso-debate-adversarial/SKILL.md +164 -0
- package/habilidades/proceso-debate-adversarial/recursos/personas.md +105 -0
- package/habilidades/proceso-dynamic-workflows/SKILL.md +138 -0
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -0
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -0
- package/habilidades/protocolo-revision-swl/SKILL.md +1 -1
- package/habilidades/seguridad-skills-ia/SKILL.md +1 -1
- package/habilidades/swl-claudemd/SKILL.md +50 -210
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -0
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -0
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -0
- package/habilidades/swl-dashboard/SKILL.md +9 -9
- package/habilidades/swl-revisar-impacto/SKILL.md +1 -1
- package/habilidades/tdd-workflow/SKILL.md +58 -5
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +3 -3
- package/hooks/calidad-pre-commit.js +340 -3
- package/hooks/ciclo-evolucion-subagente.js +26 -0
- package/hooks/ciclo-evolucion.js +26 -0
- package/hooks/contexto-iteracion.js +144 -0
- package/hooks/extraccion-aprendizajes.js +13 -0
- package/hooks/lib/ciclo-evolucion.js +47 -0
- package/hooks/{auto-evolucion.js → lib/etapa-auto-evolucion.js} +701 -700
- package/hooks/{metricas-evolucion.js → lib/etapa-metricas.js} +388 -376
- package/hooks/{actualizar-perfil-usuario.js → lib/etapa-perfil-usuario.js} +376 -364
- package/hooks/lib/evolution-tracker.js +24 -3
- package/hooks/lib/loop-telemetry.js +321 -0
- package/hooks/notificacion-telegram.js +11 -3
- package/hooks/spec-gate.js +211 -0
- package/hooks/tdd-gate.js +241 -0
- package/hooks/validar-intent-spec.js +30 -10
- package/llms.txt +29 -0
- package/manifiestos/hooks-config.json +36 -18
- package/manifiestos/modulos.json +23 -14
- package/manifiestos/skills-lock.json +100 -72
- package/package.json +4 -3
- package/plugin.json +9 -10
- package/reglas/accesibilidad.md +10 -0
- package/reglas/api-diseno.md +9 -0
- package/reglas/arquitectura.evolved.json +7 -0
- package/reglas/arquitectura.md +65 -0
- package/reglas/auditorias-documentales-estructurales.md +7 -0
- package/reglas/cloud-infra.md +8 -0
- package/reglas/fragmentos-compartidos.md +5 -0
- package/reglas/gobernanza.md +4 -4
- package/reglas/hooks.md +6 -0
- package/reglas/intent-engineering.md +4 -0
- package/reglas/markitdown.md +8 -0
- package/reglas/memoria-consolidada.md +1 -1
- package/reglas/patrones.md +6 -0
- package/reglas/registro-componentes-nuevos.md +10 -1
- package/reglas/seguridad-agentes.md +1 -1
- package/reglas/seguridad.evolved.json +7 -0
- package/reglas/seguridad.md +144 -0
- package/reglas/skills-estandar.md +6 -0
- package/reglas/testing.md +7 -0
- package/reglas/tests-cleanup.md +4 -0
- package/reglas/usar-sistema-swl.md +1 -1
- package/scripts/generar-inventario.js +64 -1
- package/scripts/instalador.js +32 -2
- package/scripts/lib/gitignore-manifest.js +29 -1
- package/scripts/lib/plan-lock.js +275 -0
- package/scripts/migrar-fase-dominio.js +0 -1
- package/scripts/smoke-test.js +24 -2
- package/scripts/verificar-trazabilidad.js +292 -0
- package/agentes/ux-disenador-swl.md +0 -503
- package/comandos/swl/dashboard.md +0 -146
- package/comandos/swl/evolucion-estado.md +0 -191
- package/comandos/swl/metricas.md +0 -342
- package/comandos/swl/salud.md +0 -481
- package/reglas/verificar-citas-temporales.md +0 -139
|
@@ -160,7 +160,7 @@ const conFeedback = applyFeedback(instinto, 'helpful');
|
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
**Cuándo recomputar**:
|
|
163
|
-
- `/swl:salud` reporta instintos con `effective_confidence < 0.3` para revisión.
|
|
163
|
+
- `/swl:status salud` reporta instintos con `effective_confidence < 0.3` para revisión.
|
|
164
164
|
- `hooks/degradacion-instintos.js` puede marcar `status_proposed: degraded`
|
|
165
165
|
cuando `shouldAutoDeprecate(instinto)` devuelve `true`.
|
|
166
166
|
- `bootstrap-instintos.js` emite los nuevos instintos con `decay_half_life_days: 90`,
|
package/reglas/patrones.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/manifiestos/**"
|
|
4
|
+
- "**/agentes/**"
|
|
5
|
+
- "**/habilidades/**"
|
|
6
|
+
- "**/comandos/**"
|
|
7
|
+
- "**/hooks/**"
|
|
8
|
+
- "**/plugin.json"
|
|
9
|
+
---
|
|
1
10
|
# Regla: Registro obligatorio de componentes nuevos en manifiestos
|
|
2
11
|
|
|
3
12
|
Esta regla es OBLIGATORIA para el proyecto **@saulwade/swl-ses**. Aplica
|
|
@@ -26,7 +35,7 @@ propagación de cambios" del `CLAUDE.md` del proyecto.
|
|
|
26
35
|
|
|
27
36
|
El costo de registrar es ~30 segundos por componente (3 archivos a editar
|
|
28
37
|
+ un comando de regeneración). El costo de no registrar es: instalador roto
|
|
29
|
-
para usuarios del paquete público, `npm run test:all` falla, `/swl:salud`
|
|
38
|
+
para usuarios del paquete público, `npm run test:all` falla, `/swl:status salud`
|
|
30
39
|
reporta degradación, deuda acumulada difícil de detectar tras varios commits.
|
|
31
40
|
|
|
32
41
|
---
|
|
@@ -335,7 +335,7 @@ Precedente: ADR-0002 (skills) y ADR-0004 (agentes). Agregar Exclusion a un agent
|
|
|
335
335
|
|
|
336
336
|
### Auditoría
|
|
337
337
|
|
|
338
|
-
`scripts/auditar-agentes-gaps.js` reporta cobertura. Integración con `/swl:salud`
|
|
338
|
+
`scripts/auditar-agentes-gaps.js` reporta cobertura. Integración con `/swl:status salud`
|
|
339
339
|
mediante `SWL_AUDIT_AGENTES=1` (paso 5d).
|
|
340
340
|
|
|
341
341
|
### Ejemplo de frontmatter
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"evolved": true,
|
|
3
|
+
"evolved-from": "1.8.0",
|
|
4
|
+
"evolved-at": "2026-06-04",
|
|
5
|
+
"evolved-by": "evolucionar",
|
|
6
|
+
"evolved-note": "PE-003 (verificación de flags antes de asumir servicios externos LDAP/Redis/S3) + PE-004 (sanitización PII centralizada en handlers) + PE-007 (generación de passwords legibles sin chars ambiguos). Origen: OIC v1.5 2026-06-04, bug histórico manuel.monteagudo + Slice 2 v1.5 Observabilidad."
|
|
7
|
+
}
|
package/reglas/seguridad.md
CHANGED
|
@@ -141,6 +141,147 @@ vulnerabilidad del OWASP Top 10. Las más frecuentes en este stack:
|
|
|
141
141
|
|
|
142
142
|
---
|
|
143
143
|
|
|
144
|
+
## Verificación obligatoria de flags de configuración antes de asumir servicios externos
|
|
145
|
+
|
|
146
|
+
Toda rama de código que asuma un servicio externo opcional (LDAP, Redis, S3, SMTP,
|
|
147
|
+
OIDC, Auth0, etc.) DEBE verificar el flag de configuración del proyecto ANTES de
|
|
148
|
+
tomar la decisión. Sin esta verificación, una configuración no esperada deja a los
|
|
149
|
+
usuarios atrapados en flujos rotos sin error visible.
|
|
150
|
+
|
|
151
|
+
**Anti-patrón** (caso real OIC 2026-06-04, dos bugs históricos en el mismo flujo):
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
# MAL — asume LDAP siempre habilitado
|
|
155
|
+
if rol == "ADMIN":
|
|
156
|
+
hashed = hash_password(body.password)
|
|
157
|
+
else:
|
|
158
|
+
# "Para usuarios LDAP, no se almacena contraseña funcional local."
|
|
159
|
+
hashed = hash_password(uuid.uuid4().hex)
|
|
160
|
+
# ↑ Si AUTH_LDAP_ENABLED=false (caso real), el usuario queda con un hash
|
|
161
|
+
# UUID dummy que ninguna password real puede igualar → 401 perpetuo.
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# MAL — rechaza no-ADMIN sin verificar si LDAP existe siquiera
|
|
166
|
+
if rol != "ADMIN":
|
|
167
|
+
raise HTTPException(400, "Los usuarios no ADMIN gestionan su contraseña en LDAP")
|
|
168
|
+
# ↑ Sin LDAP habilitado los usuarios no tienen forma de cambiar password.
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Patrón correcto**:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# BIEN — siempre verifica el flag antes de asumir el servicio
|
|
175
|
+
if rol == "ADMIN":
|
|
176
|
+
hashed = hash_password(body.password)
|
|
177
|
+
else:
|
|
178
|
+
if body.password:
|
|
179
|
+
hashed = hash_password(body.password)
|
|
180
|
+
elif not settings.AUTH_LDAP_ENABLED:
|
|
181
|
+
# Sin LDAP: generar password funcional para que el usuario pueda entrar
|
|
182
|
+
temp = _generar_temp_password()
|
|
183
|
+
hashed = hash_password(temp)
|
|
184
|
+
# devolver `temp` en la respuesta del POST UNA SOLA VEZ
|
|
185
|
+
else:
|
|
186
|
+
# LDAP habilitado: dummy OK porque el usuario se autentica fuera
|
|
187
|
+
hashed = hash_password(uuid.uuid4().hex)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Detección temprana en code review**: cualquier comentario `"para LDAP"`,
|
|
191
|
+
`"para Redis"`, `"para S3"` debe acompañarse del check del flag correspondiente.
|
|
192
|
+
Si el comentario está solo, es bug latente — el código asume un mundo que el
|
|
193
|
+
deployment puede no tener.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Sanitización PII centralizada en handlers vs refactorear N sitios
|
|
198
|
+
|
|
199
|
+
Cuando un sistema persiste logs estructurados (audit trails, error logs,
|
|
200
|
+
telemetría) y existen N sitios donde el código emite `logger.error(..., extra={...})`
|
|
201
|
+
con potencial PII en los valores, **siempre preferir sanitización centralizada en
|
|
202
|
+
el handler** sobre refactorear cada sitio individualmente.
|
|
203
|
+
|
|
204
|
+
**Decisión arquitectónica** (caso OIC v1.5 Slice 2, 2026-06-04):
|
|
205
|
+
|
|
206
|
+
| Opción | Esfuerzo | Cobertura futura | Mantenimiento |
|
|
207
|
+
|---|---|---|---|
|
|
208
|
+
| Refactorear N sitios uno por uno | O(N) turnos | Solo lo refactorizado | Cada `logger.error` nuevo requiere auditoría |
|
|
209
|
+
| Sanitización centralizada en handler | O(1) turno | Todos los sitios + futuros automáticamente | Cero auditoría manual al agregar nuevos `logger.error` |
|
|
210
|
+
|
|
211
|
+
**Patrón portable**:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
import re
|
|
215
|
+
|
|
216
|
+
_PATRON_SENSIBLE = re.compile(
|
|
217
|
+
r'(password|token|secret|jwt|authorization|cookie|api[_-]?key)([=:])([^&\s"\']+)',
|
|
218
|
+
re.IGNORECASE,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
def sanitizar_url(url: str | None) -> str | None:
|
|
222
|
+
"""Redacta query-params sensibles preservando key y separador."""
|
|
223
|
+
if not url:
|
|
224
|
+
return url
|
|
225
|
+
return _PATRON_SENSIBLE.sub(r"\1\2<redacted>", url)
|
|
226
|
+
|
|
227
|
+
def sanitizar_valor(valor: Any) -> Any:
|
|
228
|
+
"""Sanitiza recursivamente strings dentro de dict/list/tuple."""
|
|
229
|
+
if isinstance(valor, str):
|
|
230
|
+
return _PATRON_SENSIBLE.sub(r"\1\2<redacted>", valor)
|
|
231
|
+
if isinstance(valor, dict):
|
|
232
|
+
return {k: sanitizar_valor(v) for k, v in valor.items()}
|
|
233
|
+
if isinstance(valor, (list, tuple)):
|
|
234
|
+
return [sanitizar_valor(item) for item in valor]
|
|
235
|
+
return valor
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Regla del regex**:
|
|
239
|
+
- Grupo 1 (key) y grupo 2 (`=` o `:`) se preservan → mantiene legibilidad
|
|
240
|
+
(`password=<redacted>` en vez de `<redacted>`).
|
|
241
|
+
- Grupo 3 (valor) se reemplaza por `<redacted>`.
|
|
242
|
+
- Boundary del valor: `&`, whitespace, comilla, paréntesis.
|
|
243
|
+
- `api_key` y `api-key` ambos matchean con `api[_-]?key`.
|
|
244
|
+
|
|
245
|
+
**Aplicabilidad**: handlers de logging custom, middleware HTTP que redactan headers,
|
|
246
|
+
sanitización de cookies en logs, redactor de stack traces, error reporters
|
|
247
|
+
(Sentry-style). Defensa en profundidad sin tocar el código del caller.
|
|
248
|
+
|
|
249
|
+
**Limitación documentada**: el regex opera sobre strings; NO sanitiza claves cuyo
|
|
250
|
+
nombre no esté en la lista (no detecta `contraseña` en español, `pwd`, `mot_de_passe`).
|
|
251
|
+
Mantener el regex extensible vía configuración si el proyecto opera en múltiples idiomas.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Generación de tokens y passwords legibles (sin caracteres ambiguos)
|
|
256
|
+
|
|
257
|
+
Para passwords temporales (reset por admin, primer login, recuperación) que el
|
|
258
|
+
usuario debe transcribir verbalmente o desde papel, usar alfabeto SIN caracteres
|
|
259
|
+
ambiguos: `0` (cero) vs `O` (o mayúscula), `1` (uno) vs `l` (L minúscula) vs `I`
|
|
260
|
+
(i mayúscula).
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
import secrets
|
|
264
|
+
|
|
265
|
+
# 54 chars del alfabeto seguro (sin 0, O, 1, l, I)
|
|
266
|
+
_ALFABETO_LEGIBLE = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
|
|
267
|
+
|
|
268
|
+
def generar_password_temporal(longitud: int = 12) -> str:
|
|
269
|
+
"""12 chars → ~71 bits de entropía. Suficiente para temporal que debe
|
|
270
|
+
cambiarse en primer login. NUNCA persistir en texto plano; el caller
|
|
271
|
+
la hashea con bcrypt y la devuelve UNA SOLA VEZ en la respuesta del POST."""
|
|
272
|
+
return "".join(secrets.choice(_ALFABETO_LEGIBLE) for _ in range(longitud))
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**NO usar** `secrets.token_urlsafe()` para passwords visibles al humano: incluye
|
|
276
|
+
`-` y `_` que pueden confundir al transcribir. Reservar `token_urlsafe()` para
|
|
277
|
+
tokens de sesión, CSRF, magic links — strings que no se leen ni transcriben.
|
|
278
|
+
|
|
279
|
+
**Para tokens de uso programático** (API keys, session IDs, refresh tokens):
|
|
280
|
+
`secrets.token_urlsafe(32)` (32 bytes → 256 bits) o `secrets.token_hex(32)`. Sin
|
|
281
|
+
restricción de alfabeto porque el usuario nunca los teclea manualmente.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
144
285
|
## Checklist antes de merge a main
|
|
145
286
|
|
|
146
287
|
- [ ] No hay secrets hardcodeados (revisar con `git grep -i "password\|secret\|token\|key"`)
|
|
@@ -149,3 +290,6 @@ vulnerabilidad del OWASP Top 10. Las más frecuentes en este stack:
|
|
|
149
290
|
- [ ] Sin uso de `eval`, `exec`, `shell=True`
|
|
150
291
|
- [ ] Logs sin datos sensibles
|
|
151
292
|
- [ ] Dependencias nuevas auditadas
|
|
293
|
+
- [ ] Cualquier rama que asuma servicio externo (LDAP/Redis/S3) verifica su flag de config
|
|
294
|
+
- [ ] Sanitización PII centralizada en handlers (no diseminada por N sitios)
|
|
295
|
+
- [ ] Passwords temporales generadas con alfabeto sin chars ambiguos
|
package/reglas/testing.md
CHANGED
package/reglas/tests-cleanup.md
CHANGED
|
@@ -78,7 +78,7 @@ de ejecutar.
|
|
|
78
78
|
| Capturar aprendizaje recurrente | `/swl:aprender` → APRENDIZAJES.md → posible promoción a regla/skill |
|
|
79
79
|
| Release con bump de versión | `/swl:release` (sincronización de ubicaciones de versión) |
|
|
80
80
|
| Documentación viva post-feature | `documentador-swl` |
|
|
81
|
-
| Diagnóstico del sistema | `/swl:salud` |
|
|
81
|
+
| Diagnóstico del sistema | `/swl:status salud` |
|
|
82
82
|
|
|
83
83
|
### Para tareas de búsqueda y contexto
|
|
84
84
|
|
|
@@ -33,7 +33,8 @@ const args = new Set(process.argv.slice(2));
|
|
|
33
33
|
const DRY = args.has('--dry-run');
|
|
34
34
|
const SOLO_INV = args.has('--inventario');
|
|
35
35
|
const SOLO_SAL = args.has('--salud');
|
|
36
|
-
const
|
|
36
|
+
const SOLO_LLMS = args.has('--llms');
|
|
37
|
+
const AMBOS = !SOLO_INV && !SOLO_SAL && !SOLO_LLMS;
|
|
37
38
|
|
|
38
39
|
// ── Helpers ────────────────────────────────────────────────────────────
|
|
39
40
|
|
|
@@ -427,6 +428,57 @@ function generarSalud() {
|
|
|
427
428
|
return lines.join('\n');
|
|
428
429
|
}
|
|
429
430
|
|
|
431
|
+
// ── llms.txt (convención llmstxt.org) ─────────────────────────────────
|
|
432
|
+
// Índice raíz LLM-legible para descubrimiento externo por herramientas/agentes
|
|
433
|
+
// que esperan el estándar. Cifras sincronizadas con INVENTARIO (mismo cómputo)
|
|
434
|
+
// para que el gate de release no detecte drift. Adoptado de obsidian-second-brain
|
|
435
|
+
// (análisis temp/ 2026-06-05); el resto de ese repo era redundante con swl-ses.
|
|
436
|
+
function generarLlmsTxt() {
|
|
437
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(RAIZ, 'package.json'), 'utf8'));
|
|
438
|
+
const agentes = recolectarAgentes().length;
|
|
439
|
+
const skills = recolectarSkills().length;
|
|
440
|
+
const hooks = recolectarHooks().length;
|
|
441
|
+
const comandos = contarArchivos(path.join(RAIZ, 'comandos', 'swl'), '.md');
|
|
442
|
+
const reglasBase = contarArchivos(path.join(RAIZ, 'reglas'), '.md');
|
|
443
|
+
const reglasLang = fs.readdirSync(path.join(RAIZ, 'reglas', 'lenguajes'))
|
|
444
|
+
.filter(d => fs.statSync(path.join(RAIZ, 'reglas', 'lenguajes', d)).isDirectory())
|
|
445
|
+
.reduce((acc, d) => acc + contarArchivos(path.join(RAIZ, 'reglas', 'lenguajes', d), '.md'), 0);
|
|
446
|
+
|
|
447
|
+
const L = [];
|
|
448
|
+
L.push('# swl-ses (@saulwade/swl-ses)');
|
|
449
|
+
L.push('');
|
|
450
|
+
L.push(`> Sistema de ingeniería de software auto-evolutivo multi-runtime polyglot (SDLC completo), distribuido como paquete npm y plugin de Claude Code. ${agentes} agentes, ${skills} habilidades, ${comandos} comandos, ${reglasBase} reglas base y ${hooks} hooks. Soporta 11 lenguajes y 7 runtimes (Claude Code, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot). Versión ${pkg.version}.`);
|
|
451
|
+
L.push('');
|
|
452
|
+
L.push('Archivo generado por `node scripts/generar-inventario.js` — no editar a mano. Las cifras se sincronizan con INVENTARIO.md en cada regeneración.');
|
|
453
|
+
L.push('');
|
|
454
|
+
L.push('## Documentación');
|
|
455
|
+
L.push('');
|
|
456
|
+
L.push('- [README](README.md): overview público y quickstart');
|
|
457
|
+
L.push('- [Manual de uso](MANUAL_USO.md): manual operacional completo');
|
|
458
|
+
L.push('- [Comandos](COMANDOS.md): referencia detallada de cada comando `/swl:*`');
|
|
459
|
+
L.push('- [Agentes](AGENTS.md): catálogo de agentes con capacidades');
|
|
460
|
+
L.push('- [Inventario](INVENTARIO.md): conteos oficiales de todos los componentes');
|
|
461
|
+
L.push('- [Instalación](INSTALACION.md): instalación, perfiles y configuración');
|
|
462
|
+
L.push('- [Instrucciones del proyecto](CLAUDE.md): convenciones, stack y reglas');
|
|
463
|
+
L.push('');
|
|
464
|
+
L.push('## Componentes');
|
|
465
|
+
L.push('');
|
|
466
|
+
L.push(`- ${agentes} agentes especializados en \`agentes/\` (orquestación, implementación por stack, revisión, calidad, diseño)`);
|
|
467
|
+
L.push(`- ${skills} habilidades cargables bajo demanda en \`habilidades/\` (conocimiento operacional con divulgación progresiva)`);
|
|
468
|
+
L.push(`- ${comandos} comandos \`/swl:*\` en \`comandos/swl/\` (ciclo GSD, calidad, release, diagnóstico)`);
|
|
469
|
+
L.push(`- ${reglasBase} reglas base + ${reglasLang} reglas por lenguaje en \`reglas/\` (políticas obligatorias por matcher)`);
|
|
470
|
+
L.push(`- ${hooks} hooks en \`hooks/\` (telemetría, validación, seguridad; zero-deps, escrituras atómicas)`);
|
|
471
|
+
L.push('');
|
|
472
|
+
L.push('## Opcional');
|
|
473
|
+
L.push('');
|
|
474
|
+
L.push('- [CHANGELOG](CHANGELOG.md): historial de versiones');
|
|
475
|
+
L.push('- [Índice de ADRs](.planning/adrs/README.md): decisiones de arquitectura');
|
|
476
|
+
L.push('- [Variables de entorno](docs/variables-entorno.md): configuración opt-in');
|
|
477
|
+
L.push('');
|
|
478
|
+
|
|
479
|
+
return L.join('\n');
|
|
480
|
+
}
|
|
481
|
+
|
|
430
482
|
// ── Ejecutar ──────────────────────────────────────────────────────────
|
|
431
483
|
|
|
432
484
|
if (AMBOS || SOLO_INV) {
|
|
@@ -450,3 +502,14 @@ if (AMBOS || SOLO_SAL) {
|
|
|
450
502
|
console.log('SALUD.md generado correctamente.');
|
|
451
503
|
}
|
|
452
504
|
}
|
|
505
|
+
|
|
506
|
+
if (AMBOS || SOLO_LLMS) {
|
|
507
|
+
const llms = generarLlmsTxt();
|
|
508
|
+
if (DRY) {
|
|
509
|
+
console.log('\n=== llms.txt (dry-run) ===\n');
|
|
510
|
+
console.log(llms);
|
|
511
|
+
} else {
|
|
512
|
+
atomicWriteSync(path.join(RAIZ, 'llms.txt'), llms, 'utf8');
|
|
513
|
+
console.log('llms.txt generado correctamente.');
|
|
514
|
+
}
|
|
515
|
+
}
|
package/scripts/instalador.js
CHANGED
|
@@ -210,10 +210,30 @@ async function install(opciones) {
|
|
|
210
210
|
// 2b. Filtrar reglas de lenguaje por stack detectado
|
|
211
211
|
// El stack se detecta siempre que: hay reglas de lenguaje en el perfil, O
|
|
212
212
|
// se ejecuta con --force (actualización) para poder limpiar las ya instaladas.
|
|
213
|
+
// FIX (thrashing de contexto en subagentes): en scope GLOBAL las reglas
|
|
214
|
+
// por-lenguaje NO se instalan en ~/.claude/rules/. Global no tiene un proyecto
|
|
215
|
+
// que detectar, así que se instalarían los 8 lenguajes (~69K tokens) y
|
|
216
|
+
// saturarían la ventana de todo subagente que herede ~/.claude/rules/. Las
|
|
217
|
+
// reglas por-lenguaje viven project-scoped, donde el stack-filter sí aplica.
|
|
218
|
+
if (esGlobal) {
|
|
219
|
+
const antesGlobal = resolucion.archivos.length;
|
|
220
|
+
resolucion.archivos = resolucion.archivos.filter(
|
|
221
|
+
a => !(a.rutaRelativa && a.rutaRelativa.startsWith('reglas/lenguajes/'))
|
|
222
|
+
);
|
|
223
|
+
const excluidasGlobal = antesGlobal - resolucion.archivos.length;
|
|
224
|
+
if (excluidasGlobal > 0) {
|
|
225
|
+
console.log(
|
|
226
|
+
`\n[stack] Scope global: ${excluidasGlobal} regla(s) por-lenguaje excluidas ` +
|
|
227
|
+
'(se instalan project-scoped, filtradas por stack; no en ~/.claude/rules/ ' +
|
|
228
|
+
'para no saturar el contexto de subagentes).'
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
213
233
|
const tieneReglasLenguaje = resolucion.archivos.some(
|
|
214
234
|
a => a.rutaRelativa && a.rutaRelativa.startsWith('reglas/lenguajes/')
|
|
215
235
|
);
|
|
216
|
-
const necesitaStack = (tieneReglasLenguaje || force) && !allLangs;
|
|
236
|
+
const necesitaStack = (tieneReglasLenguaje || force) && !allLangs && !esGlobal;
|
|
217
237
|
|
|
218
238
|
let stackDetectado = null;
|
|
219
239
|
|
|
@@ -224,7 +244,7 @@ async function install(opciones) {
|
|
|
224
244
|
// FIX v1.6.6: si el usuario pasa --all-langs pero el perfil actual no incluye
|
|
225
245
|
// reglas/lenguajes/, el flag se ignora silenciosamente. Antes la única pista
|
|
226
246
|
// era el conteo final de archivos. Ahora emitimos warning explícito.
|
|
227
|
-
if (allLangs && !tieneReglasLenguaje) {
|
|
247
|
+
if (allLangs && !tieneReglasLenguaje && !esGlobal) {
|
|
228
248
|
console.log(
|
|
229
249
|
'\n[stack] Aviso: --all-langs ignorado — el perfil actual (' +
|
|
230
250
|
(resolucion.perfil || 'core') +
|
|
@@ -269,6 +289,16 @@ async function install(opciones) {
|
|
|
269
289
|
}
|
|
270
290
|
}
|
|
271
291
|
|
|
292
|
+
// Scope global: purgar TODAS las reglas por-lenguaje preexistentes de
|
|
293
|
+
// ~/.claude/rules/ (instalaciones previas dejaban los 8 lenguajes always-loaded,
|
|
294
|
+
// saturando el contexto de subagentes). Corre en cada install global, no solo --force.
|
|
295
|
+
if (esGlobal && rutas.reglas) {
|
|
296
|
+
const purgaGlobal = limpiarReglasSinStack(rutas.reglas, new Set());
|
|
297
|
+
if (purgaGlobal.eliminados > 0) {
|
|
298
|
+
console.log(`\n[stack] Scope global: ${purgaGlobal.eliminados} subdir(s) de reglas por-lenguaje purgadas de ~/.claude/rules/ (${purgaGlobal.lenguajes.join(', ')}) — viven project-scoped.`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
272
302
|
// 4. Detectar _userland/
|
|
273
303
|
const userlandAgentes = path.join(process.cwd(), '_userland', 'agentes');
|
|
274
304
|
const userlandHabilidades = path.join(process.cwd(), '_userland', 'habilidades');
|
|
@@ -79,7 +79,13 @@ const ENTRADAS_BASE = [
|
|
|
79
79
|
// artefactos del proyecto usuario.
|
|
80
80
|
".planning/evolution/",
|
|
81
81
|
".planning/auto-evolution/",
|
|
82
|
-
|
|
82
|
+
// locks/: contenido runtime ignorado (singleton-guard {pid,ts},
|
|
83
|
+
// fase-activa.json) EXCEPTO los plan-locks de G1 (*PLAN.md.lock), que son
|
|
84
|
+
// evidencia de aprobación versionable (audit trail SDD — aprobar-plan.md).
|
|
85
|
+
// Patrón `dir/*` + negación: git no re-incluye archivos si el DIRECTORIO
|
|
86
|
+
// está ignorado, por eso se ignora el contenido y no el dir.
|
|
87
|
+
".planning/locks/*",
|
|
88
|
+
"!.planning/locks/*PLAN.md.lock",
|
|
83
89
|
".planning/user-profile/",
|
|
84
90
|
|
|
85
91
|
// Instintos modificados automáticamente por hooks (degradacion-instintos.js)
|
|
@@ -87,6 +93,28 @@ const ENTRADAS_BASE = [
|
|
|
87
93
|
|
|
88
94
|
// Base de datos de uso
|
|
89
95
|
"usage.db",
|
|
96
|
+
|
|
97
|
+
// ── Runtime adicional: derivados regenerables, caches y telemetría ──
|
|
98
|
+
// Cobertura completada en Fase 09 tras auditar qué genera SWL en proyectos
|
|
99
|
+
// destino vs lo que ENTRADAS_BASE propagaba. Todo esto es output de runtime,
|
|
100
|
+
// regenerable, no editado por el equipo → no se commitea.
|
|
101
|
+
".planning/feature-list.json", // derivar-feature-list.js (derivado de HOJA-RUTA.md)
|
|
102
|
+
".planning/loops/", // loop-telemetry.js (/swl:verificar, /swl:status loops)
|
|
103
|
+
".planning/archive/", // rotar-audit-auto.js (audit/logs rotados y comprimidos)
|
|
104
|
+
".planning/analysis/", // outputs de análisis
|
|
105
|
+
".planning/graph.json", // code-review-graph (cache del grafo)
|
|
106
|
+
".planning/graph-cache.json", // code-review-graph (cache incremental)
|
|
107
|
+
".planning/mcp-snapshot.json", // /swl:status (smoke test MCP) / mcp-status
|
|
108
|
+
".planning/skill-index.json", // /swl:skill-search (índice FTS de skills)
|
|
109
|
+
".planning/inventario-aviso-state.json", // throttle del aviso de inventario
|
|
110
|
+
".planning/*.lock", // locks sueltos (ej. STATE.md.lock; el dir locks/ ya está arriba)
|
|
111
|
+
|
|
112
|
+
// Estado runtime de /swl:verificar --until-converge. Vive DENTRO de
|
|
113
|
+
// .planning/fases/, que SÍ contiene plantillas commiteadas
|
|
114
|
+
// (0N-CONTEXTO/PLAN/RESUMEN/VERIFICACION.md). Glob específico para ignorar
|
|
115
|
+
// SOLO el estado de convergencia, nunca esas plantillas.
|
|
116
|
+
".planning/fases/*-converge-state.json",
|
|
117
|
+
".planning/fases/*-converge-run-*.json",
|
|
90
118
|
];
|
|
91
119
|
|
|
92
120
|
// Entradas adicionales por runtime (se agregan cuando install usa ese target)
|