@saulwade/swl-ses 1.3.5 → 1.3.8

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 v1.3.5
1
+ # CLAUDE.md — @saulwade/swl-ses v1.3.8
2
2
 
3
3
  ## Reglas de máxima prioridad (aplican SIEMPRE, sin excepción)
4
4
 
@@ -56,7 +56,7 @@ El Read tool sigue siendo correcto para `.pdf` (≤20 páginas), `.md`, `.txt` y
56
56
  - **YAML inline en frontmatter**: `tools: [Read, Write]`, `skillsInvocables: [skill-a]`. NUNCA CSV string ni mezcla con lista multilínea
57
57
  - **Mensajes de commit**: imperativo en español, formato `<tipo>(<scope>): <descripción>`
58
58
  - **Sin `console.log` en producción** — excepto en `scripts/`, `bin/`, `hooks/`, `gateway/` (CLIs y daemons)
59
- - **`@latest` en npx**: todo mensaje del installer/docs usa `npx swl-ses@latest <comando>`. Sin `@latest`, npx cachea la primera versión y el usuario corre vieja sin saberlo
59
+ - **Nombre completo del paquete en npx**: todo mensaje del installer/docs usa `npx -y @saulwade/swl-ses@latest <comando>`. **NUNCA** `npx swl-ses@latest <comando>` sin el scope `@saulwade/` — eso resuelve al paquete legacy DEPRECATED (v5.13.1) que aún existe en npm tras el rebrand de 2026-04-30. El `@latest` es indispensable: sin él npx reutiliza la primera versión cacheada y el usuario corre código viejo sin saberlo. El `-y` evita la prompt de confirmación en CI/scripts
60
60
 
61
61
  ## Convenciones de arquitectura
62
62
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # swl-ses v1.3.5
1
+ # swl-ses v1.3.8
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
 
@@ -46,8 +46,8 @@ El setup requiere **dos comandos en orden**, con propósitos distintos:
46
46
 
47
47
  | Comando | Qué crea | Dónde | Instala agentes/skills |
48
48
  |---------|----------|-------|------------------------|
49
- | `npx swl-ses@latest init` | `.planning/` y `_userland/` (plantillas vacías) | En el proyecto actual | ❌ No |
50
- | `npx swl-ses@latest install` | Agentes, skills, reglas, hooks, comandos `/swl:*` | En `.claude/` del proyecto o en `~/.claude/` global | ✅ Sí |
49
+ | `npx @saulwade/swl-ses@latest init` | `.planning/` y `_userland/` (plantillas vacías) | En el proyecto actual | ❌ No |
50
+ | `npx @saulwade/swl-ses@latest install` | Agentes, skills, reglas, hooks, comandos `/swl:*` | En `.claude/` del proyecto o en `~/.claude/` global | ✅ Sí |
51
51
 
52
52
  **`init` siempre es local al proyecto.** `install` puede ser local (`--local`, default) o global (`--global`).
53
53
 
@@ -59,9 +59,9 @@ El setup requiere **dos comandos en orden**, con propósitos distintos:
59
59
 
60
60
  ```bash
61
61
  cd /ruta/a/tu/proyecto
62
- npx swl-ses@latest init # Crea .planning/ y _userland/
63
- npx swl-ses@latest install --target claude --profile core # Instala agentes, skills, hooks y reglas
64
- npx swl-ses@latest doctor # Verifica que todo quedó correcto
62
+ npx @saulwade/swl-ses@latest init # Crea .planning/ y _userland/
63
+ npx @saulwade/swl-ses@latest install --target claude --profile core # Instala agentes, skills, hooks y reglas
64
+ npx @saulwade/swl-ses@latest doctor # Verifica que todo quedó correcto
65
65
  ```
66
66
 
67
67
  No requiere autenticación. El paquete `swl-ses` está publicado en npmjs.
@@ -131,18 +131,18 @@ claude
131
131
 
132
132
  | Comando | Descripción |
133
133
  |---------|-------------|
