@saulwade/swl-ses 1.3.7 → 1.4.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.
Files changed (129) hide show
  1. package/CLAUDE.md +12 -4
  2. package/README.md +1 -1
  3. package/bin/swl-mcp-server.js +187 -187
  4. package/bin/swl-webhook-server.js +198 -0
  5. package/comandos/swl/.evolved.json +22 -22
  6. package/comandos/swl/adoptar-proyecto.md +21 -1
  7. package/comandos/swl/claudemd.md +14 -1
  8. package/comandos/swl/contribuir.md +233 -233
  9. package/comandos/swl/exportar-vault.md +207 -7
  10. package/comandos/swl/nuevo-proyecto.md +24 -2
  11. package/gateway/adapters/base.js +109 -0
  12. package/gateway/adapters/discord.js +167 -0
  13. package/gateway/adapters/email.js +221 -0
  14. package/gateway/adapters/slack.js +192 -0
  15. package/gateway/adapters/telegram.js +183 -0
  16. package/gateway/adapters/webhook.js +113 -0
  17. package/gateway/adapters/whatsapp.js +214 -0
  18. package/gateway/agent-executor.js +322 -0
  19. package/gateway/command-relay.js +271 -0
  20. package/gateway/cron/jobs.js +263 -0
  21. package/gateway/cron/scheduler.js +322 -0
  22. package/gateway/cron/store.js +335 -0
  23. package/gateway/index.js +320 -0
  24. package/gateway/lib/event-channel.js +191 -0
  25. package/gateway/session.js +131 -0
  26. package/gateway/webhook-server.js +324 -0
  27. package/habilidades/backend-production-resilience/SKILL.md +288 -288
  28. package/habilidades/benchmark-memoria/SKILL.md +186 -186
  29. package/habilidades/build-errors-nextjs/SKILL.md +55 -1
  30. package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
  31. package/habilidades/doubt-driven-review/SKILL.md +171 -171
  32. package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
  33. package/habilidades/eval-framework/SKILL.md +212 -212
  34. package/habilidades/extractor-de-aprendizajes/SKILL.md +24 -10
  35. package/habilidades/harness-claude-code/SKILL.md +299 -299
  36. package/habilidades/infra-github-actions/SKILL.md +166 -166
  37. package/habilidades/legacy-code-rescue/SKILL.md +267 -267
  38. package/habilidades/manejo-errores/.evolved.json +8 -8
  39. package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
  40. package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -163
  41. package/habilidades/nextjs-testing/SKILL.md +89 -5
  42. package/habilidades/node-experto/SKILL.md +37 -1
  43. package/habilidades/patrones-python/SKILL.md +229 -229
  44. package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
  45. package/habilidades/planear-fase/SKILL.md +319 -319
  46. package/habilidades/react-experto/SKILL.md +45 -4
  47. package/habilidades/release-semver/.evolved.json +8 -8
  48. package/habilidades/swl-claudemd/SKILL.md +15 -1
  49. package/habilidades/tdd-workflow/SKILL.md +36 -4
  50. package/habilidades/testing-python/SKILL.md +340 -340
  51. package/hooks/claudemd-bloat-detector.js +161 -161
  52. package/hooks/inyeccion-contexto.js +8 -3
  53. package/hooks/lib/agent-routing.js +107 -107
  54. package/hooks/lib/auto-consolidator.js +335 -335
  55. package/hooks/lib/error-classifier.js +308 -308
  56. package/hooks/lib/merkle-audit.js +96 -96
  57. package/hooks/lib/provenance-tracker.js +191 -191
  58. package/hooks/lib/rate-limit-ip.js +177 -0
  59. package/hooks/lib/rate-limit-tracker.js +253 -253
  60. package/hooks/lib/resource-quota.js +122 -122
  61. package/hooks/lib/retry-jitter.js +165 -165
  62. package/hooks/lib/skill-auditor.js +588 -588
  63. package/hooks/lib/sync-status.js +228 -228
  64. package/hooks/lib/taint-tracker.js +107 -107
  65. package/hooks/lib/text-similarity.js +241 -241
  66. package/hooks/lib/toon-compressor.js +245 -245
  67. package/hooks/lib/webhook-dedup.js +184 -0
  68. package/hooks/lib/webhook-verify.js +123 -0
  69. package/hooks/proteccion-rutas.js +120 -15
  70. package/hooks/registro-turnos.js +209 -209
  71. package/hooks/sugerir-regenerar-inventario.js +170 -170
  72. package/hooks/validar-formato-post-subagente.js +140 -140
  73. package/hooks/validar-memoria-hook.js +218 -218
  74. package/instintos/prompt-appendices.yaml +57 -57
  75. package/manifiestos/agent-output-schemas.json +57 -57
  76. package/manifiestos/modulos.json +1 -0
  77. package/manifiestos/skills-lock.json +37 -37
  78. package/package.json +5 -3
  79. package/plantillas/auditor-veto-template.md +105 -105
  80. package/plantillas/github-workflows/README.md +47 -47
  81. package/plantillas/github-workflows/release-please.yml +44 -44
  82. package/plantillas/github-workflows/swl-ci.yml +107 -107
  83. package/plantillas/github-workflows/swl-security.yml +51 -51
  84. package/plugin.json +1 -1
  85. package/reglas/analisis-previo-tareas-grandes.md +172 -172
  86. package/reglas/arreglar-al-detectar.md +147 -147
  87. package/reglas/fragmentos-compartidos.md +152 -152
  88. package/reglas/harness-claude-code.md +213 -213
  89. package/reglas/usar-context7.md +226 -226
  90. package/reglas/usar-sistema-swl.md +251 -0
  91. package/schemas/diary-entry.schema.json +80 -80
  92. package/scripts/benchmark-memoria.js +167 -167
  93. package/scripts/comandos/skills.js +251 -2
  94. package/scripts/configurar-branch-protection.js +418 -418
  95. package/scripts/detectar-aprendizajes-duplicados.js +151 -151
  96. package/scripts/field-report.js +199 -199
  97. package/scripts/generar-checklists-consolidados.js +273 -273
  98. package/scripts/generar-inventario.js +420 -420
  99. package/scripts/generar-matriz-lenguajes.js +271 -271
  100. package/scripts/lib/artefactos-python.js +43 -43
  101. package/scripts/lib/benchmark-metrics.js +160 -160
  102. package/scripts/lib/budget-enforcer.js +252 -252
  103. package/scripts/lib/configurar-ci.js +380 -380
  104. package/scripts/lib/contadores-inventario.js +217 -217
  105. package/scripts/lib/detectar-stack-detallado.js +307 -307
  106. package/scripts/lib/diary-entry.js +234 -234
  107. package/scripts/lib/eval-metrics-store.js +218 -218
  108. package/scripts/lib/eval-quality.js +171 -171
  109. package/scripts/lib/eval-schemas.js +144 -144
  110. package/scripts/lib/eval-self-correct.js +106 -106
  111. package/scripts/lib/eval-validator.js +185 -185
  112. package/scripts/lib/jaccard-similarity.js +98 -98
  113. package/scripts/lib/longmemeval-runner.js +125 -125
  114. package/scripts/lib/npm-version.js +261 -261
  115. package/scripts/lib/paquetes-conocidos.js +50 -50
  116. package/scripts/lib/prompt-builder.js +264 -264
  117. package/scripts/lib/rrf-fusion.js +175 -175
  118. package/scripts/lib/scoring-instintos.js +277 -277
  119. package/scripts/lib/semantic-search.js +252 -252
  120. package/scripts/limpiar-artefactos-python.js +131 -131
  121. package/scripts/mcp-server/README.md +128 -128
  122. package/scripts/mcp-server/handlers.js +206 -206
  123. package/scripts/migrar-csv-a-array.js +168 -168
  124. package/scripts/migrar-fase-dominio.js +201 -201
  125. package/scripts/publicar.js +511 -511
  126. package/scripts/run-eval.js +141 -141
  127. package/scripts/validar-manifest.js +195 -195
  128. package/scripts/validar-userland-vacio.js +110 -110
  129. package/scripts/verificar-release.js +110 -0
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: react-experto
3
3
  description: React + Next.js mejores prácticas modernas. Cubre Server Components vs Client Components, data fetching patterns (RSC, React Query, SWR, Server Actions), state management (useState, Zustand, Jotai), performance (memo, lazy, Suspense, streaming) y Next.js App Router patterns.
