@saulwade/swl-ses 1.3.4 → 1.3.7
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 +2 -2
- package/README.md +34 -34
- package/bin/swl-mcp-server.js +187 -187
- package/bin/swl-ses.js +4 -62
- package/comandos/swl/.evolved.json +22 -22
- package/comandos/swl/adoptar-proyecto.md +207 -207
- package/comandos/swl/contribuir.md +233 -233
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/benchmark-memoria/SKILL.md +186 -186
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/SKILL.md +171 -171
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/eval-framework/SKILL.md +212 -212
- package/habilidades/extractor-de-aprendizajes/SKILL.md +321 -321
- package/habilidades/harness-claude-code/SKILL.md +299 -299
- package/habilidades/infra-github-actions/SKILL.md +166 -166
- package/habilidades/legacy-code-rescue/SKILL.md +267 -267
- package/habilidades/manejo-errores/.evolved.json +8 -8
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -163
- package/habilidades/patrones-python/SKILL.md +229 -229
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/planear-fase/SKILL.md +319 -319
- package/habilidades/release-semver/.evolved.json +8 -8
- package/habilidades/swl-claudemd/SKILL.md +220 -220
- package/habilidades/testing-python/SKILL.md +340 -340
- package/hooks/claudemd-bloat-detector.js +161 -161
- package/hooks/extraccion-aprendizajes.js +19 -12
- package/hooks/lib/agent-routing.js +107 -107
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/merkle-audit.js +96 -96
- 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/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/toon-compressor.js +245 -245
- package/hooks/registro-turnos.js +209 -209
- package/hooks/sugerir-regenerar-inventario.js +170 -170
- package/hooks/validar-formato-post-subagente.js +140 -140
- package/hooks/validar-memoria-hook.js +218 -218
- package/instintos/prompt-appendices.yaml +57 -57
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/skills-lock.json +1093 -1093
- 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/analisis-previo-tareas-grandes.md +172 -172
- package/reglas/arreglar-al-detectar.md +147 -147
- package/reglas/fragmentos-compartidos.md +152 -152
- package/reglas/harness-claude-code.md +213 -213
- package/reglas/usar-context7.md +226 -226
- package/schemas/diary-entry.schema.json +80 -80
- package/scripts/benchmark-memoria.js +167 -167
- package/scripts/comandos/info.js +1 -1
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/doctor.js +77 -3
- package/scripts/field-report.js +199 -199
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-inventario.js +420 -420
- package/scripts/generar-matriz-lenguajes.js +271 -271
- package/scripts/inicializar.js +2 -2
- package/scripts/instalador.js +40 -3
- package/scripts/instalar-git-hook.js +2 -2
- package/scripts/lib/artefactos-python.js +43 -43
- package/scripts/lib/benchmark-metrics.js +160 -160
- package/scripts/lib/budget-enforcer.js +252 -252
- package/scripts/lib/configurar-ci.js +380 -380
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- 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/gitignore-manifest.js +1 -1
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/npm-version.js +261 -261
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/parsear-opciones.js +136 -0
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/scoring-instintos.js +277 -277
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/lib/transformadores/claude.js +200 -200
- package/scripts/lib/transformadores/codex.js +1 -1
- package/scripts/lib/transformadores/copilot.js +1 -1
- package/scripts/lib/transformadores/gemini.js +1 -1
- package/scripts/lib/transformadores/opencode.js +1 -1
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/mcp-server/README.md +128 -128
- package/scripts/mcp-server/handlers.js +206 -206
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +201 -201
- package/scripts/publicar.js +511 -511
- package/scripts/run-eval.js +141 -141
- package/scripts/validar-manifest.js +195 -195
- package/scripts/validar-userland-vacio.js +110 -110
- package/scripts/verificar-release.js +5 -1
package/CLAUDE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# CLAUDE.md — @saulwade/swl-ses v1.3.
|
|
1
|
+
# CLAUDE.md — @saulwade/swl-ses v1.3.7
|
|
2
2
|
|
|
3
3
|
## Reglas de máxima prioridad (aplican SIEMPRE, sin excepción)
|
|
4
4
|
|
|
@@ -56,7 +56,7 @@ El Read tool sigue siendo correcto para `.pdf` (≤20 páginas), `.md`, `.txt` y
|
|
|
56
56
|
- **YAML inline en frontmatter**: `tools: [Read, Write]`, `skillsInvocables: [skill-a]`. NUNCA CSV string ni mezcla con lista multilínea
|
|
57
57
|
- **Mensajes de commit**: imperativo en español, formato `<tipo>(<scope>): <descripción>`
|
|
58
58
|
- **Sin `console.log` en producción** — excepto en `scripts/`, `bin/`, `hooks/`, `gateway/` (CLIs y daemons)
|
|
59
|
-
-
|
|
59
|
+
- **Nombre completo del paquete en npx**: todo mensaje del installer/docs usa `npx -y @saulwade/swl-ses@latest <comando>`. **NUNCA** `npx swl-ses@latest <comando>` sin el scope `@saulwade/` — eso resuelve al paquete legacy DEPRECATED (v5.13.1) que aún existe en npm tras el rebrand de 2026-04-30. El `@latest` es indispensable: sin él npx reutiliza la primera versión cacheada y el usuario corre código viejo sin saberlo. El `-y` evita la prompt de confirmación en CI/scripts
|
|
60
60
|
|
|
61
61
|
## Convenciones de arquitectura
|
|
62
62
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# swl-ses v1.3.
|
|
1
|
+
# swl-ses v1.3.7
|
|
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
|
|
|
@@ -46,8 +46,8 @@ El setup requiere **dos comandos en orden**, con propósitos distintos:
|
|
|
46
46
|
|
|
47
47
|
| Comando | Qué crea | Dónde | Instala agentes/skills |
|
|
48
48
|
|---------|----------|-------|------------------------|
|
|
49
|
-
| `npx swl-ses@latest init` | `.planning/` y `_userland/` (plantillas vacías) | En el proyecto actual | ❌ No |
|
|
50
|
-
| `npx swl-ses@latest install` | Agentes, skills, reglas, hooks, comandos `/swl:*` | En `.claude/` del proyecto o en `~/.claude/` global | ✅ Sí |
|
|
49
|
+
| `npx @saulwade/swl-ses@latest init` | `.planning/` y `_userland/` (plantillas vacías) | En el proyecto actual | ❌ No |
|
|
50
|
+
| `npx @saulwade/swl-ses@latest install` | Agentes, skills, reglas, hooks, comandos `/swl:*` | En `.claude/` del proyecto o en `~/.claude/` global | ✅ Sí |
|
|
51
51
|
|
|
52
52
|
**`init` siempre es local al proyecto.** `install` puede ser local (`--local`, default) o global (`--global`).
|
|
53
53
|
|
|
@@ -59,9 +59,9 @@ El setup requiere **dos comandos en orden**, con propósitos distintos:
|
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
61
|
cd /ruta/a/tu/proyecto
|
|
62
|
-
npx swl-ses@latest init # Crea .planning/ y _userland/
|
|
63
|
-
npx swl-ses@latest install --target claude --profile core # Instala agentes, skills, hooks y reglas
|
|
64
|
-
npx swl-ses@latest doctor # Verifica que todo quedó correcto
|
|
62
|
+
npx @saulwade/swl-ses@latest init # Crea .planning/ y _userland/
|
|
63
|
+
npx @saulwade/swl-ses@latest install --target claude --profile core # Instala agentes, skills, hooks y reglas
|
|
64
|
+
npx @saulwade/swl-ses@latest doctor # Verifica que todo quedó correcto
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
No requiere autenticación. El paquete `swl-ses` está publicado en npmjs.
|
|
@@ -131,18 +131,18 @@ claude
|
|
|
131
131
|
|
|
132
132
|
| Comando | Descripción |
|
|
133
133
|
|---------|-------------|
|
|
134
|
-
| `npx swl-ses@latest init` | Crea `.planning/` (plantillas de planificación) y `_userland/` (tus personalizaciones) en el proyecto actual. **No instala agentes ni skills.** |
|
|
135
|
-
| `npx swl-ses@latest install` | Instala agentes, skills, reglas, hooks y comandos `/swl:*` en el runtime destino (`.claude/` local o `~/.claude/` global). |
|
|
136
|
-
| `npx swl-ses@latest doctor` | Diagnostica problemas de la instalación |
|
|
137
|
-
| `npx swl-ses@latest update` | Actualiza componentes instalados |
|
|
138
|
-
| `npx swl-ses@latest uninstall` | Desinstala componentes del runtime |
|
|
139
|
-
| `npx swl-ses@latest info` | Muestra información del sistema instalado |
|
|
140
|
-
| `npx swl-ses@latest skills list` | Lista skills instalados |
|
|
141
|
-
| `npx swl-ses@latest skills add <fuente>` | Agrega skill desde repo Git, owner/repo, o path local |
|
|
142
|
-
| `npx swl-ses@latest skills remove <nombre>` | Remueve un skill individual |
|
|
143
|
-
| `npx swl-ses@latest agents list` | Lista agentes instalados |
|
|
144
|
-
| `npx swl-ses@latest agents add <fuente>` | Agrega agente desde repo Git o path local |
|
|
145
|
-
| `npx swl-ses@latest agents remove <nombre>` | Remueve un agente individual |
|
|
134
|
+
| `npx @saulwade/swl-ses@latest init` | Crea `.planning/` (plantillas de planificación) y `_userland/` (tus personalizaciones) en el proyecto actual. **No instala agentes ni skills.** |
|
|
135
|
+
| `npx @saulwade/swl-ses@latest install` | Instala agentes, skills, reglas, hooks y comandos `/swl:*` en el runtime destino (`.claude/` local o `~/.claude/` global). |
|
|
136
|
+
| `npx @saulwade/swl-ses@latest doctor` | Diagnostica problemas de la instalación |
|
|
137
|
+
| `npx @saulwade/swl-ses@latest update` | Actualiza componentes instalados |
|
|
138
|
+
| `npx @saulwade/swl-ses@latest uninstall` | Desinstala componentes del runtime |
|
|
139
|
+
| `npx @saulwade/swl-ses@latest info` | Muestra información del sistema instalado |
|
|
140
|
+
| `npx @saulwade/swl-ses@latest skills list` | Lista skills instalados |
|
|
141
|
+
| `npx @saulwade/swl-ses@latest skills add <fuente>` | Agrega skill desde repo Git, owner/repo, o path local |
|
|
142
|
+
| `npx @saulwade/swl-ses@latest skills remove <nombre>` | Remueve un skill individual |
|
|
143
|
+
| `npx @saulwade/swl-ses@latest agents list` | Lista agentes instalados |
|
|
144
|
+
| `npx @saulwade/swl-ses@latest agents add <fuente>` | Agrega agente desde repo Git o path local |
|
|
145
|
+
| `npx @saulwade/swl-ses@latest agents remove <nombre>` | Remueve un agente individual |
|
|
146
146
|
|
|
147
147
|
### Opciones de install
|
|
148
148
|
|
|
@@ -196,43 +196,43 @@ claude
|
|
|
196
196
|
|
|
197
197
|
```bash
|
|
198
198
|
# Perfil básico en Claude Code
|
|
199
|
-
npx swl-ses@latest install --target claude --profile core
|
|
199
|
+
npx @saulwade/swl-ses@latest install --target claude --profile core
|
|
200
200
|
|
|
201
201
|
# Backend Python en Gemini CLI
|
|
202
|
-
npx swl-ses@latest install --target gemini --profile backend-python
|
|
202
|
+
npx @saulwade/swl-ses@latest install --target gemini --profile backend-python
|
|
203
203
|
|
|
204
204
|
# Frontend React en GitHub Copilot
|
|
205
|
-
npx swl-ses@latest install --target copilot --profile frontend-react
|
|
205
|
+
npx @saulwade/swl-ses@latest install --target copilot --profile frontend-react
|
|
206
206
|
|
|
207
207
|
# Full-stack en OpenClaude (multi-proveedor, usa .claude/ igual que Claude Code)
|
|
208
|
-
npx swl-ses@latest install --target openclaude --profile fullstack-python-angular
|
|
208
|
+
npx @saulwade/swl-ses@latest install --target openclaude --profile fullstack-python-angular
|
|
209
209
|
|
|
210
210
|
# Full-stack en OpenCode
|
|
211
|
-
npx swl-ses@latest install --target opencode --profile fullstack-python-angular
|
|
211
|
+
npx @saulwade/swl-ses@latest install --target opencode --profile fullstack-python-angular
|
|
212
212
|
|
|
213
213
|
# Perfil completo en directorio global
|
|
214
|
-
npx swl-ses@latest install --target claude --profile completo --global
|
|
214
|
+
npx @saulwade/swl-ses@latest install --target claude --profile completo --global
|
|
215
215
|
|
|
216
216
|
# Agregar skills desde GitHub con selector interactivo
|
|
217
|
-
npx swl-ses@latest skills add anthropics/skills
|
|
217
|
+
npx @saulwade/swl-ses@latest skills add anthropics/skills
|
|
218
218
|
|
|
219
219
|
# Agregar un skill específico por nombre
|
|
220
|
-
npx swl-ses@latest skills add anthropics/skills --skill docx
|
|
220
|
+
npx @saulwade/swl-ses@latest skills add anthropics/skills --skill docx
|
|
221
221
|
|
|
222
222
|
# Agregar todos los skills de un repo sin selector
|
|
223
|
-
npx swl-ses@latest skills add anthropics/skills --all
|
|
223
|
+
npx @saulwade/swl-ses@latest skills add anthropics/skills --all
|
|
224
224
|
|
|
225
225
|
# Agregar skill desde URL completa
|
|
226
|
-
npx swl-ses@latest skills add https://github.com/user/repo --skill mi-skill
|
|
226
|
+
npx @saulwade/swl-ses@latest skills add https://github.com/user/repo --skill mi-skill
|
|
227
227
|
|
|
228
228
|
# Agregar agente desde path local
|
|
229
|
-
npx swl-ses@latest agents add ./mis-agentes --agent mi-agente
|
|
229
|
+
npx @saulwade/swl-ses@latest agents add ./mis-agentes --agent mi-agente
|
|
230
230
|
|
|
231
231
|
# Ver que se instalaria sin hacer cambios
|
|
232
|
-
npx swl-ses@latest install --target codex --profile core --dry-run
|
|
232
|
+
npx @saulwade/swl-ses@latest install --target codex --profile core --dry-run
|
|
233
233
|
|
|
234
234
|
# Ver información del sistema
|
|
235
|
-
npx swl-ses@latest info --target claude
|
|
235
|
+
npx @saulwade/swl-ses@latest info --target claude
|
|
236
236
|
```
|
|
237
237
|
|
|
238
238
|
## Agentes (59)
|
|
@@ -453,7 +453,7 @@ Ver [INSTALACION.md](INSTALACION.md) para configuración detallada de autenticac
|
|
|
453
453
|
## Verificación (doctor)
|
|
454
454
|
|
|
455
455
|
```bash
|
|
456
|
-
npx swl-ses@latest doctor
|
|
456
|
+
npx @saulwade/swl-ses@latest doctor
|
|
457
457
|
```
|
|
458
458
|
|
|
459
459
|
Verifica: Node.js >= 22, runtimes detectados, `.planning/` completo, `_userland/` presente, estado íntegro, permisos, `.env` en `.gitignore`. Repara automáticamente hooks sin `"type": "command"` en settings.json.
|
|
@@ -514,8 +514,8 @@ Un proyecto típico (ej. construir una App Fullstack) usando SWL sigue estos pas
|
|
|
514
514
|
|
|
515
515
|
1. **Instalación y Setup inicial**
|
|
516
516
|
```bash
|
|
517
|
-
npx swl-ses@latest init
|
|
518
|
-
npx swl-ses@latest install --target claude --profile fullstack-node-react
|
|
517
|
+
npx @saulwade/swl-ses@latest init
|
|
518
|
+
npx @saulwade/swl-ses@latest install --target claude --profile fullstack-node-react
|
|
519
519
|
```
|
|
520
520
|
|
|
521
521
|
2. **Definición del Proyecto (Discovery)**
|
package/bin/swl-mcp-server.js
CHANGED
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* swl-mcp-server — Servidor MCP **EXPERIMENTAL** para exponer la memoria
|
|
6
|
-
* de swl-ses a clientes MCP externos (Cursor, Gemini CLI, OpenCode, etc.).
|
|
7
|
-
*
|
|
8
|
-
* **NO PRODUCCIÓN — STUB EXPERIMENTAL**.
|
|
9
|
-
* Ver `scripts/mcp-server/README.md` para limitaciones detalladas.
|
|
10
|
-
*
|
|
11
|
-
* Modo de transporte: stdio (JSON-RPC sobre stdin/stdout).
|
|
12
|
-
* No HTTP, no auth, no rate limiting.
|
|
13
|
-
*
|
|
14
|
-
* Uso (cliente MCP):
|
|
15
|
-
* - Configurar el cliente para ejecutar `node /path/to/swl-ses/bin/swl-mcp-server.js`
|
|
16
|
-
* con stdio.
|
|
17
|
-
* - Los handlers leen el cwd del proceso para localizar `.planning/`,
|
|
18
|
-
* `instintos/`, `APRENDIZAJES.md`. Por defecto usa `process.cwd()`.
|
|
19
|
-
* - Override con env var `SWL_MCP_BASE_DIR` si el cliente arranca el server
|
|
20
|
-
* desde otro directorio.
|
|
21
|
-
*
|
|
22
|
-
* Protocolo MCP soportado (subset):
|
|
23
|
-
* - initialize / initialized
|
|
24
|
-
* - tools/list
|
|
25
|
-
* - tools/call
|
|
26
|
-
*
|
|
27
|
-
* NO soporta:
|
|
28
|
-
* - resources/list, prompts/list
|
|
29
|
-
* - logging, sampling
|
|
30
|
-
* - cancellation, progress
|
|
31
|
-
* - HTTP transport
|
|
32
|
-
*
|
|
33
|
-
* Trigger documentado para implementación completa: "uso ≥2 runtimes
|
|
34
|
-
* diferentes (Cursor + Claude Code o similar) consistentemente por
|
|
35
|
-
* ≥1 mes". Hoy: 0 instalaciones reportadas.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
const path = require('path');
|
|
39
|
-
|
|
40
|
-
const { HANDLERS } = require('../scripts/mcp-server/handlers');
|
|
41
|
-
|
|
42
|
-
const SERVER_NAME = 'swl-mcp-server';
|
|
43
|
-
const SERVER_VERSION = '0.1.0-experimental';
|
|
44
|
-
const PROTOCOL_VERSION = '2024-11-05';
|
|
45
|
-
|
|
46
|
-
const baseDir = process.env.SWL_MCP_BASE_DIR || process.cwd();
|
|
47
|
-
|
|
48
|
-
// ── logging ───────────────────────────────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
// Stderr para evitar contaminar stdout (que es JSON-RPC).
|
|
51
|
-
function log(level, msg, data) {
|
|
52
|
-
const linea = JSON.stringify({
|
|
53
|
-
timestamp: new Date().toISOString(),
|
|
54
|
-
level,
|
|
55
|
-
msg,
|
|
56
|
-
...(data ? { data } : {}),
|
|
57
|
-
});
|
|
58
|
-
process.stderr.write(linea + '\n');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ── JSON-RPC helpers ──────────────────────────────────────────────────────────
|
|
62
|
-
|
|
63
|
-
function respuesta(id, result) {
|
|
64
|
-
return JSON.stringify({ jsonrpc: '2.0', id, result });
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function errorResp(id, code, message) {
|
|
68
|
-
return JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } });
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ── routing ───────────────────────────────────────────────────────────────────
|
|
72
|
-
|
|
73
|
-
function manejarInitialize(request) {
|
|
74
|
-
return respuesta(request.id, {
|
|
75
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
76
|
-
capabilities: {
|
|
77
|
-
tools: { listChanged: false },
|
|
78
|
-
},
|
|
79
|
-
serverInfo: {
|
|
80
|
-
name: SERVER_NAME,
|
|
81
|
-
version: SERVER_VERSION,
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function manejarToolsList(request) {
|
|
87
|
-
const tools = Object.entries(HANDLERS).map(([name, def]) => ({
|
|
88
|
-
name,
|
|
89
|
-
description: def.description,
|
|
90
|
-
inputSchema: def.inputSchema,
|
|
91
|
-
}));
|
|
92
|
-
return respuesta(request.id, { tools });
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function manejarToolsCall(request) {
|
|
96
|
-
const { name, arguments: args } = request.params || {};
|
|
97
|
-
const def = HANDLERS[name];
|
|
98
|
-
if (!def) {
|
|
99
|
-
return errorResp(request.id, -32601, `Tool no encontrado: ${name}`);
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
const result = def.handler(baseDir, args || {});
|
|
103
|
-
return respuesta(request.id, {
|
|
104
|
-
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
105
|
-
});
|
|
106
|
-
} catch (err) {
|
|
107
|
-
log('error', `Excepción en handler ${name}`, { error: err.message });
|
|
108
|
-
return errorResp(request.id, -32603, `Error interno: ${err.message}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function rutear(request) {
|
|
113
|
-
switch (request.method) {
|
|
114
|
-
case 'initialize':
|
|
115
|
-
return manejarInitialize(request);
|
|
116
|
-
case 'initialized':
|
|
117
|
-
case 'notifications/initialized':
|
|
118
|
-
return null; // notification — sin respuesta
|
|
119
|
-
case 'tools/list':
|
|
120
|
-
return manejarToolsList(request);
|
|
121
|
-
case 'tools/call':
|
|
122
|
-
return manejarToolsCall(request);
|
|
123
|
-
case 'ping':
|
|
124
|
-
return respuesta(request.id, {});
|
|
125
|
-
default:
|
|
126
|
-
return errorResp(request.id, -32601, `Método no soportado: ${request.method}`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ── loop principal ────────────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
|
-
function arrancar() {
|
|
133
|
-
log('warn', '⚠ swl-mcp-server stub experimental — NO usar en producción');
|
|
134
|
-
log('info', `Server iniciando`, { name: SERVER_NAME, version: SERVER_VERSION, baseDir });
|
|
135
|
-
|
|
136
|
-
let buffer = '';
|
|
137
|
-
|
|
138
|
-
process.stdin.setEncoding('utf8');
|
|
139
|
-
process.stdin.on('data', (chunk) => {
|
|
140
|
-
buffer += chunk;
|
|
141
|
-
|
|
142
|
-
// Cada mensaje JSON-RPC termina con \n
|
|
143
|
-
let nlIndex;
|
|
144
|
-
while ((nlIndex = buffer.indexOf('\n')) >= 0) {
|
|
145
|
-
const linea = buffer.slice(0, nlIndex).trim();
|
|
146
|
-
buffer = buffer.slice(nlIndex + 1);
|
|
147
|
-
|
|
148
|
-
if (!linea) continue;
|
|
149
|
-
|
|
150
|
-
let request;
|
|
151
|
-
try {
|
|
152
|
-
request = JSON.parse(linea);
|
|
153
|
-
} catch (err) {
|
|
154
|
-
log('error', 'JSON inválido recibido', { error: err.message, linea: linea.slice(0, 100) });
|
|
155
|
-
process.stdout.write(errorResp(null, -32700, 'Parse error') + '\n');
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const respuestaStr = rutear(request);
|
|
160
|
-
if (respuestaStr) {
|
|
161
|
-
process.stdout.write(respuestaStr + '\n');
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
process.stdin.on('end', () => {
|
|
167
|
-
log('info', 'stdin cerrado, server termina');
|
|
168
|
-
process.exit(0);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Manejo de errores no capturados — nunca crashear silenciosamente
|
|
172
|
-
process.on('uncaughtException', (err) => {
|
|
173
|
-
log('error', 'uncaughtException', { error: err.message, stack: err.stack });
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (require.main === module) {
|
|
178
|
-
arrancar();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
module.exports = {
|
|
182
|
-
rutear,
|
|
183
|
-
arrancar,
|
|
184
|
-
SERVER_NAME,
|
|
185
|
-
SERVER_VERSION,
|
|
186
|
-
PROTOCOL_VERSION,
|
|
187
|
-
};
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* swl-mcp-server — Servidor MCP **EXPERIMENTAL** para exponer la memoria
|
|
6
|
+
* de swl-ses a clientes MCP externos (Cursor, Gemini CLI, OpenCode, etc.).
|
|
7
|
+
*
|
|
8
|
+
* **NO PRODUCCIÓN — STUB EXPERIMENTAL**.
|
|
9
|
+
* Ver `scripts/mcp-server/README.md` para limitaciones detalladas.
|
|
10
|
+
*
|
|
11
|
+
* Modo de transporte: stdio (JSON-RPC sobre stdin/stdout).
|
|
12
|
+
* No HTTP, no auth, no rate limiting.
|
|
13
|
+
*
|
|
14
|
+
* Uso (cliente MCP):
|
|
15
|
+
* - Configurar el cliente para ejecutar `node /path/to/swl-ses/bin/swl-mcp-server.js`
|
|
16
|
+
* con stdio.
|
|
17
|
+
* - Los handlers leen el cwd del proceso para localizar `.planning/`,
|
|
18
|
+
* `instintos/`, `APRENDIZAJES.md`. Por defecto usa `process.cwd()`.
|
|
19
|
+
* - Override con env var `SWL_MCP_BASE_DIR` si el cliente arranca el server
|
|
20
|
+
* desde otro directorio.
|
|
21
|
+
*
|
|
22
|
+
* Protocolo MCP soportado (subset):
|
|
23
|
+
* - initialize / initialized
|
|
24
|
+
* - tools/list
|
|
25
|
+
* - tools/call
|
|
26
|
+
*
|
|
27
|
+
* NO soporta:
|
|
28
|
+
* - resources/list, prompts/list
|
|
29
|
+
* - logging, sampling
|
|
30
|
+
* - cancellation, progress
|
|
31
|
+
* - HTTP transport
|
|
32
|
+
*
|
|
33
|
+
* Trigger documentado para implementación completa: "uso ≥2 runtimes
|
|
34
|
+
* diferentes (Cursor + Claude Code o similar) consistentemente por
|
|
35
|
+
* ≥1 mes". Hoy: 0 instalaciones reportadas.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const path = require('path');
|
|
39
|
+
|
|
40
|
+
const { HANDLERS } = require('../scripts/mcp-server/handlers');
|
|
41
|
+
|
|
42
|
+
const SERVER_NAME = 'swl-mcp-server';
|
|
43
|
+
const SERVER_VERSION = '0.1.0-experimental';
|
|
44
|
+
const PROTOCOL_VERSION = '2024-11-05';
|
|
45
|
+
|
|
46
|
+
const baseDir = process.env.SWL_MCP_BASE_DIR || process.cwd();
|
|
47
|
+
|
|
48
|
+
// ── logging ───────────────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
// Stderr para evitar contaminar stdout (que es JSON-RPC).
|
|
51
|
+
function log(level, msg, data) {
|
|
52
|
+
const linea = JSON.stringify({
|
|
53
|
+
timestamp: new Date().toISOString(),
|
|
54
|
+
level,
|
|
55
|
+
msg,
|
|
56
|
+
...(data ? { data } : {}),
|
|
57
|
+
});
|
|
58
|
+
process.stderr.write(linea + '\n');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── JSON-RPC helpers ──────────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
function respuesta(id, result) {
|
|
64
|
+
return JSON.stringify({ jsonrpc: '2.0', id, result });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function errorResp(id, code, message) {
|
|
68
|
+
return JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── routing ───────────────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
function manejarInitialize(request) {
|
|
74
|
+
return respuesta(request.id, {
|
|
75
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
76
|
+
capabilities: {
|
|
77
|
+
tools: { listChanged: false },
|
|
78
|
+
},
|
|
79
|
+
serverInfo: {
|
|
80
|
+
name: SERVER_NAME,
|
|
81
|
+
version: SERVER_VERSION,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function manejarToolsList(request) {
|
|
87
|
+
const tools = Object.entries(HANDLERS).map(([name, def]) => ({
|
|
88
|
+
name,
|
|
89
|
+
description: def.description,
|
|
90
|
+
inputSchema: def.inputSchema,
|
|
91
|
+
}));
|
|
92
|
+
return respuesta(request.id, { tools });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function manejarToolsCall(request) {
|
|
96
|
+
const { name, arguments: args } = request.params || {};
|
|
97
|
+
const def = HANDLERS[name];
|
|
98
|
+
if (!def) {
|
|
99
|
+
return errorResp(request.id, -32601, `Tool no encontrado: ${name}`);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const result = def.handler(baseDir, args || {});
|
|
103
|
+
return respuesta(request.id, {
|
|
104
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
105
|
+
});
|
|
106
|
+
} catch (err) {
|
|
107
|
+
log('error', `Excepción en handler ${name}`, { error: err.message });
|
|
108
|
+
return errorResp(request.id, -32603, `Error interno: ${err.message}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function rutear(request) {
|
|
113
|
+
switch (request.method) {
|
|
114
|
+
case 'initialize':
|
|
115
|
+
return manejarInitialize(request);
|
|
116
|
+
case 'initialized':
|
|
117
|
+
case 'notifications/initialized':
|
|
118
|
+
return null; // notification — sin respuesta
|
|
119
|
+
case 'tools/list':
|
|
120
|
+
return manejarToolsList(request);
|
|
121
|
+
case 'tools/call':
|
|
122
|
+
return manejarToolsCall(request);
|
|
123
|
+
case 'ping':
|
|
124
|
+
return respuesta(request.id, {});
|
|
125
|
+
default:
|
|
126
|
+
return errorResp(request.id, -32601, `Método no soportado: ${request.method}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ── loop principal ────────────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
function arrancar() {
|
|
133
|
+
log('warn', '⚠ swl-mcp-server stub experimental — NO usar en producción');
|
|
134
|
+
log('info', `Server iniciando`, { name: SERVER_NAME, version: SERVER_VERSION, baseDir });
|
|
135
|
+
|
|
136
|
+
let buffer = '';
|
|
137
|
+
|
|
138
|
+
process.stdin.setEncoding('utf8');
|
|
139
|
+
process.stdin.on('data', (chunk) => {
|
|
140
|
+
buffer += chunk;
|
|
141
|
+
|
|
142
|
+
// Cada mensaje JSON-RPC termina con \n
|
|
143
|
+
let nlIndex;
|
|
144
|
+
while ((nlIndex = buffer.indexOf('\n')) >= 0) {
|
|
145
|
+
const linea = buffer.slice(0, nlIndex).trim();
|
|
146
|
+
buffer = buffer.slice(nlIndex + 1);
|
|
147
|
+
|
|
148
|
+
if (!linea) continue;
|
|
149
|
+
|
|
150
|
+
let request;
|
|
151
|
+
try {
|
|
152
|
+
request = JSON.parse(linea);
|
|
153
|
+
} catch (err) {
|
|
154
|
+
log('error', 'JSON inválido recibido', { error: err.message, linea: linea.slice(0, 100) });
|
|
155
|
+
process.stdout.write(errorResp(null, -32700, 'Parse error') + '\n');
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const respuestaStr = rutear(request);
|
|
160
|
+
if (respuestaStr) {
|
|
161
|
+
process.stdout.write(respuestaStr + '\n');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
process.stdin.on('end', () => {
|
|
167
|
+
log('info', 'stdin cerrado, server termina');
|
|
168
|
+
process.exit(0);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Manejo de errores no capturados — nunca crashear silenciosamente
|
|
172
|
+
process.on('uncaughtException', (err) => {
|
|
173
|
+
log('error', 'uncaughtException', { error: err.message, stack: err.stack });
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (require.main === module) {
|
|
178
|
+
arrancar();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = {
|
|
182
|
+
rutear,
|
|
183
|
+
arrancar,
|
|
184
|
+
SERVER_NAME,
|
|
185
|
+
SERVER_VERSION,
|
|
186
|
+
PROTOCOL_VERSION,
|
|
187
|
+
};
|
package/bin/swl-ses.js
CHANGED
|
@@ -8,6 +8,10 @@ const os = require('os');
|
|
|
8
8
|
const VERSION = require('../package.json').version;
|
|
9
9
|
const NOMBRE = 'swl-ses';
|
|
10
10
|
|
|
11
|
+
// Parser extraído a scripts/lib/parsear-opciones.js en v1.3.5 para permitir
|
|
12
|
+
// tests unitarios. Soporta alias español ↔ inglés (--perfil ↔ --profile, etc.).
|
|
13
|
+
const { parsearOpciones } = require('../scripts/lib/parsear-opciones');
|
|
14
|
+
|
|
11
15
|
/**
|
|
12
16
|
* Extrae [major, minor, patch] de una versión semver. Ignora prerelease y build
|
|
13
17
|
* metadata (ej. "5.7.5-beta.1+abc"). Retorna null si el formato es inválido.
|
|
@@ -353,66 +357,4 @@ function main() {
|
|
|
353
357
|
}
|
|
354
358
|
}
|
|
355
359
|
|
|
356
|
-
function parsearOpciones(args) {
|
|
357
|
-
const opciones = { _args: [] };
|
|
358
|
-
let i = 0;
|
|
359
|
-
|
|
360
|
-
// Setea valor en ambas formas (con dashes y con underscores) para que
|
|
361
|
-
// los consumidores puedan acceder vía opciones['dry-run'] u opciones.dry_run
|
|
362
|
-
// indistintamente. Resuelve la categoría de bugs donde el parser convertía
|
|
363
|
-
// dashes a underscores solo para flags de whitelist, dejando otros con dashes
|
|
364
|
-
// — inconsistencia que llevaba a wrappers buscando la clave equivocada y a
|
|
365
|
-
// flags silenciosamente ignorados.
|
|
366
|
-
const setear = (clave, valor) => {
|
|
367
|
-
opciones[clave] = valor;
|
|
368
|
-
const conUnderscores = clave.replace(/-/g, '_');
|
|
369
|
-
if (conUnderscores !== clave) {
|
|
370
|
-
opciones[conUnderscores] = valor;
|
|
371
|
-
}
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
while (i < args.length) {
|
|
375
|
-
const arg = args[i];
|
|
376
|
-
|
|
377
|
-
if (arg.startsWith('--')) {
|
|
378
|
-
let clave = arg.slice(2);
|
|
379
|
-
// Soporta flags con valor integrado: --key=value
|
|
380
|
-
// Antes el parser dejaba 'session=claude' como nombre de flag completo,
|
|
381
|
-
// produciendo opciones['session=claude']=true en vez de opciones.session='claude'.
|
|
382
|
-
let valorIntegrado = null;
|
|
383
|
-
const idxIgual = clave.indexOf('=');
|
|
384
|
-
if (idxIgual !== -1) {
|
|
385
|
-
valorIntegrado = clave.slice(idxIgual + 1);
|
|
386
|
-
clave = clave.slice(0, idxIgual);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Opciones booleanas explícitas (whitelist) — siempre booleanas
|
|
390
|
-
if (['global', 'local', 'dry-run', 'force', 'verbose', 'all', 'all-langs', 'no-claudemd'].includes(clave)) {
|
|
391
|
-
setear(clave, true);
|
|
392
|
-
} else if (valorIntegrado !== null) {
|
|
393
|
-
// --key=value
|
|
394
|
-
setear(clave, valorIntegrado);
|
|
395
|
-
} else if (i + 1 < args.length && !args[i + 1].startsWith('--')) {
|
|
396
|
-
// --key value
|
|
397
|
-
setear(clave, args[i + 1]);
|
|
398
|
-
i++;
|
|
399
|
-
} else {
|
|
400
|
-
// --key (sin valor)
|
|
401
|
-
setear(clave, true);
|
|
402
|
-
}
|
|
403
|
-
} else if (arg.startsWith('-')) {
|
|
404
|
-
const clave = arg.slice(1);
|
|
405
|
-
if (clave === 'v') opciones.version = true;
|
|
406
|
-
else if (clave === 'h') opciones.help = true;
|
|
407
|
-
} else {
|
|
408
|
-
// Argumentos posicionales (fuente en skills add, nombre en skills remove)
|
|
409
|
-
opciones._args.push(arg);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
i++;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
return opciones;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
360
|
main();
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"release.md": {
|
|
3
|
-
"evolved": true,
|
|
4
|
-
"evolvedFrom": "5.4.0",
|
|
5
|
-
"evolvedAt": "2026-04-11",
|
|
6
|
-
"evolvedBy": "aprender",
|
|
7
|
-
"evolvedNote": "mejora de metodología: checklist obligatoria de archivos de versión en paso 6"
|
|
8
|
-
},
|
|
9
|
-
"aprender.md": {
|
|
10
|
-
"evolved": true,
|
|
11
|
-
"evolvedFrom": "5.12.3",
|
|
12
|
-
"evolvedAt": "2026-04-25",
|
|
13
|
-
"evolvedBy": "aprender",
|
|
14
|
-
"evolvedNote": "Paso 2 — filtro crítico obligatorio sobre reportes de sub-agentes Explore para evitar sobre-ingeniería al analizar papers académicos"
|
|
15
|
-
},
|
|
16
|
-
"verificar.md": {
|
|
17
|
-
"evolved": true,
|
|
18
|
-
"evolvedFrom": "5.12.3",
|
|
19
|
-
"evolvedAt": "2026-04-26",
|
|
20
|
-
"evolvedBy": "evolucionar",
|
|
21
|
-
"evolvedNote": "flag --until-converge para iterar verificar→corregir→re-verificar hasta 0 hallazgos CRÍTICO+ALTO+MAYOR (max-iter=5, --no-prompt CI, detección adversarial ≥5 hallazgos nuevos)"
|
|
22
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"release.md": {
|
|
3
|
+
"evolved": true,
|
|
4
|
+
"evolvedFrom": "5.4.0",
|
|
5
|
+
"evolvedAt": "2026-04-11",
|
|
6
|
+
"evolvedBy": "aprender",
|
|
7
|
+
"evolvedNote": "mejora de metodología: checklist obligatoria de archivos de versión en paso 6"
|
|
8
|
+
},
|
|
9
|
+
"aprender.md": {
|
|
10
|
+
"evolved": true,
|
|
11
|
+
"evolvedFrom": "5.12.3",
|
|
12
|
+
"evolvedAt": "2026-04-25",
|
|
13
|
+
"evolvedBy": "aprender",
|
|
14
|
+
"evolvedNote": "Paso 2 — filtro crítico obligatorio sobre reportes de sub-agentes Explore para evitar sobre-ingeniería al analizar papers académicos"
|
|
15
|
+
},
|
|
16
|
+
"verificar.md": {
|
|
17
|
+
"evolved": true,
|
|
18
|
+
"evolvedFrom": "5.12.3",
|
|
19
|
+
"evolvedAt": "2026-04-26",
|
|
20
|
+
"evolvedBy": "evolucionar",
|
|
21
|
+
"evolvedNote": "flag --until-converge para iterar verificar→corregir→re-verificar hasta 0 hallazgos CRÍTICO+ALTO+MAYOR (max-iter=5, --no-prompt CI, detección adversarial ≥5 hallazgos nuevos)"
|
|
22
|
+
}
|
|
23
23
|
}
|