134
- | `npx swl-ses@latest init` | Crea `.planning/` (plantillas de planificación) y `_userland/` (tus personalizaciones) en el proyecto actual. **No instala agentes ni skills.** |
135
- | `npx swl-ses@latest install` | Instala agentes, skills, reglas, hooks y comandos `/swl:*` en el runtime destino (`.claude/` local o `~/.claude/` global). |
136
- | `npx swl-ses@latest doctor` | Diagnostica problemas de la instalación |
137
- | `npx swl-ses@latest update` | Actualiza componentes instalados |
138
- | `npx swl-ses@latest uninstall` | Desinstala componentes del runtime |
139
- | `npx swl-ses@latest info` | Muestra información del sistema instalado |
140
- | `npx swl-ses@latest skills list` | Lista skills instalados |
141
- | `npx swl-ses@latest skills add <fuente>` | Agrega skill desde repo Git, owner/repo, o path local |
142
- | `npx swl-ses@latest skills remove <nombre>` | Remueve un skill individual |
143
- | `npx swl-ses@latest agents list` | Lista agentes instalados |
144
- | `npx swl-ses@latest agents add <fuente>` | Agrega agente desde repo Git o path local |
145
- | `npx swl-ses@latest agents remove <nombre>` | Remueve un agente individual |
134
+ | `npx @saulwade/swl-ses@latest init` | Crea `.planning/` (plantillas de planificación) y `_userland/` (tus personalizaciones) en el proyecto actual. **No instala agentes ni skills.** |
135
+ | `npx @saulwade/swl-ses@latest install` | Instala agentes, skills, reglas, hooks y comandos `/swl:*` en el runtime destino (`.claude/` local o `~/.claude/` global). |
136
+ | `npx @saulwade/swl-ses@latest doctor` | Diagnostica problemas de la instalación |
137
+ | `npx @saulwade/swl-ses@latest update` | Actualiza componentes instalados |
138
+ | `npx @saulwade/swl-ses@latest uninstall` | Desinstala componentes del runtime |
139
+ | `npx @saulwade/swl-ses@latest info` | Muestra información del sistema instalado |
140
+ | `npx @saulwade/swl-ses@latest skills list` | Lista skills instalados |
141
+ | `npx @saulwade/swl-ses@latest skills add <fuente>` | Agrega skill desde repo Git, owner/repo, o path local |
142
+ | `npx @saulwade/swl-ses@latest skills remove <nombre>` | Remueve un skill individual |
143
+ | `npx @saulwade/swl-ses@latest agents list` | Lista agentes instalados |
144
+ | `npx @saulwade/swl-ses@latest agents add <fuente>` | Agrega agente desde repo Git o path local |
145
+ | `npx @saulwade/swl-ses@latest agents remove <nombre>` | Remueve un agente individual |
146
146
 
147
147
  ### Opciones de install
148
148
 
@@ -196,43 +196,43 @@ claude
196
196
 
197
197
  ```bash
198
198
  # Perfil básico en Claude Code
199
- npx swl-ses@latest install --target claude --profile core
199
+ npx @saulwade/swl-ses@latest install --target claude --profile core
200
200
 
201
201
  # Backend Python en Gemini CLI
202
- npx swl-ses@latest install --target gemini --profile backend-python
202
+ npx @saulwade/swl-ses@latest install --target gemini --profile backend-python
203
203
 
204
204
  # Frontend React en GitHub Copilot
205
- npx swl-ses@latest install --target copilot --profile frontend-react
205
+ npx @saulwade/swl-ses@latest install --target copilot --profile frontend-react
206
206
 
207
207
  # Full-stack en OpenClaude (multi-proveedor, usa .claude/ igual que Claude Code)
208
- npx swl-ses@latest install --target openclaude --profile fullstack-python-angular
208
+ npx @saulwade/swl-ses@latest install --target openclaude --profile fullstack-python-angular
209
209
 
210
210
  # Full-stack en OpenCode
211
- npx swl-ses@latest install --target opencode --profile fullstack-python-angular
211
+ npx @saulwade/swl-ses@latest install --target opencode --profile fullstack-python-angular
212
212
 
213
213
  # Perfil completo en directorio global
214
- npx swl-ses@latest install --target claude --profile completo --global
214
+ npx @saulwade/swl-ses@latest install --target claude --profile completo --global
215
215
 
216
216
  # Agregar skills desde GitHub con selector interactivo
217
- npx swl-ses@latest skills add anthropics/skills
217
+ npx @saulwade/swl-ses@latest skills add anthropics/skills
218
218
 
219
219
  # Agregar un skill específico por nombre
220
- npx swl-ses@latest skills add anthropics/skills --skill docx
220
+ npx @saulwade/swl-ses@latest skills add anthropics/skills --skill docx
221
221
 
222
222
  # Agregar todos los skills de un repo sin selector
223
- npx swl-ses@latest skills add anthropics/skills --all
223
+ npx @saulwade/swl-ses@latest skills add anthropics/skills --all
224
224
 
225
225
  # Agregar skill desde URL completa
226
- npx swl-ses@latest skills add https://github.com/user/repo --skill mi-skill
226
+ npx @saulwade/swl-ses@latest skills add https://github.com/user/repo --skill mi-skill
227
227
 
228
228
  # Agregar agente desde path local
229
- npx swl-ses@latest agents add ./mis-agentes --agent mi-agente
229
+ npx @saulwade/swl-ses@latest agents add ./mis-agentes --agent mi-agente
230
230
 
231
231
  # Ver que se instalaria sin hacer cambios
232
- npx swl-ses@latest install --target codex --profile core --dry-run
232
+ npx @saulwade/swl-ses@latest install --target codex --profile core --dry-run
233
233
 
234
234
  # Ver información del sistema
235
- npx swl-ses@latest info --target claude
235
+ npx @saulwade/swl-ses@latest info --target claude
236
236
  ```
237
237
 
238
238
  ## Agentes (59)
@@ -453,7 +453,7 @@ Ver [INSTALACION.md](INSTALACION.md) para configuración detallada de autenticac
453
453
  ## Verificación (doctor)
