@saulwade/swl-ses 1.4.1 → 1.5.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 +3 -3
- package/README.md +561 -560
- package/agentes/nemesis-auditor-swl.md +161 -161
- package/bin/swl-mcp-server.js +49 -22
- package/bin/swl-ses.js +74 -0
- package/comandos/swl/.evolved.json +22 -22
- package/comandos/swl/contribuir.md +233 -233
- package/comandos/swl/ejecutar-fase.md +33 -4
- package/comandos/swl/metricas.md +72 -0
- package/comandos/swl/nemesis.md +122 -122
- package/gateway/lib/event-channel.js +191 -191
- 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/discutir-fase/SKILL.md +50 -2
- package/habilidades/doubt-driven-review/SKILL.md +171 -171
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -0
- package/habilidades/eval-framework/SKILL.md +212 -212
- package/habilidades/feynman-auditor-swl/SKILL.md +123 -123
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- 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/protocolo-revision-swl/SKILL.md +276 -0
- package/habilidades/release-semver/.evolved.json +8 -8
- package/habilidades/state-inconsistency-auditor-swl/SKILL.md +166 -166
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
- package/habilidades/testing-python/SKILL.md +340 -340
- package/habilidades/verificar-trabajo/SKILL.md +49 -5
- package/habilidades/web-fetcher-routing/SKILL.md +75 -75
- package/hooks/claudemd-bloat-detector.js +161 -161
- 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/security-net.js +201 -201
- package/hooks/lib/skill-auditor.js +588 -588
- package/hooks/lib/sync-status.js +228 -228
- package/hooks/lib/taint-tracker.js +107 -107
- package/hooks/lib/text-similarity.js +241 -241
- package/hooks/lib/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/modulos.json +1321 -1262
- package/manifiestos/perfiles.json +2 -1
- package/manifiestos/skills-lock.json +1114 -1114
- package/package.json +3 -3
- 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 +351 -343
- 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/audit-tools/audit-history.js +330 -330
- package/scripts/audit-tools/bundle-tracker.js +290 -290
- package/scripts/audit-tools/canary-monitor.js +352 -352
- package/scripts/audit-tools/code-profiler.js +605 -605
- package/scripts/audit-tools/dep-doctor.js +320 -320
- package/scripts/audit-tools/env-validator.js +206 -206
- package/scripts/audit-tools/lib/fs-walk.js +48 -48
- package/scripts/audit-tools/lib/output.js +23 -23
- package/scripts/audit-tools/migration-checker.js +392 -392
- package/scripts/audit-tools/pentest-scanner.js +1436 -1436
- package/scripts/benchmark-memoria.js +167 -167
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/derivar-feature-list.js +489 -0
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/doctor.js +31 -4
- 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/instalador.js +56 -5
- 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-runtime.js +75 -9
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/diary-entry.js +234 -234
- package/scripts/lib/estado.js +13 -1
- 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/expandir-targets.js +71 -0
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/manifiestos.js +42 -1
- package/scripts/lib/npm-version.js +261 -261
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/parsear-opciones.js +3 -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/toml-merge.js +204 -0
- package/scripts/lib/transformadores/base.js +43 -9
- package/scripts/lib/transformadores/codex.js +375 -115
- package/scripts/lib/transformadores/cursor.js +359 -0
- package/scripts/lib/transformadores/index.js +2 -0
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/mcp-server/README.md +122 -80
- package/scripts/mcp-server/auth.js +105 -0
- package/scripts/mcp-server/cache.js +106 -0
- package/scripts/mcp-server/handlers.js +386 -206
- package/scripts/mcp-server/telemetry.js +78 -0
- 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 +231 -195
- package/scripts/validar-userland-vacio.js +110 -110
|
@@ -1,151 +1,151 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* detectar-aprendizajes-duplicados.js
|
|
6
|
-
*
|
|
7
|
-
* Detecta pares de entradas en `.planning/APRENDIZAJES.md` con alta similitud
|
|
8
|
-
* de tokens (Jaccard > umbral). Útil para identificar candidatos a fusionar
|
|
9
|
-
* cuando el hook de auto-extracción genera entradas redundantes.
|
|
10
|
-
*
|
|
11
|
-
* Patrón adoptado de `temp/agentmemory-main/src/functions/auto-forget.ts`
|
|
12
|
-
* (contradiction detection con Jaccard >= 0.9). Aquí se usa con threshold
|
|
13
|
-
* configurable más bajo (0.6 default) porque queremos sugerir, no auto-borrar.
|
|
14
|
-
*
|
|
15
|
-
* NO modifica APRENDIZAJES.md. Solo reporta. La acción de fusión queda en
|
|
16
|
-
* manos del usuario o de un comando separado (`/swl:aprender consolidar`).
|
|
17
|
-
*
|
|
18
|
-
* Uso:
|
|
19
|
-
* node scripts/detectar-aprendizajes-duplicados.js [threshold]
|
|
20
|
-
*
|
|
21
|
-
* Argumentos:
|
|
22
|
-
* threshold - Similitud mínima para reportar (default: 0.6, rango [0, 1]).
|
|
23
|
-
*
|
|
24
|
-
* Exit codes:
|
|
25
|
-
* 0 - Ejecución OK (haya o no duplicados)
|
|
26
|
-
* 1 - Error de I/O o parseo
|
|
27
|
-
*
|
|
28
|
-
* Output: tabla legible en stdout. Si se detectan ≥ 1 duplicados, también
|
|
29
|
-
* imprime sugerencia para revisar/consolidar.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
const fs = require('fs');
|
|
33
|
-
const path = require('path');
|
|
34
|
-
|
|
35
|
-
const { tokenize, jaccard } = require('./lib/jaccard-similarity');
|
|
36
|
-
|
|
37
|
-
const RUTA_APRENDIZAJES = path.join(process.cwd(), '.planning', 'APRENDIZAJES.md');
|
|
38
|
-
const DEFAULT_THRESHOLD = 0.6;
|
|
39
|
-
const MAX_PARES_REPORTADOS = 30;
|
|
40
|
-
|
|
41
|
-
function parsearEntradas(contenido) {
|
|
42
|
-
const lineas = contenido.split('\n');
|
|
43
|
-
const entradas = [];
|
|
44
|
-
let actual = null;
|
|
45
|
-
|
|
46
|
-
for (let i = 0; i < lineas.length; i++) {
|
|
47
|
-
const linea = lineas[i];
|
|
48
|
-
if (linea.startsWith('## ')) {
|
|
49
|
-
if (actual) entradas.push(actual);
|
|
50
|
-
actual = {
|
|
51
|
-
lineaInicio: i + 1,
|
|
52
|
-
titulo: linea.slice(3).trim(),
|
|
53
|
-
contenido: '',
|
|
54
|
-
};
|
|
55
|
-
} else if (actual) {
|
|
56
|
-
actual.contenido += linea + '\n';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (actual) entradas.push(actual);
|
|
60
|
-
|
|
61
|
-
// Filtrar entradas vacías o triviales (< 50 chars de contenido real)
|
|
62
|
-
return entradas.filter(e => e.contenido.replace(/\s/g, '').length >= 50);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function detectarDuplicados(entradas, threshold) {
|
|
66
|
-
const tokensCache = entradas.map(e => tokenize(e.titulo + ' ' + e.contenido));
|
|
67
|
-
const pares = [];
|
|
68
|
-
|
|
69
|
-
for (let i = 0; i < entradas.length; i++) {
|
|
70
|
-
for (let j = i + 1; j < entradas.length; j++) {
|
|
71
|
-
const sim = jaccard(tokensCache[i], tokensCache[j]);
|
|
72
|
-
if (sim >= threshold) {
|
|
73
|
-
pares.push({
|
|
74
|
-
entradaA: entradas[i],
|
|
75
|
-
entradaB: entradas[j],
|
|
76
|
-
similitud: sim,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
pares.sort((a, b) => b.similitud - a.similitud);
|
|
83
|
-
return pares;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function reportarTexto(pares) {
|
|
87
|
-
if (pares.length === 0) {
|
|
88
|
-
console.log('Sin duplicados detectados sobre el umbral.');
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
console.log(`Pares con similitud Jaccard ≥ umbral: ${pares.length}`);
|
|
93
|
-
console.log('');
|
|
94
|
-
|
|
95
|
-
const limite = Math.min(pares.length, MAX_PARES_REPORTADOS);
|
|
96
|
-
for (let i = 0; i < limite; i++) {
|
|
97
|
-
const p = pares[i];
|
|
98
|
-
console.log(` [${(p.similitud * 100).toFixed(1)}%] ` +
|
|
99
|
-
`L${p.entradaA.lineaInicio} ↔ L${p.entradaB.lineaInicio}`);
|
|
100
|
-
console.log(' A: ' + p.entradaA.titulo.slice(0, 80));
|
|
101
|
-
console.log(' B: ' + p.entradaB.titulo.slice(0, 80));
|
|
102
|
-
console.log('');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (pares.length > limite) {
|
|
106
|
-
console.log(` ... ${pares.length - limite} pares adicionales no mostrados`);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
console.log('Sugerencia: revisa los pares con mayor similitud y considera ' +
|
|
110
|
-
'fusionarlos en una sola entrada con `/swl:aprender consolidar` o manualmente.');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function main() {
|
|
114
|
-
const threshold = parseFloat(process.argv[2]) || DEFAULT_THRESHOLD;
|
|
115
|
-
|
|
116
|
-
if (!Number.isFinite(threshold) || threshold < 0 || threshold > 1) {
|
|
117
|
-
console.error(`Threshold inválido: ${process.argv[2]}. Usar valor en [0, 1].`);
|
|
118
|
-
process.exit(1);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (!fs.existsSync(RUTA_APRENDIZAJES)) {
|
|
122
|
-
console.error(`No existe ${RUTA_APRENDIZAJES}.`);
|
|
123
|
-
process.exit(1);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
let contenido;
|
|
127
|
-
try {
|
|
128
|
-
contenido = fs.readFileSync(RUTA_APRENDIZAJES, 'utf8');
|
|
129
|
-
} catch (err) {
|
|
130
|
-
console.error(`Error leyendo ${RUTA_APRENDIZAJES}: ${err.message}`);
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const entradas = parsearEntradas(contenido);
|
|
135
|
-
console.log(`Entradas encontradas: ${entradas.length}`);
|
|
136
|
-
console.log(`Threshold de similitud: ${threshold}`);
|
|
137
|
-
console.log('');
|
|
138
|
-
|
|
139
|
-
const pares = detectarDuplicados(entradas, threshold);
|
|
140
|
-
reportarTexto(pares);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (require.main === module) {
|
|
144
|
-
main();
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
module.exports = {
|
|
148
|
-
parsearEntradas,
|
|
149
|
-
detectarDuplicados,
|
|
150
|
-
reportarTexto,
|
|
151
|
-
};
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* detectar-aprendizajes-duplicados.js
|
|
6
|
+
*
|
|
7
|
+
* Detecta pares de entradas en `.planning/APRENDIZAJES.md` con alta similitud
|
|
8
|
+
* de tokens (Jaccard > umbral). Útil para identificar candidatos a fusionar
|
|
9
|
+
* cuando el hook de auto-extracción genera entradas redundantes.
|
|
10
|
+
*
|
|
11
|
+
* Patrón adoptado de `temp/agentmemory-main/src/functions/auto-forget.ts`
|
|
12
|
+
* (contradiction detection con Jaccard >= 0.9). Aquí se usa con threshold
|
|
13
|
+
* configurable más bajo (0.6 default) porque queremos sugerir, no auto-borrar.
|
|
14
|
+
*
|
|
15
|
+
* NO modifica APRENDIZAJES.md. Solo reporta. La acción de fusión queda en
|
|
16
|
+
* manos del usuario o de un comando separado (`/swl:aprender consolidar`).
|
|
17
|
+
*
|
|
18
|
+
* Uso:
|
|
19
|
+
* node scripts/detectar-aprendizajes-duplicados.js [threshold]
|
|
20
|
+
*
|
|
21
|
+
* Argumentos:
|
|
22
|
+
* threshold - Similitud mínima para reportar (default: 0.6, rango [0, 1]).
|
|
23
|
+
*
|
|
24
|
+
* Exit codes:
|
|
25
|
+
* 0 - Ejecución OK (haya o no duplicados)
|
|
26
|
+
* 1 - Error de I/O o parseo
|
|
27
|
+
*
|
|
28
|
+
* Output: tabla legible en stdout. Si se detectan ≥ 1 duplicados, también
|
|
29
|
+
* imprime sugerencia para revisar/consolidar.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const fs = require('fs');
|
|
33
|
+
const path = require('path');
|
|
34
|
+
|
|
35
|
+
const { tokenize, jaccard } = require('./lib/jaccard-similarity');
|
|
36
|
+
|
|
37
|
+
const RUTA_APRENDIZAJES = path.join(process.cwd(), '.planning', 'APRENDIZAJES.md');
|
|
38
|
+
const DEFAULT_THRESHOLD = 0.6;
|
|
39
|
+
const MAX_PARES_REPORTADOS = 30;
|
|
40
|
+
|
|
41
|
+
function parsearEntradas(contenido) {
|
|
42
|
+
const lineas = contenido.split('\n');
|
|
43
|
+
const entradas = [];
|
|
44
|
+
let actual = null;
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < lineas.length; i++) {
|
|
47
|
+
const linea = lineas[i];
|
|
48
|
+
if (linea.startsWith('## ')) {
|
|
49
|
+
if (actual) entradas.push(actual);
|
|
50
|
+
actual = {
|
|
51
|
+
lineaInicio: i + 1,
|
|
52
|
+
titulo: linea.slice(3).trim(),
|
|
53
|
+
contenido: '',
|
|
54
|
+
};
|
|
55
|
+
} else if (actual) {
|
|
56
|
+
actual.contenido += linea + '\n';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (actual) entradas.push(actual);
|
|
60
|
+
|
|
61
|
+
// Filtrar entradas vacías o triviales (< 50 chars de contenido real)
|
|
62
|
+
return entradas.filter(e => e.contenido.replace(/\s/g, '').length >= 50);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function detectarDuplicados(entradas, threshold) {
|
|
66
|
+
const tokensCache = entradas.map(e => tokenize(e.titulo + ' ' + e.contenido));
|
|
67
|
+
const pares = [];
|
|
68
|
+
|
|
69
|
+
for (let i = 0; i < entradas.length; i++) {
|
|
70
|
+
for (let j = i + 1; j < entradas.length; j++) {
|
|
71
|
+
const sim = jaccard(tokensCache[i], tokensCache[j]);
|
|
72
|
+
if (sim >= threshold) {
|
|
73
|
+
pares.push({
|
|
74
|
+
entradaA: entradas[i],
|
|
75
|
+
entradaB: entradas[j],
|
|
76
|
+
similitud: sim,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
pares.sort((a, b) => b.similitud - a.similitud);
|
|
83
|
+
return pares;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function reportarTexto(pares) {
|
|
87
|
+
if (pares.length === 0) {
|
|
88
|
+
console.log('Sin duplicados detectados sobre el umbral.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`Pares con similitud Jaccard ≥ umbral: ${pares.length}`);
|
|
93
|
+
console.log('');
|
|
94
|
+
|
|
95
|
+
const limite = Math.min(pares.length, MAX_PARES_REPORTADOS);
|
|
96
|
+
for (let i = 0; i < limite; i++) {
|
|
97
|
+
const p = pares[i];
|
|
98
|
+
console.log(` [${(p.similitud * 100).toFixed(1)}%] ` +
|
|
99
|
+
`L${p.entradaA.lineaInicio} ↔ L${p.entradaB.lineaInicio}`);
|
|
100
|
+
console.log(' A: ' + p.entradaA.titulo.slice(0, 80));
|
|
101
|
+
console.log(' B: ' + p.entradaB.titulo.slice(0, 80));
|
|
102
|
+
console.log('');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (pares.length > limite) {
|
|
106
|
+
console.log(` ... ${pares.length - limite} pares adicionales no mostrados`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log('Sugerencia: revisa los pares con mayor similitud y considera ' +
|
|
110
|
+
'fusionarlos en una sola entrada con `/swl:aprender consolidar` o manualmente.');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function main() {
|
|
114
|
+
const threshold = parseFloat(process.argv[2]) || DEFAULT_THRESHOLD;
|
|
115
|
+
|
|
116
|
+
if (!Number.isFinite(threshold) || threshold < 0 || threshold > 1) {
|
|
117
|
+
console.error(`Threshold inválido: ${process.argv[2]}. Usar valor en [0, 1].`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!fs.existsSync(RUTA_APRENDIZAJES)) {
|
|
122
|
+
console.error(`No existe ${RUTA_APRENDIZAJES}.`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let contenido;
|
|
127
|
+
try {
|
|
128
|
+
contenido = fs.readFileSync(RUTA_APRENDIZAJES, 'utf8');
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.error(`Error leyendo ${RUTA_APRENDIZAJES}: ${err.message}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const entradas = parsearEntradas(contenido);
|
|
135
|
+
console.log(`Entradas encontradas: ${entradas.length}`);
|
|
136
|
+
console.log(`Threshold de similitud: ${threshold}`);
|
|
137
|
+
console.log('');
|
|
138
|
+
|
|
139
|
+
const pares = detectarDuplicados(entradas, threshold);
|
|
140
|
+
reportarTexto(pares);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (require.main === module) {
|
|
144
|
+
main();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = {
|
|
148
|
+
parsearEntradas,
|
|
149
|
+
detectarDuplicados,
|
|
150
|
+
reportarTexto,
|
|
151
|
+
};
|
package/scripts/doctor.js
CHANGED
|
@@ -335,10 +335,37 @@ async function doctor(opciones = {}) {
|
|
|
335
335
|
const { detectarStack, filtrarReglasPorStack } = require('./lib/detectar-stack');
|
|
336
336
|
const resolucion = resolverPerfil(estado.perfil, { target: estado.target });
|
|
337
337
|
|
|
338
|
-
//
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
338
|
+
// Fix v1.4.3: usar el contexto de filtrado persistido al momento del
|
|
339
|
+
// install (allLangs, stackInstalado) en lugar de recalcular desde el cwd
|
|
340
|
+
// actual del doctor. Si el estado no lo persiste (instalación previa a
|
|
341
|
+
// v1.4.3), inferirlo desde los archivos realmente instalados.
|
|
342
|
+
let stackParaFiltro;
|
|
343
|
+
let omitirFiltro = false;
|
|
344
|
+
if (estado.allLangs === true) {
|
|
345
|
+
omitirFiltro = true;
|
|
346
|
+
} else if (Array.isArray(estado.stackInstalado)) {
|
|
347
|
+
stackParaFiltro = new Set(estado.stackInstalado);
|
|
348
|
+
} else {
|
|
349
|
+
// Backward compat: instalaciones previas a v1.4.3 no persisten contexto
|
|
350
|
+
// de filtrado. Inferirlo desde los archivos realmente instalados:
|
|
351
|
+
// cada subdir bajo reglas/lenguajes/X/ corresponde a un lenguaje
|
|
352
|
+
// detectado o a --all-langs activo al momento del install.
|
|
353
|
+
// El campo persistido en estado es `origen` (ruta relativa al paquete).
|
|
354
|
+
const langsInstalados = new Set();
|
|
355
|
+
for (const archivo of estado.archivosInstalados) {
|
|
356
|
+
const ruta = (archivo.origen || '').replace(/\\/g, '/');
|
|
357
|
+
if (!ruta.startsWith('reglas/lenguajes/')) continue;
|
|
358
|
+
const resto = ruta.slice('reglas/lenguajes/'.length);
|
|
359
|
+
const lang = resto.split('/')[0];
|
|
360
|
+
if (lang) langsInstalados.add(lang);
|
|
361
|
+
}
|
|
362
|
+
stackParaFiltro = langsInstalados;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (!omitirFiltro) {
|
|
366
|
+
const filtrado = filtrarReglasPorStack(resolucion.archivos, stackParaFiltro);
|
|
367
|
+
resolucion.archivos = filtrado.archivos;
|
|
368
|
+
}
|
|
342
369
|
|
|
343
370
|
// Contar esperados por tipo (solo tipos principales)
|
|
344
371
|
const tiposPrincipales = ['agentes', 'habilidades', 'comandos', 'reglas'];
|