@saulwade/swl-ses 1.7.4 → 1.9.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 (97) hide show
  1. package/CLAUDE.md +196 -196
  2. package/README.md +579 -579
  3. package/agentes/auto-evolucion-swl.md +7 -7
  4. package/agentes/disenador-ui-swl.md +12 -0
  5. package/agentes/investigador-ux-swl.md +9 -0
  6. package/agentes/orquestador-swl.md +89 -1
  7. package/agentes/perfilador-usuario-swl.md +2 -2
  8. package/agentes/revisor-codigo-swl.md +34 -10
  9. package/agentes/revisor-seguridad-swl.md +7 -0
  10. package/agentes/tdd-qa-swl.md +23 -2
  11. package/agentes/ux-disenador-swl.md +6 -0
  12. package/comandos/swl/autoresearch.md +102 -6
  13. package/comandos/swl/evaluar-skill.md +1 -1
  14. package/comandos/swl/evolucion-estado.md +5 -5
  15. package/comandos/swl/evolucionar.md +2 -2
  16. package/comandos/swl/inbox.md +1 -1
  17. package/comandos/swl/metricas.md +34 -0
  18. package/comandos/swl/nemesis.md +42 -1
  19. package/comandos/swl/planear-fase.md +8 -0
  20. package/comandos/swl/predecir.md +139 -0
  21. package/comandos/swl/reflect-skills.md +2 -2
  22. package/comandos/swl/salud.md +1 -1
  23. package/comandos/swl/verificar.md +50 -7
  24. package/habilidades/ai-runtime-security/SKILL.md +2 -2
  25. package/habilidades/angular-moderno/SKILL.md +44 -1
  26. package/habilidades/auto-evolucion-protocolo/SKILL.md +2 -2
  27. package/habilidades/autoresearch/SKILL.md +15 -1
  28. package/habilidades/benchmark-memoria/SKILL.md +2 -2
  29. package/habilidades/calidad-mutation-testing/SKILL.md +170 -0
  30. package/habilidades/changelog-generator/scripts/parse-commits.js +2 -1
  31. package/habilidades/checklist-seguridad/SKILL.md +29 -1
  32. package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -0
  33. package/habilidades/css-moderno/SKILL.md +3 -1
  34. package/habilidades/drift-detection/SKILL.md +3 -3
  35. package/habilidades/eval-framework/SKILL.md +1 -1
  36. package/habilidades/fastapi-experto/SKILL.md +56 -5
  37. package/habilidades/guardrail-semantico/SKILL.md +4 -4
  38. package/habilidades/patrones-python/SKILL.md +8 -5
  39. package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
  40. package/habilidades/proceso-debate-adversarial/SKILL.md +164 -0
  41. package/habilidades/proceso-debate-adversarial/recursos/personas.md +105 -0
  42. package/habilidades/proceso-dynamic-workflows/SKILL.md +138 -0
  43. package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -0
  44. package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -0
  45. package/habilidades/swl-claudemd/SKILL.md +2 -2
  46. package/habilidades/tdd-workflow/SKILL.md +14 -1
  47. package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -0
  48. package/habilidades/testing-python/SKILL.md +1 -1
  49. package/habilidades/tracing-processor/SKILL.md +1 -1
  50. package/hooks/actualizar-perfil-usuario.js +2 -2
  51. package/hooks/aiisms-detector.js +2 -2
  52. package/hooks/auto-evolucion.js +1 -1
  53. package/hooks/captura-feedback-usuario.js +2 -2
  54. package/hooks/claudemd-bloat-detector.js +2 -2
  55. package/hooks/claudemd-duplicacion-detector.js +1 -1
  56. package/hooks/contexto-iteracion.js +144 -0
  57. package/hooks/guardrail-modelo.js +2 -2
  58. package/hooks/lib/loop-telemetry.js +321 -0
  59. package/hooks/lib/memory-search.js +1 -1
  60. package/hooks/lib/nudge-tracker.js +1 -1
  61. package/hooks/metricas-evolucion.js +3 -3
  62. package/hooks/notificacion-telegram.js +11 -3
  63. package/hooks/rotar-audit-auto.js +2 -2
  64. package/hooks/validar-formato-post-subagente.js +2 -2
  65. package/hooks/validar-intent-spec.js +1 -1
  66. package/hooks/validar-planning-paths.js +134 -0
  67. package/llms.txt +29 -0
  68. package/manifiestos/hooks-config.json +30 -12
  69. package/manifiestos/modulos.json +1358 -1351
  70. package/manifiestos/planning-paths.json +44 -0
  71. package/manifiestos/skills-lock.json +1275 -1254
  72. package/package.json +93 -92
  73. package/plugin.json +375 -372
  74. package/reglas/arquitectura.evolved.json +7 -0
  75. package/reglas/arquitectura.md +65 -0
  76. package/reglas/gobernanza.md +1 -1
  77. package/reglas/memoria-consolidada.md +7 -7
  78. package/reglas/seguridad.evolved.json +7 -0
  79. package/reglas/seguridad.md +144 -0
  80. package/reglas/sin-duplicacion-reglas-globales.md +1 -1
  81. package/scripts/auditar-agentes-gaps.js +1 -1
  82. package/scripts/auditar-cobertura-frameworks.js +2 -2
  83. package/scripts/auditar-skills-gaps.js +2 -2
  84. package/scripts/benchmark-memoria.js +3 -3
  85. package/scripts/generar-inventario.js +64 -1
  86. package/scripts/inferir-herramientas-permitidas.js +1 -1
  87. package/scripts/instalador.js +80 -2
  88. package/scripts/lib/dashboard-widgets.js +3 -3
  89. package/scripts/lib/drift-detector.js +3 -3
  90. package/scripts/lib/eval-metrics-store.js +3 -3
  91. package/scripts/lib/gitignore-manifest.js +3 -3
  92. package/scripts/mcp-server/README.md +1 -1
  93. package/scripts/mcp-server/telemetry.js +2 -2
  94. package/scripts/reflect-skills.js +4 -4
  95. package/scripts/rotar-audit-logs.js +2 -2
  96. package/scripts/run-skill-evals.js +2 -2
  97. package/scripts/smoke-test.js +24 -2
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: validar-planning-paths.js
6
+ * Tipo: PostToolUse (aplica a: Write, Edit, MultiEdit)
7
+ *
8
+ * Advierte cuando una sesion crea un directorio top-level NUEVO en .planning/
9
+ * que NO esta en la allowlist canonica (manifiestos/planning-paths.json).
10
+ * Atrapa divergencias es/en (auditoria/ vs audit/, ux/ vs design/) ANTES de
11
+ * que proliferen.
12
+ *
13
+ * Aplica reglas/analizar-directorios-antes-de-escribir.md y cierra
14
+ * DT-PLANNING-OUTPUT-PATHS. No bloquea (modo warn-only). ADR-0031.
15
+ *
16
+ * Opt-out: SWL_PLANNING_PATHS=0 desactiva el hook.
17
+ *
18
+ * Formato del nudge: kind "planning-path-divergente" -> documentador-swl.
19
+ */
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+ const crypto = require('crypto');
24
+
25
+ if (process.env.SWL_PLANNING_PATHS === '0') process.exit(0);
26
+
27
+ let evento;
28
+ try {
29
+ evento = JSON.parse(fs.readFileSync(0, 'utf-8'));
30
+ } catch (_) {
31
+ process.exit(0);
32
+ }
33
+
34
+ const toolName = evento?.tool_name;
35
+ const toolInput = evento?.tool_input;
36
+ if (!toolName || !['Write', 'Edit', 'MultiEdit'].includes(toolName)) process.exit(0);
37
+
38
+ const filePath = toolInput?.file_path;
39
+ if (!filePath) process.exit(0);
40
+
41
+ const norm = filePath.replace(/\\/g, '/');
42
+
43
+ // Solo nos interesa lo que cae dentro de .planning/. Soporta path absoluto
44
+ // (con '/.planning/' embebido, lo que Claude Code envia en produccion) y path
45
+ // relativo ('.planning/...'). `resto` es todo lo que sigue a '.planning/'.
46
+ const marcador = '/.planning/';
47
+ let resto;
48
+ const idx = norm.indexOf(marcador);
49
+ if (idx >= 0) {
50
+ resto = norm.slice(idx + marcador.length); // path absoluto / embebido
51
+ } else if (norm.startsWith('.planning/')) {
52
+ resto = norm.slice('.planning/'.length); // path relativo
53
+ } else {
54
+ process.exit(0); // fuera de .planning/
55
+ }
56
+
57
+ // resto = "<segmento>/..." o "<archivo>"
58
+ const partes = resto.split('/').filter(Boolean);
59
+ if (partes.length === 0) process.exit(0);
60
+
61
+ // Si es un archivo directo en .planning/ (sin subdirectorio), es archivo
62
+ // top-level: lo permitimos (ESTADO.md, nudges.jsonl, etc.).
63
+ if (partes.length === 1) process.exit(0);
64
+
65
+ const topDir = partes[0];
66
+
67
+ // ─── Allowlist embebida (fallback portable) ────────────────────────────────
68
+ // manifiestos/ NO se propaga a proyectos consumidores; el hook debe ser
69
+ // autosuficiente. En el repo swl-ses se prefiere el manifest (fuente de
70
+ // verdad); en consumidores se usa esta lista. Mantener ambas en sync.
71
+ const DIRS_CANONICOS = [
72
+ 'adrs', 'analysis', 'archive', 'audit', 'auto-evolution', 'backups',
73
+ 'benchmark', 'comms', 'cron', 'design', 'evolution', 'fases', 'gateway',
74
+ 'inbox', 'knowledge', 'locks', 'red-team', 'research', 'runs', 'sessions',
75
+ 'traces', 'user-profile', 'wiki',
76
+ ];
77
+
78
+ // ─── Cargar allowlist (manifest si existe, embebida si no) ──────────────────
79
+ const CWD = process.cwd();
80
+ const allowlistPath = path.join(CWD, 'manifiestos', 'planning-paths.json');
81
+ let permitidos;
82
+ try {
83
+ const allow = JSON.parse(fs.readFileSync(allowlistPath, 'utf-8'));
84
+ permitidos = new Set((allow.directorios || []).map((d) => d.nombre));
85
+ } catch (_) {
86
+ permitidos = new Set(DIRS_CANONICOS);
87
+ }
88
+ if (permitidos.has(topDir)) process.exit(0);
89
+
90
+ // Directorio top-level NO canonico -> divergencia potencial.
91
+ // Detectar variante es/en conocida para sugerir el canonico correcto.
92
+ const VARIANTES = {
93
+ auditoria: 'audit', auditorias: 'audit',
94
+ ux: 'design', ui: 'design', diseno: 'design', 'diseno-visual': 'design',
95
+ investigacion: 'research', conocimiento: 'knowledge',
96
+ evolucion: 'evolution', 'auto-evolucion': 'auto-evolution',
97
+ 'perfil-usuario': 'user-profile', archivo: 'archive',
98
+ sesiones: 'sessions', decisiones: 'adrs',
99
+ };
100
+ const sugerido = VARIANTES[topDir] || null;
101
+
102
+ // Ruta de display relativa a .planning/, independiente de si el path era
103
+ // absoluto o relativo (resto ya es todo lo que sigue a '.planning/').
104
+ const rutaRelativa = '.planning/' + resto;
105
+ const nudge = {
106
+ id: crypto.randomBytes(8).toString('hex'),
107
+ kind: 'planning-path-divergente',
108
+ target: 'documentador-swl',
109
+ source: 'hooks/validar-planning-paths.js',
110
+ message:
111
+ `[planning-path] Se escribio en \`.planning/${topDir}/\`, un directorio top-level ` +
112
+ `NO canonico (${rutaRelativa}).\n` +
113
+ (sugerido
114
+ ? ` Probable divergencia es/en: usa el canonico \`.planning/${sugerido}/\` en su lugar.\n`
115
+ : ` Si es un dominio nuevo legitimo, agregalo a \`manifiestos/planning-paths.json\`.\n`) +
116
+ ` Ver \`reglas/analizar-directorios-antes-de-escribir.md\` y la allowlist canonica.`,
117
+ data: {
118
+ dir_detectado: topDir,
119
+ canonico_sugerido: sugerido,
120
+ archivo: rutaRelativa,
121
+ },
122
+ ts: new Date().toISOString(),
123
+ accionado: false,
124
+ accionado_ts: null,
125
+ accionado_por: null,
126
+ };
127
+
128
+ try {
129
+ const nudgesPath = path.join(CWD, '.planning', 'evolution', 'nudges.jsonl');
130
+ fs.mkdirSync(path.dirname(nudgesPath), { recursive: true });
131
+ fs.appendFileSync(nudgesPath, JSON.stringify(nudge) + '\n', 'utf-8');
132
+ } catch (_) { /* no fallar el hook */ }
133
+
134
+ process.exit(0);
package/llms.txt ADDED
@@ -0,0 +1,29 @@
1
+ # swl-ses (@saulwade/swl-ses)
2
+
3
+ > Sistema de ingeniería de software auto-evolutivo multi-runtime polyglot (SDLC completo), distribuido como paquete npm y plugin de Claude Code. 61 agentes, 181 habilidades, 45 comandos, 31 reglas base y 45 hooks. Soporta 11 lenguajes y 7 runtimes (Claude Code, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot). Versión 1.9.0.
4
+
5
+ Archivo generado por `node scripts/generar-inventario.js` — no editar a mano. Las cifras se sincronizan con INVENTARIO.md en cada regeneración.
6
+
7
+ ## Documentación
8
+
9
+ - [README](README.md): overview público y quickstart
10
+ - [Manual de uso](MANUAL_USO.md): manual operacional completo
11
+ - [Comandos](COMANDOS.md): referencia detallada de cada comando `/swl:*`
12
+ - [Agentes](AGENTS.md): catálogo de agentes con capacidades
13
+ - [Inventario](INVENTARIO.md): conteos oficiales de todos los componentes
14
+ - [Instalación](INSTALACION.md): instalación, perfiles y configuración
15
+ - [Instrucciones del proyecto](CLAUDE.md): convenciones, stack y reglas
16
+
17
+ ## Componentes
18
+
19
+ - 61 agentes especializados en `agentes/` (orquestación, implementación por stack, revisión, calidad, diseño)
20
+ - 181 habilidades cargables bajo demanda en `habilidades/` (conocimiento operacional con divulgación progresiva)
21
+ - 45 comandos `/swl:*` en `comandos/swl/` (ciclo GSD, calidad, release, diagnóstico)
22
+ - 31 reglas base + 40 reglas por lenguaje en `reglas/` (políticas obligatorias por matcher)
23
+ - 45 hooks en `hooks/` (telemetría, validación, seguridad; zero-deps, escrituras atómicas)
24
+
25
+ ## Opcional
26
+
27
+ - [CHANGELOG](CHANGELOG.md): historial de versiones
28
+ - [Índice de ADRs](.planning/adrs/README.md): decisiones de arquitectura
29
+ - [Variables de entorno](docs/variables-entorno.md): configuración opt-in
@@ -17,13 +17,13 @@
17
17
  },
