@saulwade/swl-ses 1.2.2 → 1.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 +199 -255
- package/README.md +4 -4
- package/comandos/swl/claudemd.md +136 -0
- package/comandos/swl/salud.md +29 -0
- package/habilidades/nextjs-experto/SKILL.md +5 -5
- package/habilidades/nextjs-testing/SKILL.md +26 -1
- package/habilidades/nuevo-proyecto/SKILL.md +82 -2
- package/habilidades/planear-fase/SKILL.md +24 -4
- package/habilidades/react-experto/SKILL.md +25 -4
- package/habilidades/swl-claudemd/SKILL.md +220 -0
- package/habilidades/tdd-workflow/SKILL.md +8 -1
- package/hooks/claudemd-bloat-detector.js +161 -0
- package/hooks/lib/privacy-filter.js +42 -4
- package/manifiestos/hooks-config.json +9 -0
- package/manifiestos/modulos.json +21 -2
- package/manifiestos/skills-lock.json +68 -40
- package/package.json +87 -87
- package/plugin.json +343 -343
- package/reglas/seguridad-agentes.md +12 -0
- package/scripts/auditar-claudemd.js +297 -0
- package/scripts/instalador.js +4 -0
- package/scripts/lib/detectar-stack-detallado.js +307 -0
- package/scripts/lib/transformadores/claude.js +200 -124
- package/scripts/publicar.js +166 -12
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tdd-workflow
|
|
3
3
|
description: Flujo completo de Test-Driven Development. Ciclo RED (el test falla) → GREEN (implementación mínima) → REFACTOR (limpieza). Incluye cobertura mínima obligatoria, tests de frontera, factories, fixtures y estrategias para diferentes tipos de código (APIs, services, componentes Angular).
|
|
4
|
-
version: "1.0.
|
|
4
|
+
version: "1.0.1"
|
|
5
|
+
evolved: true
|
|
6
|
+
evolved-from: "1.0.0"
|
|
7
|
+
evolved-at: "2026-05-11"
|
|
8
|
+
evolved-by: "aprender"
|
|
9
|
+
evolved-note: "L-109 SIGM: nombrar tests por causa raíz (no por feature) — test_repository_no_usa_columna_inexistente_p_monto detectó bug en F1.4 sin necesidad de reproducción manual"
|
|
5
10
|
herramientasPermitidas: [Read, Bash]
|
|
6
11
|
evolvable: true # default para skill estandar
|
|
7
12
|
exclusiones:
|
|
@@ -291,3 +296,5 @@ pytest --cov=src/services --cov-fail-under=90
|
|
|
291
296
|
**La fase REFACTOR del ciclo TDD en componentes Angular introduce regresiones silenciosas cuando se extrae lógica a un `computed()` pero el template sigue usando la función directa que ahora devuelve `undefined`**: refactorizar `getTotal()` como método del componente hacia `total = computed(() => ...)` y olvidar actualizar el template de `{{ getTotal() }}` a `{{ total() }}` no genera error de compilación con Angular 17+; el template simplemente muestra `undefined`. Causa: Angular no verifica en tiempo de compilación que los métodos referenciados en templates existen en la clase si el template usa la sintaxis de interpolación sin type-checking estricto. Fix: activar `strictTemplates: true` en `tsconfig.app.json` para que el compilador de Angular valide que todas las referencias en templates corresponden a miembros públicos del componente. Ejecutar `ng build` antes de considerar el REFACTOR completo.
|
|
292
297
|
|
|
293
298
|
**`db_session.rollback()` en el fixture de pytest-asyncio no deshace los datos insertados por `db.flush()` dentro de la función testeada cuando la sesión usa `autocommit=True` implícito por configuración del engine**: algunos proyectos configuran `AsyncEngine` con `isolation_level="AUTOCOMMIT"` para compatibilidad con operaciones DDL; en ese contexto, cada `flush()` hace commit inmediatamente y el `rollback()` del fixture no puede deshacer esos cambios. Causa: `AUTOCOMMIT` en PostgreSQL significa que no hay transacción activa que se pueda revertir. Fix: verificar que el engine de tests NO use `isolation_level="AUTOCOMMIT"` (la configuración debe ser solo para el engine de migraciones Alembic, no para el de la app). Para tests que necesitan AUTOCOMMIT por alguna razón, usar una BD de test separada que se trunca con `TRUNCATE ... RESTART IDENTITY CASCADE` en el teardown del fixture.
|
|
299
|
+
|
|
300
|
+
**Tests nombrados por feature (`test_emitir_factura_exitosa`) pierden poder regresivo; nombrados por causa raíz (`test_repository_no_usa_columna_inexistente_p_monto`) detectan regresiones específicas sin reproducción manual** [CONFIRMADO en SIGM Opción C F1.4]: cuando se descubre un bug por una causa raíz concreta (typo en nombre de columna SQL, omisión de `selectinload`, mock que devuelve dict en vez de objeto, schema obsoleto), el test de regresión que se escribe debe llevar el nombre de la causa, no del feature afectado. Caso real: durante F1.4 de SIGM, el repository de pagos referenciaba `p.monto` cuando la columna se llamaba `p.monto_pagado`; el test escrito como `test_repository_no_usa_columna_inexistente_p_monto` falló inmediatamente en la siguiente sesión cuando otro agente reintrodujo el typo, sin necesidad de reproducir el escenario de negocio (emitir cobro real, verificar respuesta). Causa: los nombres orientados a feature (`test_pago_exitoso`) son ambiguos sobre QUÉ falla — si el test falla, el desarrollador debe diagnosticar; los nombres orientados a causa raíz (`test_X_no_usa_Y`, `test_query_incluye_selectinload_Z`, `test_service_devuelve_dict_no_objeto`) son auto-diagnósticos. Fix: para cada bug que cueste >30 min diagnosticar, escribir UN test adicional cuyo nombre describa la condición técnica violada, no el escenario de negocio. Convención: `test_<componente>_<condicion_tecnica>` o `test_<componente>_no_<anti_patron>`. Estos tests son tu segunda línea de defensa contra regresiones de la misma causa raíz, complementarios a los tests de comportamiento.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: claudemd-bloat-detector.js
|
|
6
|
+
* Tipo: PostToolUse (aplica a: Write, Edit, MultiEdit)
|
|
7
|
+
*
|
|
8
|
+
* Ejecuta `scripts/auditar-claudemd.js` contra archivos `CLAUDE.md`
|
|
9
|
+
* recién modificados y emite un nudge a `.planning/evolucion/nudges.jsonl`
|
|
10
|
+
* si el veredicto es WARN o ERROR.
|
|
11
|
+
*
|
|
12
|
+
* Aplica ADR-0016 (best practices Anthropic "The CLAUDE.md file"):
|
|
13
|
+
* detecta inflación (líneas excesivas, bullets monolíticos, secciones
|
|
14
|
+
* canónicas ausentes, ausencia de @references) y sugiere intervención
|
|
15
|
+
* con `/swl:claudemd refactor`.
|
|
16
|
+
*
|
|
17
|
+
* Opt-out: SWL_CLAUDEMD_BLOAT=0 desactiva completamente el hook.
|
|
18
|
+
*
|
|
19
|
+
* Comportamiento:
|
|
20
|
+
* - Nunca bloquea operaciones (exit code 0 siempre)
|
|
21
|
+
* - Solo emite nudge cuando veredicto != OK — ruido mínimo
|
|
22
|
+
* - Solo se dispara con archivos cuyo basename sea exactamente CLAUDE.md
|
|
23
|
+
* - Respeta exclusiones: temp/, node_modules/, respositorios-git/
|
|
24
|
+
*
|
|
25
|
+
* Formato del nudge:
|
|
26
|
+
* {
|
|
27
|
+
* id: string,
|
|
28
|
+
* kind: "claudemd-bloat",
|
|
29
|
+
* target: "documentador-swl",
|
|
30
|
+
* source: "hooks/claudemd-bloat-detector.js",
|
|
31
|
+
* message: "...",
|
|
32
|
+
* data: { archivo, veredicto, lineas, hallazgos_count },
|
|
33
|
+
* ts: ISO,
|
|
34
|
+
* accionado: false
|
|
35
|
+
* }
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const fs = require('fs');
|
|
39
|
+
const path = require('path');
|
|
40
|
+
const crypto = require('crypto');
|
|
41
|
+
|
|
42
|
+
// ─── Opt-out global ───────────────────────────────────────────────────────
|
|
43
|
+
if (process.env.SWL_CLAUDEMD_BLOAT === '0') {
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let hookInput = '';
|
|
48
|
+
try {
|
|
49
|
+
hookInput = fs.readFileSync(0, 'utf-8');
|
|
50
|
+
} catch (_) {
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let evento;
|
|
55
|
+
try {
|
|
56
|
+
evento = JSON.parse(hookInput);
|
|
57
|
+
} catch (_) {
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const toolName = evento?.tool_name;
|
|
62
|
+
const toolInput = evento?.tool_input;
|
|
63
|
+
|
|
64
|
+
if (!toolName || !['Write', 'Edit', 'MultiEdit'].includes(toolName)) {
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const filePath = toolInput?.file_path;
|
|
69
|
+
if (!filePath) {
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Solo CLAUDE.md (basename exacto, case-sensitive)
|
|
74
|
+
const basename = path.basename(filePath);
|
|
75
|
+
if (basename !== 'CLAUDE.md') {
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const pathNormalized = filePath.replace(/\\/g, '/');
|
|
80
|
+
const RUTAS_EXCLUIDAS = [
|
|
81
|
+
'/temp/',
|
|
82
|
+
'/node_modules/',
|
|
83
|
+
'/respositorios-git/',
|
|
84
|
+
'/.planning/',
|
|
85
|
+
];
|
|
86
|
+
if (RUTAS_EXCLUIDAS.some((excluida) => pathNormalized.includes(excluida))) {
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// El archivo debe existir
|
|
91
|
+
if (!fs.existsSync(filePath)) {
|
|
92
|
+
process.exit(0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ─── Ejecutar auditor (módulo, no subproceso) ─────────────────────────────
|
|
96
|
+
const CWD = process.cwd();
|
|
97
|
+
const auditorPath = path.join(CWD, 'scripts', 'auditar-claudemd.js');
|
|
98
|
+
if (!fs.existsSync(auditorPath)) {
|
|
99
|
+
// No hay auditor instalado en este destino; salir silenciosamente
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let resultado;
|
|
104
|
+
try {
|
|
105
|
+
const { auditar } = require(auditorPath);
|
|
106
|
+
resultado = auditar(filePath);
|
|
107
|
+
} catch (_) {
|
|
108
|
+
// Cualquier error del auditor: salir silenciosamente, no romper el hook
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Solo emitir nudge si veredicto != OK
|
|
113
|
+
if (!resultado || resultado.veredicto === 'OK') {
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ─── Construir nudge ──────────────────────────────────────────────────────
|
|
118
|
+
const rutaRelativa = path.relative(CWD, filePath).replace(/\\/g, '/');
|
|
119
|
+
const topHallazgos = (resultado.hallazgos || [])
|
|
120
|
+
.slice(0, 3)
|
|
121
|
+
.map((h) => ` - [${h.severidad}] ${h.mensaje}`)
|
|
122
|
+
.join('\n');
|
|
123
|
+
|
|
124
|
+
const nudge = {
|
|
125
|
+
id: crypto.randomBytes(8).toString('hex'),
|
|
126
|
+
kind: 'claudemd-bloat',
|
|
127
|
+
target: 'documentador-swl',
|
|
128
|
+
source: 'hooks/claudemd-bloat-detector.js',
|
|
129
|
+
message:
|
|
130
|
+
`[claudemd] ${rutaRelativa} veredicto: ${resultado.veredicto} ` +
|
|
131
|
+
`(${resultado.hallazgos.length} hallazgos)\n` +
|
|
132
|
+
topHallazgos + '\n' +
|
|
133
|
+
` Ejecutar \`/swl:claudemd audit\` para detalle, ` +
|
|
134
|
+
`\`/swl:claudemd refactor\` para sugerencias de extracción.`,
|
|
135
|
+
data: {
|
|
136
|
+
archivo: rutaRelativa,
|
|
137
|
+
veredicto: resultado.veredicto,
|
|
138
|
+
lineas: resultado.metricas?.lineas,
|
|
139
|
+
secciones_ausentes: resultado.metricas?.secciones_ausentes || [],
|
|
140
|
+
tiene_at_references: resultado.metricas?.tiene_at_references,
|
|
141
|
+
hallazgos_count: resultado.hallazgos.length,
|
|
142
|
+
},
|
|
143
|
+
ts: new Date().toISOString(),
|
|
144
|
+
accionado: false,
|
|
145
|
+
accionado_ts: null,
|
|
146
|
+
accionado_por: null,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// ─── Persistir a nudges.jsonl ─────────────────────────────────────────────
|
|
150
|
+
try {
|
|
151
|
+
const nudgesPath = path.join(CWD, '.planning', 'evolucion', 'nudges.jsonl');
|
|
152
|
+
const nudgesDir = path.dirname(nudgesPath);
|
|
153
|
+
if (!fs.existsSync(nudgesDir)) {
|
|
154
|
+
fs.mkdirSync(nudgesDir, { recursive: true });
|
|
155
|
+
}
|
|
156
|
+
fs.appendFileSync(nudgesPath, JSON.stringify(nudge) + '\n', 'utf-8');
|
|
157
|
+
} catch (_) {
|
|
158
|
+
// No fallar el hook por error de escritura
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
process.exit(0);
|
|
@@ -83,8 +83,42 @@ function contieneTagsPrivados(texto) {
|
|
|
83
83
|
* - Email: formato RFC5322 simplificado.
|
|
84
84
|
* - IPv4 fuera de rangos privados (posible doxxing).
|
|
85
85
|
*/
|
|
86
|
+
/**
|
|
87
|
+
* Validación Luhn (mod 10) — algoritmo estándar de la industria para tarjetas
|
|
88
|
+
* de credito/debito (Visa, MasterCard, Amex, etc.). Toda tarjeta emitida pasa
|
|
89
|
+
* Luhn check; secuencias numericas arbitrarias (timestamps, IDs, hashes) NO
|
|
90
|
+
* pasan en >90% de los casos.
|
|
91
|
+
*
|
|
92
|
+
* Reduce falsos positivos masivamente sin sacrificar detección real:
|
|
93
|
+
* - `20260510-215306` (timestamp YYYYMMDD-HHMMSS de 14 dígitos): NO pasa
|
|
94
|
+
* - `4111-1111-1111-1111` (Visa test): SÍ pasa
|
|
95
|
+
* - `5500-0000-0000-0004` (MasterCard test): SÍ pasa
|
|
96
|
+
*
|
|
97
|
+
* Patrón usado por gitleaks, trufflehog y la mayoría de scanners modernos.
|
|
98
|
+
*/
|
|
99
|
+
function pasaLuhn(s) {
|
|
100
|
+
const digitos = String(s).replace(/\D/g, '');
|
|
101
|
+
if (digitos.length < 13 || digitos.length > 19) return false;
|
|
102
|
+
let suma = 0;
|
|
103
|
+
let duplicar = false;
|
|
104
|
+
for (let i = digitos.length - 1; i >= 0; i--) {
|
|
105
|
+
let d = digitos.charCodeAt(i) - 48; // '0' = 48
|
|
106
|
+
if (d < 0 || d > 9) return false;
|
|
107
|
+
if (duplicar) {
|
|
108
|
+
d *= 2;
|
|
109
|
+
if (d > 9) d -= 9;
|
|
110
|
+
}
|
|
111
|
+
suma += d;
|
|
112
|
+
duplicar = !duplicar;
|
|
113
|
+
}
|
|
114
|
+
return suma % 10 === 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
86
117
|
const PATTERNS_PII = [
|
|
87
|
-
|
|
118
|
+
// El patrón captura por formato; pasaLuhn() valida después para eliminar
|
|
119
|
+
// falsos positivos (timestamps, IDs numericos, hashes que casualmente
|
|
120
|
+
// tienen 13-19 dígitos con separadores).
|
|
121
|
+
{ regex: /\b(?:\d[ -]?){13,19}\b/, tipo: 'tarjeta_credito', validar: pasaLuhn },
|
|
88
122
|
{ regex: /\b[A-Z]{4}\d{6}[HMX][A-Z]{5}[A-Z0-9]{2}\b/, tipo: 'curp' },
|
|
89
123
|
{ regex: /\b[A-ZÑ&]{4}\d{6}[A-Z0-9]{3}\b/, tipo: 'rfc_persona_fisica' },
|
|
90
124
|
{ regex: /\b[A-Z]{6}\d{8}[HM]\d{3}\b/, tipo: 'ife_ine' },
|
|
@@ -112,10 +146,14 @@ const PATTERNS_PII = [
|
|
|
112
146
|
function detectarPII(texto) {
|
|
113
147
|
if (!texto || typeof texto !== 'string') return [];
|
|
114
148
|
const hallazgos = [];
|
|
115
|
-
for (const { regex, tipo } of PATTERNS_PII) {
|
|
149
|
+
for (const { regex, tipo, validar } of PATTERNS_PII) {
|
|
116
150
|
const matches = texto.match(new RegExp(regex.source, regex.flags + 'g'));
|
|
117
151
|
if (!matches) continue;
|
|
118
|
-
|
|
152
|
+
// Aplicar validador secundario si el patrón lo declara. Filtra falsos
|
|
153
|
+
// positivos de formato cuando hay una invariante adicional (Luhn para
|
|
154
|
+
// tarjetas, etc.). Sin validador se mantiene el comportamiento legacy.
|
|
155
|
+
const validados = validar ? matches.filter(validar) : matches;
|
|
156
|
+
for (const m of validados.slice(0, 3)) { // max 3 muestras por tipo
|
|
119
157
|
const muestra = m.length > 8
|
|
120
158
|
? m.slice(0, 2) + '***' + m.slice(-2)
|
|
121
159
|
: '***';
|
|
@@ -125,4 +163,4 @@ function detectarPII(texto) {
|
|
|
125
163
|
return hallazgos;
|
|
126
164
|
}
|
|
127
165
|
|
|
128
|
-
module.exports = { filtrarPrivacidad, contieneTagsPrivados, detectarPII, MAX_TAGS, PATTERNS_PII };
|
|
166
|
+
module.exports = { filtrarPrivacidad, contieneTagsPrivados, detectarPII, pasaLuhn, MAX_TAGS, PATTERNS_PII };
|
|
@@ -347,6 +347,15 @@
|
|
|
347
347
|
"maxConsecutiveFailures": 5,
|
|
348
348
|
"degradeOnFailure": "skip"
|
|
349
349
|
},
|
|
350
|
+
"claudemd-bloat-detector.js": {
|
|
351
|
+
"event": "PostToolUse",
|
|
352
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
353
|
+
"description": "Ejecuta scripts/auditar-claudemd.js contra archivos CLAUDE.md recién modificados (basename exacto, no cualquier .md). Emite nudge a .planning/evolucion/nudges.jsonl si veredicto != OK (líneas excesivas, bullets gigantes, secciones canónicas ausentes, sin @references, placeholders). Aplica ADR-0016 (best practices Anthropic 'The CLAUDE.md file'). No bloquea. Excluye temp/, node_modules/, respositorios-git/, .planning/. Opt-out: SWL_CLAUDEMD_BLOAT=0.",
|
|
354
|
+
"blocking": false,
|
|
355
|
+
"async": true,
|
|
356
|
+
"maxConsecutiveFailures": 5,
|
|
357
|
+
"degradeOnFailure": "skip"
|
|
358
|
+
},
|
|
350
359
|
"notificacion-telegram.js": {
|
|
351
360
|
"event": "Stop",
|
|
352
361
|
"matcher": "",
|
package/manifiestos/modulos.json
CHANGED
|
@@ -698,11 +698,12 @@
|
|
|
698
698
|
]
|
|
699
699
|
},
|
|
700
700
|
"habilidades-swl-herramientas": {
|
|
701
|
-
"descripcion": "Herramientas internas SWL: markitdown, revisar-impacto, NestJS",
|
|
701
|
+
"descripcion": "Herramientas internas SWL: markitdown, revisar-impacto, claudemd, NestJS",
|
|
702
702
|
"tipo": "habilidades",
|
|
703
703
|
"archivos": [
|
|
704
704
|
"habilidades/swl-markitdown",
|
|
705
705
|
"habilidades/swl-revisar-impacto",
|
|
706
|
+
"habilidades/swl-claudemd",
|
|
706
707
|
"habilidades/nestjs-experto"
|
|
707
708
|
],
|
|
708
709
|
"targets": [
|
|
@@ -801,7 +802,8 @@
|
|
|
801
802
|
"comandos/swl/exportar-vault.md",
|
|
802
803
|
"comandos/swl/ayuda.md",
|
|
803
804
|
"comandos/swl/inbox.md",
|
|
804
|
-
"comandos/swl/reflect-skills.md"
|
|
805
|
+
"comandos/swl/reflect-skills.md",
|
|
806
|
+
"comandos/swl/claudemd.md"
|
|
805
807
|
],
|
|
806
808
|
"targets": [
|
|
807
809
|
"claude",
|
|
@@ -956,6 +958,7 @@
|
|
|
956
958
|
"hooks/captura-feedback-usuario.js",
|
|
957
959
|
"hooks/inbox-aviso.js",
|
|
958
960
|
"hooks/aiisms-detector.js",
|
|
961
|
+
"hooks/claudemd-bloat-detector.js",
|
|
959
962
|
"hooks/sugerir-regenerar-inventario.js",
|
|
960
963
|
"hooks/sugerir-contribuir.js",
|
|
961
964
|
"hooks/_run-hook.sh",
|
|
@@ -1136,6 +1139,22 @@
|
|
|
1136
1139
|
"gemini"
|
|
1137
1140
|
]
|
|
1138
1141
|
},
|
|
1142
|
+
"claudemd-auditor": {
|
|
1143
|
+
"descripcion": "Auditor de calidad de CLAUDE.md según best practices Anthropic (ADR-0016). Detecta inflación (líneas excesivas, bullets gigantes, secciones canónicas ausentes, sin @references, placeholders). Usado por el comando /swl:claudemd y por el hook claudemd-bloat-detector. Zero-deps. Soporta --json y --strict. Umbrales configurables: SWL_CLAUDEMD_MAX_LINES (default 200), SWL_CLAUDEMD_MAX_BULLET_CHARS (default 1000).",
|
|
1144
|
+
"tipo": "scripts",
|
|
1145
|
+
"archivos": [
|
|
1146
|
+
"scripts/auditar-claudemd.js",
|
|
1147
|
+
"docs/variables-entorno.md"
|
|
1148
|
+
],
|
|
1149
|
+
"targets": [
|
|
1150
|
+
"claude",
|
|
1151
|
+
"openclaude",
|
|
1152
|
+
"copilot",
|
|
1153
|
+
"opencode",
|
|
1154
|
+
"codex",
|
|
1155
|
+
"gemini"
|
|
1156
|
+
]
|
|
1157
|
+
},
|
|
1139
1158
|
"mcp-server-swl": {
|
|
1140
1159
|
"descripcion": "MCP server stub experimental que expone memoria SWL (aprendizajes, sesiones, instintos) a clientes MCP externos (Cursor, Gemini CLI, OpenCode, Cline, Claude Desktop). Modo stdio. 3 endpoints: swl_memory_search, swl_aprendizajes_recientes, swl_instintos_activos. SIN auth, SIN rate limiting, SIN HTTP transport, SIN tests integración. NO USAR EN PRODUCCIÓN. Trigger para hardening: uso real ≥2 runtimes diferentes consistentemente por ≥1 mes. El binario `swl-mcp-server` se instala automáticamente vía npm install -g (declarado en package.json bin). NO se propaga al runtime SWL — vive en el paquete npm como herramienta opt-in. Ver scripts/mcp-server/README.md para 11 limitaciones explícitas y diseño futuro.",
|
|
1141
1160
|
"tipo": "scripts",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"lockfileVersion": 1,
|
|
3
|
-
"generatedAt": "2026-05-
|
|
4
|
-
"skillsCount":
|
|
5
|
-
"lockHash": "sha256:
|
|
3
|
+
"generatedAt": "2026-05-11T03:35:46.021Z",
|
|
4
|
+
"skillsCount": 155,
|
|
5
|
+
"lockHash": "sha256:92e415132658a0de593795e73b5561d952194f39a138fdb429f16743bb5837ff",
|
|
6
6
|
"skills": [
|
|
7
7
|
{
|
|
8
8
|
"nombre": "accesibilidad-a11y",
|
|
@@ -109,6 +109,13 @@
|
|
|
109
109
|
"bytes": 13620,
|
|
110
110
|
"version": "\"1.0.0\""
|
|
111
111
|
},
|
|
112
|
+
{
|
|
113
|
+
"nombre": "benchmark-memoria",
|
|
114
|
+
"path": "habilidades/benchmark-memoria/SKILL.md",
|
|
115
|
+
"hash": "sha256:9f2c36b648fb667d6edce9135e04226d2f932f6b23eef6b27625ef72eee9c77e",
|
|
116
|
+
"bytes": 7484,
|
|
117
|
+
"version": "\"1.0.0\""
|
|
118
|
+
},
|
|
112
119
|
{
|
|
113
120
|
"nombre": "brainstorming",
|
|
114
121
|
"path": "habilidades/brainstorming/SKILL.md",
|
|
@@ -238,9 +245,9 @@
|
|
|
238
245
|
{
|
|
239
246
|
"nombre": "contenedores-docker",
|
|
240
247
|
"path": "habilidades/contenedores-docker/SKILL.md",
|
|
241
|
-
"hash": "sha256:
|
|
242
|
-
"bytes":
|
|
243
|
-
"version": "\"1.0.
|
|
248
|
+
"hash": "sha256:a3a816bfb4bfceef7eeac90838392eddf474c86665e3c5cc600ecbedf29d448e",
|
|
249
|
+
"bytes": 9574,
|
|
250
|
+
"version": "\"1.0.1\""
|
|
244
251
|
},
|
|
245
252
|
{
|
|
246
253
|
"nombre": "context-builder",
|
|
@@ -287,9 +294,9 @@
|
|
|
287
294
|
{
|
|
288
295
|
"nombre": "datos-etl",
|
|
289
296
|
"path": "habilidades/datos-etl/SKILL.md",
|
|
290
|
-
"hash": "sha256:
|
|
291
|
-
"bytes":
|
|
292
|
-
"version": "\"1.0.
|
|
297
|
+
"hash": "sha256:adae4c508c3895b77c68b5e84a65649d1c8043837eb69d721ff56a033731617b",
|
|
298
|
+
"bytes": 9595,
|
|
299
|
+
"version": "\"1.0.1\""
|
|
293
300
|
},
|
|
294
301
|
{
|
|
295
302
|
"nombre": "dbml-experto",
|
|
@@ -368,6 +375,13 @@
|
|
|
368
375
|
"bytes": 12806,
|
|
369
376
|
"version": "\"1.0.0\""
|
|
370
377
|
},
|
|
378
|
+
{
|
|
379
|
+
"nombre": "doubt-driven-review",
|
|
380
|
+
"path": "habilidades/doubt-driven-review/SKILL.md",
|
|
381
|
+
"hash": "sha256:5677f6c92a0fc183f9bbe06171cca14e3ad85695dba055acd1de56d81bff182b",
|
|
382
|
+
"bytes": 7620,
|
|
383
|
+
"version": null
|
|
384
|
+
},
|
|
371
385
|
{
|
|
372
386
|
"nombre": "drift-detection",
|
|
373
387
|
"path": "habilidades/drift-detection/SKILL.md",
|
|
@@ -396,6 +410,13 @@
|
|
|
396
410
|
"bytes": 11583,
|
|
397
411
|
"version": "\"1.0.0\""
|
|
398
412
|
},
|
|
413
|
+
{
|
|
414
|
+
"nombre": "eval-framework",
|
|
415
|
+
"path": "habilidades/eval-framework/SKILL.md",
|
|
416
|
+
"hash": "sha256:0b00cfaa631e0bd6af0bf5d9a01aa54fcc7d0656b8c9760c97d56f8493fdfb5d",
|
|
417
|
+
"bytes": 7778,
|
|
418
|
+
"version": "\"1.0.0\""
|
|
419
|
+
},
|
|
399
420
|
{
|
|
400
421
|
"nombre": "evaluacion-agentes",
|
|
401
422
|
"path": "habilidades/evaluacion-agentes/SKILL.md",
|
|
@@ -427,9 +448,9 @@
|
|
|
427
448
|
{
|
|
428
449
|
"nombre": "fastapi-experto",
|
|
429
450
|
"path": "habilidades/fastapi-experto/SKILL.md",
|
|
430
|
-
"hash": "sha256:
|
|
431
|
-
"bytes":
|
|
432
|
-
"version": "\"1.
|
|
451
|
+
"hash": "sha256:19e472102b7d59c1b1e1719e9ea6096467977ad8a73035d6013e56178f94ab05",
|
|
452
|
+
"bytes": 17608,
|
|
453
|
+
"version": "\"1.2.0\""
|
|
433
454
|
},
|
|
434
455
|
{
|
|
435
456
|
"nombre": "filament-admin",
|
|
@@ -616,15 +637,15 @@
|
|
|
616
637
|
{
|
|
617
638
|
"nombre": "memoria-busqueda",
|
|
618
639
|
"path": "habilidades/memoria-busqueda/SKILL.md",
|
|
619
|
-
"hash": "sha256:
|
|
620
|
-
"bytes":
|
|
621
|
-
"version": "\"1.
|
|
640
|
+
"hash": "sha256:3a23c11eff134da8f2317fdb87aa4f5fd9e37bcaa7ea4591058beacc36874a9e",
|
|
641
|
+
"bytes": 10423,
|
|
642
|
+
"version": "\"1.1.0\""
|
|
622
643
|
},
|
|
623
644
|
{
|
|
624
645
|
"nombre": "meta-skills-estandar",
|
|
625
646
|
"path": "habilidades/meta-skills-estandar/SKILL.md",
|
|
626
|
-
"hash": "sha256:
|
|
627
|
-
"bytes":
|
|
647
|
+
"hash": "sha256:6c2861defb5f5c46c1ac851ecf2ec06958be714fd14d3f7f512ba916b43e3b7b",
|
|
648
|
+
"bytes": 13101,
|
|
628
649
|
"version": "\"1.0.0\""
|
|
629
650
|
},
|
|
630
651
|
{
|
|
@@ -672,9 +693,9 @@
|
|
|
672
693
|
{
|
|
673
694
|
"nombre": "nextjs-experto",
|
|
674
695
|
"path": "habilidades/nextjs-experto/SKILL.md",
|
|
675
|
-
"hash": "sha256:
|
|
676
|
-
"bytes":
|
|
677
|
-
"version": "\"1.
|
|
696
|
+
"hash": "sha256:689e4ce7f045a233efbb8fb9126e3345d9f9be9f2a7a56786b8149260455399a",
|
|
697
|
+
"bytes": 16165,
|
|
698
|
+
"version": "\"1.1.1\""
|
|
678
699
|
},
|
|
679
700
|
{
|
|
680
701
|
"nombre": "nextjs-patrones",
|
|
@@ -686,9 +707,9 @@
|
|
|
686
707
|
{
|
|
687
708
|
"nombre": "nextjs-testing",
|
|
688
709
|
"path": "habilidades/nextjs-testing/SKILL.md",
|
|
689
|
-
"hash": "sha256:
|
|
690
|
-
"bytes":
|
|
691
|
-
"version": "\"1.0.
|
|
710
|
+
"hash": "sha256:66742e5c32822ffd1b79ab44922fed64367d28c2510f4c55efd4cd7ad5727a6d",
|
|
711
|
+
"bytes": 15435,
|
|
712
|
+
"version": "\"1.0.1\""
|
|
692
713
|
},
|
|
693
714
|
{
|
|
694
715
|
"nombre": "node-experto",
|
|
@@ -707,8 +728,8 @@
|
|
|
707
728
|
{
|
|
708
729
|
"nombre": "nuevo-proyecto",
|
|
709
730
|
"path": "habilidades/nuevo-proyecto/SKILL.md",
|
|
710
|
-
"hash": "sha256:
|
|
711
|
-
"bytes":
|
|
731
|
+
"hash": "sha256:8244596084fce93e17b194a43e10ec00da75cd12f97891b51b641e55ce1303c8",
|
|
732
|
+
"bytes": 11956,
|
|
712
733
|
"version": "\"1.0.0\""
|
|
713
734
|
},
|
|
714
735
|
{
|
|
@@ -770,16 +791,16 @@
|
|
|
770
791
|
{
|
|
771
792
|
"nombre": "planear-fase",
|
|
772
793
|
"path": "habilidades/planear-fase/SKILL.md",
|
|
773
|
-
"hash": "sha256:
|
|
774
|
-
"bytes":
|
|
775
|
-
"version": "\"1.
|
|
794
|
+
"hash": "sha256:199b9abb865739d17b0654a3a67d116d95a2133140ffde92bda89d3ed9f41b98",
|
|
795
|
+
"bytes": 14372,
|
|
796
|
+
"version": "\"1.2.0\""
|
|
776
797
|
},
|
|
777
798
|
{
|
|
778
799
|
"nombre": "postgresql-experto",
|
|
779
800
|
"path": "habilidades/postgresql-experto/SKILL.md",
|
|
780
|
-
"hash": "sha256:
|
|
781
|
-
"bytes":
|
|
782
|
-
"version": "\"1.
|
|
801
|
+
"hash": "sha256:7beba10b4479f705a250067103064944fe45c3ef666fd5513bfc9441d9009498",
|
|
802
|
+
"bytes": 9711,
|
|
803
|
+
"version": "\"1.1.0\""
|
|
783
804
|
},
|
|
784
805
|
{
|
|
785
806
|
"nombre": "prevencion-racionalizacion",
|
|
@@ -826,9 +847,9 @@
|
|
|
826
847
|
{
|
|
827
848
|
"nombre": "react-experto",
|
|
828
849
|
"path": "habilidades/react-experto/SKILL.md",
|
|
829
|
-
"hash": "sha256:
|
|
830
|
-
"bytes":
|
|
831
|
-
"version": "\"1.
|
|
850
|
+
"hash": "sha256:f1f0d478de5c16b1b0fb787caf45ca7151a0eab3dcf71352fdc3f871b1d1948b",
|
|
851
|
+
"bytes": 11776,
|
|
852
|
+
"version": "\"1.1.1\""
|
|
832
853
|
},
|
|
833
854
|
{
|
|
834
855
|
"nombre": "react-optimizacion",
|
|
@@ -928,6 +949,13 @@
|
|
|
928
949
|
"bytes": 10257,
|
|
929
950
|
"version": "\"1.0.0\""
|
|
930
951
|
},
|
|
952
|
+
{
|
|
953
|
+
"nombre": "swl-claudemd",
|
|
954
|
+
"path": "habilidades/swl-claudemd/SKILL.md",
|
|
955
|
+
"hash": "sha256:8b8b0cd03c815e0cfadeffc81a49f0858105be9c564eb5f8e83dfd1cb78dd05e",
|
|
956
|
+
"bytes": 10312,
|
|
957
|
+
"version": "\"1.0.0\""
|
|
958
|
+
},
|
|
931
959
|
{
|
|
932
960
|
"nombre": "swl-dashboard",
|
|
933
961
|
"path": "habilidades/swl-dashboard/SKILL.md",
|
|
@@ -959,9 +987,9 @@
|
|
|
959
987
|
{
|
|
960
988
|
"nombre": "tdd-workflow",
|
|
961
989
|
"path": "habilidades/tdd-workflow/SKILL.md",
|
|
962
|
-
"hash": "sha256:
|
|
963
|
-
"bytes":
|
|
964
|
-
"version": "\"1.0.
|
|
990
|
+
"hash": "sha256:4050e995cd6ce8422b965793c98605ce8a9ead4025784b5addb5a0cb24fc7acb",
|
|
991
|
+
"bytes": 15307,
|
|
992
|
+
"version": "\"1.0.1\""
|
|
965
993
|
},
|
|
966
994
|
{
|
|
967
995
|
"nombre": "terraform-experto",
|
|
@@ -1036,9 +1064,9 @@
|
|
|
1036
1064
|
{
|
|
1037
1065
|
"nombre": "verificar-trabajo",
|
|
1038
1066
|
"path": "habilidades/verificar-trabajo/SKILL.md",
|
|
1039
|
-
"hash": "sha256:
|
|
1040
|
-
"bytes":
|
|
1041
|
-
"version": "\"1.1.
|
|
1067
|
+
"hash": "sha256:001fd34fbeefbe995c4b76fb55fa1a5277577f701b098998f189fd7d0c35e40e",
|
|
1068
|
+
"bytes": 14619,
|
|
1069
|
+
"version": "\"1.1.1\""
|
|
1042
1070
|
},
|
|
1043
1071
|
{
|
|
1044
1072
|
"nombre": "wiki-conocimiento",
|