454
454
 
455
455
  ```bash
456
- npx swl-ses@latest doctor
456
+ npx @saulwade/swl-ses@latest doctor
457
457
  ```
458
458
 
459
459
  Verifica: Node.js >= 22, runtimes detectados, `.planning/` completo, `_userland/` presente, estado íntegro, permisos, `.env` en `.gitignore`. Repara automáticamente hooks sin `"type": "command"` en settings.json.
@@ -514,8 +514,8 @@ Un proyecto típico (ej. construir una App Fullstack) usando SWL sigue estos pas
514
514
 
515
515
  1. **Instalación y Setup inicial**
516
516
  ```bash
517
- npx swl-ses@latest init
518
- npx swl-ses@latest install --target claude --profile fullstack-node-react
517
+ npx @saulwade/swl-ses@latest init
518
+ npx @saulwade/swl-ses@latest install --target claude --profile fullstack-node-react
519
519
  ```
520
520
 
521
521
  2. **Definición del Proyecto (Discovery)**
@@ -17,9 +17,12 @@ Este comando es **complementario a `/swl:compactar`**, no lo reemplaza. Compacta
17
17
  - Saul lo pide explícitamente.
18
18
  - La sesión produjo una decisión arquitectural que afecta a otros proyectos del ecosistema.
19
19
 
20
- ## Paso 0 — Validación del destino
20
+ ## Paso 0 — Validación del destino y canal de escritura
21
21
 
22
- Verifica que el vault existe y es accesible:
22
+ Hay **dos canales** posibles para escribir al vault. El canal preferido es el
23
+ MCP de Obsidian; el filesystem directo es fallback documentado.
24
+
25
+ ### 0a — Validar el vault en filesystem (para lectura y detección)
23
26
 
24
27
  ```bash
25
28
  test -d "F:\Google Drive\Developer\Obsidian\Vault\SWL\00-Inbox" \
@@ -29,6 +32,29 @@ test -d "F:\Google Drive\Developer\Obsidian\Vault\SWL\00-Inbox" \
29
32
 
30
33
  Si la ruta no es accesible (por ejemplo, Google Drive no sincronizado o letra de unidad distinta), **abortar con mensaje claro**. No intentes rutas alternativas sin permiso explícito.
31
34
 
35
+ ### 0b — Detectar disponibilidad del MCP de Obsidian
36
+
37
+ Verifica si los tools `mcp__obsidian__obsidian_append_content` o
38
+ `mcp__obsidian__obsidian_patch_content` están cargados o deferidos:
39
+
40
+ - Si aparecen como **deferred** en `<system-reminder>`, cargar el schema con
41
+ `ToolSearch(query="select:mcp__obsidian__obsidian_append_content", ...)`.
42
+ - Si tras `ToolSearch` siguen sin estar disponibles, el MCP server no está
43
+ corriendo (Obsidian cerrado o plugin Local REST API desactivado). En ese
44
+ caso usar canal de fallback (filesystem directo) — ver Paso 4.
45
+
46
+ **Por qué MCP-first**: el hook `proteccion-rutas.js` bloquea la herramienta
47
+ `Write` con destino fuera del CWD del proyecto. La ruta del vault
48
+ (`F:\Google Drive\...`) siempre cae fuera del CWD si trabajas en
49
+ `D:\Python\<proyecto>\`. El MCP de Obsidian opera vía HTTPS al puerto 27124
50
+ del plugin Local REST API — **no pasa por el hook de filesystem**, así que
51
+ nunca dispara el bloqueo.
52
+
53
+ Defaultear a filesystem cuando el MCP está disponible es un anti-patrón
54
+ documentado en `reglas/consultar-vault-primero.md § Workflow forzoso para
55
+ escritura al vault`. El bloqueo por `proteccion-rutas.js` no es una falla a
56
+ esquivar — es una señal de que el canal correcto es el MCP.
57
+
32
58
  ## Paso 1 — Identificación del proyecto actual
33
59
 
34
60
  Detecta qué proyecto eres leyendo:
@@ -205,25 +231,72 @@ Ejecutar `/sync-projects {proyecto-slug}` en el vault para integrar los cambios
205
231
 
206
232
  ## Paso 4 — Escritura en el vault
207
233
 
208
- Escribe el archivo en:
234
+ El archivo destino es:
209
235
 
210
236
  ```
211
237
  F:\Google Drive\Developer\Obsidian\Vault\SWL\00-Inbox\YYYY-MM-DD_HHMM_export-{proyecto-slug}.md
