@saulwade/swl-ses 1.7.3 → 1.8.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 +196 -196
- package/README.md +578 -578
- package/agentes/auto-evolucion-swl.md +7 -7
- package/agentes/disenador-ui-swl.md +12 -0
- package/agentes/investigador-ux-swl.md +9 -0
- package/agentes/perfilador-usuario-swl.md +2 -2
- package/agentes/ux-disenador-swl.md +6 -0
- package/comandos/swl/evaluar-skill.md +1 -1
- package/comandos/swl/evolucion-estado.md +5 -5
- package/comandos/swl/evolucionar.md +2 -2
- package/comandos/swl/inbox.md +1 -1
- package/comandos/swl/reflect-skills.md +2 -2
- package/comandos/swl/salud.md +1 -1
- package/habilidades/ai-runtime-security/SKILL.md +2 -2
- package/habilidades/auto-evolucion-protocolo/SKILL.md +2 -2
- package/habilidades/benchmark-memoria/SKILL.md +2 -2
- package/habilidades/drift-detection/SKILL.md +3 -3
- package/habilidades/eval-framework/SKILL.md +1 -1
- package/habilidades/guardrail-semantico/SKILL.md +4 -4
- package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
- package/habilidades/swl-claudemd/SKILL.md +2 -2
- package/habilidades/testing-python/SKILL.md +1 -1
- package/habilidades/tracing-processor/SKILL.md +1 -1
- package/hooks/actualizar-perfil-usuario.js +2 -2
- package/hooks/aiisms-detector.js +2 -2
- package/hooks/auto-evolucion.js +1 -1
- package/hooks/captura-feedback-usuario.js +2 -2
- package/hooks/claudemd-bloat-detector.js +2 -2
- package/hooks/claudemd-duplicacion-detector.js +1 -1
- package/hooks/guardrail-modelo.js +2 -2
- package/hooks/lib/memory-search.js +1 -1
- package/hooks/lib/nudge-tracker.js +1 -1
- package/hooks/metricas-evolucion.js +3 -3
- package/hooks/rotar-audit-auto.js +2 -2
- package/hooks/validar-formato-post-subagente.js +2 -2
- package/hooks/validar-intent-spec.js +1 -1
- package/hooks/validar-planning-paths.js +134 -0
- package/manifiestos/hooks-config.json +20 -11
- package/manifiestos/modulos.json +1352 -1351
- package/manifiestos/planning-paths.json +44 -0
- package/manifiestos/skills-lock.json +13 -13
- package/package.json +92 -92
- package/plugin.json +372 -372
- package/reglas/gobernanza.md +1 -1
- package/reglas/harness-claude-code.md +39 -0
- package/reglas/memoria-consolidada.md +7 -7
- package/reglas/sin-duplicacion-reglas-globales.md +1 -1
- package/scripts/auditar-agentes-gaps.js +1 -1
- package/scripts/auditar-cobertura-frameworks.js +2 -2
- package/scripts/auditar-skills-gaps.js +2 -2
- package/scripts/benchmark-memoria.js +3 -3
- package/scripts/inferir-herramientas-permitidas.js +1 -1
- package/scripts/instalador.js +48 -0
- package/scripts/lib/dashboard-widgets.js +3 -3
- package/scripts/lib/drift-detector.js +3 -3
- package/scripts/lib/eval-metrics-store.js +3 -3
- package/scripts/lib/gitignore-manifest.js +3 -3
- package/scripts/mcp-server/README.md +1 -1
- package/scripts/mcp-server/telemetry.js +2 -2
- package/scripts/reflect-skills.js +4 -4
- package/scripts/rotar-audit-logs.js +2 -2
- package/scripts/run-skill-evals.js +2 -2
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* agente no tiene schema declarado, el hook no hace nada — no asume
|
|
11
11
|
* que todo agente debe seguir el formato compacto.
|
|
12
12
|
*
|
|
13
|
-
* Registra el resultado en `.planning/
|
|
13
|
+
* Registra el resultado en `.planning/evolution/formato-violaciones.jsonl`
|
|
14
14
|
* para que `metricas-evolucion.js` calcule la tasa de violación por
|
|
15
15
|
* agente y la incluya en el dashboard de calidad conductual.
|
|
16
16
|
*
|
|
@@ -27,7 +27,7 @@ const path = require('path');
|
|
|
27
27
|
|
|
28
28
|
const CWD = process.cwd();
|
|
29
29
|
const SCHEMAS_PATH = path.join(CWD, 'manifiestos', 'agent-output-schemas.json');
|
|
30
|
-
const LOG_PATH = path.join(CWD, '.planning', '
|
|
30
|
+
const LOG_PATH = path.join(CWD, '.planning', 'evolution', 'formato-violaciones.jsonl');
|
|
31
31
|
|
|
32
32
|
// ---------------------------------------------------------------------------
|
|
33
33
|
// Carga del schema (una vez)
|
|
@@ -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);
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
},
|
|
18
18
|
"riskThresholds": {
|
|
19
19
|
"allow": 0.35,
|
|
20
|
-
"review": 0.
|
|
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.
|
|
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/
|
|
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/
|
|
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-
|
|
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/
|
|
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,
|
|
@@ -323,7 +323,7 @@
|
|
|
323
323
|
"captura-feedback-usuario.js": {
|
|
324
324
|
"event": "UserPromptSubmit",
|
|
325
325
|
"matcher": "",
|
|
326
|
-
"description": "Detecta correcciones explícitas del usuario (no hagas X, prefiero Y, recuerda Z, nunca W) y las encola en .planning/
|
|
326
|
+
"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
327
|
"blocking": false,
|
|
328
328
|
"async": true,
|
|
329
329
|
"maxConsecutiveFailures": 5,
|
|
@@ -341,7 +341,7 @@
|
|
|
341
341
|
"aiisms-detector.js": {
|
|
342
342
|
"event": "PostToolUse",
|
|
343
343
|
"matcher": "Write|Edit|MultiEdit",
|
|
344
|
-
"description": "Ejecuta detector portable Python contra archivos .md recién modificados y emite nudge a .planning/
|
|
344
|
+
"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
345
|
"blocking": false,
|
|
346
346
|
"async": true,
|
|
347
347
|
"maxConsecutiveFailures": 5,
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
"claudemd-bloat-detector.js": {
|
|
351
351
|
"event": "PostToolUse",
|
|
352
352
|
"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/
|
|
353
|
+
"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
354
|
"blocking": false,
|
|
355
355
|
"async": true,
|
|
356
356
|
"maxConsecutiveFailures": 5,
|
|
@@ -359,7 +359,7 @@
|
|
|
359
359
|
"claudemd-duplicacion-detector.js": {
|
|
360
360
|
"event": "PostToolUse",
|
|
361
361
|
"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/
|
|
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/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
363
|
"blocking": false,
|
|
364
364
|
"async": true,
|
|
365
365
|
"maxConsecutiveFailures": 5,
|
|
@@ -368,7 +368,7 @@
|
|
|
368
368
|
"validar-intent-spec.js": {
|
|
369
369
|
"event": "PostToolUse",
|
|
370
370
|
"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/
|
|
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/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
372
|
"blocking": false,
|
|
373
373
|
"async": true,
|
|
374
374
|
"maxConsecutiveFailures": 5,
|
|
@@ -409,6 +409,15 @@
|
|
|
409
409
|
"async": false,
|
|
410
410
|
"maxConsecutiveFailures": 5,
|
|
411
411
|
"degradeOnFailure": "skip"
|
|
412
|
+
},
|
|
413
|
+
"validar-planning-paths.js": {
|
|
414
|
+
"event": "PostToolUse",
|
|
415
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
416
|
+
"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.",
|
|
417
|
+
"blocking": false,
|
|
418
|
+
"async": true,
|
|
419
|
+
"maxConsecutiveFailures": 5,
|
|
420
|
+
"degradeOnFailure": "skip"
|
|
412
421
|
}
|
|
413
422
|
}
|
|
414
423
|
}
|