@saulwade/swl-ses 2.3.0 → 2.4.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 +241 -199
- package/README.md +597 -597
- package/agentes/_intent-spec.md +73 -73
- package/agentes/_propose-step.md +90 -90
- package/agentes/accesibilidad-wcag-swl.md +2 -2
- package/agentes/arquitecto-swl.md +2 -2
- package/agentes/auto-evolucion-swl.md +2 -2
- package/agentes/backend-api-swl.md +2 -2
- package/agentes/backend-csharp-swl.md +2 -2
- package/agentes/backend-go-swl.md +2 -2
- package/agentes/backend-java-swl.md +2 -2
- package/agentes/backend-node-swl.md +2 -2
- package/agentes/backend-python-swl.md +2 -2
- package/agentes/backend-rust-swl.md +2 -2
- package/agentes/backend-workers-swl.md +2 -2
- package/agentes/cloud-infra-swl.md +2 -2
- package/agentes/consolidador-swl.md +2 -2
- package/agentes/datos-swl.md +2 -2
- package/agentes/depurador-swl.md +2 -2
- package/agentes/devops-ci-swl.md +2 -2
- package/agentes/disenador-ui-swl.md +2 -2
- package/agentes/documentador-swl.md +2 -2
- package/agentes/frontend-angular-swl.md +2 -2
- package/agentes/frontend-css-swl.md +2 -2
- package/agentes/frontend-react-swl.md +2 -2
- package/agentes/frontend-swl.md +2 -2
- package/agentes/frontend-tailwind-swl.md +2 -2
- package/agentes/gh-fix-ci-swl.md +275 -275
- package/agentes/implementador-swl.md +2 -2
- package/agentes/investigador-swl.md +2 -2
- package/agentes/investigador-ux-swl.md +2 -2
- package/agentes/llm-apps-swl.md +2 -2
- package/agentes/migrador-swl.md +2 -2
- package/agentes/mobile-android-swl.md +2 -2
- package/agentes/mobile-cross-swl.md +2 -2
- package/agentes/mobile-ios-swl.md +2 -2
- package/agentes/mobile-testing-swl.md +2 -2
- package/agentes/nemesis-auditor-swl.md +1 -1
- package/agentes/notificador-swl.md +2 -2
- package/agentes/observabilidad-swl.md +2 -2
- package/agentes/orquestador-swl.md +41 -14
- package/agentes/pagos-swl.md +2 -2
- package/agentes/perfilador-usuario-swl.md +2 -2
- package/agentes/planificador-swl.md +2 -2
- package/agentes/producto-prd-swl.md +2 -2
- package/agentes/red-team-swl.md +218 -218
- package/agentes/release-manager-swl.md +2 -2
- package/agentes/rendimiento-swl.md +2 -2
- package/agentes/resolutor-build-swl.md +2 -2
- package/agentes/revisor-angular-swl.md +2 -2
- package/agentes/revisor-codigo-swl.md +36 -3
- package/agentes/revisor-csharp-swl.md +2 -2
- package/agentes/revisor-go-swl.md +2 -2
- package/agentes/revisor-java-swl.md +2 -2
- package/agentes/revisor-kotlin-swl.md +2 -2
- package/agentes/revisor-nextjs-swl.md +2 -2
- package/agentes/revisor-php-swl.md +2 -2
- package/agentes/revisor-react-swl.md +2 -2
- package/agentes/revisor-rust-swl.md +2 -2
- package/agentes/revisor-seguridad-swl.md +2 -2
- package/agentes/revisor-swift-swl.md +2 -2
- package/agentes/revisor-typescript-swl.md +2 -2
- package/agentes/sre-swl.md +2 -2
- package/agentes/tdd-qa-swl.md +2 -2
- package/comandos/swl/briefing.md +119 -119
- package/comandos/swl/contexto.md +0 -2
- package/comandos/swl/contribuir.md +233 -233
- package/comandos/swl/deuda-codigo.md +97 -0
- package/comandos/swl/predecir.md +139 -139
- package/comandos/swl/sesiones.md +1 -1
- package/gateway/agent-executor.js +1 -1
- package/gateway/lib/event-channel.js +191 -191
- package/habilidades/agent-deep-links/SKILL.md +148 -148
- package/habilidades/agentes-como-servicio/SKILL.md +2 -2
- package/habilidades/angular-moderno/SKILL.md +24 -1
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
- package/habilidades/backend-async-postgres-testing/SKILL.md +215 -215
- package/habilidades/backend-error-design/SKILL.md +221 -221
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/benchmark-memoria/SKILL.md +186 -186
- package/habilidades/calidad-anti-patrones-universales/SKILL.md +368 -368
- package/habilidades/calidad-contract-testing/SKILL.md +165 -165
- package/habilidades/calidad-mutation-testing/SKILL.md +170 -170
- package/habilidades/changelog-generator/scripts/parse-commits.js +367 -367
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
- package/habilidades/contenedores-docker/SKILL.md +3 -1
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/drift-detection/SKILL.md +179 -179
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +1 -1
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
- package/habilidades/eval-framework/SKILL.md +212 -212
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- package/habilidades/harness-claude-code/SKILL.md +4 -4
- package/habilidades/harness-claude-code/recursos/disciplina-harness-regla.md +253 -252
- package/habilidades/legacy-code-rescue/SKILL.md +268 -267
- package/habilidades/meta-skills-estandar/SKILL.md +1 -1
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +2 -2
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/postgresql-experto/SKILL.md +3 -1
- package/habilidades/prevencion-sobreingenieria/SKILL.md +70 -92
- package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
- package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -0
- package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -0
- package/habilidades/proceso-ddia-fundamentos/SKILL.md +255 -255
- package/habilidades/proceso-ddia-streaming/SKILL.md +231 -231
- package/habilidades/proceso-debate-adversarial/recursos/personas.md +105 -105
- package/habilidades/proceso-discovery-machote/SKILL.md +157 -157
- package/habilidades/proceso-dynamic-workflows/SKILL.md +138 -138
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -65
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -65
- package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
- package/habilidades/proceso-modular-split/SKILL.md +256 -256
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +2 -2
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
- package/habilidades/structured-outputs/SKILL.md +2 -2
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -83
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -85
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -94
- package/habilidades/swl-dashboard/SKILL.md +2 -2
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +1 -1
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +1 -1
- package/hooks/audit-trail.js +4 -4
- package/hooks/calidad-pre-commit.js +15 -11
- package/hooks/captura-acciones-post.js +3 -2
- package/hooks/captura-acciones-session.js +3 -2
- package/hooks/ciclo-evolucion-subagente.js +26 -26
- package/hooks/ciclo-evolucion.js +26 -26
- package/hooks/claudemd-bloat-detector.js +161 -161
- package/hooks/claudemd-duplicacion-detector.js +170 -170
- package/hooks/contexto-iteracion.js +145 -144
- package/hooks/contexto-subagente.js +68 -0
- package/hooks/guardrail-modelo.js +14 -4
- package/hooks/inyeccion-contexto.js +12 -12
- package/hooks/lib/agent-routing.js +107 -107
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/autonomia.js +208 -208
- package/hooks/lib/ciclo-evolucion.js +47 -47
- package/hooks/lib/deep-links.js +185 -185
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/etapa-auto-evolucion.js +701 -701
- package/hooks/lib/etapa-metricas.js +388 -388
- package/hooks/lib/etapa-perfil-usuario.js +376 -376
- package/hooks/lib/loop-telemetry.js +321 -321
- package/hooks/lib/merkle-audit.js +96 -96
- package/hooks/lib/model-router.js +2 -2
- package/hooks/lib/propose-step.js +358 -358
- 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/token-estimator.js +1 -0
- package/hooks/lib/toon-compressor.js +245 -245
- package/hooks/lib/usage-model.js +1 -1
- package/hooks/registro-turnos.js +210 -209
- package/hooks/session-briefing.js +98 -98
- package/hooks/spec-gate.js +212 -211
- package/hooks/sugerir-contribuir.js +2 -1
- package/hooks/sugerir-regenerar-inventario.js +171 -170
- package/hooks/tdd-gate.js +242 -241
- package/hooks/telemetria-skill-routing.js +100 -100
- package/hooks/validar-formato-post-subagente.js +140 -140
- package/hooks/validar-intent-spec.js +242 -242
- package/hooks/validar-memoria-hook.js +218 -218
- package/hooks/validar-planning-paths.js +134 -134
- package/instintos/autonomia.yaml +27 -27
- package/instintos/prompt-appendices.yaml +57 -57
- package/llms.txt +29 -29
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/canonical-hashes.json +2948 -1964
- package/manifiestos/hook-profiles.json +0 -2
- package/manifiestos/hooks-config.json +469 -477
- package/manifiestos/invariantes-criticos.json +30 -0
- package/manifiestos/modulos.json +1390 -1390
- package/manifiestos/planning-paths.json +44 -44
- package/manifiestos/skills-lock.json +1282 -1282
- package/package.json +93 -93
- 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 +369 -371
- package/reglas/accesibilidad.md +10 -10
- package/reglas/analisis-previo-tareas-grandes.md +172 -172
- package/reglas/api-diseno.md +9 -9
- package/reglas/arreglar-al-detectar.md +240 -240
- package/reglas/auditorias-documentales-estructurales.md +7 -7
- package/reglas/cloud-infra.md +8 -8
- package/reglas/consultar-vault-primero.md +195 -195
- package/reglas/debatir-antes-de-aceptar.md +158 -158
- package/reglas/fragmentos-compartidos.md +183 -183
- package/reglas/hooks.md +6 -6
- package/reglas/intent-engineering.md +218 -218
- package/reglas/markitdown.md +8 -8
- package/reglas/monitor-ci.md +309 -309
- package/reglas/patrones.md +6 -6
- package/reglas/sesiones-paralelas.md +180 -180
- package/reglas/sin-duplicacion-reglas-globales.md +182 -182
- package/reglas/skills-estandar.md +6 -6
- package/reglas/testing.md +7 -7
- package/reglas/tests-cleanup.md +224 -224
- package/reglas/usar-code-review-graph.md +155 -155
- package/reglas/usar-context7.md +226 -226
- package/reglas/verificar-citas-normativas.md +548 -548
- package/schemas/agent-frontmatter.schema.json +5 -3
- package/schemas/agent-message.schema.json +73 -73
- package/schemas/agent-output-implementacion.schema.json +114 -114
- package/schemas/agent-output-planificacion.schema.json +150 -150
- package/schemas/agent-output-review.schema.json +98 -98
- package/schemas/diary-entry.schema.json +112 -112
- package/schemas/hook-profiles.schema.json +54 -54
- package/schemas/hooks-config.schema.json +89 -89
- package/schemas/modulos.schema.json +38 -38
- package/schemas/perfiles.schema.json +36 -36
- package/schemas/plugin.schema.json +77 -77
- package/schemas/skill-evals.schema.json +119 -119
- package/schemas/skill-frontmatter.schema.json +245 -245
- 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/cli/aprobar-plan.js +73 -73
- package/scripts/cli/briefing.js +23 -23
- package/scripts/cli/ciclo-evolucion.js +26 -26
- package/scripts/cli/configurar-ci.js +40 -40
- package/scripts/cli/derivar-feature-list.js +25 -25
- package/scripts/cli/detectar-host.js +27 -27
- package/scripts/cli/diary-entry.js +69 -69
- package/scripts/cli/execution-state.js +18 -18
- package/scripts/cli/gateway-notify.js +41 -41
- package/scripts/cli/liberar-fase.js +42 -42
- package/scripts/cli/loop-telemetry.js +125 -125
- package/scripts/cli/mark-evolved.js +56 -56
- package/scripts/cli/metricas-dora.js +26 -26
- package/scripts/cli/near-duplicate.js +55 -55
- package/scripts/cli/notificaciones.js +123 -123
- package/scripts/cli/propose-step.js +29 -29
- package/scripts/cli/schedule-parse.js +19 -19
- package/scripts/cli/sugerir-modelo.js +20 -20
- package/scripts/cli/verificar-plan.js +36 -36
- package/scripts/cli/verificar-trazabilidad.js +35 -35
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/field-report.js +199 -199
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-matriz-lenguajes.js +271 -271
- package/scripts/instalador.js +4 -1
- package/scripts/lib/artefactos-python.js +43 -43
- package/scripts/lib/auditar-invocaciones-comandos.js +104 -104
- package/scripts/lib/benchmark-metrics.js +160 -160
- package/scripts/lib/budget-enforcer.js +252 -252
- package/scripts/lib/ci-reader.js +193 -193
- package/scripts/lib/claude-sessions.js +1 -0
- package/scripts/lib/configurar-ci.js +380 -380
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-host-swl.js +175 -175
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/detector-autoduplicacion-intra-archivo.js +234 -234
- package/scripts/lib/detector-reglas-duplicadas.js +220 -220
- 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/evidencia-release.js +322 -322
- package/scripts/lib/gate-hooks-requires.js +249 -249
- package/scripts/lib/gate-licencias.js +212 -212
- package/scripts/lib/git-metricas.js +257 -257
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/metricas-dora.js +204 -204
- package/scripts/lib/npm-version.js +261 -261
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/plan-lock.js +275 -275
- package/scripts/lib/pr-analyzer.js +399 -399
- package/scripts/lib/preservar-usuario.js +39 -5
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/reglas-globales-conocidas.json +180 -180
- package/scripts/lib/resolver-plan-fase.js +37 -37
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/schema-version.js +164 -164
- package/scripts/lib/scoring-instintos.js +277 -277
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/lib/tool-cost-analyzer.js +1 -0
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +200 -200
- package/scripts/publicar.js +497 -497
- package/scripts/run-eval.js +141 -141
- package/scripts/tui/componentes/selector-multi.js +189 -189
- package/scripts/tui/componentes/selector-unico.js +158 -158
- package/scripts/tui/ejecutores.js +375 -375
- package/scripts/tui/index.js +162 -162
- package/scripts/tui/lib/colores.js +129 -129
- package/scripts/tui/lib/render.js +264 -264
- package/scripts/tui/lib/teclas.js +113 -113
- package/scripts/tui/pantallas/inspect.js +173 -173
- package/scripts/tui/pantallas/install-wizard.js +334 -334
- package/scripts/tui/pantallas/menu-principal.js +52 -52
- package/scripts/tui/pantallas/progreso.js +274 -274
- package/scripts/tui/pantallas/resumen.js +132 -132
- package/scripts/tui/pantallas/uninstall-wizard.js +208 -208
- package/scripts/tui/pantallas/update-wizard.js +232 -232
- package/scripts/tui/pantallas/welcome.js +187 -187
- package/scripts/validar-userland-vacio.js +110 -110
- package/scripts/validar.js +1 -1
- package/scripts/verificar-release.js +51 -0
- package/hooks/lib/context-compressor.js +0 -657
- package/hooks/linea-estado.js +0 -326
- package/hooks/monitor-contexto.js +0 -373
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* auditar-invocaciones-comandos.js
|
|
5
|
-
*
|
|
6
|
-
* Gate anti-regresión de la clase de bug "invocación relativa al proyecto en
|
|
7
|
-
* comandos user-facing" (ver docs/invocacion-cli-cross-scope.md).
|
|
8
|
-
*
|
|
9
|
-
* Un comando que corre en el proyecto del usuario NUNCA debe invocar scripts SWL
|
|
10
|
-
* con ruta relativa al proyecto (`node scripts/lib/...`, `node hooks/...`,
|
|
11
|
-
* `require('./scripts/...')`): esas rutas no existen downstream. Debe usar el
|
|
12
|
-
* subcomando del CLI (`swl-ses <sub>` / `npx ... <sub>` / `node scripts/cli/<sub>.js`).
|
|
13
|
-
*
|
|
14
|
-
* Solo escanea bloques de código (``` ... ```) para no marcar menciones
|
|
15
|
-
* prohibitivas en prosa. Excluye `scripts/cli/` (forma repo-madre sancionada).
|
|
16
|
-
*
|
|
17
|
-
* Función pura + entrypoint CLI con exit 1 si hay violaciones.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
const fs = require('node:fs');
|
|
21
|
-
const path = require('node:path');
|
|
22
|
-
|
|
23
|
-
// Comandos que corren SOLO en el repo madre de swl-ses (el CWD ES el repo, así
|
|
24
|
-
// que `node scripts/...` relativo es correcto). NO son user-facing.
|
|
25
|
-
const SELF_DEV = new Set([
|
|
26
|
-
'release',
|
|
27
|
-
'contribuir',
|
|
28
|
-
'evaluar-skill',
|
|
29
|
-
'reflect-skills',
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
// Patrones de invocación relativa al proyecto que se rompen downstream.
|
|
33
|
-
// Se evalúan SOLO dentro de bloques de código.
|
|
34
|
-
const PATRONES = [
|
|
35
|
-
{ re: /\bnode\s+(?:\.\/)?scripts\/(?!cli\/)/, desc: 'node scripts/ (usa swl-ses <sub>)' },
|
|
36
|
-
{ re: /\bnode\s+(?:\.\/)?hooks\//, desc: 'node hooks/ (usa swl-ses <sub>)' },
|
|
37
|
-
{ re: /require\(\s*['"]\.\.?\/scripts\//, desc: "require('./scripts/ inline" },
|
|
38
|
-
{ re: /require\(\s*['"]\.\.?\/hooks\//, desc: "require('./hooks/ inline" },
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @param {string} [comandosDir] default: comandos/swl relativo al repo de este script.
|
|
43
|
-
* @returns {{ok:boolean, violaciones:Array<{comando:string,linea:number,texto:string,patron:string}>, escaneados:number}}
|
|
44
|
-
*/
|
|
45
|
-
function auditarInvocacionesComandos(comandosDir) {
|
|
46
|
-
const dir = comandosDir || path.join(__dirname, '..', '..', 'comandos', 'swl');
|
|
47
|
-
const violaciones = [];
|
|
48
|
-
let escaneados = 0;
|
|
49
|
-
|
|
50
|
-
let archivos;
|
|
51
|
-
try {
|
|
52
|
-
archivos = fs.readdirSync(dir).filter((f) => f.endsWith('.md') && !f.startsWith('_'));
|
|
53
|
-
} catch {
|
|
54
|
-
return { ok: true, violaciones, escaneados: 0 };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
for (const archivo of archivos) {
|
|
58
|
-
const comando = archivo.replace(/\.md$/, '');
|
|
59
|
-
if (SELF_DEV.has(comando)) continue;
|
|
60
|
-
escaneados++;
|
|
61
|
-
|
|
62
|
-
const contenido = fs.readFileSync(path.join(dir, archivo), 'utf8');
|
|
63
|
-
const lineas = contenido.split('\n');
|
|
64
|
-
let dentroCodigo = false;
|
|
65
|
-
|
|
66
|
-
for (let i = 0; i < lineas.length; i++) {
|
|
67
|
-
const linea = lineas[i];
|
|
68
|
-
if (/^\s*```/.test(linea)) {
|
|
69
|
-
dentroCodigo = !dentroCodigo;
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (!dentroCodigo) continue;
|
|
73
|
-
for (const { re, desc } of PATRONES) {
|
|
74
|
-
if (re.test(linea)) {
|
|
75
|
-
violaciones.push({
|
|
76
|
-
comando,
|
|
77
|
-
linea: i + 1,
|
|
78
|
-
texto: linea.trim(),
|
|
79
|
-
patron: desc,
|
|
80
|
-
});
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return { ok: violaciones.length === 0, violaciones, escaneados };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
module.exports = { auditarInvocacionesComandos, SELF_DEV };
|
|
91
|
-
|
|
92
|
-
if (require.main === module) {
|
|
93
|
-
const r = auditarInvocacionesComandos();
|
|
94
|
-
if (r.ok) {
|
|
95
|
-
console.log(`[OK] invocaciones-comandos — ${r.escaneados} comandos user-facing sin rutas relativas al proyecto`);
|
|
96
|
-
process.exit(0);
|
|
97
|
-
}
|
|
98
|
-
console.error(`[FALLA] invocaciones-comandos — ${r.violaciones.length} invocación(es) relativa(s) al proyecto en comandos user-facing:`);
|
|
99
|
-
for (const v of r.violaciones) {
|
|
100
|
-
console.error(` ${v.comando}.md:${v.linea} [${v.patron}] ${v.texto}`);
|
|
101
|
-
}
|
|
102
|
-
console.error('\nUsa el patrón cross-scope (docs/invocacion-cli-cross-scope.md): swl-ses <sub> / npx ... <sub> / node scripts/cli/<sub>.js');
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* auditar-invocaciones-comandos.js
|
|
5
|
+
*
|
|
6
|
+
* Gate anti-regresión de la clase de bug "invocación relativa al proyecto en
|
|
7
|
+
* comandos user-facing" (ver docs/invocacion-cli-cross-scope.md).
|
|
8
|
+
*
|
|
9
|
+
* Un comando que corre en el proyecto del usuario NUNCA debe invocar scripts SWL
|
|
10
|
+
* con ruta relativa al proyecto (`node scripts/lib/...`, `node hooks/...`,
|
|
11
|
+
* `require('./scripts/...')`): esas rutas no existen downstream. Debe usar el
|
|
12
|
+
* subcomando del CLI (`swl-ses <sub>` / `npx ... <sub>` / `node scripts/cli/<sub>.js`).
|
|
13
|
+
*
|
|
14
|
+
* Solo escanea bloques de código (``` ... ```) para no marcar menciones
|
|
15
|
+
* prohibitivas en prosa. Excluye `scripts/cli/` (forma repo-madre sancionada).
|
|
16
|
+
*
|
|
17
|
+
* Función pura + entrypoint CLI con exit 1 si hay violaciones.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('node:fs');
|
|
21
|
+
const path = require('node:path');
|
|
22
|
+
|
|
23
|
+
// Comandos que corren SOLO en el repo madre de swl-ses (el CWD ES el repo, así
|
|
24
|
+
// que `node scripts/...` relativo es correcto). NO son user-facing.
|
|
25
|
+
const SELF_DEV = new Set([
|
|
26
|
+
'release',
|
|
27
|
+
'contribuir',
|
|
28
|
+
'evaluar-skill',
|
|
29
|
+
'reflect-skills',
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
// Patrones de invocación relativa al proyecto que se rompen downstream.
|
|
33
|
+
// Se evalúan SOLO dentro de bloques de código.
|
|
34
|
+
const PATRONES = [
|
|
35
|
+
{ re: /\bnode\s+(?:\.\/)?scripts\/(?!cli\/)/, desc: 'node scripts/ (usa swl-ses <sub>)' },
|
|
36
|
+
{ re: /\bnode\s+(?:\.\/)?hooks\//, desc: 'node hooks/ (usa swl-ses <sub>)' },
|
|
37
|
+
{ re: /require\(\s*['"]\.\.?\/scripts\//, desc: "require('./scripts/ inline" },
|
|
38
|
+
{ re: /require\(\s*['"]\.\.?\/hooks\//, desc: "require('./hooks/ inline" },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} [comandosDir] default: comandos/swl relativo al repo de este script.
|
|
43
|
+
* @returns {{ok:boolean, violaciones:Array<{comando:string,linea:number,texto:string,patron:string}>, escaneados:number}}
|
|
44
|
+
*/
|
|
45
|
+
function auditarInvocacionesComandos(comandosDir) {
|
|
46
|
+
const dir = comandosDir || path.join(__dirname, '..', '..', 'comandos', 'swl');
|
|
47
|
+
const violaciones = [];
|
|
48
|
+
let escaneados = 0;
|
|
49
|
+
|
|
50
|
+
let archivos;
|
|
51
|
+
try {
|
|
52
|
+
archivos = fs.readdirSync(dir).filter((f) => f.endsWith('.md') && !f.startsWith('_'));
|
|
53
|
+
} catch {
|
|
54
|
+
return { ok: true, violaciones, escaneados: 0 };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const archivo of archivos) {
|
|
58
|
+
const comando = archivo.replace(/\.md$/, '');
|
|
59
|
+
if (SELF_DEV.has(comando)) continue;
|
|
60
|
+
escaneados++;
|
|
61
|
+
|
|
62
|
+
const contenido = fs.readFileSync(path.join(dir, archivo), 'utf8');
|
|
63
|
+
const lineas = contenido.split('\n');
|
|
64
|
+
let dentroCodigo = false;
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < lineas.length; i++) {
|
|
67
|
+
const linea = lineas[i];
|
|
68
|
+
if (/^\s*```/.test(linea)) {
|
|
69
|
+
dentroCodigo = !dentroCodigo;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!dentroCodigo) continue;
|
|
73
|
+
for (const { re, desc } of PATRONES) {
|
|
74
|
+
if (re.test(linea)) {
|
|
75
|
+
violaciones.push({
|
|
76
|
+
comando,
|
|
77
|
+
linea: i + 1,
|
|
78
|
+
texto: linea.trim(),
|
|
79
|
+
patron: desc,
|
|
80
|
+
});
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { ok: violaciones.length === 0, violaciones, escaneados };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = { auditarInvocacionesComandos, SELF_DEV };
|
|
91
|
+
|
|
92
|
+
if (require.main === module) {
|
|
93
|
+
const r = auditarInvocacionesComandos();
|
|
94
|
+
if (r.ok) {
|
|
95
|
+
console.log(`[OK] invocaciones-comandos — ${r.escaneados} comandos user-facing sin rutas relativas al proyecto`);
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
console.error(`[FALLA] invocaciones-comandos — ${r.violaciones.length} invocación(es) relativa(s) al proyecto en comandos user-facing:`);
|
|
99
|
+
for (const v of r.violaciones) {
|
|
100
|
+
console.error(` ${v.comando}.md:${v.linea} [${v.patron}] ${v.texto}`);
|
|
101
|
+
}
|
|
102
|
+
console.error('\nUsa el patrón cross-scope (docs/invocacion-cli-cross-scope.md): swl-ses <sub> / npx ... <sub> / node scripts/cli/<sub>.js');
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* benchmark-metrics.js — Métricas de retrieval para benchmark de memoria SWL.
|
|
5
|
-
*
|
|
6
|
-
* Patrón adoptado de `temp/agentmemory-main/benchmark/longmemeval-bench.ts`.
|
|
7
|
-
* Funciones puras zero-deps. Adaptado a IDs SWL (aprendizaje, sesion,
|
|
8
|
-
* instinto) en lugar de session_id de agentmemory.
|
|
9
|
-
*
|
|
10
|
-
* Métricas:
|
|
11
|
-
* - recallAt(k): 1.0 si al menos un gold ID está en los top-k, sino 0.0
|
|
12
|
-
* - precisionAt(k): proporción de top-k que son gold
|
|
13
|
-
* - mrr: Mean Reciprocal Rank (1/rank del primer gold encontrado)
|
|
14
|
-
* - ndcgAt(k): Normalized Discounted Cumulative Gain
|
|
15
|
-
*
|
|
16
|
-
* @module scripts/lib/benchmark-metrics
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
function asSet(arr) {
|
|
22
|
-
return new Set(Array.isArray(arr) ? arr : []);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// ── métricas individuales ─────────────────────────────────────────────────────
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Recall @ k: 1.0 si ALGÚN id gold está en los primeros k retrieved.
|
|
29
|
-
*
|
|
30
|
-
* @param {string[]} retrievedIds - IDs ordenados (mejor primero).
|
|
31
|
-
* @param {string[]} goldIds - IDs correctos esperados.
|
|
32
|
-
* @param {number} k
|
|
33
|
-
* @returns {number} 0 o 1
|
|
34
|
-
*/
|
|
35
|
-
function recallAt(retrievedIds, goldIds, k) {
|
|
36
|
-
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds)) return 0;
|
|
37
|
-
const topK = new Set(retrievedIds.slice(0, k));
|
|
38
|
-
return goldIds.some(g => topK.has(g)) ? 1.0 : 0.0;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Precision @ k: proporción de los primeros k retrieved que son gold.
|
|
43
|
-
*
|
|
44
|
-
* @param {string[]} retrievedIds
|
|
45
|
-
* @param {string[]} goldIds
|
|
46
|
-
* @param {number} k
|
|
47
|
-
* @returns {number} en [0, 1]
|
|
48
|
-
*/
|
|
49
|
-
function precisionAt(retrievedIds, goldIds, k) {
|
|
50
|
-
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds) || k <= 0) return 0;
|
|
51
|
-
const goldSet = asSet(goldIds);
|
|
52
|
-
const topK = retrievedIds.slice(0, k);
|
|
53
|
-
if (topK.length === 0) return 0;
|
|
54
|
-
const hits = topK.filter(id => goldSet.has(id)).length;
|
|
55
|
-
return hits / topK.length;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Mean Reciprocal Rank: 1/rank del primer gold encontrado, o 0 si ninguno.
|
|
60
|
-
*
|
|
61
|
-
* @param {string[]} retrievedIds
|
|
62
|
-
* @param {string[]} goldIds
|
|
63
|
-
* @returns {number} en [0, 1]
|
|
64
|
-
*/
|
|
65
|
-
function mrr(retrievedIds, goldIds) {
|
|
66
|
-
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds)) return 0;
|
|
67
|
-
const goldSet = asSet(goldIds);
|
|
68
|
-
for (let i = 0; i < retrievedIds.length; i++) {
|
|
69
|
-
if (goldSet.has(retrievedIds[i])) {
|
|
70
|
-
return 1 / (i + 1);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function dcg(relevancias, k) {
|
|
77
|
-
let suma = 0;
|
|
78
|
-
for (let i = 0; i < Math.min(k, relevancias.length); i++) {
|
|
79
|
-
suma += (relevancias[i] ? 1 : 0) / Math.log2(i + 2);
|
|
80
|
-
}
|
|
81
|
-
return suma;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Normalized Discounted Cumulative Gain @ k.
|
|
86
|
-
*
|
|
87
|
-
* @param {string[]} retrievedIds
|
|
88
|
-
* @param {string[]} goldIds
|
|
89
|
-
* @param {number} k
|
|
90
|
-
* @returns {number} en [0, 1]
|
|
91
|
-
*/
|
|
92
|
-
function ndcgAt(retrievedIds, goldIds, k) {
|
|
93
|
-
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds) || k <= 0) return 0;
|
|
94
|
-
const goldSet = asSet(goldIds);
|
|
95
|
-
const rels = retrievedIds.slice(0, k).map(id => goldSet.has(id));
|
|
96
|
-
const idealRels = Array.from({ length: Math.min(k, goldSet.size) }, () => true);
|
|
97
|
-
const idealDCG = dcg(idealRels, k);
|
|
98
|
-
if (idealDCG === 0) return 0;
|
|
99
|
-
return dcg(rels, k) / idealDCG;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ── agregados ─────────────────────────────────────────────────────────────────
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Calcula el conjunto completo de métricas para una query.
|
|
106
|
-
*
|
|
107
|
-
* @param {string[]} retrievedIds
|
|
108
|
-
* @param {string[]} goldIds
|
|
109
|
-
* @returns {{ recall_at_5, recall_at_10, recall_at_20, mrr, ndcg_at_10, precision_at_5 }}
|
|
110
|
-
*/
|
|
111
|
-
function calcularMetricas(retrievedIds, goldIds) {
|
|
112
|
-
return {
|
|
113
|
-
recall_at_5: recallAt(retrievedIds, goldIds, 5),
|
|
114
|
-
recall_at_10: recallAt(retrievedIds, goldIds, 10),
|
|
115
|
-
recall_at_20: recallAt(retrievedIds, goldIds, 20),
|
|
116
|
-
mrr: mrr(retrievedIds, goldIds),
|
|
117
|
-
ndcg_at_10: ndcgAt(retrievedIds, goldIds, 10),
|
|
118
|
-
precision_at_5: precisionAt(retrievedIds, goldIds, 5),
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Promedia métricas sobre múltiples queries.
|
|
124
|
-
*
|
|
125
|
-
* @param {Array<object>} resultados - Array de objetos producidos por calcularMetricas().
|
|
126
|
-
* @returns {object} Promedios con campo `n` (cantidad de queries).
|
|
127
|
-
*/
|
|
128
|
-
function promediar(resultados) {
|
|
129
|
-
if (!Array.isArray(resultados) || resultados.length === 0) {
|
|
130
|
-
return {
|
|
131
|
-
n: 0,
|
|
132
|
-
recall_at_5: 0,
|
|
133
|
-
recall_at_10: 0,
|
|
134
|
-
recall_at_20: 0,
|
|
135
|
-
mrr: 0,
|
|
136
|
-
ndcg_at_10: 0,
|
|
137
|
-
precision_at_5: 0,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const claves = ['recall_at_5', 'recall_at_10', 'recall_at_20', 'mrr', 'ndcg_at_10', 'precision_at_5'];
|
|
142
|
-
const promedio = { n: resultados.length };
|
|
143
|
-
for (const k of claves) {
|
|
144
|
-
const sum = resultados.reduce((a, r) => a + (r[k] || 0), 0);
|
|
145
|
-
promedio[k] = sum / resultados.length;
|
|
146
|
-
}
|
|
147
|
-
return promedio;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// ── exports ───────────────────────────────────────────────────────────────────
|
|
151
|
-
|
|
152
|
-
module.exports = {
|
|
153
|
-
recallAt,
|
|
154
|
-
precisionAt,
|
|
155
|
-
mrr,
|
|
156
|
-
ndcgAt,
|
|
157
|
-
dcg,
|
|
158
|
-
calcularMetricas,
|
|
159
|
-
promediar,
|
|
160
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* benchmark-metrics.js — Métricas de retrieval para benchmark de memoria SWL.
|
|
5
|
+
*
|
|
6
|
+
* Patrón adoptado de `temp/agentmemory-main/benchmark/longmemeval-bench.ts`.
|
|
7
|
+
* Funciones puras zero-deps. Adaptado a IDs SWL (aprendizaje, sesion,
|
|
8
|
+
* instinto) en lugar de session_id de agentmemory.
|
|
9
|
+
*
|
|
10
|
+
* Métricas:
|
|
11
|
+
* - recallAt(k): 1.0 si al menos un gold ID está en los top-k, sino 0.0
|
|
12
|
+
* - precisionAt(k): proporción de top-k que son gold
|
|
13
|
+
* - mrr: Mean Reciprocal Rank (1/rank del primer gold encontrado)
|
|
14
|
+
* - ndcgAt(k): Normalized Discounted Cumulative Gain
|
|
15
|
+
*
|
|
16
|
+
* @module scripts/lib/benchmark-metrics
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
function asSet(arr) {
|
|
22
|
+
return new Set(Array.isArray(arr) ? arr : []);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ── métricas individuales ─────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Recall @ k: 1.0 si ALGÚN id gold está en los primeros k retrieved.
|
|
29
|
+
*
|
|
30
|
+
* @param {string[]} retrievedIds - IDs ordenados (mejor primero).
|
|
31
|
+
* @param {string[]} goldIds - IDs correctos esperados.
|
|
32
|
+
* @param {number} k
|
|
33
|
+
* @returns {number} 0 o 1
|
|
34
|
+
*/
|
|
35
|
+
function recallAt(retrievedIds, goldIds, k) {
|
|
36
|
+
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds)) return 0;
|
|
37
|
+
const topK = new Set(retrievedIds.slice(0, k));
|
|
38
|
+
return goldIds.some(g => topK.has(g)) ? 1.0 : 0.0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Precision @ k: proporción de los primeros k retrieved que son gold.
|
|
43
|
+
*
|
|
44
|
+
* @param {string[]} retrievedIds
|
|
45
|
+
* @param {string[]} goldIds
|
|
46
|
+
* @param {number} k
|
|
47
|
+
* @returns {number} en [0, 1]
|
|
48
|
+
*/
|
|
49
|
+
function precisionAt(retrievedIds, goldIds, k) {
|
|
50
|
+
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds) || k <= 0) return 0;
|
|
51
|
+
const goldSet = asSet(goldIds);
|
|
52
|
+
const topK = retrievedIds.slice(0, k);
|
|
53
|
+
if (topK.length === 0) return 0;
|
|
54
|
+
const hits = topK.filter(id => goldSet.has(id)).length;
|
|
55
|
+
return hits / topK.length;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Mean Reciprocal Rank: 1/rank del primer gold encontrado, o 0 si ninguno.
|
|
60
|
+
*
|
|
61
|
+
* @param {string[]} retrievedIds
|
|
62
|
+
* @param {string[]} goldIds
|
|
63
|
+
* @returns {number} en [0, 1]
|
|
64
|
+
*/
|
|
65
|
+
function mrr(retrievedIds, goldIds) {
|
|
66
|
+
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds)) return 0;
|
|
67
|
+
const goldSet = asSet(goldIds);
|
|
68
|
+
for (let i = 0; i < retrievedIds.length; i++) {
|
|
69
|
+
if (goldSet.has(retrievedIds[i])) {
|
|
70
|
+
return 1 / (i + 1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function dcg(relevancias, k) {
|
|
77
|
+
let suma = 0;
|
|
78
|
+
for (let i = 0; i < Math.min(k, relevancias.length); i++) {
|
|
79
|
+
suma += (relevancias[i] ? 1 : 0) / Math.log2(i + 2);
|
|
80
|
+
}
|
|
81
|
+
return suma;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Normalized Discounted Cumulative Gain @ k.
|
|
86
|
+
*
|
|
87
|
+
* @param {string[]} retrievedIds
|
|
88
|
+
* @param {string[]} goldIds
|
|
89
|
+
* @param {number} k
|
|
90
|
+
* @returns {number} en [0, 1]
|
|
91
|
+
*/
|
|
92
|
+
function ndcgAt(retrievedIds, goldIds, k) {
|
|
93
|
+
if (!Array.isArray(retrievedIds) || !Array.isArray(goldIds) || k <= 0) return 0;
|
|
94
|
+
const goldSet = asSet(goldIds);
|
|
95
|
+
const rels = retrievedIds.slice(0, k).map(id => goldSet.has(id));
|
|
96
|
+
const idealRels = Array.from({ length: Math.min(k, goldSet.size) }, () => true);
|
|
97
|
+
const idealDCG = dcg(idealRels, k);
|
|
98
|
+
if (idealDCG === 0) return 0;
|
|
99
|
+
return dcg(rels, k) / idealDCG;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ── agregados ─────────────────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Calcula el conjunto completo de métricas para una query.
|
|
106
|
+
*
|
|
107
|
+
* @param {string[]} retrievedIds
|
|
108
|
+
* @param {string[]} goldIds
|
|
109
|
+
* @returns {{ recall_at_5, recall_at_10, recall_at_20, mrr, ndcg_at_10, precision_at_5 }}
|
|
110
|
+
*/
|
|
111
|
+
function calcularMetricas(retrievedIds, goldIds) {
|
|
112
|
+
return {
|
|
113
|
+
recall_at_5: recallAt(retrievedIds, goldIds, 5),
|
|
114
|
+
recall_at_10: recallAt(retrievedIds, goldIds, 10),
|
|
115
|
+
recall_at_20: recallAt(retrievedIds, goldIds, 20),
|
|
116
|
+
mrr: mrr(retrievedIds, goldIds),
|
|
117
|
+
ndcg_at_10: ndcgAt(retrievedIds, goldIds, 10),
|
|
118
|
+
precision_at_5: precisionAt(retrievedIds, goldIds, 5),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Promedia métricas sobre múltiples queries.
|
|
124
|
+
*
|
|
125
|
+
* @param {Array<object>} resultados - Array de objetos producidos por calcularMetricas().
|
|
126
|
+
* @returns {object} Promedios con campo `n` (cantidad de queries).
|
|
127
|
+
*/
|
|
128
|
+
function promediar(resultados) {
|
|
129
|
+
if (!Array.isArray(resultados) || resultados.length === 0) {
|
|
130
|
+
return {
|
|
131
|
+
n: 0,
|
|
132
|
+
recall_at_5: 0,
|
|
133
|
+
recall_at_10: 0,
|
|
134
|
+
recall_at_20: 0,
|
|
135
|
+
mrr: 0,
|
|
136
|
+
ndcg_at_10: 0,
|
|
137
|
+
precision_at_5: 0,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const claves = ['recall_at_5', 'recall_at_10', 'recall_at_20', 'mrr', 'ndcg_at_10', 'precision_at_5'];
|
|
142
|
+
const promedio = { n: resultados.length };
|
|
143
|
+
for (const k of claves) {
|
|
144
|
+
const sum = resultados.reduce((a, r) => a + (r[k] || 0), 0);
|
|
145
|
+
promedio[k] = sum / resultados.length;
|
|
146
|
+
}
|
|
147
|
+
return promedio;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ── exports ───────────────────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
module.exports = {
|
|
153
|
+
recallAt,
|
|
154
|
+
precisionAt,
|
|
155
|
+
mrr,
|
|
156
|
+
ndcgAt,
|
|
157
|
+
dcg,
|
|
158
|
+
calcularMetricas,
|
|
159
|
+
promediar,
|
|
160
|
+
};
|