212
238
  ```
213
239
 
214
- Usar UTF-8 sin BOM. En PowerShell:
240
+ Con UTF-8 sin BOM. Usar **uno de dos canales** según disponibilidad:
241
+
242
+ ### Canal A (preferido) — MCP de Obsidian
243
+
244
+ Si el Paso 0b confirmó que `mcp__obsidian__obsidian_append_content` está
245
+ disponible (cargado directamente o tras `ToolSearch`), usar este canal:
246
+
247
+ ```jsonc
248
+ // La ruta es RELATIVA al vault root (no incluye F:\...\SWL\)
249
+ mcp__obsidian__obsidian_append_content({
250
+ filepath: "00-Inbox/YYYY-MM-DD_HHMM_export-{proyecto-slug}.md",
251
+ content: "<contenido completo del export>"
252
+ })
253
+ ```
254
+
255
+ Ventajas frente al filesystem:
256
+ - **No pasa por `proteccion-rutas.js`** — el MCP opera vía HTTPS al puerto
257
+ 27124, fuera del flujo de Bash/Write/Edit.
258
+ - **Sin staging intermedio**: escribe directamente al archivo final del vault.
259
+ - **Auditable**: el plugin Local REST API de Obsidian registra el acceso.
260
+ - **Cross-OS**: el wrapper funciona idéntico en Windows/macOS/Linux sin
261
+ manejar separators de path.
262
+
263
+ Notas operativas:
264
+ - Si el archivo ya existe con ese timestamp (raro), agregar sufijo `_b`
265
+ al nombre antes de invocar `append_content`. El MCP de obsidian no
266
+ sobreescribe si el archivo existe — `append` agrega al final.
267
+ - Si se necesita escribir secciones específicas en lugar de un archivo
268
+ completo, usar `mcp__obsidian__obsidian_patch_content` con
269
+ `target_type: "heading"`.
270
+
271
+ ### Canal B (fallback) — Filesystem directo
272
+
273
+ Solo cuando el MCP no responde tras `ToolSearch` (Obsidian cerrado, plugin
274
+ desactivado, sin red local). **Esto va a chocar con `proteccion-rutas.js`**
275
+ si el CWD es el directorio del proyecto, así que requiere ejecución vía
276
+ Bash con redirección o vía un comando del CLI nativo del SO:
215
277
 
216
278
  ```powershell
279
+ # PowerShell — UTF-8 sin BOM
217
280
  $encoding = New-Object System.Text.UTF8Encoding($false)
218
281
  [System.IO.File]::WriteAllText($path, $content, $encoding)
219
282
  ```
220
283
 
221
- En Node.js hook o script:
222
-
223
- ```javascript
224
- fs.writeFileSync(path, content, { encoding: 'utf8' });
284
+ ```bash
285
+ # Bash + heredoc — UTF-8 sin BOM por default en Node 18+
286
+ cat > "$path" <<'EOF'
287
+ <contenido del export>
288
+ EOF
225
289
  ```
226
290
 
291
+ **No usar `Write` directo** desde la herramienta del agente — `proteccion-rutas.js`
292
+ lo bloquea. Si por algún motivo el agente necesita usar `Write`, primero
293
+ escribe a `_userland/staging/<timestamp>.md` dentro del CWD, luego mueve con
294
+ `Bash` (`mv` o PowerShell `Move-Item`).
295
+
296
+ Reportar al usuario qué canal se usó:
297
+ - Canal A → `[OK] Vía: MCP Obsidian (puerto 27124)`
298
+ - Canal B → `[OK] Vía: filesystem directo (MCP no disponible)`
299
+
227
300
  ## Paso 5 — Confirmación
228
301
 
229
302
  Reporta al usuario:
@@ -267,6 +340,12 @@ Próximo paso: al abrir el vault, ejecuta:
267
340
  - Duplicar con el `COMPACTACION.md` del proyecto (copiar pega tal cual). El export es una **síntesis para vault**, no un espejo.
268
341
  - Intentar escribir directamente en `02-Projects/` del vault. Eso es zona ⚠️ en el vault — solo Saul decide si promoverlo.
269
342
  - Usar rutas con backslash no escapadas en código generado.
343
+ - **Defaultear a filesystem cuando el MCP de Obsidian está disponible**.
344
+ El bloqueo por `proteccion-rutas.js` no es una falla a esquivar con Bash
345
+ staging — es señal de que el canal correcto es el MCP. Ver Paso 0b.
346
+ - **Recurrir al workaround del filesystem antes de cargar el schema del
347
+ MCP con `ToolSearch`**. Tools deferred ≠ tools ausentes — el MCP server
348
+ está corriendo, solo falta cargar el schema. Cargar antes de defaultear.
270
349
 
271
350
  ## Relación con otros comandos SWL
272
351
 
@@ -285,7 +364,20 @@ Produce:
285
364
 
286
365
  ```
287
366
  [OK] Export creado: F:\Google Drive\Developer\Obsidian\Vault\SWL\00-Inbox\2026-04-16_2130_export-sigaf.md (487 palabras)
367
+ [OK] Vía: MCP Obsidian (puerto 27124)
368
+ [OK] Enlace canónico: [[DEV - SIGAF]]
288
369
 
289
370
  Próximo paso: al abrir el vault, ejecuta:
290
371
  /sync-projects sigaf
291
372
  ```