18
18
  "riskThresholds": {
19
19
  "allow": 0.35,
20
- "review": 0.60,
20
+ "review": 0.6,
21
21
  "confirm": 0.85
22
22
  },
23
23
  "costBudget": {
24
24
  "maxUsd": 10.0,
25
25
  "maxTokens": 500000,
26
- "alertAt": 0.80
26
+ "alertAt": 0.8
27
27
  },
28
28
  "circuitBreaker": {
29
29
  "maxConsecutiveFailures": 3,
@@ -171,7 +171,7 @@
171
171
  "actualizar-perfil-usuario.js": {
172
172
  "event": "Stop",
173
173
  "matcher": "",
174
- "description": "Detecta señales de corrección/preferencia del usuario y acumula un dirty-bit en .planning/perfil-usuario/. Emite nudge a perfilador-usuario-swl cuando cruza el umbral (default 3 señales).",
174
+ "description": "Detecta señales de corrección/preferencia del usuario y acumula un dirty-bit en .planning/user-profile/. Emite nudge a perfilador-usuario-swl cuando cruza el umbral (default 3 señales).",
175
175
  "blocking": false,
176
176
  "async": true,
177
177
  "maxConsecutiveFailures": 5,
@@ -180,7 +180,7 @@
180
180
  "metricas-evolucion.js": {
181
181
  "event": "Stop",
182
182
  "matcher": "",
183
- "description": "Consolida métricas del ciclo de evolución (nudges accionados/pendientes, instintos, fallos de agentes, evoluciones aplicadas/revertidas) y actualiza .planning/evolucion/metricas.json con health_score compuesto. Dispara escalamiento a alertas persistentes si >=5 nudges del mismo tipo ignorados en 14d.",
183
+ "description": "Consolida métricas del ciclo de evolución (nudges accionados/pendientes, instintos, fallos de agentes, evoluciones aplicadas/revertidas) y actualiza .planning/evolution/metricas.json con health_score compuesto. Dispara escalamiento a alertas persistentes si >=5 nudges del mismo tipo ignorados en 14d.",
184
184
  "blocking": false,
185
185
  "async": true,
186
186
  "maxConsecutiveFailures": 5,
@@ -198,7 +198,7 @@
198
198
  "auto-evolucion.js": {
199
199
  "event": "SubagentStop",
200
200
  "matcher": "",
201
- "description": "Registra cada terminación de subagente SWL en .planning/auto-evolucion/agentes.jsonl y emite nudge a /swl:evolucionar cuando un agente acumula fallos o volumen de runs (ventana 14 días, throttle 24h).",
201
+ "description": "Registra cada terminación de subagente SWL en .planning/auto-evolution/agentes.jsonl y emite nudge a /swl:evolucionar cuando un agente acumula fallos o volumen de runs (ventana 14 días, throttle 24h).",
202
202
  "blocking": false,
203
203
  "async": true,
204
204
  "maxConsecutiveFailures": 5,
@@ -207,7 +207,7 @@
207
207
  "validar-formato-post-subagente.js": {
208
208
  "event": "SubagentStop",
209
209
  "matcher": "",
210
- "description": "Valida output de subagentes con schema declarado en manifiestos/agent-output-schemas.json (revisor-* y tdd-qa). Registra violaciones en .planning/evolucion/formato-violaciones.jsonl. Opt-out: SWL_FORMATO_VALIDACION=0.",
210
+ "description": "Valida output de subagentes con schema declarado en manifiestos/agent-output-schemas.json (revisor-* y tdd-qa). Registra violaciones en .planning/evolution/formato-violaciones.jsonl. Opt-out: SWL_FORMATO_VALIDACION=0.",
211
211
  "blocking": false,
212
212
  "async": true,
213
213
  "maxConsecutiveFailures": 3,
@@ -301,6 +301,15 @@
301
301
  "maxConsecutiveFailures": 5,
302
302
  "degradeOnFailure": "skip"
303
303
  },
304
+ "contexto-iteracion.js": {
305
+ "event": "UserPromptSubmit",
306
+ "matcher": "",
307
+ "description": "Anti-context-rot para loops iterativos: inyecta el estado de la corrida activa en .planning/loops/ (iteración, últimas filas del TSV, plateau/recomendación de trayectoria). Throttled a 1 inyección cada 4 min por corrida. Opt-out: SWL_CONTEXTO_ITERACION=0.",
308
+ "blocking": false,
309
+ "async": true,
310
+ "maxConsecutiveFailures": 5,
311
+ "degradeOnFailure": "skip"
312
+ },
304
313
  "guardrail-modelo.js": {
305
314
  "event": "PreToolUse",
306
315
  "matcher": "Task|Agent",
@@ -323,7 +332,7 @@
323
332
  "captura-feedback-usuario.js": {
324
333
  "event": "UserPromptSubmit",
325
334
  "matcher": "",
326
- "description": "Detecta correcciones explícitas del usuario (no hagas X, prefiero Y, recuerda Z, nunca W) y las encola en .planning/evolucion/feedback-queue.jsonl para consumo por perfilador-usuario-swl y el ciclo AGP. Patrones regex en español e inglés. Opt-out: SWL_CAPTURAR_FEEDBACK=0.",
335
+ "description": "Detecta correcciones explícitas del usuario (no hagas X, prefiero Y, recuerda Z, nunca W) y las encola en .planning/evolution/feedback-queue.jsonl para consumo por perfilador-usuario-swl y el ciclo AGP. Patrones regex en español e inglés. Opt-out: SWL_CAPTURAR_FEEDBACK=0.",
327
336
  "blocking": false,
328
337
  "async": true,
329
338
  "maxConsecutiveFailures": 5,
@@ -341,7 +350,7 @@
341
350
  "aiisms-detector.js": {
342
351
  "event": "PostToolUse",
343
352
  "matcher": "Write|Edit|MultiEdit",
344
- "description": "Ejecuta detector portable Python contra archivos .md recién modificados y emite nudge a .planning/evolucion/nudges.jsonl si encuentra al menos un AI-ism P0. No bloquea. Requiere Python 3.10+. Respeta auto-referencia (habilidades/estilo-sin-ai-isms/), .planning/, temp/, node_modules/. Opt-out: SWL_AIISMS_HOOK=0.",
353
+ "description": "Ejecuta detector portable Python contra archivos .md recién modificados y emite nudge a .planning/evolution/nudges.jsonl si encuentra al menos un AI-ism P0. No bloquea. Requiere Python 3.10+. Respeta auto-referencia (habilidades/estilo-sin-ai-isms/), .planning/, temp/, node_modules/. Opt-out: SWL_AIISMS_HOOK=0.",
345
354
  "blocking": false,
346
355
  "async": true,
347
356
  "maxConsecutiveFailures": 5,
@@ -350,7 +359,7 @@
350
359
  "claudemd-bloat-detector.js": {
351
360
  "event": "PostToolUse",
352
361
  "matcher": "Write|Edit|MultiEdit",
353
- "description": "Ejecuta scripts/auditar-claudemd.js contra archivos CLAUDE.md recién modificados (basename exacto, no cualquier .md). Emite nudge a .planning/evolucion/nudges.jsonl si veredicto != OK (líneas excesivas, bullets gigantes, secciones canónicas ausentes, sin @references, placeholders). Aplica ADR-0016 (best practices Anthropic 'The CLAUDE.md file'). No bloquea. Excluye temp/, node_modules/, respositorios-git/, .planning/. Opt-out: SWL_CLAUDEMD_BLOAT=0.",
362
+ "description": "Ejecuta scripts/auditar-claudemd.js contra archivos CLAUDE.md recién modificados (basename exacto, no cualquier .md). Emite nudge a .planning/evolution/nudges.jsonl si veredicto != OK (líneas excesivas, bullets gigantes, secciones canónicas ausentes, sin @references, placeholders). Aplica ADR-0016 (best practices Anthropic 'The CLAUDE.md file'). No bloquea. Excluye temp/, node_modules/, respositorios-git/, .planning/. Opt-out: SWL_CLAUDEMD_BLOAT=0.",
354
363
  "blocking": false,
355
364
  "async": true,
356
365
  "maxConsecutiveFailures": 5,
@@ -359,7 +368,7 @@
359
368
  "claudemd-duplicacion-detector.js": {
360
369
  "event": "PostToolUse",
361
370
  "matcher": "Write|Edit|MultiEdit",
362
- "description": "Detecta duplicación de reglas globales (~/.claude/rules/) inline en CLAUDE.md de proyecto. Consume scripts/lib/detector-reglas-duplicadas.js + catálogo scripts/lib/reglas-globales-conocidas.json. Aplica regla reglas/sin-duplicacion-reglas-globales.md. Emite nudge a .planning/evolucion/nudges.jsonl si hay duplicaciones detectadas. No bloquea — kind: claudemd-duplicacion-reglas. Excluye temp/, node_modules/, respositorios-git/, .planning/, ~/.claude/ (user-level). Opt-out: SWL_CLAUDEMD_DUPLICACION=0.",
371
+ "description": "Detecta duplicación de reglas globales (~/.claude/rules/) inline en CLAUDE.md de proyecto. Consume scripts/lib/detector-reglas-duplicadas.js + catálogo scripts/lib/reglas-globales-conocidas.json. Aplica regla reglas/sin-duplicacion-reglas-globales.md. Emite nudge a .planning/evolution/nudges.jsonl si hay duplicaciones detectadas. No bloquea — kind: claudemd-duplicacion-reglas. Excluye temp/, node_modules/, respositorios-git/, .planning/, ~/.claude/ (user-level). Opt-out: SWL_CLAUDEMD_DUPLICACION=0.",
363
372
  "blocking": false,
364
373
  "async": true,
365
374
  "maxConsecutiveFailures": 5,
@@ -368,7 +377,7 @@
368
377
  "validar-intent-spec.js": {
369
378
  "event": "PostToolUse",
370
379
  "matcher": "Write|Edit|MultiEdit",
371
- "description": "Verifica que agentes nivelRiesgo:ALTO declaren las 6 partes del framework Intent Engineering (strategy, healthMetrics, steering, hardGuardrails, maxTurnos, fragmentos:[_intent-spec]) segun reglas/intent-engineering.md. Solo aplica a agentes/*.md no fragmentos. Emite nudge a .planning/evolucion/nudges.jsonl si faltan campos. No bloquea (modo warn-only inicial; promocion a blocking:true tras 2 semanas estables). Excluye temp/, node_modules/, respositorios-git/, _userland/, .planning/. Opt-out: SWL_INTENT_SPEC=0. ADR-0027.",
380
+ "description": "Verifica que agentes nivelRiesgo:ALTO declaren las 6 partes del framework Intent Engineering (strategy, healthMetrics, steering, hardGuardrails, maxTurnos, fragmentos:[_intent-spec]) segun reglas/intent-engineering.md. Solo aplica a agentes/*.md no fragmentos. Emite nudge a .planning/evolution/nudges.jsonl si faltan campos. No bloquea (modo warn-only inicial; promocion a blocking:true tras 2 semanas estables). Excluye temp/, node_modules/, respositorios-git/, _userland/, .planning/. Opt-out: SWL_INTENT_SPEC=0. ADR-0027.",
372
381
  "blocking": false,
373
382
  "async": true,
374
383
  "maxConsecutiveFailures": 5,
@@ -395,7 +404,7 @@
395
404
  "notificacion-telegram-subagent.js": {
396
405
  "event": "SubagentStop",
397
406
  "matcher": "",
398
- "description": "Envía notificación Telegram cuando un subagente termina su turno. Best-effort: siempre exit 0. Comparte implementación con notificacion-telegram.js. Opt-out: SWL_NOTIFICACIONES_TELEGRAM=0.",
407
+ "description": "Envía notificación Telegram cuando un subagente termina su turno. INERTE por default: SubagentStop no está en los eventos default del script compartido porque duplica la notificación del Stop final (mismo cuerpo, dos mensajes). Activar con CLAUDE_NOTIFY_EVENTS=Stop,Notification,SubagentStop. Best-effort: siempre exit 0. Opt-out global: SWL_NOTIFICACIONES_TELEGRAM=0.",
399
408
  "blocking": false,
400
409
  "async": true,
401
410
  "maxConsecutiveFailures": 5,
@@ -409,6 +418,15 @@
409
418
  "async": false,
410
419
  "maxConsecutiveFailures": 5,
411
420
  "degradeOnFailure": "skip"
421
+ },
422
+ "validar-planning-paths.js": {
423
+ "event": "PostToolUse",
424
+ "matcher": "Write|Edit|MultiEdit",
425
+ "description": "Advierte cuando una sesion crea un directorio top-level NUEVO en .planning/ fuera de la allowlist canonica (manifiestos/planning-paths.json). Atrapa divergencias es/en (auditoria/ vs audit/, ux/ vs design/) antes de que proliferen. Aplica reglas/analizar-directorios-antes-de-escribir.md, cierra DT-PLANNING-OUTPUT-PATHS (ADR-0031). Emite nudge kind: planning-path-divergente a .planning/evolution/nudges.jsonl. No bloquea (warn-only). Opt-out: SWL_PLANNING_PATHS=0.",
426
+ "blocking": false,
427
+ "async": true,
428
+ "maxConsecutiveFailures": 5,
429
+ "degradeOnFailure": "skip"
412
430
  }
413
431
  }
414
432
  }