@saulwade/swl-ses 1.5.2 → 1.6.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 +1 -1
- package/README.md +19 -2
- package/bin/swl-ses.js +49 -7
- package/hooks/extraccion-aprendizajes.js +11 -0
- package/manifiestos/skills-lock.json +46 -18
- package/package.json +4 -3
- package/plugin.json +3 -1
- package/scripts/desinstalar.js +105 -24
- package/scripts/instalador.js +55 -4
- package/scripts/lib/parsear-opciones.js +3 -0
- package/scripts/lib/ui.js +148 -22
- package/scripts/tui/componentes/selector-multi.js +189 -0
- package/scripts/tui/componentes/selector-unico.js +158 -0
- package/scripts/tui/ejecutores.js +375 -0
- package/scripts/tui/index.js +162 -0
- package/scripts/tui/lib/colores.js +129 -0
- package/scripts/tui/lib/render.js +264 -0
- package/scripts/tui/lib/teclas.js +113 -0
- package/scripts/tui/pantallas/inspect.js +173 -0
- package/scripts/tui/pantallas/install-wizard.js +334 -0
- package/scripts/tui/pantallas/menu-principal.js +52 -0
- package/scripts/tui/pantallas/progreso.js +274 -0
- package/scripts/tui/pantallas/resumen.js +132 -0
- package/scripts/tui/pantallas/uninstall-wizard.js +208 -0
- package/scripts/tui/pantallas/update-wizard.js +232 -0
- package/scripts/tui/pantallas/welcome.js +187 -0
- package/scripts/verificar-docs-vs-codigo.js +425 -0
package/CLAUDE.md
CHANGED
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# swl-ses v1.
|
|
1
|
+
# swl-ses v1.6.0
|
|
2
2
|
|
|
3
3
|
> El paquete anterior `@saulwadeleon/swl-software-engineering-system` está deprecado. Migrar a `@saulwade/swl-ses` (npmjs.org canónico) o `@saul-wade/swl-ses` (mirror en GitHub Packages) — el CLI `swl-ses` no cambia.
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ Sistema de ingeniería de software auto-evolutivo **multi-runtime** con agentes
|
|
|
6
6
|
|
|
7
7
|
Soporta 7 runtimes de IA: Claude Code, OpenClaude, OpenCode y Gemini CLI (soporte completo); Cursor, Codex CLI y GitHub Copilot (soporte parcial — reglas + MCP server o consolidación en archivo de instrucciones según el runtime). Incluye sistema de transformadores que adapta el formato canónico SWL al formato nativo de cada runtime, **multi-target install** (`--target=claude,cursor,codex` en una sola invocación), y **`swl-mcp-server` v1.0.0** con auth opt-in para que Cursor, Codex y otros clientes MCP consulten la memoria SWL (aprendizajes, instintos, sesiones).
|
|
8
8
|
|
|
9
|
-
Cubre el SDLC completo: discovery, requisitos, arquitectura, UX/UI, frontend, backend, mobile, datos, testing, seguridad, CI/CD, observabilidad, releases, documentación, notificaciones y auto-evolución. Incluye sistema de notificaciones Telegram opt-in (hook saliente, bot bidireccional con 15 comandos, autostart cross-platform)
|
|
9
|
+
Cubre el SDLC completo: discovery, requisitos, arquitectura, UX/UI, frontend, backend, mobile, datos, testing, seguridad, CI/CD, observabilidad, releases, documentación, notificaciones y auto-evolución. Incluye sistema de notificaciones Telegram opt-in (hook saliente, bot bidireccional con 15 comandos, autostart cross-platform), **auditoría profunda Nemesis** (loop iterativo Feynman + State Inconsistency hasta convergencia, ahora con loop evaluator-optimizer opt-in vía `/swl:nemesis --remediar` desde v1.5.2 - ADR-0021) con 8 tools ejecutables JSON-output para code-profiler, pentest-scanner, dep-doctor, bundle-tracker y más (ADR-0018, v1.4.1), e **instalador/actualizador TUI custom** zero-deps con paneles, multi-select y barra de progreso por categoría (v1.6.0).
|
|
10
10
|
|
|
11
11
|
## Inventario
|
|
12
12
|
|
|
@@ -56,6 +56,23 @@ El setup requiere **dos comandos en orden**, con propósitos distintos:
|
|
|
56
56
|
> y los hace disponibles en todos tus proyectos. Aun así, cada proyecto necesita su propio `init`
|
|
57
57
|
> para obtener `.planning/` y `_userland/`.
|
|
58
58
|
|
|
59
|
+
### Modo recomendado: TUI visual (v1.6.0+)
|
|
60
|
+
|
|
61
|
+
Desde v1.6.0, al ejecutar `install` o `update` sin flags desde una terminal
|
|
62
|
+
interactiva, swl-ses lanza un **TUI custom** con paneles, selectores con
|
|
63
|
+
flechas, multi-select con espacio y barra de progreso por categoría.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Lanza el TUI: Welcome → Menú → Wizard → Progreso → Resumen
|
|
67
|
+
npx -y @saulwade/swl-ses@latest install
|
|
68
|
+
npx -y @saulwade/swl-ses@latest update
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Opt-out con `--no-tui` para usar el asistido lineal clásico, o pasa cualquier
|
|
72
|
+
flag (`--target`, `--profile`, `--force`, etc.) y el CLI usa el flujo directo
|
|
73
|
+
sin prompts. Ver [`MANUAL_USO.md`](./MANUAL_USO.md) sección "Opción C — Modo
|
|
74
|
+
TUI visual" para capturas ASCII de cada pantalla.
|
|
75
|
+
|
|
59
76
|
### Opción 1: CLI vía npmjs (recomendada)
|
|
60
77
|
|
|
61
78
|
```bash
|
package/bin/swl-ses.js
CHANGED
|
@@ -190,7 +190,7 @@ GESTIÓN DE COMPONENTES:
|
|
|
190
190
|
agents remove <nombre> Remueve un agente individual
|
|
191
191
|
|
|
192
192
|
OPCIONES DE INSTALL:
|
|
193
|
-
--target <runtime> Runtime destino: claude|openclaude|copilot|opencode|codex|gemini (default: claude)
|
|
193
|
+
--target <runtime> Runtime destino: claude|openclaude|copilot|opencode|codex|gemini|cursor (default: claude)
|
|
194
194
|
--profile <perfil> Perfil: core|backend-python|backend-node|frontend-react|frontend-angular|
|
|
195
195
|
fullstack-python-angular|fullstack-node-react|mobile|devops|completo (default: core)
|
|
196
196
|
--with <componentes> Incluir componentes adicionales (separados por coma)
|
|
@@ -200,10 +200,19 @@ OPCIONES DE INSTALL:
|
|
|
200
200
|
--dry-run Mostrar plan sin aplicar cambios
|
|
201
201
|
--force Sobreescribir archivos existentes sin confirmar
|
|
202
202
|
--all-langs Instalar reglas de todos los lenguajes (omite detección automática de stack)
|
|
203
|
+
--with-mcp Configura el MCP server swl-memory automáticamente (v1.5.0+)
|
|
204
|
+
--tui Fuerza el modo TUI visual aunque pases otros flags (v1.6.0+)
|
|
205
|
+
--no-tui Desactiva el TUI; usa el asistido lineal clásico (v1.6.0+)
|
|
206
|
+
--verbose Expande el panel de log del Progreso del TUI de 8 a 24 líneas (v1.6.0+)
|
|
203
207
|
--no-claudemd No modificar el CLAUDE.md del proyecto (solo aplica con --target claude).
|
|
204
208
|
Por defecto el instalador crea o actualiza un bloque delimitado por
|
|
205
209
|
<!-- SWL-BEGIN vX.Y.Z --> / <!-- SWL-END --> preservando el resto del archivo.
|
|
206
210
|
|
|
211
|
+
MODOS DE INVOCACIÓN (v1.6.0+):
|
|
212
|
+
TTY + sin flags → TUI visual completo (recomendado)
|
|
213
|
+
TTY + --no-tui → Asistido lineal clásico (preguntas en serie)
|
|
214
|
+
No-TTY o con flags → Modo directo sin prompts (CI/scripts)
|
|
215
|
+
|
|
207
216
|
OPCIONES DE SKILLS/AGENTS:
|
|
208
217
|
--skill <nombre> Nombre del skill a extraer del repo (con skills add)
|
|
209
218
|
--agent <nombre> Nombre del agente a extraer del repo (con agents add)
|
|
@@ -215,11 +224,14 @@ OPCIONES GENERALES:
|
|
|
215
224
|
|
|
216
225
|
EJEMPLOS:
|
|
217
226
|
${NOMBRE} init
|
|
218
|
-
${NOMBRE} install (
|
|
227
|
+
${NOMBRE} install (TUI visual — recomendado para primera vez)
|
|
228
|
+
${NOMBRE} install --no-tui (asistido lineal clásico)
|
|
219
229
|
${NOMBRE} install --target claude --profile backend-python
|
|
220
230
|
${NOMBRE} install --target openclaude --profile fullstack-python-angular
|
|
221
231
|
${NOMBRE} install --target gemini --profile core
|
|
222
232
|
${NOMBRE} install --target copilot --profile fullstack-node-react
|
|
233
|
+
${NOMBRE} update (TUI visual con multi-select de runtimes)
|
|
234
|
+
${NOMBRE} update --no-tui (preguntas lineales clásicas)
|
|
223
235
|
${NOMBRE} skills list --target claude
|
|
224
236
|
${NOMBRE} skills add https://github.com/user/repo --skill mi-skill
|
|
225
237
|
${NOMBRE} agents add ./path/local --agent mi-agente
|
|
@@ -312,14 +324,44 @@ function main() {
|
|
|
312
324
|
|
|
313
325
|
const opciones = parsearOpciones(args.slice(1));
|
|
314
326
|
|
|
315
|
-
// Modo asistido: `install` sin flags →
|
|
316
|
-
//
|
|
317
|
-
|
|
318
|
-
|
|
327
|
+
// Modo asistido / TUI: `install` o `update` sin flags relevantes → modo visual.
|
|
328
|
+
//
|
|
329
|
+
// Niveles de fallback:
|
|
330
|
+
// 1. TTY + sin flags (excepto --tui): lanzar TUI completo (scripts/tui/index.js)
|
|
331
|
+
// 2. TTY + --no-tui: lanzar install-asistido clásico (preguntarOpcion lineal)
|
|
332
|
+
// 3. No TTY (CI/pipe): flujo clásico con flags por defecto sin asistido
|
|
333
|
+
//
|
|
334
|
+
// El usuario puede forzar el TUI incluso con flags pasando --tui.
|
|
335
|
+
if (comando === 'install' || comando === 'update') {
|
|
336
|
+
const flagsIrrelevantesParaAsistido = ['verbose', 'tui'];
|
|
319
337
|
const flagsEspecificados = Object.keys(opciones).filter(
|
|
320
338
|
k => k !== '_args' && !flagsIrrelevantesParaAsistido.includes(k)
|
|
321
339
|
);
|
|
322
|
-
|
|
340
|
+
const stdinTty = !!process.stdin.isTTY;
|
|
341
|
+
const optoutTui = opciones['no-tui'] || opciones.no_tui;
|
|
342
|
+
const forzarTui = opciones.tui;
|
|
343
|
+
const sinFlags = flagsEspecificados.length === 0;
|
|
344
|
+
|
|
345
|
+
if ((sinFlags || forzarTui) && stdinTty && !optoutTui) {
|
|
346
|
+
try {
|
|
347
|
+
const { iniciarTui } = require('../scripts/tui');
|
|
348
|
+
iniciarTui({ operacionInicial: comando }).then(() => {
|
|
349
|
+
process.exit(0);
|
|
350
|
+
}).catch(err => {
|
|
351
|
+
console.error(`Error en TUI: ${err.message}`);
|
|
352
|
+
if (opciones.verbose) console.error(err.stack);
|
|
353
|
+
process.exit(1);
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
} catch (err) {
|
|
357
|
+
console.error(`Error cargando TUI: ${err.message}`);
|
|
358
|
+
if (opciones.verbose) console.error(err.stack);
|
|
359
|
+
// Caer al asistido clásico como fallback
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (comando === 'install' && sinFlags && !forzarTui) {
|
|
364
|
+
// Fallback al asistido lineal (sin TUI) — preserva la UX de versiones previas
|
|
323
365
|
try {
|
|
324
366
|
const asistido = require('../scripts/comandos/install-asistido');
|
|
325
367
|
asistido.main().catch(err => {
|
|
@@ -618,6 +618,17 @@ const PATRONES_ARCHIVO_SWL_EXCLUIDO = [
|
|
|
618
618
|
/(?:^|[\\/])plantillas[\\/]/,
|
|
619
619
|
/(?:^|[\\/])contextos[\\/]/,
|
|
620
620
|
/(?:^|[\\/])instintos[\\/]/,
|
|
621
|
+
// Tests (cualquier convención): los comentarios JSDoc/docstring de un test
|
|
622
|
+
// describen el SUT y suelen contener palabras como "bug", "patrón", "fix"
|
|
623
|
+
// de forma narrativa-descriptiva, no como descubrimiento. Detectado cuando
|
|
624
|
+
// el hook capturó comentarios del propio test que valida un fix y los
|
|
625
|
+
// promovió a APRENDIZAJES.md como entradas truncadas.
|
|
626
|
+
/(?:^|[\\/])tests?[\\/]/,
|
|
627
|
+
/(?:^|[\\/])__tests__[\\/]/,
|
|
628
|
+
/(?:^|[\\/])spec[\\/]/,
|
|
629
|
+
/\.(?:test|spec)\.(?:js|ts|jsx|tsx|mjs|cjs)$/i,
|
|
630
|
+
/(?:^|[\\/])test_.*\.py$/,
|
|
631
|
+
/_test\.(?:py|go)$/i,
|
|
621
632
|
// Todo .planning/ salvo wiki/ (que puede contener conocimiento del proyecto usuario).
|
|
622
633
|
// En swl-ses .planning/ es meta del sistema; los aprendizajes se gestionan manualmente.
|
|
623
634
|
/(?:^|[\\/])\.planning[\\/](?!wiki[\\/])/,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"lockfileVersion": 1,
|
|
3
|
-
"generatedAt": "2026-05-
|
|
4
|
-
"skillsCount":
|
|
5
|
-
"lockHash": "sha256:
|
|
3
|
+
"generatedAt": "2026-05-16T18:45:23.117Z",
|
|
4
|
+
"skillsCount": 162,
|
|
5
|
+
"lockHash": "sha256:20e7bde29e6c2ca22f9fa77c436ebc2a9085d6f45c0378478ba2d7717f00875c",
|
|
6
6
|
"skills": [
|
|
7
7
|
{
|
|
8
8
|
"nombre": "accesibilidad-a11y",
|
|
@@ -343,9 +343,9 @@
|
|
|
343
343
|
{
|
|
344
344
|
"nombre": "discutir-fase",
|
|
345
345
|
"path": "habilidades/discutir-fase/SKILL.md",
|
|
346
|
-
"hash": "sha256:
|
|
347
|
-
"bytes":
|
|
348
|
-
"version": "\"1.
|
|
346
|
+
"hash": "sha256:c3e77c9a40ee4fcec31d26a0be8e34b915c6ce1d704b02900456328669f4fad5",
|
|
347
|
+
"bytes": 11591,
|
|
348
|
+
"version": "\"1.1.0\""
|
|
349
349
|
},
|
|
350
350
|
{
|
|
351
351
|
"nombre": "diseno-herramientas-agente",
|
|
@@ -396,6 +396,13 @@
|
|
|
396
396
|
"bytes": 19364,
|
|
397
397
|
"version": "\"1.1.0\""
|
|
398
398
|
},
|
|
399
|
+
{
|
|
400
|
+
"nombre": "ejecutar-task-iterativo",
|
|
401
|
+
"path": "habilidades/ejecutar-task-iterativo/SKILL.md",
|
|
402
|
+
"hash": "sha256:ca8780fd72ad10dd21085c6cbbbd3baa0e625c0ba0834e1c3ec8e2b5934b88ba",
|
|
403
|
+
"bytes": 13131,
|
|
404
|
+
"version": "\"1.0.0\""
|
|
405
|
+
},
|
|
399
406
|
{
|
|
400
407
|
"nombre": "estilo-sin-ai-isms",
|
|
401
408
|
"path": "habilidades/estilo-sin-ai-isms/SKILL.md",
|
|
@@ -651,9 +658,9 @@
|
|
|
651
658
|
{
|
|
652
659
|
"nombre": "meta-skills-estandar",
|
|
653
660
|
"path": "habilidades/meta-skills-estandar/SKILL.md",
|
|
654
|
-
"hash": "sha256:
|
|
655
|
-
"bytes":
|
|
656
|
-
"version": "\"1.
|
|
661
|
+
"hash": "sha256:4908de280db0d143643fc96ae748519edc2142aa9ef35c415cd84074c274d613",
|
|
662
|
+
"bytes": 23181,
|
|
663
|
+
"version": "\"1.1.1\""
|
|
657
664
|
},
|
|
658
665
|
{
|
|
659
666
|
"nombre": "microservicios",
|
|
@@ -690,6 +697,20 @@
|
|
|
690
697
|
"bytes": 11807,
|
|
691
698
|
"version": "\"1.0.1\""
|
|
692
699
|
},
|
|
700
|
+
{
|
|
701
|
+
"nombre": "nemesis-evaluacion-json",
|
|
702
|
+
"path": "habilidades/nemesis-evaluacion-json/SKILL.md",
|
|
703
|
+
"hash": "sha256:e8c84252b6d6080101486b5acc021af14c9eeab6d25b71a0fc0f450177d5782d",
|
|
704
|
+
"bytes": 10610,
|
|
705
|
+
"version": null
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
"nombre": "nemesis-redistribuir",
|
|
709
|
+
"path": "habilidades/nemesis-redistribuir/SKILL.md",
|
|
710
|
+
"hash": "sha256:171919fe921f411b065644ab09a93bd32c68fa74f43669d83522ad237e4b0590",
|
|
711
|
+
"bytes": 13610,
|
|
712
|
+
"version": null
|
|
713
|
+
},
|
|
693
714
|
{
|
|
694
715
|
"nombre": "nestjs-experto",
|
|
695
716
|
"path": "habilidades/nestjs-experto/SKILL.md",
|
|
@@ -721,9 +742,9 @@
|
|
|
721
742
|
{
|
|
722
743
|
"nombre": "node-experto",
|
|
723
744
|
"path": "habilidades/node-experto/SKILL.md",
|
|
724
|
-
"hash": "sha256:
|
|
725
|
-
"bytes":
|
|
726
|
-
"version": "\"1.0.
|
|
745
|
+
"hash": "sha256:bf8ea36fadabf2b7a30590a2a1658ca39ddb15b4285c709db4379c631259f2b2",
|
|
746
|
+
"bytes": 19290,
|
|
747
|
+
"version": "\"1.0.2\""
|
|
727
748
|
},
|
|
728
749
|
{
|
|
729
750
|
"nombre": "notificaciones-multicanal",
|
|
@@ -837,6 +858,13 @@
|
|
|
837
858
|
"bytes": 21302,
|
|
838
859
|
"version": "\"1.1.0\""
|
|
839
860
|
},
|
|
861
|
+
{
|
|
862
|
+
"nombre": "protocolo-revision-swl",
|
|
863
|
+
"path": "habilidades/protocolo-revision-swl/SKILL.md",
|
|
864
|
+
"hash": "sha256:5ebbe37b828d70f7e5190f49116fd56e75280cc9a39e5c53302064e211437215",
|
|
865
|
+
"bytes": 15867,
|
|
866
|
+
"version": "\"1.0.1\""
|
|
867
|
+
},
|
|
840
868
|
{
|
|
841
869
|
"nombre": "rag-arquitectura",
|
|
842
870
|
"path": "habilidades/rag-arquitectura/SKILL.md",
|
|
@@ -1001,9 +1029,9 @@
|
|
|
1001
1029
|
{
|
|
1002
1030
|
"nombre": "tdd-workflow",
|
|
1003
1031
|
"path": "habilidades/tdd-workflow/SKILL.md",
|
|
1004
|
-
"hash": "sha256:
|
|
1005
|
-
"bytes":
|
|
1006
|
-
"version": "\"1.0.
|
|
1032
|
+
"hash": "sha256:5bc34fef3315efa871c56210fc1942f430e1b5fb61dc54ab23891c352555e638",
|
|
1033
|
+
"bytes": 23870,
|
|
1034
|
+
"version": "\"1.0.4\""
|
|
1007
1035
|
},
|
|
1008
1036
|
{
|
|
1009
1037
|
"nombre": "terraform-experto",
|
|
@@ -1078,9 +1106,9 @@
|
|
|
1078
1106
|
{
|
|
1079
1107
|
"nombre": "verificar-trabajo",
|
|
1080
1108
|
"path": "habilidades/verificar-trabajo/SKILL.md",
|
|
1081
|
-
"hash": "sha256:
|
|
1082
|
-
"bytes":
|
|
1083
|
-
"version": "\"1.
|
|
1109
|
+
"hash": "sha256:4aeab56aee56b7b481d8e2c59a4da505ad5bad6abff22e83e4e116c58fa1bbbf",
|
|
1110
|
+
"bytes": 21346,
|
|
1111
|
+
"version": "\"1.2.1\""
|
|
1084
1112
|
},
|
|
1085
1113
|
{
|
|
1086
1114
|
"nombre": "web-fetcher-routing",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saulwade/swl-ses",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Sistema de ingenieria de software auto-evolutivo multi-runtime polyglot con 60 agentes, 162 habilidades, 44 comandos, 66 reglas y 41 hooks. Soporta 11 lenguajes y 7 runtimes: Claude Code, OpenClaude, OpenCode, Gemini CLI, Cursor, Codex CLI (soporte completo); GitHub Copilot (soporte parcial). 100% en espanol (Mexico). Multi-target install (--target CSV / --all-runtimes), autoconfig MCP en Cursor/Codex con --with-mcp, agentes Codex en TOML, hooks Cursor (17 eventos) y Codex (6 eventos). Gateway bidireccional con relay Telegram y auditoria profunda Nemesis con loop evaluator-optimizer opt-in (ADR-0021) y 8 tools ejecutables.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"swl-ses": "bin/swl-ses.js",
|
|
@@ -28,12 +28,13 @@
|
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
30
|
"postinstall": "echo '\n swl-software-engineering-system instalado.\n Ejecuta: npx swl-ses init\n'",
|
|
31
|
-
"test": "node --test tests/lib/*.test.js tests/scripts/*.test.js tests/scripts/lib/*.test.js tests/hooks/*.test.js tests/gateway/*.test.js tests/bin/*.test.js tests/transformadores/*.test.js tests/mcp-server/*.test.js",
|
|
31
|
+
"test": "node --test tests/lib/*.test.js tests/scripts/*.test.js tests/scripts/lib/*.test.js tests/scripts/tui/*.test.js tests/hooks/*.test.js tests/gateway/*.test.js tests/bin/*.test.js tests/transformadores/*.test.js tests/mcp-server/*.test.js",
|
|
32
32
|
"test:validate": "node scripts/validar.js",
|
|
33
33
|
"test:manifest": "node scripts/validar-manifest.js",
|
|
34
|
+
"test:docs": "node scripts/verificar-docs-vs-codigo.js",
|
|
34
35
|
"test:smoke": "node scripts/smoke-test.js",
|
|
35
36
|
"test:aislamiento": "node scripts/validar-tests-aislamiento.js",
|
|
36
|
-
"test:all": "npm test && node scripts/validar.js && node scripts/validar-manifest.js",
|
|
37
|
+
"test:all": "npm test && node scripts/validar.js && node scripts/validar-manifest.js && node scripts/verificar-docs-vs-codigo.js",
|
|
37
38
|
"test:userland": "node scripts/validar-userland-vacio.js",
|
|
38
39
|
"test:release": "npm run test:all && npm run test:userland && npm run test:smoke",
|
|
39
40
|
"doctor": "node scripts/doctor.js",
|
package/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swl-ses",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Sistema de ingenieria de software auto-evolutivo multi-runtime polyglot. 60 agentes, 162 habilidades, 44 comandos, 66 reglas y 41 hooks. 62 librerias. 11 lenguajes. Soporta Claude Code, Copilot, OpenCode, Codex y Gemini CLI. Loop evaluator-optimizer en /swl:nemesis (ADR-0021).",
|
|
5
5
|
"author": "Saul Wade Leon",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"habilidades/doubt-driven-review",
|
|
63
63
|
"habilidades/drift-detection",
|
|
64
64
|
"habilidades/ejecutar-fase",
|
|
65
|
+
"habilidades/ejecutar-task-iterativo",
|
|
65
66
|
"habilidades/estilo-sin-ai-isms",
|
|
66
67
|
"habilidades/estructura-proyecto-claude",
|
|
67
68
|
"habilidades/eval-framework",
|
|
@@ -127,6 +128,7 @@
|
|
|
127
128
|
"habilidades/prevencion-sobreingenieria",
|
|
128
129
|
"habilidades/privacy-memoria",
|
|
129
130
|
"habilidades/prompt-engineering",
|
|
131
|
+
"habilidades/protocolo-revision-swl",
|
|
130
132
|
"habilidades/rag-arquitectura",
|
|
131
133
|
"habilidades/rails-experto",
|
|
132
134
|
"habilidades/react-experto",
|
package/scripts/desinstalar.js
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* swl-ses uninstall
|
|
5
5
|
* Desinstala componentes SWL del runtime especificado.
|
|
6
|
+
*
|
|
7
|
+
* Contrato adicional: opciones.onProgress(evento)
|
|
8
|
+
*
|
|
9
|
+
* Si se pasa una función onProgress, el desinstalador emite eventos
|
|
10
|
+
* estructurados en vez de imprimir cada archivo a stdout:
|
|
11
|
+
* { tipo: 'archivo-eliminado', componente, archivo, destino }
|
|
12
|
+
* { tipo: 'bloque-eliminado', archivo, etiqueta }
|
|
13
|
+
* { tipo: 'archivo-no-encontrado', archivo }
|
|
14
|
+
* { tipo: 'error', archivo, mensaje }
|
|
15
|
+
* { tipo: 'log', linea }
|
|
16
|
+
*
|
|
17
|
+
* Backward compat: si onProgress no se pasa, los console.log son idénticos
|
|
18
|
+
* a antes. El CLI clásico (uninstall sin TUI) no cambia.
|
|
19
|
+
*
|
|
20
|
+
* Devuelve { eliminados, noEncontrados, bloquesEliminados } para que el
|
|
21
|
+
* caller (TUI) pueda mostrar resumen sin re-parsear stdout.
|
|
6
22
|
*/
|
|
7
23
|
|
|
8
24
|
const fs = require('fs');
|
|
@@ -15,23 +31,40 @@ const { eliminarBloque } = require('./lib/append-con-marcadores');
|
|
|
15
31
|
function uninstall(opciones) {
|
|
16
32
|
const target = opciones.target || 'claude';
|
|
17
33
|
const esGlobal = opciones.global || false;
|
|
34
|
+
const onProgress = typeof opciones.onProgress === 'function' ? opciones.onProgress : null;
|
|
18
35
|
|
|
19
|
-
|
|
20
|
-
|
|
36
|
+
function _emitir(evento, mensajeFallback) {
|
|
37
|
+
if (onProgress) {
|
|
38
|
+
onProgress(evento);
|
|
39
|
+
} else if (mensajeFallback) {
|
|
40
|
+
console.log(mensajeFallback);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!onProgress) {
|
|
45
|
+
console.log('swl-ses uninstall');
|
|
46
|
+
console.log('='.repeat(40));
|
|
47
|
+
}
|
|
21
48
|
|
|
22
49
|
const runtime = obtenerRuntime(target);
|
|
23
50
|
const rutas = calcularRutas(target, { global: esGlobal });
|
|
24
51
|
|
|
25
52
|
const estado = cargarEstado(rutas.base);
|
|
26
53
|
if (!estado) {
|
|
54
|
+
if (onProgress) {
|
|
55
|
+
onProgress({ tipo: 'log', linea: `No se encontró instalación SWL en ${rutas.base}` });
|
|
56
|
+
return { eliminados: 0, noEncontrados: 0, bloquesEliminados: 0, error: 'instalacion-no-encontrada' };
|
|
57
|
+
}
|
|
27
58
|
console.log(`No se encontró instalación SWL en ${rutas.base}`);
|
|
28
59
|
process.exit(1);
|
|
29
60
|
}
|
|
30
61
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
if (!onProgress) {
|
|
63
|
+
console.log(`Target: ${target} (${runtime.nombre})`);
|
|
64
|
+
console.log(`Ubicación: ${rutas.base}`);
|
|
65
|
+
console.log(`Archivos a eliminar: ${estado.archivosInstalados.length}`);
|
|
66
|
+
console.log('');
|
|
67
|
+
}
|
|
35
68
|
|
|
36
69
|
let eliminados = 0;
|
|
37
70
|
let noEncontrados = 0;
|
|
@@ -56,10 +89,17 @@ function uninstall(opciones) {
|
|
|
56
89
|
if (accionInstall === 'creado') {
|
|
57
90
|
try {
|
|
58
91
|
fs.unlinkSync(archivo.destino);
|
|
59
|
-
|
|
92
|
+
_emitir(
|
|
93
|
+
{ tipo: 'archivo-eliminado', componente: archivo.tipo, archivo: archivo.destino, motivo: 'creado-por-swl' },
|
|
94
|
+
` - ${archivo.destino} (creado por swl-ses, eliminación completa)`
|
|
95
|
+
);
|
|
60
96
|
eliminados++;
|
|
61
97
|
} catch (err) {
|
|
62
|
-
|
|
98
|
+
_emitir(
|
|
99
|
+
{ tipo: 'error', archivo: archivo.destino, mensaje: err.message },
|
|
100
|
+
null
|
|
101
|
+
);
|
|
102
|
+
if (!onProgress) console.error(` ! Error eliminando ${archivo.destino}: ${err.message}`);
|
|
63
103
|
}
|
|
64
104
|
} else {
|
|
65
105
|
try {
|
|
@@ -70,12 +110,19 @@ function uninstall(opciones) {
|
|
|
70
110
|
'sin-cambios': 'sin bloque SWL presente (ya limpio)',
|
|
71
111
|
'error': `error: ${r.detalle || 'desconocido'}`,
|
|
72
112
|
}[r.accion] || r.accion;
|
|
73
|
-
|
|
113
|
+
_emitir(
|
|
114
|
+
{ tipo: 'bloque-eliminado', archivo: archivo.destino, etiqueta, accion: r.accion },
|
|
115
|
+
` ~ ${archivo.destino} (${etiqueta})`
|
|
116
|
+
);
|
|
74
117
|
if (r.accion === 'bloque-eliminado' || r.accion === 'archivo-eliminado') {
|
|
75
118
|
bloquesEliminados++;
|
|
76
119
|
}
|
|
77
120
|
} catch (err) {
|
|
78
|
-
|
|
121
|
+
_emitir(
|
|
122
|
+
{ tipo: 'error', archivo: archivo.destino, mensaje: err.message },
|
|
123
|
+
null
|
|
124
|
+
);
|
|
125
|
+
if (!onProgress) console.error(` ! Error limpiando bloque en ${archivo.destino}: ${err.message}`);
|
|
79
126
|
}
|
|
80
127
|
}
|
|
81
128
|
continue;
|
|
@@ -88,26 +135,47 @@ function uninstall(opciones) {
|
|
|
88
135
|
} else {
|
|
89
136
|
fs.unlinkSync(archivo.destino);
|
|
90
137
|
}
|
|
91
|
-
|
|
138
|
+
_emitir(
|
|
139
|
+
{ tipo: 'archivo-eliminado', componente: archivo.tipo, archivo: archivo.destino },
|
|
140
|
+
` - ${archivo.destino}`
|
|
141
|
+
);
|
|
92
142
|
eliminados++;
|
|
93
143
|
} catch (err) {
|
|
94
|
-
|
|
144
|
+
_emitir(
|
|
145
|
+
{ tipo: 'error', archivo: archivo.destino, mensaje: err.message },
|
|
146
|
+
null
|
|
147
|
+
);
|
|
148
|
+
if (!onProgress) console.error(` ! Error eliminando ${archivo.destino}: ${err.message}`);
|
|
95
149
|
}
|
|
96
150
|
}
|
|
97
151
|
|
|
98
152
|
// Desregistrar hooks de settings.json
|
|
153
|
+
let hooksDesregistrados = 0;
|
|
154
|
+
let hooksPreservados = 0;
|
|
99
155
|
if (runtime.soportaHooks) {
|
|
100
156
|
const settingsPath = rutaSettings(runtime, rutas.base);
|
|
101
157
|
try {
|
|
102
158
|
const resultado = desregistrarHooks(settingsPath);
|
|
103
|
-
|
|
104
|
-
|
|
159
|
+
hooksDesregistrados = resultado.eliminados || 0;
|
|
160
|
+
hooksPreservados = resultado.preservados || 0;
|
|
161
|
+
if (hooksDesregistrados > 0) {
|
|
162
|
+
_emitir(
|
|
163
|
+
{ tipo: 'hooks-desregistrados', cuenta: hooksDesregistrados },
|
|
164
|
+
` - Hooks desregistrados de settings.json: ${hooksDesregistrados}`
|
|
165
|
+
);
|
|
105
166
|
}
|
|
106
|
-
if (
|
|
107
|
-
|
|
167
|
+
if (hooksPreservados > 0) {
|
|
168
|
+
_emitir(
|
|
169
|
+
{ tipo: 'hooks-preservados', cuenta: hooksPreservados },
|
|
170
|
+
` (${hooksPreservados} hooks externos preservados)`
|
|
171
|
+
);
|
|
108
172
|
}
|
|
109
173
|
} catch (err) {
|
|
110
|
-
|
|
174
|
+
_emitir(
|
|
175
|
+
{ tipo: 'error', mensaje: `Error desregistrando hooks: ${err.message}` },
|
|
176
|
+
null
|
|
177
|
+
);
|
|
178
|
+
if (!onProgress) console.error(` ! Error desregistrando hooks: ${err.message}`);
|
|
111
179
|
}
|
|
112
180
|
}
|
|
113
181
|
|
|
@@ -117,14 +185,27 @@ function uninstall(opciones) {
|
|
|
117
185
|
fs.unlinkSync(estadoPath);
|
|
118
186
|
}
|
|
119
187
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
188
|
+
if (!onProgress) {
|
|
189
|
+
console.log('');
|
|
190
|
+
console.log(`Eliminados: ${eliminados}`);
|
|
191
|
+
if (bloquesEliminados > 0) {
|
|
192
|
+
console.log(`Bloques SWL quitados (contenido de usuario preservado): ${bloquesEliminados}`);
|
|
193
|
+
}
|
|
194
|
+
console.log(`No encontrados: ${noEncontrados}`);
|
|
195
|
+
console.log('');
|
|
196
|
+
console.log('Nota: .planning/ y _userland/ no se eliminan (contienen datos del proyecto).');
|
|
124
197
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
eliminados,
|
|
201
|
+
noEncontrados,
|
|
202
|
+
bloquesEliminados,
|
|
203
|
+
hooksDesregistrados,
|
|
204
|
+
hooksPreservados,
|
|
205
|
+
target,
|
|
206
|
+
scope: esGlobal ? 'global' : 'proyecto',
|
|
207
|
+
ubicacion: rutas.base,
|
|
208
|
+
};
|
|
128
209
|
}
|
|
129
210
|
|
|
130
211
|
module.exports = uninstall;
|
package/scripts/instalador.js
CHANGED
|
@@ -42,6 +42,24 @@ const { actualizarGitignore, entradasParaRuntime, limpiarTracked, leerManifest,
|
|
|
42
42
|
const RAIZ_PKG = path.resolve(__dirname, '..');
|
|
43
43
|
const VERSION = require('../package.json').version;
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Contrato adicional: `opciones.onProgress(evento)`
|
|
47
|
+
*
|
|
48
|
+
* Si se pasa una función `opciones.onProgress`, el instalador deja de imprimir
|
|
49
|
+
* cada archivo copiado/backup/symlink a stdout y en su lugar emite eventos
|
|
50
|
+
* estructurados que el caller (típicamente la TUI) puede consumir para mostrar
|
|
51
|
+
* barra de progreso + contadores por categoría.
|
|
52
|
+
*
|
|
53
|
+
* Eventos emitidos:
|
|
54
|
+
* { tipo: 'archivo-copiado', componente: 'agentes'|'habilidades'|... , archivo: 'nombre.md' }
|
|
55
|
+
* { tipo: 'backup', componente: <tipo>, archivo, rutaBackup }
|
|
56
|
+
* { tipo: 'symlink', componente: <tipo>, archivo }
|
|
57
|
+
* { tipo: 'colision', componente: <tipo>, archivo }
|
|
58
|
+
* { tipo: 'log', linea: 'mensaje libre' } — para mensajes informativos
|
|
59
|
+
*
|
|
60
|
+
* Backward compat: si onProgress NO se pasa, los console.log siguen iguales.
|
|
61
|
+
* El comportamiento sin TUI no cambia.
|
|
62
|
+
*/
|
|
45
63
|
async function install(opciones) {
|
|
46
64
|
// Leer manifest .swl-ses si existe — sus valores son defaults que el CLI puede sobreescribir
|
|
47
65
|
const manifest = leerManifest(process.cwd());
|
|
@@ -990,7 +1008,15 @@ function instalarArchivo(archivo, rutas, runtime, opciones = {}) {
|
|
|
990
1008
|
|
|
991
1009
|
// Verificar colisión
|
|
992
1010
|
if (fs.existsSync(destino) && !opciones.force) {
|
|
993
|
-
|
|
1011
|
+
if (typeof opciones.onProgress === 'function') {
|
|
1012
|
+
opciones.onProgress({
|
|
1013
|
+
tipo: 'colision',
|
|
1014
|
+
componente: archivo.tipo,
|
|
1015
|
+
archivo: nombreArchivo,
|
|
1016
|
+
});
|
|
1017
|
+
} else {
|
|
1018
|
+
console.log(` - Colisión: ${nombreArchivo} (usa --force para sobreescribir)`);
|
|
1019
|
+
}
|
|
994
1020
|
return { instalado: false, colision: true };
|
|
995
1021
|
}
|
|
996
1022
|
|
|
@@ -998,7 +1024,16 @@ function instalarArchivo(archivo, rutas, runtime, opciones = {}) {
|
|
|
998
1024
|
if (fs.existsSync(destino) && opciones.force && opciones.versionAnterior) {
|
|
999
1025
|
const backup = crearBackup(process.cwd(), destino, opciones.versionAnterior);
|
|
1000
1026
|
if (backup.respaldado) {
|
|
1001
|
-
|
|
1027
|
+
if (typeof opciones.onProgress === 'function') {
|
|
1028
|
+
opciones.onProgress({
|
|
1029
|
+
tipo: 'backup',
|
|
1030
|
+
componente: archivo.tipo,
|
|
1031
|
+
archivo: nombreArchivo,
|
|
1032
|
+
rutaBackup: backup.rutaBackup,
|
|
1033
|
+
});
|
|
1034
|
+
} else {
|
|
1035
|
+
console.log(` ↩ Backup: ${nombreArchivo} → ${path.relative(process.cwd(), backup.rutaBackup)}`);
|
|
1036
|
+
}
|
|
1002
1037
|
if (opciones.estado) {
|
|
1003
1038
|
registrarBackup(opciones.estado, {
|
|
1004
1039
|
rutaOriginal: destino,
|
|
@@ -1027,7 +1062,15 @@ function instalarArchivo(archivo, rutas, runtime, opciones = {}) {
|
|
|
1027
1062
|
}
|
|
1028
1063
|
const origenAbsoluto = path.resolve(archivo.origen);
|
|
1029
1064
|
fs.symlinkSync(origenAbsoluto, destino, stat.isDirectory() ? 'junction' : 'file');
|
|
1030
|
-
|
|
1065
|
+
if (typeof opciones.onProgress === 'function') {
|
|
1066
|
+
opciones.onProgress({
|
|
1067
|
+
tipo: 'symlink',
|
|
1068
|
+
componente: archivo.tipo,
|
|
1069
|
+
archivo: nombreArchivo,
|
|
1070
|
+
});
|
|
1071
|
+
} else {
|
|
1072
|
+
console.log(` ~ ${path.relative(rutas.base, destino)} (symlink)`);
|
|
1073
|
+
}
|
|
1031
1074
|
return { instalado: true, destino };
|
|
1032
1075
|
} catch (symlinkErr) {
|
|
1033
1076
|
// Fallback a copy si symlink falla (permisos, filesystem)
|
|
@@ -1045,7 +1088,15 @@ function instalarArchivo(archivo, rutas, runtime, opciones = {}) {
|
|
|
1045
1088
|
} else {
|
|
1046
1089
|
fs.copyFileSync(archivo.origen, destino);
|
|
1047
1090
|
}
|
|
1048
|
-
|
|
1091
|
+
if (typeof opciones.onProgress === 'function') {
|
|
1092
|
+
opciones.onProgress({
|
|
1093
|
+
tipo: 'archivo-copiado',
|
|
1094
|
+
componente: archivo.tipo,
|
|
1095
|
+
archivo: nombreArchivo,
|
|
1096
|
+
});
|
|
1097
|
+
} else {
|
|
1098
|
+
console.log(` + ${path.relative(rutas.base, destino)}`);
|
|
1099
|
+
}
|
|
1049
1100
|
return { instalado: true, destino };
|
|
1050
1101
|
} else {
|
|
1051
1102
|
return { instalado: false, razon: 'origen no existe' };
|
|
@@ -45,6 +45,9 @@ const BOOLEANAS = [
|
|
|
45
45
|
// ADR-0019 — Codex/Cursor + MCP autoconfig opt-in
|
|
46
46
|
'with-mcp', 'no-mcp',
|
|
47
47
|
'all-runtimes',
|
|
48
|
+
// TUI opt-out (Fase 4 instalador visual). Default: si stdin es TTY y no
|
|
49
|
+
// hay flags, lanza el TUI. Con --no-tui cae al install-asistido clásico.
|
|
50
|
+
'no-tui', 'tui',
|
|
48
51
|
];
|
|
49
52
|
|
|
50
53
|
/**
|