@saulwade/swl-ses 2.3.0 → 2.3.1
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 +47 -6
- package/README.md +1 -1
- package/agentes/accesibilidad-wcag-swl.md +690 -690
- package/agentes/arquitecto-swl.md +267 -267
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/backend-api-swl.md +472 -472
- package/agentes/backend-csharp-swl.md +420 -420
- package/agentes/backend-go-swl.md +390 -390
- package/agentes/backend-java-swl.md +281 -281
- package/agentes/backend-node-swl.md +479 -479
- package/agentes/backend-python-swl.md +605 -605
- package/agentes/backend-rust-swl.md +364 -364
- package/agentes/backend-workers-swl.md +482 -482
- package/agentes/cloud-infra-swl.md +509 -509
- package/agentes/consolidador-swl.md +541 -541
- package/agentes/datos-swl.md +605 -605
- package/agentes/depurador-swl.md +352 -352
- package/agentes/devops-ci-swl.md +400 -400
- package/agentes/disenador-ui-swl.md +569 -569
- package/agentes/documentador-swl.md +345 -345
- package/agentes/frontend-angular-swl.md +621 -621
- package/agentes/frontend-css-swl.md +716 -716
- package/agentes/frontend-react-swl.md +692 -692
- package/agentes/frontend-swl.md +496 -496
- package/agentes/frontend-tailwind-swl.md +826 -826
- package/agentes/gh-fix-ci-swl.md +2 -2
- package/agentes/implementador-swl.md +328 -328
- package/agentes/investigador-swl.md +432 -432
- package/agentes/investigador-ux-swl.md +505 -505
- package/agentes/llm-apps-swl.md +278 -278
- package/agentes/migrador-swl.md +442 -442
- package/agentes/mobile-android-swl.md +511 -511
- package/agentes/mobile-cross-swl.md +541 -541
- package/agentes/mobile-ios-swl.md +502 -502
- package/agentes/mobile-testing-swl.md +302 -302
- package/agentes/nemesis-auditor-swl.md +285 -285
- package/agentes/notificador-swl.md +918 -918
- package/agentes/observabilidad-swl.md +438 -438
- package/agentes/orquestador-swl.md +1026 -1026
- package/agentes/pagos-swl.md +310 -310
- package/agentes/perfilador-usuario-swl.md +321 -321
- package/agentes/planificador-swl.md +399 -399
- package/agentes/producto-prd-swl.md +589 -589
- package/agentes/red-team-swl.md +1 -1
- package/agentes/release-manager-swl.md +590 -590
- package/agentes/rendimiento-swl.md +713 -713
- package/agentes/resolutor-build-swl.md +245 -245
- package/agentes/revisor-angular-swl.md +278 -278
- package/agentes/revisor-codigo-swl.md +505 -505
- package/agentes/revisor-csharp-swl.md +264 -264
- package/agentes/revisor-go-swl.md +259 -259
- package/agentes/revisor-java-swl.md +257 -257
- package/agentes/revisor-kotlin-swl.md +273 -273
- package/agentes/revisor-nextjs-swl.md +281 -281
- package/agentes/revisor-php-swl.md +271 -271
- package/agentes/revisor-react-swl.md +278 -278
- package/agentes/revisor-rust-swl.md +346 -346
- package/agentes/revisor-seguridad-swl.md +399 -399
- package/agentes/revisor-swift-swl.md +268 -268
- package/agentes/revisor-typescript-swl.md +346 -346
- package/agentes/sre-swl.md +291 -291
- package/agentes/tdd-qa-swl.md +393 -393
- package/comandos/swl/briefing.md +119 -119
- package/comandos/swl/contribuir.md +233 -233
- package/comandos/swl/predecir.md +139 -139
- package/comandos/swl/sesiones.md +1 -1
- package/gateway/agent-executor.js +1 -1
- package/gateway/lib/event-channel.js +191 -191
- package/habilidades/agent-deep-links/SKILL.md +148 -148
- package/habilidades/agentes-como-servicio/SKILL.md +2 -2
- package/habilidades/angular-moderno/SKILL.md +20 -1
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
- package/habilidades/backend-async-postgres-testing/SKILL.md +215 -215
- package/habilidades/backend-error-design/SKILL.md +221 -221
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/benchmark-memoria/SKILL.md +186 -186
- package/habilidades/calidad-anti-patrones-universales/SKILL.md +368 -368
- package/habilidades/calidad-contract-testing/SKILL.md +165 -165
- package/habilidades/calidad-mutation-testing/SKILL.md +170 -170
- package/habilidades/changelog-generator/scripts/parse-commits.js +367 -367
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/drift-detection/SKILL.md +179 -179
- package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +1 -1
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
- package/habilidades/eval-framework/SKILL.md +212 -212
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- package/habilidades/harness-claude-code/recursos/disciplina-harness-regla.md +252 -252
- package/habilidades/legacy-code-rescue/SKILL.md +267 -267
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
- package/habilidades/proceso-ddia-fundamentos/SKILL.md +255 -255
- package/habilidades/proceso-ddia-streaming/SKILL.md +231 -231
- package/habilidades/proceso-debate-adversarial/recursos/personas.md +105 -105
- package/habilidades/proceso-discovery-machote/SKILL.md +157 -157
- package/habilidades/proceso-dynamic-workflows/SKILL.md +138 -138
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -65
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -65
- package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
- package/habilidades/proceso-modular-split/SKILL.md +256 -256
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +2 -2
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
- package/habilidades/structured-outputs/SKILL.md +2 -2
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -83
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -85
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -94
- package/habilidades/swl-dashboard/SKILL.md +2 -2
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +1 -1
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +1 -1
- package/hooks/ciclo-evolucion-subagente.js +26 -26
- package/hooks/ciclo-evolucion.js +26 -26
- package/hooks/claudemd-bloat-detector.js +161 -161
- package/hooks/claudemd-duplicacion-detector.js +170 -170
- package/hooks/contexto-iteracion.js +144 -144
- package/hooks/guardrail-modelo.js +1 -1
- package/hooks/lib/agent-routing.js +107 -107
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/autonomia.js +208 -208
- package/hooks/lib/ciclo-evolucion.js +47 -47
- package/hooks/lib/deep-links.js +185 -185
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/etapa-auto-evolucion.js +701 -701
- package/hooks/lib/etapa-metricas.js +388 -388
- package/hooks/lib/etapa-perfil-usuario.js +376 -376
- package/hooks/lib/loop-telemetry.js +321 -321
- package/hooks/lib/merkle-audit.js +96 -96
- package/hooks/lib/model-router.js +2 -2
- package/hooks/lib/propose-step.js +358 -358
- package/hooks/lib/provenance-tracker.js +191 -191
- package/hooks/lib/rate-limit-tracker.js +253 -253
- package/hooks/lib/resource-quota.js +122 -122
- package/hooks/lib/retry-jitter.js +165 -165
- package/hooks/lib/security-net.js +201 -201
- package/hooks/lib/skill-auditor.js +588 -588
- package/hooks/lib/sync-status.js +228 -228
- package/hooks/lib/taint-tracker.js +107 -107
- package/hooks/lib/text-similarity.js +241 -241
- package/hooks/lib/token-estimator.js +1 -0
- package/hooks/lib/toon-compressor.js +245 -245
- package/hooks/lib/usage-model.js +1 -1
- package/hooks/linea-estado.js +2 -0
- package/hooks/registro-turnos.js +209 -209
- package/hooks/session-briefing.js +98 -98
- package/hooks/spec-gate.js +211 -211
- package/hooks/sugerir-regenerar-inventario.js +170 -170
- package/hooks/tdd-gate.js +241 -241
- package/hooks/telemetria-skill-routing.js +100 -100
- package/hooks/validar-formato-post-subagente.js +140 -140
- package/hooks/validar-intent-spec.js +242 -242
- package/hooks/validar-memoria-hook.js +218 -218
- package/hooks/validar-planning-paths.js +134 -134
- package/instintos/autonomia.yaml +27 -27
- package/instintos/prompt-appendices.yaml +57 -57
- package/llms.txt +29 -29
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/canonical-hashes.json +2291 -1964
- package/manifiestos/planning-paths.json +44 -44
- package/manifiestos/skills-lock.json +1282 -1282
- package/package.json +1 -1
- package/plantillas/auditor-veto-template.md +105 -105
- package/plantillas/github-workflows/README.md +47 -47
- package/plantillas/github-workflows/release-please.yml +44 -44
- package/plantillas/github-workflows/swl-ci.yml +107 -107
- package/plantillas/github-workflows/swl-security.yml +51 -51
- package/plugin.json +1 -1
- package/reglas/accesibilidad.md +10 -10
- package/reglas/analisis-previo-tareas-grandes.md +172 -172
- package/reglas/api-diseno.md +9 -9
- package/reglas/arreglar-al-detectar.md +240 -240
- package/reglas/auditorias-documentales-estructurales.md +7 -7
- package/reglas/cloud-infra.md +8 -8
- package/reglas/consultar-vault-primero.md +195 -195
- package/reglas/debatir-antes-de-aceptar.md +158 -158
- package/reglas/fragmentos-compartidos.md +183 -183
- package/reglas/hooks.md +6 -6
- package/reglas/intent-engineering.md +218 -218
- package/reglas/markitdown.md +8 -8
- package/reglas/monitor-ci.md +309 -309
- package/reglas/patrones.md +6 -6
- package/reglas/sesiones-paralelas.md +180 -180
- package/reglas/sin-duplicacion-reglas-globales.md +182 -182
- package/reglas/skills-estandar.md +6 -6
- package/reglas/testing.md +7 -7
- package/reglas/tests-cleanup.md +224 -224
- package/reglas/usar-code-review-graph.md +155 -155
- package/reglas/usar-context7.md +226 -226
- package/reglas/verificar-citas-normativas.md +548 -548
- package/schemas/agent-frontmatter.schema.json +3 -3
- package/schemas/agent-message.schema.json +73 -73
- package/schemas/agent-output-implementacion.schema.json +114 -114
- package/schemas/agent-output-planificacion.schema.json +150 -150
- package/schemas/agent-output-review.schema.json +98 -98
- package/schemas/diary-entry.schema.json +112 -112
- package/schemas/hook-profiles.schema.json +54 -54
- package/schemas/hooks-config.schema.json +89 -89
- package/schemas/modulos.schema.json +38 -38
- package/schemas/perfiles.schema.json +36 -36
- package/schemas/plugin.schema.json +77 -77
- package/schemas/skill-evals.schema.json +119 -119
- package/schemas/skill-frontmatter.schema.json +245 -245
- package/scripts/audit-tools/audit-history.js +330 -330
- package/scripts/audit-tools/bundle-tracker.js +290 -290
- package/scripts/audit-tools/canary-monitor.js +352 -352
- package/scripts/audit-tools/code-profiler.js +605 -605
- package/scripts/audit-tools/dep-doctor.js +320 -320
- package/scripts/audit-tools/env-validator.js +206 -206
- package/scripts/audit-tools/lib/fs-walk.js +48 -48
- package/scripts/audit-tools/lib/output.js +23 -23
- package/scripts/audit-tools/migration-checker.js +392 -392
- package/scripts/audit-tools/pentest-scanner.js +1436 -1436
- package/scripts/benchmark-memoria.js +167 -167
- package/scripts/cli/aprobar-plan.js +73 -73
- package/scripts/cli/briefing.js +23 -23
- package/scripts/cli/ciclo-evolucion.js +26 -26
- package/scripts/cli/configurar-ci.js +40 -40
- package/scripts/cli/derivar-feature-list.js +25 -25
- package/scripts/cli/detectar-host.js +27 -27
- package/scripts/cli/diary-entry.js +69 -69
- package/scripts/cli/execution-state.js +18 -18
- package/scripts/cli/gateway-notify.js +41 -41
- package/scripts/cli/liberar-fase.js +42 -42
- package/scripts/cli/loop-telemetry.js +125 -125
- package/scripts/cli/mark-evolved.js +56 -56
- package/scripts/cli/metricas-dora.js +26 -26
- package/scripts/cli/near-duplicate.js +55 -55
- package/scripts/cli/notificaciones.js +123 -123
- package/scripts/cli/propose-step.js +29 -29
- package/scripts/cli/schedule-parse.js +19 -19
- package/scripts/cli/sugerir-modelo.js +20 -20
- package/scripts/cli/verificar-plan.js +36 -36
- package/scripts/cli/verificar-trazabilidad.js +35 -35
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/field-report.js +199 -199
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-matriz-lenguajes.js +271 -271
- package/scripts/lib/artefactos-python.js +43 -43
- package/scripts/lib/auditar-invocaciones-comandos.js +104 -104
- package/scripts/lib/benchmark-metrics.js +160 -160
- package/scripts/lib/budget-enforcer.js +252 -252
- package/scripts/lib/ci-reader.js +193 -193
- package/scripts/lib/claude-sessions.js +1 -0
- package/scripts/lib/configurar-ci.js +380 -380
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-host-swl.js +175 -175
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/detector-autoduplicacion-intra-archivo.js +234 -234
- package/scripts/lib/detector-reglas-duplicadas.js +220 -220
- package/scripts/lib/diary-entry.js +234 -234
- package/scripts/lib/eval-metrics-store.js +218 -218
- package/scripts/lib/eval-quality.js +171 -171
- package/scripts/lib/eval-schemas.js +144 -144
- package/scripts/lib/eval-self-correct.js +106 -106
- package/scripts/lib/eval-validator.js +185 -185
- package/scripts/lib/evidencia-release.js +322 -322
- package/scripts/lib/expandir-targets.js +71 -71
- package/scripts/lib/gate-hooks-requires.js +249 -249
- package/scripts/lib/gate-licencias.js +212 -212
- package/scripts/lib/git-metricas.js +257 -257
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/metricas-dora.js +204 -204
- package/scripts/lib/npm-version.js +261 -261
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/plan-lock.js +275 -275
- package/scripts/lib/pr-analyzer.js +399 -399
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/reglas-globales-conocidas.json +180 -180
- package/scripts/lib/resolver-plan-fase.js +37 -37
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/schema-version.js +164 -164
- package/scripts/lib/scoring-instintos.js +277 -277
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/lib/toml-merge.js +204 -204
- package/scripts/lib/tool-cost-analyzer.js +1 -0
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/mcp-server/auth.js +105 -105
- package/scripts/mcp-server/cache.js +106 -106
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +200 -200
- package/scripts/publicar.js +497 -497
- package/scripts/run-eval.js +141 -141
- package/scripts/tui/componentes/selector-multi.js +189 -189
- package/scripts/tui/componentes/selector-unico.js +158 -158
- package/scripts/tui/ejecutores.js +375 -375
- package/scripts/tui/index.js +162 -162
- package/scripts/tui/lib/colores.js +129 -129
- package/scripts/tui/lib/render.js +264 -264
- package/scripts/tui/lib/teclas.js +113 -113
- package/scripts/tui/pantallas/inspect.js +173 -173
- package/scripts/tui/pantallas/install-wizard.js +334 -334
- package/scripts/tui/pantallas/menu-principal.js +52 -52
- package/scripts/tui/pantallas/progreso.js +274 -274
- package/scripts/tui/pantallas/resumen.js +132 -132
- package/scripts/tui/pantallas/uninstall-wizard.js +208 -208
- package/scripts/tui/pantallas/update-wizard.js +232 -232
- package/scripts/tui/pantallas/welcome.js +187 -187
- package/scripts/validar-userland-vacio.js +110 -110
|
@@ -1,218 +1,218 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Hook: validar-memoria-hook.js
|
|
6
|
-
* Tipo: PostToolUse (matcher: Write|Edit|MultiEdit)
|
|
7
|
-
*
|
|
8
|
-
* Cierra el gap señalado en `reglas/memoria-consolidada.md`: el script
|
|
9
|
-
* `scripts/validar-memoria.js` solo se ejecuta manualmente vía CLI, así
|
|
10
|
-
* que la contaminación entre canales (perfil-usuario, APRENDIZAJES,
|
|
11
|
-
* instintos) sucedía sin que nadie se enterara hasta que un humano
|
|
12
|
-
* corría el validador.
|
|
13
|
-
*
|
|
14
|
-
* Este hook dispara `validar-memoria.js` en modo JSON cada vez que se
|
|
15
|
-
* escribe un archivo de memoria sensible:
|
|
16
|
-
* - `.planning/APRENDIZAJES.md`
|
|
17
|
-
* - `instintos/perfil-usuario.yaml`
|
|
18
|
-
* - `instintos/proyecto.yaml`
|
|
19
|
-
* - `instintos/global.yaml`
|
|
20
|
-
*
|
|
21
|
-
* Comportamiento:
|
|
22
|
-
* - Sin violaciones → silencioso (exit 0).
|
|
23
|
-
* - Violaciones menores (canal incorrecto, duplicación cross-canal) →
|
|
24
|
-
* emite nudge informativo via systemMessage.
|
|
25
|
-
* - Violaciones críticas (secretos detectados) → emite mensaje fuerte
|
|
26
|
-
* pero NO bloquea (siguiendo el contrato de hooks PostToolUse: ya pasó).
|
|
27
|
-
* El bloqueo de secretos en escritura corresponde a `escaneo-secretos`
|
|
28
|
-
* (PreToolUse), este hook es la red de defensa secundaria.
|
|
29
|
-
*
|
|
30
|
-
* Opt-out: SWL_VALIDAR_MEMORIA=0 desactiva el hook.
|
|
31
|
-
*
|
|
32
|
-
* El hook nunca bloquea el flujo (siempre exit 0). Los errores internos
|
|
33
|
-
* se ignoran silenciosamente — la regla "PostToolUse no rompe nada".
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
const fs = require('fs');
|
|
37
|
-
const path = require('path');
|
|
38
|
-
const { spawnSync } = require('child_process');
|
|
39
|
-
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
// Configuración
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
|
|
44
|
-
/** Archivos cuya modificación dispara la validación. Paths relativos al CWD. */
|
|
45
|
-
const ARCHIVOS_MEMORIA = [
|
|
46
|
-
'.planning/APRENDIZAJES.md',
|
|
47
|
-
'instintos/perfil-usuario.yaml',
|
|
48
|
-
'instintos/proyecto.yaml',
|
|
49
|
-
'instintos/global.yaml',
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
/** Path del validador. */
|
|
53
|
-
const VALIDADOR = path.join(process.cwd(), 'scripts', 'validar-memoria.js');
|
|
54
|
-
|
|
55
|
-
/** Timeout para el validador (ms). Si tarda más, se aborta sin bloquear. */
|
|
56
|
-
const TIMEOUT_MS = 5000;
|
|
57
|
-
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// Utilidades
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
/** Normaliza un path a forma POSIX para comparar contra ARCHIVOS_MEMORIA. */
|
|
63
|
-
function normalizar(p) {
|
|
64
|
-
if (!p) return '';
|
|
65
|
-
return String(p).replace(/\\/g, '/').replace(/^\.\//, '');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** ¿El path tocado coincide con algún archivo de memoria? */
|
|
69
|
-
function esArchivoMemoria(filePath) {
|
|
70
|
-
const norm = normalizar(filePath);
|
|
71
|
-
return ARCHIVOS_MEMORIA.some(target => norm.endsWith(target));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Extrae el(los) path(s) afectado(s) por la herramienta del payload del hook.
|
|
76
|
-
* @param {object} data - Payload del hook (tool_input).
|
|
77
|
-
* @returns {string[]} Lista de paths afectados.
|
|
78
|
-
*/
|
|
79
|
-
function extraerPaths(data) {
|
|
80
|
-
const ti = data.tool_input || {};
|
|
81
|
-
const paths = [];
|
|
82
|
-
if (ti.file_path) paths.push(ti.file_path);
|
|
83
|
-
if (ti.notebook_path) paths.push(ti.notebook_path);
|
|
84
|
-
// MultiEdit: file_path único + edits[]; ya cubierto arriba.
|
|
85
|
-
return paths;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Ejecuta el validador y devuelve un resumen normalizado.
|
|
90
|
-
* Schema esperado del validador (--json):
|
|
91
|
-
* {
|
|
92
|
-
* totalNoCriticas: N,
|
|
93
|
-
* totalCriticas: N,
|
|
94
|
-
* issues: {
|
|
95
|
-
* usuario_en_aprendizajes: [...],
|
|
96
|
-
* anti_tecnico_en_perfil: [...],
|
|
97
|
-
* duplicados_cross_canal: [...],
|
|
98
|
-
* secretos: [...], // críticas
|
|
99
|
-
* pii: [...], // críticas
|
|
100
|
-
* }
|
|
101
|
-
* }
|
|
102
|
-
*
|
|
103
|
-
* Si el validador falla o no existe, devuelve null (silencio).
|
|
104
|
-
*/
|
|
105
|
-
function ejecutarValidador() {
|
|
106
|
-
if (!fs.existsSync(VALIDADOR)) return null;
|
|
107
|
-
try {
|
|
108
|
-
const r = spawnSync(process.execPath, [VALIDADOR, '--json'], {
|
|
109
|
-
cwd: process.cwd(),
|
|
110
|
-
encoding: 'utf8',
|
|
111
|
-
timeout: TIMEOUT_MS,
|
|
112
|
-
windowsHide: true,
|
|
113
|
-
});
|
|
114
|
-
if (r.status === null) return null;
|
|
115
|
-
if (!r.stdout) return null;
|
|
116
|
-
const parsed = JSON.parse(r.stdout);
|
|
117
|
-
const issues = parsed.issues || {};
|
|
118
|
-
return {
|
|
119
|
-
totalNoCriticas: Number.isInteger(parsed.totalNoCriticas) ? parsed.totalNoCriticas : 0,
|
|
120
|
-
totalCriticas: Number.isInteger(parsed.totalCriticas) ? parsed.totalCriticas : 0,
|
|
121
|
-
criticas: [
|
|
122
|
-
...(issues.secretos || []).map(x => ({ tipo: 'secreto', detalle: x })),
|
|
123
|
-
...(issues.pii || []).map(x => ({ tipo: 'pii', detalle: x })),
|
|
124
|
-
],
|
|
125
|
-
menores: [
|
|
126
|
-
...(issues.usuario_en_aprendizajes || []).map(x => ({ tipo: 'canal: usuario en aprendizajes', detalle: x })),
|
|
127
|
-
...(issues.anti_tecnico_en_perfil || []).map(x => ({ tipo: 'canal: anti-patrón técnico en perfil', detalle: x })),
|
|
128
|
-
...(issues.duplicados_cross_canal || []).map(x => ({ tipo: 'duplicación cross-canal', detalle: x })),
|
|
129
|
-
],
|
|
130
|
-
};
|
|
131
|
-
} catch (_) {
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/** Trunca y limpia un detalle para mostrarlo en una línea. */
|
|
137
|
-
function describir(item) {
|
|
138
|
-
if (typeof item === 'string') return item.slice(0, 120);
|
|
139
|
-
if (item && typeof item === 'object') {
|
|
140
|
-
const partes = [];
|
|
141
|
-
if (item.titulo) partes.push(item.titulo);
|
|
142
|
-
if (item.canal) partes.push(`canal=${item.canal}`);
|
|
143
|
-
if (item.linea) partes.push(`L${item.linea}`);
|
|
144
|
-
if (item.muestra) partes.push(item.muestra);
|
|
145
|
-
if (partes.length === 0) return JSON.stringify(item).slice(0, 120);
|
|
146
|
-
return partes.join(' | ').slice(0, 120);
|
|
147
|
-
}
|
|
148
|
-
return String(item).slice(0, 120);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Construye el mensaje de nudge según el resultado.
|
|
153
|
-
*/
|
|
154
|
-
function construirMensaje(resultado, archivo) {
|
|
155
|
-
const { criticas, menores } = resultado;
|
|
156
|
-
if (criticas.length > 0) {
|
|
157
|
-
const lineas = [
|
|
158
|
-
'',
|
|
159
|
-
'╔══════════════════════════════════════════════════════╗',
|
|
160
|
-
'║ MEMORIA: VIOLACIÓN CRÍTICA DETECTADA ║',
|
|
161
|
-
'╚══════════════════════════════════════════════════════╝',
|
|
162
|
-
` Archivo modificado: ${archivo}`,
|
|
163
|
-
` Críticas: ${criticas.length}`,
|
|
164
|
-
];
|
|
165
|
-
for (const c of criticas.slice(0, 3)) {
|
|
166
|
-
lineas.push(` • ${c.tipo}: ${describir(c.detalle)}`);
|
|
167
|
-
}
|
|
168
|
-
lineas.push(' Acción recomendada: revertir el cambio o sanitizar antes de commit.');
|
|
169
|
-
lineas.push(' Ver: reglas/memoria-consolidada.md');
|
|
170
|
-
lineas.push('');
|
|
171
|
-
return lineas.join('\n');
|
|
172
|
-
}
|
|
173
|
-
if (menores.length > 0) {
|
|
174
|
-
const lineas = [
|
|
175
|
-
'',
|
|
176
|
-
'⚠ Memoria: posibles violaciones de canal',
|
|
177
|
-
` Archivo: ${archivo} | ${menores.length} hallazgo(s)`,
|
|
178
|
-
];
|
|
179
|
-
for (const v of menores.slice(0, 3)) {
|
|
180
|
-
lineas.push(` • ${v.tipo}: ${describir(v.detalle)}`);
|
|
181
|
-
}
|
|
182
|
-
if (menores.length > 3) {
|
|
183
|
-
lineas.push(` • (y ${menores.length - 3} más — ejecutar: node scripts/validar-memoria.js)`);
|
|
184
|
-
}
|
|
185
|
-
lineas.push(' Ver: reglas/memoria-consolidada.md (canal correcto por tipo de dato)');
|
|
186
|
-
lineas.push('');
|
|
187
|
-
return lineas.join('\n');
|
|
188
|
-
}
|
|
189
|
-
return '';
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// ---------------------------------------------------------------------------
|
|
193
|
-
// Entrypoint
|
|
194
|
-
// ---------------------------------------------------------------------------
|
|
195
|
-
|
|
196
|
-
let inputRaw = '';
|
|
197
|
-
process.stdin.on('data', chunk => { inputRaw += chunk; });
|
|
198
|
-
|
|
199
|
-
process.stdin.on('end', () => {
|
|
200
|
-
try {
|
|
201
|
-
if (process.env.SWL_VALIDAR_MEMORIA === '0') return;
|
|
202
|
-
|
|
203
|
-
const data = JSON.parse(inputRaw);
|
|
204
|
-
const paths = extraerPaths(data);
|
|
205
|
-
const archivoTocado = paths.find(esArchivoMemoria);
|
|
206
|
-
if (!archivoTocado) return;
|
|
207
|
-
|
|
208
|
-
const resultado = ejecutarValidador();
|
|
209
|
-
if (!resultado) return;
|
|
210
|
-
|
|
211
|
-
const mensaje = construirMensaje(resultado, normalizar(archivoTocado));
|
|
212
|
-
if (mensaje) {
|
|
213
|
-
process.stdout.write(JSON.stringify({ systemMessage: mensaje }));
|
|
214
|
-
}
|
|
215
|
-
} catch (_) {
|
|
216
|
-
// PostToolUse no bloquea por errores internos.
|
|
217
|
-
}
|
|
218
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: validar-memoria-hook.js
|
|
6
|
+
* Tipo: PostToolUse (matcher: Write|Edit|MultiEdit)
|
|
7
|
+
*
|
|
8
|
+
* Cierra el gap señalado en `reglas/memoria-consolidada.md`: el script
|
|
9
|
+
* `scripts/validar-memoria.js` solo se ejecuta manualmente vía CLI, así
|
|
10
|
+
* que la contaminación entre canales (perfil-usuario, APRENDIZAJES,
|
|
11
|
+
* instintos) sucedía sin que nadie se enterara hasta que un humano
|
|
12
|
+
* corría el validador.
|
|
13
|
+
*
|
|
14
|
+
* Este hook dispara `validar-memoria.js` en modo JSON cada vez que se
|
|
15
|
+
* escribe un archivo de memoria sensible:
|
|
16
|
+
* - `.planning/APRENDIZAJES.md`
|
|
17
|
+
* - `instintos/perfil-usuario.yaml`
|
|
18
|
+
* - `instintos/proyecto.yaml`
|
|
19
|
+
* - `instintos/global.yaml`
|
|
20
|
+
*
|
|
21
|
+
* Comportamiento:
|
|
22
|
+
* - Sin violaciones → silencioso (exit 0).
|
|
23
|
+
* - Violaciones menores (canal incorrecto, duplicación cross-canal) →
|
|
24
|
+
* emite nudge informativo via systemMessage.
|
|
25
|
+
* - Violaciones críticas (secretos detectados) → emite mensaje fuerte
|
|
26
|
+
* pero NO bloquea (siguiendo el contrato de hooks PostToolUse: ya pasó).
|
|
27
|
+
* El bloqueo de secretos en escritura corresponde a `escaneo-secretos`
|
|
28
|
+
* (PreToolUse), este hook es la red de defensa secundaria.
|
|
29
|
+
*
|
|
30
|
+
* Opt-out: SWL_VALIDAR_MEMORIA=0 desactiva el hook.
|
|
31
|
+
*
|
|
32
|
+
* El hook nunca bloquea el flujo (siempre exit 0). Los errores internos
|
|
33
|
+
* se ignoran silenciosamente — la regla "PostToolUse no rompe nada".
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const fs = require('fs');
|
|
37
|
+
const path = require('path');
|
|
38
|
+
const { spawnSync } = require('child_process');
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Configuración
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
/** Archivos cuya modificación dispara la validación. Paths relativos al CWD. */
|
|
45
|
+
const ARCHIVOS_MEMORIA = [
|
|
46
|
+
'.planning/APRENDIZAJES.md',
|
|
47
|
+
'instintos/perfil-usuario.yaml',
|
|
48
|
+
'instintos/proyecto.yaml',
|
|
49
|
+
'instintos/global.yaml',
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/** Path del validador. */
|
|
53
|
+
const VALIDADOR = path.join(process.cwd(), 'scripts', 'validar-memoria.js');
|
|
54
|
+
|
|
55
|
+
/** Timeout para el validador (ms). Si tarda más, se aborta sin bloquear. */
|
|
56
|
+
const TIMEOUT_MS = 5000;
|
|
57
|
+
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Utilidades
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
/** Normaliza un path a forma POSIX para comparar contra ARCHIVOS_MEMORIA. */
|
|
63
|
+
function normalizar(p) {
|
|
64
|
+
if (!p) return '';
|
|
65
|
+
return String(p).replace(/\\/g, '/').replace(/^\.\//, '');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** ¿El path tocado coincide con algún archivo de memoria? */
|
|
69
|
+
function esArchivoMemoria(filePath) {
|
|
70
|
+
const norm = normalizar(filePath);
|
|
71
|
+
return ARCHIVOS_MEMORIA.some(target => norm.endsWith(target));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Extrae el(los) path(s) afectado(s) por la herramienta del payload del hook.
|
|
76
|
+
* @param {object} data - Payload del hook (tool_input).
|
|
77
|
+
* @returns {string[]} Lista de paths afectados.
|
|
78
|
+
*/
|
|
79
|
+
function extraerPaths(data) {
|
|
80
|
+
const ti = data.tool_input || {};
|
|
81
|
+
const paths = [];
|
|
82
|
+
if (ti.file_path) paths.push(ti.file_path);
|
|
83
|
+
if (ti.notebook_path) paths.push(ti.notebook_path);
|
|
84
|
+
// MultiEdit: file_path único + edits[]; ya cubierto arriba.
|
|
85
|
+
return paths;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Ejecuta el validador y devuelve un resumen normalizado.
|
|
90
|
+
* Schema esperado del validador (--json):
|
|
91
|
+
* {
|
|
92
|
+
* totalNoCriticas: N,
|
|
93
|
+
* totalCriticas: N,
|
|
94
|
+
* issues: {
|
|
95
|
+
* usuario_en_aprendizajes: [...],
|
|
96
|
+
* anti_tecnico_en_perfil: [...],
|
|
97
|
+
* duplicados_cross_canal: [...],
|
|
98
|
+
* secretos: [...], // críticas
|
|
99
|
+
* pii: [...], // críticas
|
|
100
|
+
* }
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* Si el validador falla o no existe, devuelve null (silencio).
|
|
104
|
+
*/
|
|
105
|
+
function ejecutarValidador() {
|
|
106
|
+
if (!fs.existsSync(VALIDADOR)) return null;
|
|
107
|
+
try {
|
|
108
|
+
const r = spawnSync(process.execPath, [VALIDADOR, '--json'], {
|
|
109
|
+
cwd: process.cwd(),
|
|
110
|
+
encoding: 'utf8',
|
|
111
|
+
timeout: TIMEOUT_MS,
|
|
112
|
+
windowsHide: true,
|
|
113
|
+
});
|
|
114
|
+
if (r.status === null) return null;
|
|
115
|
+
if (!r.stdout) return null;
|
|
116
|
+
const parsed = JSON.parse(r.stdout);
|
|
117
|
+
const issues = parsed.issues || {};
|
|
118
|
+
return {
|
|
119
|
+
totalNoCriticas: Number.isInteger(parsed.totalNoCriticas) ? parsed.totalNoCriticas : 0,
|
|
120
|
+
totalCriticas: Number.isInteger(parsed.totalCriticas) ? parsed.totalCriticas : 0,
|
|
121
|
+
criticas: [
|
|
122
|
+
...(issues.secretos || []).map(x => ({ tipo: 'secreto', detalle: x })),
|
|
123
|
+
...(issues.pii || []).map(x => ({ tipo: 'pii', detalle: x })),
|
|
124
|
+
],
|
|
125
|
+
menores: [
|
|
126
|
+
...(issues.usuario_en_aprendizajes || []).map(x => ({ tipo: 'canal: usuario en aprendizajes', detalle: x })),
|
|
127
|
+
...(issues.anti_tecnico_en_perfil || []).map(x => ({ tipo: 'canal: anti-patrón técnico en perfil', detalle: x })),
|
|
128
|
+
...(issues.duplicados_cross_canal || []).map(x => ({ tipo: 'duplicación cross-canal', detalle: x })),
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
} catch (_) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Trunca y limpia un detalle para mostrarlo en una línea. */
|
|
137
|
+
function describir(item) {
|
|
138
|
+
if (typeof item === 'string') return item.slice(0, 120);
|
|
139
|
+
if (item && typeof item === 'object') {
|
|
140
|
+
const partes = [];
|
|
141
|
+
if (item.titulo) partes.push(item.titulo);
|
|
142
|
+
if (item.canal) partes.push(`canal=${item.canal}`);
|
|
143
|
+
if (item.linea) partes.push(`L${item.linea}`);
|
|
144
|
+
if (item.muestra) partes.push(item.muestra);
|
|
145
|
+
if (partes.length === 0) return JSON.stringify(item).slice(0, 120);
|
|
146
|
+
return partes.join(' | ').slice(0, 120);
|
|
147
|
+
}
|
|
148
|
+
return String(item).slice(0, 120);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Construye el mensaje de nudge según el resultado.
|
|
153
|
+
*/
|
|
154
|
+
function construirMensaje(resultado, archivo) {
|
|
155
|
+
const { criticas, menores } = resultado;
|
|
156
|
+
if (criticas.length > 0) {
|
|
157
|
+
const lineas = [
|
|
158
|
+
'',
|
|
159
|
+
'╔══════════════════════════════════════════════════════╗',
|
|
160
|
+
'║ MEMORIA: VIOLACIÓN CRÍTICA DETECTADA ║',
|
|
161
|
+
'╚══════════════════════════════════════════════════════╝',
|
|
162
|
+
` Archivo modificado: ${archivo}`,
|
|
163
|
+
` Críticas: ${criticas.length}`,
|
|
164
|
+
];
|
|
165
|
+
for (const c of criticas.slice(0, 3)) {
|
|
166
|
+
lineas.push(` • ${c.tipo}: ${describir(c.detalle)}`);
|
|
167
|
+
}
|
|
168
|
+
lineas.push(' Acción recomendada: revertir el cambio o sanitizar antes de commit.');
|
|
169
|
+
lineas.push(' Ver: reglas/memoria-consolidada.md');
|
|
170
|
+
lineas.push('');
|
|
171
|
+
return lineas.join('\n');
|
|
172
|
+
}
|
|
173
|
+
if (menores.length > 0) {
|
|
174
|
+
const lineas = [
|
|
175
|
+
'',
|
|
176
|
+
'⚠ Memoria: posibles violaciones de canal',
|
|
177
|
+
` Archivo: ${archivo} | ${menores.length} hallazgo(s)`,
|
|
178
|
+
];
|
|
179
|
+
for (const v of menores.slice(0, 3)) {
|
|
180
|
+
lineas.push(` • ${v.tipo}: ${describir(v.detalle)}`);
|
|
181
|
+
}
|
|
182
|
+
if (menores.length > 3) {
|
|
183
|
+
lineas.push(` • (y ${menores.length - 3} más — ejecutar: node scripts/validar-memoria.js)`);
|
|
184
|
+
}
|
|
185
|
+
lineas.push(' Ver: reglas/memoria-consolidada.md (canal correcto por tipo de dato)');
|
|
186
|
+
lineas.push('');
|
|
187
|
+
return lineas.join('\n');
|
|
188
|
+
}
|
|
189
|
+
return '';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Entrypoint
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
let inputRaw = '';
|
|
197
|
+
process.stdin.on('data', chunk => { inputRaw += chunk; });
|
|
198
|
+
|
|
199
|
+
process.stdin.on('end', () => {
|
|
200
|
+
try {
|
|
201
|
+
if (process.env.SWL_VALIDAR_MEMORIA === '0') return;
|
|
202
|
+
|
|
203
|
+
const data = JSON.parse(inputRaw);
|
|
204
|
+
const paths = extraerPaths(data);
|
|
205
|
+
const archivoTocado = paths.find(esArchivoMemoria);
|
|
206
|
+
if (!archivoTocado) return;
|
|
207
|
+
|
|
208
|
+
const resultado = ejecutarValidador();
|
|
209
|
+
if (!resultado) return;
|
|
210
|
+
|
|
211
|
+
const mensaje = construirMensaje(resultado, normalizar(archivoTocado));
|
|
212
|
+
if (mensaje) {
|
|
213
|
+
process.stdout.write(JSON.stringify({ systemMessage: mensaje }));
|
|
214
|
+
}
|
|
215
|
+
} catch (_) {
|
|
216
|
+
// PostToolUse no bloquea por errores internos.
|
|
217
|
+
}
|
|
218
|
+
});
|