373
+
374
+ ## Historial de cambios del comando
375
+
376
+ - **v1.3.8** (2026-05-11) — Agregado flujo MCP-first en Paso 4 con detección
377
+ en Paso 0b. Origen: en la sesión v1.3.4 → v1.3.8 el comando defaultó a
378
+ `Write` directo al filesystem que fue bloqueado por `proteccion-rutas.js`.
379
+ El fallback al MCP funcionó pero quedó manual. Esta versión documenta
380
+ el orden de preferencia (MCP primero, filesystem como fallback explícito)
381
+ y agrega la nota de "tools deferred ≠ tools ausentes" en anti-patrones.
382
+ Aplicación de la regla `consultar-vault-primero.md § Workflow forzoso
383
+ para escritura al vault`.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: extractor-de-aprendizajes
3
3
  description: Convertir errores y patrones descubiertos durante la implementación en nuevas habilidades o reglas. Ciclo de mejora continua del sistema SWL.
4
- version: "1.0.3"
4
+ version: "1.0.4"
5
5
  herramientasPermitidas: [Read]
6
6
  exclusiones:
7
7
  - "No cargar para actualizar el perfil del usuario — las correcciones explícitas del usuario van a `instintos/perfil-usuario.yaml` vía `perfilador-usuario-swl`, no a APRENDIZAJES.md."
@@ -10,8 +10,8 @@ exclusiones:
10
10
  - "No cargar si el aprendizaje no tiene causa raíz identificada — documentar síntoma sin causa produce reglas que no previenen el error real."
11
11
  evolvable: true # default para skill estandar
12
12
  evolved: true
13
- evolved-from: "1.1.1"
14
- evolved-at: "2026-05-02"
13
+ evolved-from: "1.0.3"
14
+ evolved-at: "2026-05-11"
15
15
  evolved-by: "aprender"
16
16
  evolved-note: "Extender gotcha Explore (papers → papers+repos) tras confirmación x4 — sync desde skill global"
17
17
  ---
@@ -308,6 +308,10 @@ Durante `/swl:aprender`, aplicar estas reglas:
308
308
 
309
309
  *Para repos externos (Modo B)*: 4 filtros críticos: (1) ¿qué % es teoría/código no-portable vs portable? — si >70% no-portable, recortar; (2) **¿la propuesta reescribe mecanismos existentes en el proyecto destino?** — VERIFICAR con `Grep`/`Read` 2-3 afirmaciones concretas del agente contra el código real ANTES de aceptar (ej: agente dice "X usa Y" → `grep -l Y` para confirmar); (3) ¿LOC nuevas estimadas vs reutilizar lo existente? — si la propuesta supera 500 LOC para un solo patrón, hay sobre-ingeniería; (4) ¿el alcance reducido cubre 80% del valor? — Pareto: identificar el patrón mínimo que captura la mayor parte del beneficio. **Patrón de validación obligatorio**: extraer 2-3 afirmaciones factuales del reporte del Explore (ej: "X usa LiteLLM", "no existe Gleaning en el proyecto") y verificar cada una con `Grep`/`Read` antes de aceptar el plan.
310
310
  - **Hooks de calidad pre-commit bloquean fixtures de tests como falsos positivos**: el hook `calidad-pre-commit.js` aplica regex `\b(api_key|password|token|secret)\s*[=:]\s*["'][^"'\s]{4,}["']` que matchea fixtures legítimos en archivos de test. Caso real: test que valida que la función `sanitizar()` redacta `api_key="abc12345xyz"` se bloquea. Causa: el hook no distingue contexto de test vs producción. Solución: en archivos de test, construir fixtures con concatenación de strings (`'api' + '_key'`, `'pass' + 'word'`) o agregar marcador placeholder reconocido por el hook (`fake_`, `dummy_`, `placeholder`, `example`, `os.environ`). NUNCA bypassear el hook con `--no-verify` — el detector cumple su función; ajustar el fixture es lo correcto.