4
- version: "1.1.1"
4
+ version: "1.2.0"
5
5
  evolved: true
6
- evolved-from: "1.1.0"
7
- evolved-at: "2026-05-11"
6
+ evolved-from: "1.1.1"
7
+ evolved-at: "2026-05-12"
8
8
  evolved-by: "aprender"
9
- evolved-note: "L-105 SIGM: setState dentro de useEffect bloqueado por react-hooks/set-state-in-effect (eslint-plugin-react-hooks v7+) - 3 patrones de reemplazo (lazy init, useMemo, useSyncExternalStore) confirmados x3 en F1.2/F1.3/F3"
9
+ evolved-note: "Backport L-138 SIGM: Sidebar/menu con RBAC debe ocultar secciones cuyos items quedan todos filtrados; previo L-105 setState in useEffect"
10
10
  herramientasPermitidas: [Read]
11
11
  exclusiones:
12
12
  - "No cargar para optimización de rendimiento React (memo, useMemo, useCallback, virtualización, code splitting) — para rendimiento cargar `react-optimizacion`."
@@ -158,6 +158,47 @@ useEffect(() => {
158
158
  const filtrados = useMemo(() => usuarios.filter(u => u.activo), [usuarios]);
159
159
  ```
160
160
 
161
+ ### Sidebar/menu con RBAC: ocultar secciones cuyos items quedan todos filtrados
162
+
163
+ **Problema** (L-138 SIGM 2026-05-12): un sidebar con secciones colapsables filtra items por permiso del usuario. Si un usuario sin el permiso requerido ve la sección con su header y chevron pero al expandirla aparece un `<ul>` vacío, el bug confunde — el usuario reporta "el menú no despliega nada", sin saber si es bug del sistema o falta data. Caso SIGM: sección "Ventanilla" tenía 1 item con permiso `CAJA:cobrar`; cuando ningún usuario tenía ese string literal (era `RECAUDACION:CAJA:cobrar`), todos los usuarios veían la sección vacía.
164
+
165
+ ```tsx
166
+ // MAL — header se renderiza aunque el <ul> quede vacío
167
+ {NAV_SECTIONS.map((section) => (
168
+ <Section key={section.title}>
169
+ <SectionHeader title={section.title} />
170
+ <ul>
171
+ {section.items
172
+ .filter((item) => !item.permiso || tienePermiso(item.permiso))
173
+ .map((item) => <NavItem key={item.href} {...item} />)}
174
+ </ul>
175
+ </Section>
176
+ ))}
177
+ ```
178
+
179
+ ```tsx
180
+ // BIEN — filtrar items ANTES de decidir si renderizar la sección
181
+ {NAV_SECTIONS.map((section) => {
182
+ const itemsVisibles = section.items.filter(
183
+ (item) => !item.permiso || tienePermiso(item.permiso),
184
+ )
185
+ if (itemsVisibles.length === 0) return null // ← omitir sección entera
186
+
187
+ return (
188
+ <Section key={section.title}>
189
+ <SectionHeader title={section.title} />
190
+ <ul>
191
+ {itemsVisibles.map((item) => <NavItem key={item.href} {...item} />)}
192
+ </ul>
193
+ </Section>
194
+ )
195
+ })}
196
+ ```
197
+
198
+ **Aplica también a**: tabs, breadcrumbs, dropdowns de filtros, paneles de configuración con secciones por permiso. Patrón: cualquier UI que agrupa items en secciones donde los items pueden filtrarse por RBAC.
199
+
200
+ **Test obligatorio**: cuando el mock de `useAuth` NO incluye los permisos de una sección, esa sección NO debe renderizarse en el DOM (`expect(queryByText('NombreSección')).not.toBeInTheDocument()`).
201
+
161
202
  ```tsx
162
203
  // MAL: fetch en Client Component cuando podria ser RSC
163
204
  useEffect(() => {
@@ -1,9 +1,9 @@
1
- {
2
- "SKILL.md": {
3
- "evolved": true,
4
- "evolvedFrom": "1.0.1",
5
- "evolvedAt": "2026-05-02",
6
- "evolvedBy": "aprender",
7
- "evolvedNote": "Sección nueva: publish a múltiples registries (republish-only + auth GitHub Packages)"
8
- }
1
+ {
2
+ "SKILL.md": {
3
+ "evolved": true,
4
+ "evolvedFrom": "1.0.1",
5
+ "evolvedAt": "2026-05-02",
6
+ "evolvedBy": "aprender",
7
+ "evolvedNote": "Sección nueva: publish a múltiples registries (republish-only + auth GitHub Packages)"
8
+ }
9
9
  }
@@ -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,12 +1,12 @@
1
1
  ---
2
2
  name: tdd-workflow
3
3
  description: Flujo completo de Test-Driven Development. Ciclo RED (el test falla) → GREEN (implementación mínima) → REFACTOR (limpieza). Incluye cobertura mínima obligatoria, tests de frontera, factories, fixtures y estrategias para diferentes tipos de código (APIs, services, componentes Angular).
4
- version: "1.0.1"
4
+ version: "1.0.2"
5
5
  evolved: true
6
- evolved-from: "1.0.0"
7
- evolved-at: "2026-05-11"
6
+ evolved-from: "1.0.1"
7
+ evolved-at: "2026-05-14"
8
8
  evolved-by: "aprender"
9
- evolved-note: "L-109 SIGM: nombrar tests por causa raíz (no por feature) test_repository_no_usa_columna_inexistente_p_monto detectó bug en F1.4 sin necesidad de reproducción manual"
9
+ evolved-note: "Patrón reloj inyectable (parámetro `ahora` con default Date.now()) para tests deterministas sin freezegun/jest.useFakeTimers validado en 3 módulos sesión webhook Opción C"
10
10
  herramientasPermitidas: [Read, Bash]
11
11
  evolvable: true # default para skill estandar
12
12
  exclusiones:
@@ -297,4 +297,36 @@ pytest --cov=src/services --cov-fail-under=90
297
297
 
298
298
  **`db_session.rollback()` en el fixture de pytest-asyncio no deshace los datos insertados por `db.flush()` dentro de la función testeada cuando la sesión usa `autocommit=True` implícito por configuración del engine**: algunos proyectos configuran `AsyncEngine` con `isolation_level="AUTOCOMMIT"` para compatibilidad con operaciones DDL; en ese contexto, cada `flush()` hace commit inmediatamente y el `rollback()` del fixture no puede deshacer esos cambios. Causa: `AUTOCOMMIT` en PostgreSQL significa que no hay transacción activa que se pueda revertir. Fix: verificar que el engine de tests NO use `isolation_level="AUTOCOMMIT"` (la configuración debe ser solo para el engine de migraciones Alembic, no para el de la app). Para tests que necesitan AUTOCOMMIT por alguna razón, usar una BD de test separada que se trunca con `TRUNCATE ... RESTART IDENTITY CASCADE` en el teardown del fixture.
299
299
 
300
+ **Reloj inyectable como parámetro `ahora` habilita tests deterministas sin `freezegun`, `jest.useFakeTimers()` ni `sinon.useFakeTimers()`** [PATRÓN VALIDADO en SWL Opción C webhook]: cuando una API depende del tiempo (rate-limit con bucket que se rellena, dedup con ventana de retención, cache con TTL, schedulers), recibir el timestamp por parámetro en lugar de llamar `Date.now()` internamente permite que los tests pasen 1000 segundos en 0 ms reales. Diseño: `metodo(arg1, arg2, ahora = Date.now())` — producción no cambia (llamadas siguen siendo `obj.consumir(1)`), tests pasan `ahora` explícito (`obj.consumir(1, T0 + 5000)`). Validado en 3 módulos esta sesión: `rate-limit-ip.js` (40+ tests bucket refill, capacidad, cleanup), `webhook-dedup.js` (ventana de retención, rotación idempotente), helpers internos de `webhook-server.js`. Ningún test usa `sleep`, ningún test es flaky, ningún test mockea `Date`. Aplicable a JS/TS y a Python (`def consumir(self, tokens, ahora=None)` con `ahora = ahora or datetime.now(UTC)` al inicio).
301
+
302
+ ```js
303
+ // MAL — test no-determinista, requiere sleep o mock global
304
+ class Bucket {
305
+ consumir(n) {
306
+ const ahora = Date.now(); // ← imposible de controlar desde el test
307
+ this._rellenar(ahora);
308
+ if (this.tokens >= n) { this.tokens -= n; return true; }
309
+ return false;
310
+ }
311
+ }
312
+
313
+ // BIEN — reloj inyectable, test determinista
314
+ class Bucket {
315
+ consumir(n, ahora = Date.now()) { // ← default en producción, inyectable en test
316
+ this._rellenar(ahora);
317
+ if (this.tokens >= n) { this.tokens -= n; return true; }
318
+ return false;
319
+ }
320
+ }
321
+
322
+ // En el test:
323
+ const T0 = 1700000000000;
324
+ const b = new Bucket(10, 1, T0);
325
+ for (let i = 0; i < 10; i++) b.consumir(1, T0); // saturar
326
+ assert.equal(b.consumir(1, T0), false); // sin refill aún
327
+ assert.equal(b.consumir(5, T0 + 5000), true); // 5 seg después: 5 tokens
328
+ ```
329
+
330
+ Aplica también a tests de clock skew (tiempo retrocede por NTP): pasar `T0 - 1000` y validar que la lógica no rompe. Origen: rate-limit-ip.js + webhook-dedup.js sesión 2026-05-13.
331
+
300
332
  **Tests nombrados por feature (`test_emitir_factura_exitosa`) pierden poder regresivo; nombrados por causa raíz (`test_repository_no_usa_columna_inexistente_p_monto`) detectan regresiones específicas sin reproducción manual** [CONFIRMADO en SIGM Opción C F1.4]: cuando se descubre un bug por una causa raíz concreta (typo en nombre de columna SQL, omisión de `selectinload`, mock que devuelve dict en vez de objeto, schema obsoleto), el test de regresión que se escribe debe llevar el nombre de la causa, no del feature afectado. Caso real: durante F1.4 de SIGM, el repository de pagos referenciaba `p.monto` cuando la columna se llamaba `p.monto_pagado`; el test escrito como `test_repository_no_usa_columna_inexistente_p_monto` falló inmediatamente en la siguiente sesión cuando otro agente reintrodujo el typo, sin necesidad de reproducir el escenario de negocio (emitir cobro real, verificar respuesta). Causa: los nombres orientados a feature (`test_pago_exitoso`) son ambiguos sobre QUÉ falla — si el test falla, el desarrollador debe diagnosticar; los nombres orientados a causa raíz (`test_X_no_usa_Y`, `test_query_incluye_selectinload_Z`, `test_service_devuelve_dict_no_objeto`) son auto-diagnósticos. Fix: para cada bug que cueste >30 min diagnosticar, escribir UN test adicional cuyo nombre describa la condición técnica violada, no el escenario de negocio. Convención: `test_<componente>_<condicion_tecnica>` o `test_<componente>_no_<anti_patron>`. Estos tests son tu segunda línea de defensa contra regresiones de la misma causa raíz, complementarios a los tests de comportamiento.