@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,131 +1,131 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* limpiar-artefactos-python.js — limpia caché Python antes de empaquetar.
|
|
6
|
-
*
|
|
7
|
-
* Se ejecuta como `prepack` antes de `npm pack` y `npm publish` para evitar
|
|
8
|
-
* que artefactos locales (.pyc, __pycache__/) contaminen el tarball publicado.
|
|
9
|
-
*
|
|
10
|
-
* Reglas de seguridad (defensa en profundidad):
|
|
11
|
-
* 1. Aborta si cwd no coincide con la raíz del package.json del repo.
|
|
12
|
-
* 2. Profundidad máxima de recursión: 3 niveles desde la raíz.
|
|
13
|
-
* 3. Allowlist explícita de directorios a EXCLUIR de la búsqueda
|
|
14
|
-
* (node_modules, .git, temp, .planning, respositorios-git, _userland).
|
|
15
|
-
* 4. Solo elimina directorios cuyo nombre coincide exactamente con el
|
|
16
|
-
* conjunto cerrado: __pycache__, .pytest_cache, .mypy_cache, .ruff_cache.
|
|
17
|
-
* 5. Solo elimina archivos sueltos con extensiones .pyc, .pyo.
|
|
18
|
-
* 6. En CI no-interactivo respeta el flag SWL_PREPACK_DRY=1 (no borra,
|
|
19
|
-
* solo lista).
|
|
20
|
-
*
|
|
21
|
-
* Exit codes:
|
|
22
|
-
* 0 — OK (limpieza ejecutada o nada que limpiar)
|
|
23
|
-
* 1 — error de invariante (cwd incorrecto, package.json no encontrado)
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
const fs = require('fs');
|
|
27
|
-
const path = require('path');
|
|
28
|
-
|
|
29
|
-
const { NOMBRES_VALIDOS } = require('./lib/paquetes-conocidos');
|
|
30
|
-
const {
|
|
31
|
-
DIRS_ARTEFACTOS_PYTHON: DIRS_A_LIMPIAR,
|
|
32
|
-
EXTS_ARTEFACTOS_PYTHON: EXTS_A_LIMPIAR,
|
|
33
|
-
} = require('./lib/artefactos-python');
|
|
34
|
-
|
|
35
|
-
const PROFUNDIDAD_MAX = 3;
|
|
36
|
-
const DIRS_EXCLUIDOS = new Set([
|
|
37
|
-
'node_modules', '.git', 'temp', '.planning', 'respositorios-git',
|
|
38
|
-
'_userland', 'tests', '.github',
|
|
39
|
-
]);
|
|
40
|
-
|
|
41
|
-
const dryRun = process.env.SWL_PREPACK_DRY === '1';
|
|
42
|
-
|
|
43
|
-
function log(msg) { process.stdout.write(`[prepack] ${msg}\n`); }
|
|
44
|
-
function err(msg) { process.stderr.write(`[prepack] ERROR: ${msg}\n`); }
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Verifica que el cwd actual contiene el package.json del repo swl-ses.
|
|
48
|
-
* Esto evita que el script borre directorios en la máquina del usuario si
|
|
49
|
-
* algún día se invocara desde un cwd incorrecto (ej. dentro de un tarball
|
|
50
|
-
* extraído por npm en .npm/_cacache).
|
|
51
|
-
*/
|
|
52
|
-
function verificarRaiz() {
|
|
53
|
-
const cwd = process.cwd();
|
|
54
|
-
const pkgPath = path.join(cwd, 'package.json');
|
|
55
|
-
if (!fs.existsSync(pkgPath)) {
|
|
56
|
-
err(`no existe package.json en cwd: ${cwd}`);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
60
|
-
if (!NOMBRES_VALIDOS.includes(pkg.name)) {
|
|
61
|
-
err(`package.json en ${cwd} no corresponde a swl-ses (name: ${pkg.name}). Abortando por seguridad.`);
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
return cwd;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Recorre el árbol desde root con profundidad limitada y elimina los
|
|
69
|
-
* artefactos Python detectados. No sigue symlinks.
|
|
70
|
-
*/
|
|
71
|
-
function limpiar(root, profundidad = 0) {
|
|
72
|
-
if (profundidad > PROFUNDIDAD_MAX) return { dirs: 0, files: 0 };
|
|
73
|
-
|
|
74
|
-
let dirsEliminados = 0;
|
|
75
|
-
let filesEliminados = 0;
|
|
76
|
-
|
|
77
|
-
let entries;
|
|
78
|
-
try {
|
|
79
|
-
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
80
|
-
} catch (e) {
|
|
81
|
-
err(`no se pudo leer ${root}: ${e.message}`);
|
|
82
|
-
return { dirs: 0, files: 0 };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
for (const entry of entries) {
|
|
86
|
-
if (entry.isSymbolicLink()) continue;
|
|
87
|
-
const fullPath = path.join(root, entry.name);
|
|
88
|
-
|
|
89
|
-
if (entry.isDirectory()) {
|
|
90
|
-
if (DIRS_A_LIMPIAR.has(entry.name)) {
|
|
91
|
-
if (dryRun) {
|
|
92
|
-
log(`[dry-run] borraría dir: ${path.relative(process.cwd(), fullPath)}`);
|
|
93
|
-
} else {
|
|
94
|
-
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
95
|
-
log(`borrado dir: ${path.relative(process.cwd(), fullPath)}`);
|
|
96
|
-
}
|
|
97
|
-
dirsEliminados++;
|
|
98
|
-
} else if (!DIRS_EXCLUIDOS.has(entry.name) && !entry.name.startsWith('.')) {
|
|
99
|
-
const sub = limpiar(fullPath, profundidad + 1);
|
|
100
|
-
dirsEliminados += sub.dirs;
|
|
101
|
-
filesEliminados += sub.files;
|
|
102
|
-
}
|
|
103
|
-
} else if (entry.isFile()) {
|
|
104
|
-
const ext = path.extname(entry.name).toLowerCase();
|
|
105
|
-
if (EXTS_A_LIMPIAR.has(ext)) {
|
|
106
|
-
if (dryRun) {
|
|
107
|
-
log(`[dry-run] borraría archivo: ${path.relative(process.cwd(), fullPath)}`);
|
|
108
|
-
} else {
|
|
109
|
-
fs.rmSync(fullPath, { force: true });
|
|
110
|
-
}
|
|
111
|
-
filesEliminados++;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return { dirs: dirsEliminados, files: filesEliminados };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function main() {
|
|
120
|
-
const root = verificarRaiz();
|
|
121
|
-
const result = limpiar(root);
|
|
122
|
-
|
|
123
|
-
if (result.dirs === 0 && result.files === 0) {
|
|
124
|
-
log('sin artefactos Python que limpiar.');
|
|
125
|
-
} else {
|
|
126
|
-
const accion = dryRun ? 'detectados' : 'eliminados';
|
|
127
|
-
log(`${accion}: ${result.dirs} directorios + ${result.files} archivos.`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
main();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* limpiar-artefactos-python.js — limpia caché Python antes de empaquetar.
|
|
6
|
+
*
|
|
7
|
+
* Se ejecuta como `prepack` antes de `npm pack` y `npm publish` para evitar
|
|
8
|
+
* que artefactos locales (.pyc, __pycache__/) contaminen el tarball publicado.
|
|
9
|
+
*
|
|
10
|
+
* Reglas de seguridad (defensa en profundidad):
|
|
11
|
+
* 1. Aborta si cwd no coincide con la raíz del package.json del repo.
|
|
12
|
+
* 2. Profundidad máxima de recursión: 3 niveles desde la raíz.
|
|
13
|
+
* 3. Allowlist explícita de directorios a EXCLUIR de la búsqueda
|
|
14
|
+
* (node_modules, .git, temp, .planning, respositorios-git, _userland).
|
|
15
|
+
* 4. Solo elimina directorios cuyo nombre coincide exactamente con el
|
|
16
|
+
* conjunto cerrado: __pycache__, .pytest_cache, .mypy_cache, .ruff_cache.
|
|
17
|
+
* 5. Solo elimina archivos sueltos con extensiones .pyc, .pyo.
|
|
18
|
+
* 6. En CI no-interactivo respeta el flag SWL_PREPACK_DRY=1 (no borra,
|
|
19
|
+
* solo lista).
|
|
20
|
+
*
|
|
21
|
+
* Exit codes:
|
|
22
|
+
* 0 — OK (limpieza ejecutada o nada que limpiar)
|
|
23
|
+
* 1 — error de invariante (cwd incorrecto, package.json no encontrado)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const fs = require('fs');
|
|
27
|
+
const path = require('path');
|
|
28
|
+
|
|
29
|
+
const { NOMBRES_VALIDOS } = require('./lib/paquetes-conocidos');
|
|
30
|
+
const {
|
|
31
|
+
DIRS_ARTEFACTOS_PYTHON: DIRS_A_LIMPIAR,
|
|
32
|
+
EXTS_ARTEFACTOS_PYTHON: EXTS_A_LIMPIAR,
|
|
33
|
+
} = require('./lib/artefactos-python');
|
|
34
|
+
|
|
35
|
+
const PROFUNDIDAD_MAX = 3;
|
|
36
|
+
const DIRS_EXCLUIDOS = new Set([
|
|
37
|
+
'node_modules', '.git', 'temp', '.planning', 'respositorios-git',
|
|
38
|
+
'_userland', 'tests', '.github',
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const dryRun = process.env.SWL_PREPACK_DRY === '1';
|
|
42
|
+
|
|
43
|
+
function log(msg) { process.stdout.write(`[prepack] ${msg}\n`); }
|
|
44
|
+
function err(msg) { process.stderr.write(`[prepack] ERROR: ${msg}\n`); }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Verifica que el cwd actual contiene el package.json del repo swl-ses.
|
|
48
|
+
* Esto evita que el script borre directorios en la máquina del usuario si
|
|
49
|
+
* algún día se invocara desde un cwd incorrecto (ej. dentro de un tarball
|
|
50
|
+
* extraído por npm en .npm/_cacache).
|
|
51
|
+
*/
|
|
52
|
+
function verificarRaiz() {
|
|
53
|
+
const cwd = process.cwd();
|
|
54
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
55
|
+
if (!fs.existsSync(pkgPath)) {
|
|
56
|
+
err(`no existe package.json en cwd: ${cwd}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
60
|
+
if (!NOMBRES_VALIDOS.includes(pkg.name)) {
|
|
61
|
+
err(`package.json en ${cwd} no corresponde a swl-ses (name: ${pkg.name}). Abortando por seguridad.`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
return cwd;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Recorre el árbol desde root con profundidad limitada y elimina los
|
|
69
|
+
* artefactos Python detectados. No sigue symlinks.
|
|
70
|
+
*/
|
|
71
|
+
function limpiar(root, profundidad = 0) {
|
|
72
|
+
if (profundidad > PROFUNDIDAD_MAX) return { dirs: 0, files: 0 };
|
|
73
|
+
|
|
74
|
+
let dirsEliminados = 0;
|
|
75
|
+
let filesEliminados = 0;
|
|
76
|
+
|
|
77
|
+
let entries;
|
|
78
|
+
try {
|
|
79
|
+
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
80
|
+
} catch (e) {
|
|
81
|
+
err(`no se pudo leer ${root}: ${e.message}`);
|
|
82
|
+
return { dirs: 0, files: 0 };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (entry.isSymbolicLink()) continue;
|
|
87
|
+
const fullPath = path.join(root, entry.name);
|
|
88
|
+
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
if (DIRS_A_LIMPIAR.has(entry.name)) {
|
|
91
|
+
if (dryRun) {
|
|
92
|
+
log(`[dry-run] borraría dir: ${path.relative(process.cwd(), fullPath)}`);
|
|
93
|
+
} else {
|
|
94
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
95
|
+
log(`borrado dir: ${path.relative(process.cwd(), fullPath)}`);
|
|
96
|
+
}
|
|
97
|
+
dirsEliminados++;
|
|
98
|
+
} else if (!DIRS_EXCLUIDOS.has(entry.name) && !entry.name.startsWith('.')) {
|
|
99
|
+
const sub = limpiar(fullPath, profundidad + 1);
|
|
100
|
+
dirsEliminados += sub.dirs;
|
|
101
|
+
filesEliminados += sub.files;
|
|
102
|
+
}
|
|
103
|
+
} else if (entry.isFile()) {
|
|
104
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
105
|
+
if (EXTS_A_LIMPIAR.has(ext)) {
|
|
106
|
+
if (dryRun) {
|
|
107
|
+
log(`[dry-run] borraría archivo: ${path.relative(process.cwd(), fullPath)}`);
|
|
108
|
+
} else {
|
|
109
|
+
fs.rmSync(fullPath, { force: true });
|
|
110
|
+
}
|
|
111
|
+
filesEliminados++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return { dirs: dirsEliminados, files: filesEliminados };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function main() {
|
|
120
|
+
const root = verificarRaiz();
|
|
121
|
+
const result = limpiar(root);
|
|
122
|
+
|
|
123
|
+
if (result.dirs === 0 && result.files === 0) {
|
|
124
|
+
log('sin artefactos Python que limpiar.');
|
|
125
|
+
} else {
|
|
126
|
+
const accion = dryRun ? 'detectados' : 'eliminados';
|
|
127
|
+
log(`${accion}: ${result.dirs} directorios + ${result.files} archivos.`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
main();
|
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Auth opt-in para swl-mcp-server v1.0.0 (ADR-0019 Sub-fase 3).
|
|
5
|
-
*
|
|
6
|
-
* El stub experimental v0.1.x corría sin auth. Cualquier proceso con acceso al
|
|
7
|
-
* stdio podía leer toda la memoria SWL. Esa decisión era aceptable solo en
|
|
8
|
-
* single-user local — no en multi-usuario, no expuesto a red, no compartido.
|
|
9
|
-
*
|
|
10
|
-
* v1.0.0 introduce auth **opt-in**:
|
|
11
|
-
* - Si `SWL_MCP_API_KEY` NO está definida en el entorno del server, el comportamiento
|
|
12
|
-
* es idéntico al stub (sin auth). Compatibilidad total con clientes existentes.
|
|
13
|
-
* - Si `SWL_MCP_API_KEY` ESTÁ definida, cada `tools/call` debe incluir
|
|
14
|
-
* `params._auth = "<api-key>"`. Sin el token o con token incorrecto, se devuelve
|
|
15
|
-
* `-32001 Unauthorized`.
|
|
16
|
-
*
|
|
17
|
-
* Decisión deliberada de NO usar header `Authorization: Bearer ...`:
|
|
18
|
-
* - El protocolo MCP sobre stdio NO transporta headers HTTP.
|
|
19
|
-
* - Inventar un campo en `initialize.capabilities` específico para swl-ses
|
|
20
|
-
* rompería la spec del protocolo.
|
|
21
|
-
* - `_auth` como campo en `params` es el patrón de menor fricción.
|
|
22
|
-
*
|
|
23
|
-
* Limitaciones aceptadas:
|
|
24
|
-
* - Token estático sin rotación automática — el operador rota manualmente
|
|
25
|
-
* cambiando la env var del proceso.
|
|
26
|
-
* - Sin scopes (read/write) porque v1 sigue siendo read-only.
|
|
27
|
-
*
|
|
28
|
-
* @module scripts/mcp-server/auth
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
const ENV_VAR_NAME = 'SWL_MCP_API_KEY';
|
|
32
|
-
const ERROR_CODE_UNAUTHORIZED = -32001;
|
|
33
|
-
const ERROR_CODE_FORBIDDEN = -32002;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Construye un validador de auth desde el entorno actual.
|
|
37
|
-
*
|
|
38
|
-
* Pattern de "construct once, use many": leer la env var una sola vez al arranque
|
|
39
|
-
* y devolver una función pura que valida cada request. Evita race conditions con
|
|
40
|
-
* tests que mutan process.env.
|
|
41
|
-
*
|
|
42
|
-
* @param {object} [opciones] - { env: NodeJS.ProcessEnv } sustituible para tests.
|
|
43
|
-
* @returns {{ requerida: boolean, validar: (request: object) => { ok: boolean, code?: number, message?: string } }}
|
|
44
|
-
*/
|
|
45
|
-
function construirValidador(opciones = {}) {
|
|
46
|
-
const env = opciones.env || process.env;
|
|
47
|
-
const apiKey = env[ENV_VAR_NAME];
|
|
48
|
-
const requerida = typeof apiKey === 'string' && apiKey.length > 0;
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
requerida,
|
|
52
|
-
validar: (request) => {
|
|
53
|
-
if (!requerida) return { ok: true };
|
|
54
|
-
// Solo validar tools/call — initialize, ping, tools/list son metadata pública.
|
|
55
|
-
const metodo = request && request.method;
|
|
56
|
-
if (metodo !== 'tools/call') return { ok: true };
|
|
57
|
-
|
|
58
|
-
const params = request.params || {};
|
|
59
|
-
const tokenCliente = params._auth;
|
|
60
|
-
|
|
61
|
-
if (typeof tokenCliente !== 'string' || tokenCliente.length === 0) {
|
|
62
|
-
return {
|
|
63
|
-
ok: false,
|
|
64
|
-
code: ERROR_CODE_UNAUTHORIZED,
|
|
65
|
-
message: 'swl-mcp-server requiere autenticación: SWL_MCP_API_KEY está configurada en el server. El cliente debe enviar params._auth con el API key.',
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
if (!comparacionConstante(tokenCliente, apiKey)) {
|
|
69
|
-
return {
|
|
70
|
-
ok: false,
|
|
71
|
-
code: ERROR_CODE_FORBIDDEN,
|
|
72
|
-
message: 'Token inválido.',
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
return { ok: true };
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Comparación de strings en tiempo constante para evitar timing attacks
|
|
82
|
-
* sobre el API key. Implementación zero-deps simple.
|
|
83
|
-
*
|
|
84
|
-
* Si las longitudes difieren, igual se itera la longitud máxima para no filtrar
|
|
85
|
-
* información sobre el largo del secreto vía duración de la comparación.
|
|
86
|
-
*/
|
|
87
|
-
function comparacionConstante(a, b) {
|
|
88
|
-
if (typeof a !== 'string' || typeof b !== 'string') return false;
|
|
89
|
-
const len = Math.max(a.length, b.length);
|
|
90
|
-
let diff = a.length ^ b.length;
|
|
91
|
-
for (let i = 0; i < len; i++) {
|
|
92
|
-
const ca = i < a.length ? a.charCodeAt(i) : 0;
|
|
93
|
-
const cb = i < b.length ? b.charCodeAt(i) : 0;
|
|
94
|
-
diff |= ca ^ cb;
|
|
95
|
-
}
|
|
96
|
-
return diff === 0;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
module.exports = {
|
|
100
|
-
construirValidador,
|
|
101
|
-
comparacionConstante,
|
|
102
|
-
ENV_VAR_NAME,
|
|
103
|
-
ERROR_CODE_UNAUTHORIZED,
|
|
104
|
-
ERROR_CODE_FORBIDDEN,
|
|
105
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Auth opt-in para swl-mcp-server v1.0.0 (ADR-0019 Sub-fase 3).
|
|
5
|
+
*
|
|
6
|
+
* El stub experimental v0.1.x corría sin auth. Cualquier proceso con acceso al
|
|
7
|
+
* stdio podía leer toda la memoria SWL. Esa decisión era aceptable solo en
|
|
8
|
+
* single-user local — no en multi-usuario, no expuesto a red, no compartido.
|
|
9
|
+
*
|
|
10
|
+
* v1.0.0 introduce auth **opt-in**:
|
|
11
|
+
* - Si `SWL_MCP_API_KEY` NO está definida en el entorno del server, el comportamiento
|
|
12
|
+
* es idéntico al stub (sin auth). Compatibilidad total con clientes existentes.
|
|
13
|
+
* - Si `SWL_MCP_API_KEY` ESTÁ definida, cada `tools/call` debe incluir
|
|
14
|
+
* `params._auth = "<api-key>"`. Sin el token o con token incorrecto, se devuelve
|
|
15
|
+
* `-32001 Unauthorized`.
|
|
16
|
+
*
|
|
17
|
+
* Decisión deliberada de NO usar header `Authorization: Bearer ...`:
|
|
18
|
+
* - El protocolo MCP sobre stdio NO transporta headers HTTP.
|
|
19
|
+
* - Inventar un campo en `initialize.capabilities` específico para swl-ses
|
|
20
|
+
* rompería la spec del protocolo.
|
|
21
|
+
* - `_auth` como campo en `params` es el patrón de menor fricción.
|
|
22
|
+
*
|
|
23
|
+
* Limitaciones aceptadas:
|
|
24
|
+
* - Token estático sin rotación automática — el operador rota manualmente
|
|
25
|
+
* cambiando la env var del proceso.
|
|
26
|
+
* - Sin scopes (read/write) porque v1 sigue siendo read-only.
|
|
27
|
+
*
|
|
28
|
+
* @module scripts/mcp-server/auth
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const ENV_VAR_NAME = 'SWL_MCP_API_KEY';
|
|
32
|
+
const ERROR_CODE_UNAUTHORIZED = -32001;
|
|
33
|
+
const ERROR_CODE_FORBIDDEN = -32002;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Construye un validador de auth desde el entorno actual.
|
|
37
|
+
*
|
|
38
|
+
* Pattern de "construct once, use many": leer la env var una sola vez al arranque
|
|
39
|
+
* y devolver una función pura que valida cada request. Evita race conditions con
|
|
40
|
+
* tests que mutan process.env.
|
|
41
|
+
*
|
|
42
|
+
* @param {object} [opciones] - { env: NodeJS.ProcessEnv } sustituible para tests.
|
|
43
|
+
* @returns {{ requerida: boolean, validar: (request: object) => { ok: boolean, code?: number, message?: string } }}
|
|
44
|
+
*/
|
|
45
|
+
function construirValidador(opciones = {}) {
|
|
46
|
+
const env = opciones.env || process.env;
|
|
47
|
+
const apiKey = env[ENV_VAR_NAME];
|
|
48
|
+
const requerida = typeof apiKey === 'string' && apiKey.length > 0;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
requerida,
|
|
52
|
+
validar: (request) => {
|
|
53
|
+
if (!requerida) return { ok: true };
|
|
54
|
+
// Solo validar tools/call — initialize, ping, tools/list son metadata pública.
|
|
55
|
+
const metodo = request && request.method;
|
|
56
|
+
if (metodo !== 'tools/call') return { ok: true };
|
|
57
|
+
|
|
58
|
+
const params = request.params || {};
|
|
59
|
+
const tokenCliente = params._auth;
|
|
60
|
+
|
|
61
|
+
if (typeof tokenCliente !== 'string' || tokenCliente.length === 0) {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
code: ERROR_CODE_UNAUTHORIZED,
|
|
65
|
+
message: 'swl-mcp-server requiere autenticación: SWL_MCP_API_KEY está configurada en el server. El cliente debe enviar params._auth con el API key.',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (!comparacionConstante(tokenCliente, apiKey)) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
code: ERROR_CODE_FORBIDDEN,
|
|
72
|
+
message: 'Token inválido.',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return { ok: true };
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Comparación de strings en tiempo constante para evitar timing attacks
|
|
82
|
+
* sobre el API key. Implementación zero-deps simple.
|
|
83
|
+
*
|
|
84
|
+
* Si las longitudes difieren, igual se itera la longitud máxima para no filtrar
|
|
85
|
+
* información sobre el largo del secreto vía duración de la comparación.
|
|
86
|
+
*/
|
|
87
|
+
function comparacionConstante(a, b) {
|
|
88
|
+
if (typeof a !== 'string' || typeof b !== 'string') return false;
|
|
89
|
+
const len = Math.max(a.length, b.length);
|
|
90
|
+
let diff = a.length ^ b.length;
|
|
91
|
+
for (let i = 0; i < len; i++) {
|
|
92
|
+
const ca = i < a.length ? a.charCodeAt(i) : 0;
|
|
93
|
+
const cb = i < b.length ? b.charCodeAt(i) : 0;
|
|
94
|
+
diff |= ca ^ cb;
|
|
95
|
+
}
|
|
96
|
+
return diff === 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = {
|
|
100
|
+
construirValidador,
|
|
101
|
+
comparacionConstante,
|
|
102
|
+
ENV_VAR_NAME,
|
|
103
|
+
ERROR_CODE_UNAUTHORIZED,
|
|
104
|
+
ERROR_CODE_FORBIDDEN,
|
|
105
|
+
};
|