311
+ - **Regex de path-matching `/[\\/]<dir>[\\/]/` falla con paths relativos sin slash inicial** [CONFIRMADO x4]: hooks que filtran archivos por directorio (ej: `hooks/extraccion-aprendizajes.js` con `PATRONES_ARCHIVO_SWL_EXCLUIDO`) usan patrones que requieren un separator ANTES del nombre. Caso real: path `scripts/lib/foo.js` (sin slash inicial) eludía el filtro de exclusión y generaba placeholders espurios en APRENDIZAJES.md cada vez que se hacía `Edit` o `Write` sobre archivos del sistema SWL. Causa: el regex `[\\/]` requiere un caracter slash/backslash previo; cuando el path empieza con el nombre del directorio directamente, no matchea. Solución: usar `/(?:^|[\\/])<dir>[\\/]/` para aceptar tanto el inicio del string como un separator previo. Evidencia: 4 placeholders eliminados manualmente entre v1.3.3-v1.3.5 antes de identificar la causa raíz; fix endurecido aplicado en v1.3.5 (Fix I).
312
+ - **`git ls-files` es preferible a `fs.readdir` recursivo para tests anti-regresión que escanean el repo**: usar `execSync('git ls-files')` limita el escaneo a archivos versionados — evita `node_modules/`, `.git/`, `_userland/`, archivos temporales y backups sin enumerar exclusiones. Caso real: `tests/scripts/no-legacy-npx-pattern.test.js` v1.3.6 escanea 1000+ archivos versionados en <200ms; el equivalente con `fs.readdir` recursivo más exclusiones manuales sería más lento y propenso a olvidar paths. Cuando el test es de "calidad del repo" (no de comportamiento), `git ls-files` es la primitiva correcta.
313
+ - **Whitelist enumerado versión-por-versión en tests anti-regresión genera deuda perpetua**: un whitelist tipo `RELEASE-NOTES-v1.3.[0-5].md` requiere agregar una entrada con cada release nueva — el test fallará al publicar v1.3.6, v1.3.7, etc. Caso real: v1.3.6 publicó a GitHub Packages pero falló en npmjs porque el whitelist v1.3.5 no cubría el nuevo `RELEASE-NOTES-v1.3.6.md`. Causa: enumeración cuando la categoría es semánticamente catch-all. Solución: si el archivo es histórico inmutable por definición (release notes, ADRs, changelog entries cerrados), usar patrón catch-all `^RELEASE-NOTES-.*\.md$` desde el inicio. Aplicar regla: *si cada release nueva agregaría entry al whitelist, el whitelist está mal diseñado.*
314
+ - **Fix combinado en dos capas (específico A + general B) es más robusto que cada uno aislado** [PATRÓN VALIDADO]: cuando un bug tiene múltiples vectores de entrada, aplicar dos defensas con cobertura distinta. Caso real: `hooks/extraccion-aprendizajes.js` v1.3.4 — Capa A: lista de archivos meta excluidos (`RELEASE-NOTES-*.md`, `RESUMEN.md`, etc.) que filtra por path; Capa B: detector estructural de "contexto solo headings" (>60% líneas son `##`/`###`) que filtra por contenido. Si A falla (archivo con nombre nuevo no en lista), B protege. Si B falsea (heading legítimo en bug real), A asegura. Patrón aplicable a cualquier filtro de seguridad/calidad donde el espacio de inputs hostiles es abierto.
311
315
 
312
316
  ## Anti-patrones del proceso de extracción
313
317
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: swl-claudemd
3
3
  description: Conocimiento operacional para auditar y mantener archivos CLAUDE.md — contrato canónico de secciones (best practices Anthropic, ADR-0016), umbrales de bloat (líneas totales, bullets gigantes, placeholders, @references rotas), reglas de extracción a archivos referenciados con @, y plantillas de inicialización (init-user para ~/.claude/CLAUDE.md, init-project para CLAUDE.md raíz detectando stack). Provee las reglas; el comando /swl:claudemd ejecuta el flujo. Cargar desde ese comando o cuando el hook claudemd-bloat-detector sugiera intervención.
4
- version: "1.0.1"
4
+ version: "1.0.2"
5
5
  herramientasPermitidas: [Read, Write, Edit, Bash, Glob, Grep]
6
6
  exclusiones:
7
7
  - "No cargar para editar reglas globales en ~/.claude/rules/ — usar Edit directo."
@@ -205,6 +205,20 @@ Genera `./CLAUDE.md` raíz del proyecto detectando stack actual.
205
205
  pueden NO tener todas las secciones canónicas (porque heredan del root).
206
206
  Por ahora el auditor aplica el contrato uniforme; si el ADR-0007 se
207
207
  acepta, el auditor debe distinguir root vs subdirectorio.
208
+ - **Codificar el patrón legacy/malo como ejemplo "correcto" en una regla
209
+ de CLAUDE.md codifica el bug**: una regla cuya prosa enseña el patrón
210
+ correcto pero cuyo *ejemplo* muestra el patrón malo se auto-perpetúa.
211
+ Cada release nuevo copia el ejemplo y replica el problema. Caso real:
212
+ CLAUDE.md v1.3.5 línea 59 decía *"todo mensaje del installer/docs usa
213
+ `npx swl-ses@latest <comando>`"* — pero `npx swl-ses@latest` sin scope
214
+ resuelve al paquete legacy DEPRECATED tras el rebrand 2026-04-30. La
215
+ regla acumuló 152 ocurrencias del patrón malo en 8 releases consecutivos
216
+ hasta v1.3.6. Solución: las reglas DEBEN mostrar el patrón correcto en
217
+ el ejemplo. Si la regla tiene que citar un patrón malo (para
218
+ prohibirlo), envolverlo en bloque "NUNCA" explícito separado del
219
+ ejemplo de uso correcto. Pregunta de auditoría: *si un autor de release
220
+ futuro copia el ejemplo de esta regla literalmente, ¿produce código
221
+ correcto?* Si no, la regla está mal escrita.
208
222
 
209
223
  ## Señales de alerta
