@saulwade/swl-ses 1.3.3 → 1.3.5
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 +1 -1
- 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 +43 -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 +27 -27
- 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/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/instalador.js +38 -1
- 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/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/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
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Migración 3A — convierte campos CSV a array YAML inline en frontmatter de
|
|
4
|
-
* agentes. Afecta `tools`, `skillsInvocables`, `skillsRestringidos`.
|
|
5
|
-
*
|
|
6
|
-
* Antes: tools: Read, Write, Edit, Bash
|
|
7
|
-
* Después: tools: [Read, Write, Edit, Bash]
|
|
8
|
-
*
|
|
9
|
-
* Razón: el schema declara `type: array` pero el uso real es CSV string. YAML
|
|
10
|
-
* estándar NO convierte CSV a array — el parser produce una sola string. Esto
|
|
11
|
-
* causó bugs históricos documentados en CLAUDE.md ("regla obligatoria CSV
|
|
12
|
-
* estricto"). Migrar a array inline elimina la ambigüedad.
|
|
13
|
-
*
|
|
14
|
-
* Idempotente: skip si ya es array.
|
|
15
|
-
*
|
|
16
|
-
* Casos especiales detectados en agentes:
|
|
17
|
-
* - skillsInvocables: <ninguno> → mantener literal
|
|
18
|
-
* - skillsRestringidos: ninguno → convertir a [] (array vacío)
|
|
19
|
-
* - skillsRestringidos: \n - x\n → ya es array YAML multilinea, mantener
|
|
20
|
-
*
|
|
21
|
-
* Uso:
|
|
22
|
-
* node scripts/migrar-csv-a-array.js [--dry-run]
|
|
23
|
-
*
|
|
24
|
-
* Zero-dependencies. Compatible Windows (CRLF-safe), Node 18+.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
'use strict';
|
|
28
|
-
|
|
29
|
-
const fs = require('fs');
|
|
30
|
-
const path = require('path');
|
|
31
|
-
|
|
32
|
-
const AGENTES_DIR = path.join(__dirname, '..', 'agentes');
|
|
33
|
-
const DRY_RUN = process.argv.includes('--dry-run');
|
|
34
|
-
|
|
35
|
-
// Campos que migran de CSV a array
|
|
36
|
-
const CAMPOS_CSV = ['tools', 'skillsInvocables', 'skillsRestringidos'];
|
|
37
|
-
|
|
38
|
-
// Valores especiales que NO son listas y deben preservarse
|
|
39
|
-
const VALORES_LITERAL = new Set(['ninguno', 'ninguna', '<ninguno>', '<ninguna>', 'none', 'null']);
|
|
40
|
-
|
|
41
|
-
function parsearValorCSV(valorStr) {
|
|
42
|
-
// Detectar si ya es array inline `[a, b, c]`
|
|
43
|
-
if (/^\s*\[/.test(valorStr)) return null;
|
|
44
|
-
|
|
45
|
-
// Limpiar
|
|
46
|
-
const valor = valorStr.trim();
|
|
47
|
-
if (!valor) return [];
|
|
48
|
-
|
|
49
|
-
// Valor especial literal
|
|
50
|
-
if (VALORES_LITERAL.has(valor.toLowerCase())) return [];
|
|
51
|
-
|
|
52
|
-
// CSV split
|
|
53
|
-
return valor
|
|
54
|
-
.split(',')
|
|
55
|
-
.map((s) => s.trim())
|
|
56
|
-
.filter(Boolean);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function migrarFrontmatter(contenido) {
|
|
60
|
-
const match = contenido.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
61
|
-
if (!match) return { contenido, cambios: 0 };
|
|
62
|
-
|
|
63
|
-
const eol = match[0].includes('\r\n') ? '\r\n' : '\n';
|
|
64
|
-
const fmCompleto = match[0];
|
|
65
|
-
|
|
66
|
-
let nuevoFm = fmCompleto;
|
|
67
|
-
let cambios = 0;
|
|
68
|
-
|
|
69
|
-
for (const campo of CAMPOS_CSV) {
|
|
70
|
-
// Patrón 2 PRIMERO: array YAML multilínea
|
|
71
|
-
// skillsRestringidos:
|
|
72
|
-
// - angular-moderno
|
|
73
|
-
// - typescript-avanzado
|
|
74
|
-
// El campo está solo en su línea (sin valor) seguido de líneas con ` - X`
|
|
75
|
-
const re2 = new RegExp(`^(${campo}):[ \\t]*\\r?\\n((?:[ \\t]+-[ \\t]+[^\\r\\n]+\\r?\\n)+)`, 'm');
|
|
76
|
-
const m2 = nuevoFm.match(re2);
|
|
77
|
-
if (m2) {
|
|
78
|
-
const bloque = m2[2];
|
|
79
|
-
const items = bloque
|
|
80
|
-
.split(/\r?\n/)
|
|
81
|
-
.map((l) => l.trim())
|
|
82
|
-
.filter((l) => l.startsWith('- '))
|
|
83
|
-
.map((l) => l.slice(2).trim().replace(/^["']|["']$/g, ''));
|
|
84
|
-
if (items.length > 0) {
|
|
85
|
-
const arrayInline = `[${items.join(', ')}]`;
|
|
86
|
-
const reemplazo = `${campo}: ${arrayInline}${eol}`;
|
|
87
|
-
nuevoFm = nuevoFm.replace(re2, reemplazo);
|
|
88
|
-
cambios++;
|
|
89
|
-
}
|
|
90
|
-
continue; // procesado, no aplicar regex 1
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Patrón 1: campo en una sola línea con valor (CSV o array inline)
|
|
94
|
-
// tools: Read, Write
|
|
95
|
-
// skillsRestringidos: ninguno
|
|
96
|
-
// tools: [Read, Write] ← skip, ya es array
|
|
97
|
-
// CRÍTICO: usar [ \\t]* (NO \\s*) para no consumir newlines
|
|
98
|
-
const re1 = new RegExp(`^(${campo}):[ \\t]*([^\\r\\n]+)$`, 'm');
|
|
99
|
-
const m1 = nuevoFm.match(re1);
|
|
100
|
-
if (m1) {
|
|
101
|
-
const valorStr = m1[2];
|
|
102
|
-
const items = parsearValorCSV(valorStr);
|
|
103
|
-
if (items === null) continue; // ya es array, skip
|
|
104
|
-
const arrayInline = `[${items.join(', ')}]`;
|
|
105
|
-
const reemplazo = `${campo}: ${arrayInline}`;
|
|
106
|
-
if (m1[0] !== reemplazo) {
|
|
107
|
-
nuevoFm = nuevoFm.replace(re1, reemplazo);
|
|
108
|
-
cambios++;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (cambios === 0) return { contenido, cambios: 0 };
|
|
114
|
-
|
|
115
|
-
return { contenido: contenido.replace(fmCompleto, nuevoFm), cambios };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function migrarAgente(archivo) {
|
|
119
|
-
const contenido = fs.readFileSync(archivo, 'utf-8');
|
|
120
|
-
const { contenido: nuevo, cambios } = migrarFrontmatter(contenido);
|
|
121
|
-
|
|
122
|
-
if (cambios === 0) {
|
|
123
|
-
return { archivo: path.basename(archivo), status: 'sin-cambios' };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (DRY_RUN) {
|
|
127
|
-
return { archivo: path.basename(archivo), status: 'dry-run', cambios };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
fs.writeFileSync(archivo, nuevo, 'utf-8');
|
|
131
|
-
return { archivo: path.basename(archivo), status: 'migrado', cambios };
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function main() {
|
|
135
|
-
console.log(`Migrando CSV → array YAML${DRY_RUN ? ' (dry-run)' : ''}...\n`);
|
|
136
|
-
|
|
137
|
-
const archivos = fs
|
|
138
|
-
.readdirSync(AGENTES_DIR)
|
|
139
|
-
.filter((f) => f.endsWith('.md') && !f.startsWith('_'))
|
|
140
|
-
.map((f) => path.join(AGENTES_DIR, f));
|
|
141
|
-
|
|
142
|
-
const resultados = archivos.map(migrarAgente);
|
|
143
|
-
|
|
144
|
-
const stats = {
|
|
145
|
-
'sin-cambios': 0,
|
|
146
|
-
migrado: 0,
|
|
147
|
-
'dry-run': 0,
|
|
148
|
-
totalCambios: 0,
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
for (const r of resultados) {
|
|
152
|
-
stats[r.status] = (stats[r.status] || 0) + 1;
|
|
153
|
-
if (r.cambios) stats.totalCambios += r.cambios;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
console.log(`Sin cambios: ${stats['sin-cambios']}`);
|
|
157
|
-
console.log(`Migrados: ${stats.migrado}`);
|
|
158
|
-
console.log(`Dry-run: ${stats['dry-run']}`);
|
|
159
|
-
console.log(`Total ediciones: ${stats.totalCambios}`);
|
|
160
|
-
|
|
161
|
-
process.exit(0);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (require.main === module) {
|
|
165
|
-
main();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
module.exports = { parsearValorCSV, migrarFrontmatter };
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Migración 3A — convierte campos CSV a array YAML inline en frontmatter de
|
|
4
|
+
* agentes. Afecta `tools`, `skillsInvocables`, `skillsRestringidos`.
|
|
5
|
+
*
|
|
6
|
+
* Antes: tools: Read, Write, Edit, Bash
|
|
7
|
+
* Después: tools: [Read, Write, Edit, Bash]
|
|
8
|
+
*
|
|
9
|
+
* Razón: el schema declara `type: array` pero el uso real es CSV string. YAML
|
|
10
|
+
* estándar NO convierte CSV a array — el parser produce una sola string. Esto
|
|
11
|
+
* causó bugs históricos documentados en CLAUDE.md ("regla obligatoria CSV
|
|
12
|
+
* estricto"). Migrar a array inline elimina la ambigüedad.
|
|
13
|
+
*
|
|
14
|
+
* Idempotente: skip si ya es array.
|
|
15
|
+
*
|
|
16
|
+
* Casos especiales detectados en agentes:
|
|
17
|
+
* - skillsInvocables: <ninguno> → mantener literal
|
|
18
|
+
* - skillsRestringidos: ninguno → convertir a [] (array vacío)
|
|
19
|
+
* - skillsRestringidos: \n - x\n → ya es array YAML multilinea, mantener
|
|
20
|
+
*
|
|
21
|
+
* Uso:
|
|
22
|
+
* node scripts/migrar-csv-a-array.js [--dry-run]
|
|
23
|
+
*
|
|
24
|
+
* Zero-dependencies. Compatible Windows (CRLF-safe), Node 18+.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const fs = require('fs');
|
|
30
|
+
const path = require('path');
|
|
31
|
+
|
|
32
|
+
const AGENTES_DIR = path.join(__dirname, '..', 'agentes');
|
|
33
|
+
const DRY_RUN = process.argv.includes('--dry-run');
|
|
34
|
+
|
|
35
|
+
// Campos que migran de CSV a array
|
|
36
|
+
const CAMPOS_CSV = ['tools', 'skillsInvocables', 'skillsRestringidos'];
|
|
37
|
+
|
|
38
|
+
// Valores especiales que NO son listas y deben preservarse
|
|
39
|
+
const VALORES_LITERAL = new Set(['ninguno', 'ninguna', '<ninguno>', '<ninguna>', 'none', 'null']);
|
|
40
|
+
|
|
41
|
+
function parsearValorCSV(valorStr) {
|
|
42
|
+
// Detectar si ya es array inline `[a, b, c]`
|
|
43
|
+
if (/^\s*\[/.test(valorStr)) return null;
|
|
44
|
+
|
|
45
|
+
// Limpiar
|
|
46
|
+
const valor = valorStr.trim();
|
|
47
|
+
if (!valor) return [];
|
|
48
|
+
|
|
49
|
+
// Valor especial literal
|
|
50
|
+
if (VALORES_LITERAL.has(valor.toLowerCase())) return [];
|
|
51
|
+
|
|
52
|
+
// CSV split
|
|
53
|
+
return valor
|
|
54
|
+
.split(',')
|
|
55
|
+
.map((s) => s.trim())
|
|
56
|
+
.filter(Boolean);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function migrarFrontmatter(contenido) {
|
|
60
|
+
const match = contenido.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
61
|
+
if (!match) return { contenido, cambios: 0 };
|
|
62
|
+
|
|
63
|
+
const eol = match[0].includes('\r\n') ? '\r\n' : '\n';
|
|
64
|
+
const fmCompleto = match[0];
|
|
65
|
+
|
|
66
|
+
let nuevoFm = fmCompleto;
|
|
67
|
+
let cambios = 0;
|
|
68
|
+
|
|
69
|
+
for (const campo of CAMPOS_CSV) {
|
|
70
|
+
// Patrón 2 PRIMERO: array YAML multilínea
|
|
71
|
+
// skillsRestringidos:
|
|
72
|
+
// - angular-moderno
|
|
73
|
+
// - typescript-avanzado
|
|
74
|
+
// El campo está solo en su línea (sin valor) seguido de líneas con ` - X`
|
|
75
|
+
const re2 = new RegExp(`^(${campo}):[ \\t]*\\r?\\n((?:[ \\t]+-[ \\t]+[^\\r\\n]+\\r?\\n)+)`, 'm');
|
|
76
|
+
const m2 = nuevoFm.match(re2);
|
|
77
|
+
if (m2) {
|
|
78
|
+
const bloque = m2[2];
|
|
79
|
+
const items = bloque
|
|
80
|
+
.split(/\r?\n/)
|
|
81
|
+
.map((l) => l.trim())
|
|
82
|
+
.filter((l) => l.startsWith('- '))
|
|
83
|
+
.map((l) => l.slice(2).trim().replace(/^["']|["']$/g, ''));
|
|
84
|
+
if (items.length > 0) {
|
|
85
|
+
const arrayInline = `[${items.join(', ')}]`;
|
|
86
|
+
const reemplazo = `${campo}: ${arrayInline}${eol}`;
|
|
87
|
+
nuevoFm = nuevoFm.replace(re2, reemplazo);
|
|
88
|
+
cambios++;
|
|
89
|
+
}
|
|
90
|
+
continue; // procesado, no aplicar regex 1
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Patrón 1: campo en una sola línea con valor (CSV o array inline)
|
|
94
|
+
// tools: Read, Write
|
|
95
|
+
// skillsRestringidos: ninguno
|
|
96
|
+
// tools: [Read, Write] ← skip, ya es array
|
|
97
|
+
// CRÍTICO: usar [ \\t]* (NO \\s*) para no consumir newlines
|
|
98
|
+
const re1 = new RegExp(`^(${campo}):[ \\t]*([^\\r\\n]+)$`, 'm');
|
|
99
|
+
const m1 = nuevoFm.match(re1);
|
|
100
|
+
if (m1) {
|
|
101
|
+
const valorStr = m1[2];
|
|
102
|
+
const items = parsearValorCSV(valorStr);
|
|
103
|
+
if (items === null) continue; // ya es array, skip
|
|
104
|
+
const arrayInline = `[${items.join(', ')}]`;
|
|
105
|
+
const reemplazo = `${campo}: ${arrayInline}`;
|
|
106
|
+
if (m1[0] !== reemplazo) {
|
|
107
|
+
nuevoFm = nuevoFm.replace(re1, reemplazo);
|
|
108
|
+
cambios++;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (cambios === 0) return { contenido, cambios: 0 };
|
|
114
|
+
|
|
115
|
+
return { contenido: contenido.replace(fmCompleto, nuevoFm), cambios };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function migrarAgente(archivo) {
|
|
119
|
+
const contenido = fs.readFileSync(archivo, 'utf-8');
|
|
120
|
+
const { contenido: nuevo, cambios } = migrarFrontmatter(contenido);
|
|
121
|
+
|
|
122
|
+
if (cambios === 0) {
|
|
123
|
+
return { archivo: path.basename(archivo), status: 'sin-cambios' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (DRY_RUN) {
|
|
127
|
+
return { archivo: path.basename(archivo), status: 'dry-run', cambios };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fs.writeFileSync(archivo, nuevo, 'utf-8');
|
|
131
|
+
return { archivo: path.basename(archivo), status: 'migrado', cambios };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function main() {
|
|
135
|
+
console.log(`Migrando CSV → array YAML${DRY_RUN ? ' (dry-run)' : ''}...\n`);
|
|
136
|
+
|
|
137
|
+
const archivos = fs
|
|
138
|
+
.readdirSync(AGENTES_DIR)
|
|
139
|
+
.filter((f) => f.endsWith('.md') && !f.startsWith('_'))
|
|
140
|
+
.map((f) => path.join(AGENTES_DIR, f));
|
|
141
|
+
|
|
142
|
+
const resultados = archivos.map(migrarAgente);
|
|
143
|
+
|
|
144
|
+
const stats = {
|
|
145
|
+
'sin-cambios': 0,
|
|
146
|
+
migrado: 0,
|
|
147
|
+
'dry-run': 0,
|
|
148
|
+
totalCambios: 0,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
for (const r of resultados) {
|
|
152
|
+
stats[r.status] = (stats[r.status] || 0) + 1;
|
|
153
|
+
if (r.cambios) stats.totalCambios += r.cambios;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.log(`Sin cambios: ${stats['sin-cambios']}`);
|
|
157
|
+
console.log(`Migrados: ${stats.migrado}`);
|
|
158
|
+
console.log(`Dry-run: ${stats['dry-run']}`);
|
|
159
|
+
console.log(`Total ediciones: ${stats.totalCambios}`);
|
|
160
|
+
|
|
161
|
+
process.exit(0);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (require.main === module) {
|
|
165
|
+
main();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = { parsearValorCSV, migrarFrontmatter };
|