210
224
 
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "lockfileVersion": 1,
3
- "generatedAt": "2026-05-11T20:58:20.028Z",
3
+ "generatedAt": "2026-05-11T22:55:18.517Z",
4
4
  "skillsCount": 155,
5
- "lockHash": "sha256:32199636eb3c585dd1090cb9f6081aaaaef886241b304c697b2eaf27fd0303ca",
5
+ "lockHash": "sha256:b4860049091d23b9e822f9b2930f5d1bfb19cd9299fa074e4bb71852518769cc",
6
6
  "skills": [
7
7
  {
8
8
  "nombre": "accesibilidad-a11y",
@@ -441,9 +441,9 @@
441
441
  {
442
442
  "nombre": "extractor-de-aprendizajes",
443
443
  "path": "habilidades/extractor-de-aprendizajes/SKILL.md",
444
- "hash": "sha256:2e791dc7c05395272e7de47573daac087faa99142023a22c29e24b3f749b8cd3",
445
- "bytes": 17541,
446
- "version": "\"1.0.3\""
444
+ "hash": "sha256:4e7ec2961f7c4c6bc52759516a1d7f9f9c839883c09b95951f0c68b4d803ad3d",
445
+ "bytes": 20527,
446
+ "version": "\"1.0.4\""
447
447
  },
448
448
  {
449
449
  "nombre": "fastapi-experto",
@@ -952,9 +952,9 @@
952
952
  {
953
953
  "nombre": "swl-claudemd",
954
954
  "path": "habilidades/swl-claudemd/SKILL.md",
955
- "hash": "sha256:18f56f2c9d19e0671a42b47186465b04246ac38c41ec058440c25d683a57b92b",
956
- "bytes": 10578,
957
- "version": "\"1.0.1\""
955
+ "hash": "sha256:18cef250bd32a7841db3b6362b9303679bf2851e5e1efe7f3d81f0dd514ec5eb",
956
+ "bytes": 11585,
957
+ "version": "\"1.0.2\""
958
958
  },
959
959
  {
960
960
  "nombre": "swl-dashboard",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saulwade/swl-ses",
3
- "version": "1.3.5",
3
+ "version": "1.3.8",
4
4
  "description": "Sistema de ingenieria de software auto-evolutivo multi-runtime polyglot con 59 agentes, 155 habilidades, 43 comandos, 64 reglas y 41 hooks. Soporta 11 lenguajes y 5 runtimes: Claude Code, Copilot, OpenCode, Codex y Gemini CLI. 100% en espanol (Mexico). Incluye gateway bidireccional con relay Telegram a Claude Code.",
5
5
  "bin": {
6
6
  "swl-ses": "bin/swl-ses.js",
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swl-ses",
3
- "version": "1.3.5",
3
+ "version": "1.3.8",
4
4
  "description": "Sistema de ingenieria de software auto-evolutivo multi-runtime polyglot. 59 agentes, 155 habilidades, 43 comandos, 64 reglas y 41 hooks. 62 librerias. 11 lenguajes. Soporta Claude Code, Copilot, OpenCode, Codex y Gemini CLI.",
5
5
  "author": "Saul Wade Leon",
6
6
  "license": "MIT",
@@ -29,7 +29,7 @@ function info(_subcomando, opciones) {
29
29
 
30
30
  if (runtimes.length === 0) {
31
31
  console.log(' (ninguno instalado)');
32
- console.log(' Ejecuta: npx swl-ses@latest install --target claude');
32
+ console.log(' Ejecuta: npx @saulwade/swl-ses@latest install --target claude');
33
33
  } else {
34
34
  for (const runtime of runtimes) {
35
35
  const dirs = [];
@@ -116,8 +116,8 @@ function init(opciones) {
116
116
  console.log(` Commitéalo. Los archivos en .claude/agents/, hooks/, etc. NO.`);
117
117
  console.log('');
118
118
  console.log(`Siguiente paso:`);
119
- console.log(` npx swl-ses@latest install --target claude --profile core`);
120
- console.log(` npx swl-ses@latest doctor`);
119
+ console.log(` npx @saulwade/swl-ses@latest install --target claude --profile core`);
120
+ console.log(` npx @saulwade/swl-ses@latest doctor`);
121
121
  console.log('');
122
122
  console.log(` (usar @latest evita que npx use una versión cacheada vieja)`);
123
123
  console.log('');
@@ -528,7 +528,7 @@ async function install(opciones) {
528
528
  if (hookFilesInstalados.length > 0) {
529
529
  if (esGlobal) {
530
530
  console.log(' ~ Hooks: omitiendo registro en settings global (solo se registran a nivel proyecto)');
531
- console.log(' Los hooks se activan al instalar a nivel proyecto con: npx swl-ses@latest install --target claude');
531
+ console.log(' Los hooks se activan al instalar a nivel proyecto con: npx @saulwade/swl-ses@latest install --target claude');
532
532
  } else {
533
533
  const settingsPath = rutaSettings(runtime, rutas.base);
534
534
  try {
@@ -794,7 +794,7 @@ async function install(opciones) {
794
794
  }
795
795
 
796
796
  console.log('\nSiguiente paso:');
797
- console.log(' npx swl-ses@latest doctor');
797
+ console.log(' npx @saulwade/swl-ses@latest doctor');
798
798
  console.log('');
799
799
  console.log(' (usar @latest evita el caché stale de npx — ver MANUAL_USO.md)');
800
800
  console.log('');
@@ -19,8 +19,8 @@
19
19
  * redirige stderr para que falle silenciosamente.
20
20
  *
21
21
  * Uso:
22
- * npx swl-ses@latest install-git-hook
23
- * npx swl-ses@latest install-git-hook --force (reemplaza hook existente)
22
+ * npx @saulwade/swl-ses@latest install-git-hook
23
+ * npx @saulwade/swl-ses@latest install-git-hook --force (reemplaza hook existente)
24
24
  */
25
25
 
26
26
  const fs = require('fs');
@@ -192,7 +192,7 @@ function actualizarGitignore(cwd, extras = []) {
192
192
  MARKER_INICIO,
193
193
  "# swl-ses: tooling de desarrollo — no forma parte del proyecto.",
194
194
  "# Framework, runtime y métricas generadas automáticamente.",
195
- "# Para reinstalar: npx swl-ses@latest install",
195
+ "# Para reinstalar: npx @saulwade/swl-ses@latest install",
196
196
  ...entradas,
197
197
  MARKER_FIN,
198
198
  "",
@@ -65,7 +65,7 @@ class TransformadorClaude extends TransformadorBase {
65
65
  const lineas = [
66
66
  `> Gestionado por swl-ses v${contexto.version} — no editar entre estos marcadores.`,
67
67
  `> Regenerado en ${fecha} con perfil \`${contexto.perfil || 'default'}\`.`,
68
- `> Para excluir este bloque en futuras actualizaciones: \`npx swl-ses@latest install --no-claudemd\`.`,
68
+ `> Para excluir este bloque en futuras actualizaciones: \`npx @saulwade/swl-ses@latest install --no-claudemd\`.`,
69
69
  '',
70
70
  ];
71
71
 
@@ -39,7 +39,7 @@ class TransformadorCodex extends TransformadorBase {
39
39
  lineas.push('# AGENTS.md — Sistema SWL');
40
40
  lineas.push('');
41
41
  lineas.push(`> Generado por swl-ses v${contexto.version} — ${new Date().toISOString().split('T')[0]}`);
42
- lineas.push('> NO editar manualmente. Regenerar con: npx swl-ses@latest install --target codex');
42
+ lineas.push('> NO editar manualmente. Regenerar con: npx @saulwade/swl-ses@latest install --target codex');
43
43
  lineas.push('');
44
44
  lineas.push(`Sistema: swl-ses v${contexto.version}`);
45
45
  lineas.push(`Perfil: ${contexto.perfil}`);
@@ -47,7 +47,7 @@ class TransformadorCopilot extends TransformadorBase {
47
47
  lineas.push('# Instrucciones del proyecto — SWL');
48
48
  lineas.push('');
49
49
  lineas.push(`> Generado por swl-ses v${contexto.version} — ${new Date().toISOString().split('T')[0]}`);
50
- lineas.push('> NO editar manualmente. Regenerar con: npx swl-ses@latest install --target copilot');
50
+ lineas.push('> NO editar manualmente. Regenerar con: npx @saulwade/swl-ses@latest install --target copilot');
51
51
  lineas.push('');
52
52
 
53
53
  if (contexto.reglas && contexto.reglas.length > 0) {
@@ -46,7 +46,7 @@ class TransformadorGemini extends TransformadorBase {
46
46
  lineas.push('# GEMINI.md — Sistema SWL');
47
47
  lineas.push('');
48
48
  lineas.push(`> Generado por swl-ses v${contexto.version} — ${new Date().toISOString().split('T')[0]}`);
49
- lineas.push('> NO editar manualmente. Regenerar con: npx swl-ses@latest install --target gemini');
49
+ lineas.push('> NO editar manualmente. Regenerar con: npx @saulwade/swl-ses@latest install --target gemini');
50
50
  lineas.push('');
51
51
  lineas.push(`Este proyecto usa el sistema SWL con perfil "${contexto.perfil}".`);
52
52
  lineas.push('');
@@ -47,7 +47,7 @@ class TransformadorOpenCode extends TransformadorBase {
47
47
  lineas.push('# AGENTS.md — Sistema SWL');
48
48
  lineas.push('');
49
49
  lineas.push(`> Generado por swl-ses v${contexto.version} — ${new Date().toISOString().split('T')[0]}`);
50
- lineas.push('> NO editar manualmente. Regenerar con: npx swl-ses@latest install --target opencode');
50
+ lineas.push('> NO editar manualmente. Regenerar con: npx @saulwade/swl-ses@latest install --target opencode');
51
51
  lineas.push('');
52
52
  lineas.push(`Este proyecto usa el sistema SWL con perfil "${contexto.perfil}".`);
53
53
  lineas.push('');