@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,170 +1,171 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Hook: sugerir-regenerar-inventario.js
|
|
6
|
-
* Tipo: PostToolUse (aplica a: Write, Edit, MultiEdit)
|
|
7
|
-
*
|
|
8
|
-
* Cuando el agente edita o crea un componente registrado en INVENTARIO.md
|
|
9
|
-
* (agentes, habilidades, comandos, hooks o reglas), sugiere — sin bloquear —
|
|
10
|
-
* regenerar el inventario antes del próximo commit.
|
|
11
|
-
*
|
|
12
|
-
* Motivado por el drift recurrente detectado el 2026-04-29: tras agregar el
|
|
13
|
-
* skill `harness-claude-code` el inventario quedó stale en 5 archivos canónicos
|
|
14
|
-
* porque nadie regeneró `INVENTARIO.md` después de la edición. La regeneración
|
|
15
|
-
* es 1 comando (`node scripts/generar-inventario.js`) pero es fácil olvidarla.
|
|
16
|
-
*
|
|
17
|
-
* Cooldown: una vez por sesión por carpeta afectada para no spammear cuando
|
|
18
|
-
* el agente edita docenas de archivos seguidos. Estado persistente en
|
|
19
|
-
* `.planning/inventario-aviso-state.json`.
|
|
20
|
-
*
|
|
21
|
-
* Resultado:
|
|
22
|
-
* - Edición sobre carpeta inventariada y sin cooldown → sugerencia en stdout (exit 0)
|
|
23
|
-
* - Edición sobre carpeta no inventariada → sin output (exit 0)
|
|
24
|
-
* - Error interno → sin output (nunca bloquear)
|
|
25
|
-
*
|
|
26
|
-
* Activo por defecto. Para silenciar: SWL_SUGERIR_REGEN_INVENTARIO=0.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
const fs = require('fs');
|
|
30
|
-
const path = require('path');
|
|
31
|
-
|
|
32
|
-
// Carpetas cuyo cambio invalida los contadores de INVENTARIO.md
|
|
33
|
-
const CARPETAS_INVENTARIADAS = [
|
|
34
|
-
{ ruta: 'agentes/', etiqueta: 'agentes' },
|
|
35
|
-
{ ruta: 'habilidades/', etiqueta: 'habilidades' },
|
|
36
|
-
{ ruta: 'comandos/swl/', etiqueta: 'comandos' },
|
|
37
|
-
{ ruta: 'hooks/', etiqueta: 'hooks', excluir: ['hooks/lib/'] },
|
|
38
|
-
{ ruta: 'reglas/', etiqueta: 'reglas' },
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const STATE_FILE = path.join(process.cwd(), '.planning', 'inventario-aviso-state.json');
|
|
42
|
-
const COOLDOWN_MS = 30 * 60 * 1000; // 30 min
|
|
43
|
-
|
|
44
|
-
function normalizarSeparadores(p) {
|
|
45
|
-
return String(p).replace(/\\/g, '/');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function detectarCarpeta(rutaRaw) {
|
|
49
|
-
if (!rutaRaw) return null;
|
|
50
|
-
let normalizada = normalizarSeparadores(rutaRaw);
|
|
51
|
-
|
|
52
|
-
// Solo nos interesan rutas relativas al proyecto. Si es absoluta, intentamos
|
|
53
|
-
// hacerla relativa al CWD actual.
|
|
54
|
-
if (path.isAbsolute(normalizada)) {
|
|
55
|
-
const cwd = normalizarSeparadores(process.cwd());
|
|
56
|
-
if (normalizada.toLowerCase().startsWith(cwd.toLowerCase())) {
|
|
57
|
-
normalizada = normalizada.slice(cwd.length).replace(/^\/+/, '');
|
|
58
|
-
} else {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
normalizada = normalizada.replace(/^\.\//, '');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
for (const c of CARPETAS_INVENTARIADAS) {
|
|
66
|
-
if (normalizada.startsWith(c.ruta)) {
|
|
67
|
-
if (c.excluir && c.excluir.some(ex => normalizada.startsWith(ex))) continue;
|
|
68
|
-
return c.etiqueta;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function leerEstado() {
|
|
75
|
-
try {
|
|
76
|
-
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
|
|
77
|
-
} catch {
|
|
78
|
-
return {};
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function escribirEstado(estado) {
|
|
83
|
-
try {
|
|
84
|
-
fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
|
|
85
|
-
const tmp = STATE_FILE + '.tmp';
|
|
86
|
-
fs.writeFileSync(tmp, JSON.stringify(estado, null, 2), 'utf8');
|
|
87
|
-
fs.renameSync(tmp, STATE_FILE);
|
|
88
|
-
} catch {
|
|
89
|
-
// Falla silenciosa — el cooldown no es crítico
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function dentroDeCooldown(estado, etiqueta) {
|
|
94
|
-
const ultima = estado[etiqueta];
|
|
95
|
-
if (!ultima) return false;
|
|
96
|
-
return Date.now() - ultima < COOLDOWN_MS;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function marcarAviso(estado, etiqueta) {
|
|
100
|
-
estado[etiqueta] = Date.now();
|
|
101
|
-
escribirEstado(estado);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function construirMensaje(etiqueta) {
|
|
105
|
-
return (
|
|
106
|
-
'\n[swl-ses] Tocaste un archivo en `' + etiqueta + '/` — los contadores ' +
|
|
107
|
-
'de INVENTARIO.md pueden quedar stale.\n' +
|
|
108
|
-
' Antes del próximo commit, ejecuta:\n' +
|
|
109
|
-
' node scripts/generar-inventario.js\n' +
|
|
110
|
-
' y verifica con:\n' +
|
|
111
|
-
' node scripts/verificar-release.js\n' +
|
|
112
|
-
' (silenciar con SWL_SUGERIR_REGEN_INVENTARIO=0)\n'
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function extraerRuta(toolInput) {
|
|
117
|
-
if (!toolInput || typeof toolInput !== 'object') return null;
|
|
118
|
-
return (
|
|
119
|
-
toolInput.file_path ||
|
|
120
|
-
toolInput.path ||
|
|
121
|
-
toolInput.notebook_path ||
|
|
122
|
-
null
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function ejecutarComoHook() {
|
|
127
|
-
let inputRaw = '';
|
|
128
|
-
|
|
129
|
-
process.stdin.on('data', chunk => { inputRaw += chunk; });
|
|
130
|
-
|
|
131
|
-
process.stdin.on('end', () => {
|
|
132
|
-
try {
|
|
133
|
-
if (process.env.SWL_SUGERIR_REGEN_INVENTARIO === '0') return;
|
|
134
|
-
|
|
135
|
-
const data = JSON.parse(inputRaw || '{}');
|
|
136
|
-
const toolName = String(data.tool_name || data.tool?.name || '');
|
|
137
|
-
const toolInput = data.tool_input || data.tool?.input || {};
|
|
138
|
-
|
|
139
|
-
if (!['Write', 'Edit', 'MultiEdit'].includes(toolName)) return;
|
|
140
|
-
|
|
141
|
-
const ruta = extraerRuta(toolInput);
|
|
142
|
-
if (!ruta) return;
|
|
143
|
-
|
|
144
|
-
const etiqueta = detectarCarpeta(ruta);
|
|
145
|
-
if (!etiqueta) return;
|
|
146
|
-
|
|
147
|
-
const estado = leerEstado();
|
|
148
|
-
if (dentroDeCooldown(estado, etiqueta)) return;
|
|
149
|
-
|
|
150
|
-
process.stdout.write(construirMensaje(etiqueta));
|
|
151
|
-
marcarAviso(estado, etiqueta);
|
|
152
|
-
} catch {
|
|
153
|
-
// Errores internos nunca bloquean
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Solo escuchar stdin cuando
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: sugerir-regenerar-inventario.js
|
|
6
|
+
* Tipo: PostToolUse (aplica a: Write, Edit, MultiEdit)
|
|
7
|
+
*
|
|
8
|
+
* Cuando el agente edita o crea un componente registrado en INVENTARIO.md
|
|
9
|
+
* (agentes, habilidades, comandos, hooks o reglas), sugiere — sin bloquear —
|
|
10
|
+
* regenerar el inventario antes del próximo commit.
|
|
11
|
+
*
|
|
12
|
+
* Motivado por el drift recurrente detectado el 2026-04-29: tras agregar el
|
|
13
|
+
* skill `harness-claude-code` el inventario quedó stale en 5 archivos canónicos
|
|
14
|
+
* porque nadie regeneró `INVENTARIO.md` después de la edición. La regeneración
|
|
15
|
+
* es 1 comando (`node scripts/generar-inventario.js`) pero es fácil olvidarla.
|
|
16
|
+
*
|
|
17
|
+
* Cooldown: una vez por sesión por carpeta afectada para no spammear cuando
|
|
18
|
+
* el agente edita docenas de archivos seguidos. Estado persistente en
|
|
19
|
+
* `.planning/inventario-aviso-state.json`.
|
|
20
|
+
*
|
|
21
|
+
* Resultado:
|
|
22
|
+
* - Edición sobre carpeta inventariada y sin cooldown → sugerencia en stdout (exit 0)
|
|
23
|
+
* - Edición sobre carpeta no inventariada → sin output (exit 0)
|
|
24
|
+
* - Error interno → sin output (nunca bloquear)
|
|
25
|
+
*
|
|
26
|
+
* Activo por defecto. Para silenciar: SWL_SUGERIR_REGEN_INVENTARIO=0.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const fs = require('fs');
|
|
30
|
+
const path = require('path');
|
|
31
|
+
|
|
32
|
+
// Carpetas cuyo cambio invalida los contadores de INVENTARIO.md
|
|
33
|
+
const CARPETAS_INVENTARIADAS = [
|
|
34
|
+
{ ruta: 'agentes/', etiqueta: 'agentes' },
|
|
35
|
+
{ ruta: 'habilidades/', etiqueta: 'habilidades' },
|
|
36
|
+
{ ruta: 'comandos/swl/', etiqueta: 'comandos' },
|
|
37
|
+
{ ruta: 'hooks/', etiqueta: 'hooks', excluir: ['hooks/lib/'] },
|
|
38
|
+
{ ruta: 'reglas/', etiqueta: 'reglas' },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const STATE_FILE = path.join(process.cwd(), '.planning', 'inventario-aviso-state.json');
|
|
42
|
+
const COOLDOWN_MS = 30 * 60 * 1000; // 30 min
|
|
43
|
+
|
|
44
|
+
function normalizarSeparadores(p) {
|
|
45
|
+
return String(p).replace(/\\/g, '/');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function detectarCarpeta(rutaRaw) {
|
|
49
|
+
if (!rutaRaw) return null;
|
|
50
|
+
let normalizada = normalizarSeparadores(rutaRaw);
|
|
51
|
+
|
|
52
|
+
// Solo nos interesan rutas relativas al proyecto. Si es absoluta, intentamos
|
|
53
|
+
// hacerla relativa al CWD actual.
|
|
54
|
+
if (path.isAbsolute(normalizada)) {
|
|
55
|
+
const cwd = normalizarSeparadores(process.cwd());
|
|
56
|
+
if (normalizada.toLowerCase().startsWith(cwd.toLowerCase())) {
|
|
57
|
+
normalizada = normalizada.slice(cwd.length).replace(/^\/+/, '');
|
|
58
|
+
} else {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
normalizada = normalizada.replace(/^\.\//, '');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const c of CARPETAS_INVENTARIADAS) {
|
|
66
|
+
if (normalizada.startsWith(c.ruta)) {
|
|
67
|
+
if (c.excluir && c.excluir.some(ex => normalizada.startsWith(ex))) continue;
|
|
68
|
+
return c.etiqueta;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function leerEstado() {
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
|
|
77
|
+
} catch {
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function escribirEstado(estado) {
|
|
83
|
+
try {
|
|
84
|
+
fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
|
|
85
|
+
const tmp = STATE_FILE + '.tmp';
|
|
86
|
+
fs.writeFileSync(tmp, JSON.stringify(estado, null, 2), 'utf8');
|
|
87
|
+
fs.renameSync(tmp, STATE_FILE);
|
|
88
|
+
} catch {
|
|
89
|
+
// Falla silenciosa — el cooldown no es crítico
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function dentroDeCooldown(estado, etiqueta) {
|
|
94
|
+
const ultima = estado[etiqueta];
|
|
95
|
+
if (!ultima) return false;
|
|
96
|
+
return Date.now() - ultima < COOLDOWN_MS;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function marcarAviso(estado, etiqueta) {
|
|
100
|
+
estado[etiqueta] = Date.now();
|
|
101
|
+
escribirEstado(estado);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function construirMensaje(etiqueta) {
|
|
105
|
+
return (
|
|
106
|
+
'\n[swl-ses] Tocaste un archivo en `' + etiqueta + '/` — los contadores ' +
|
|
107
|
+
'de INVENTARIO.md pueden quedar stale.\n' +
|
|
108
|
+
' Antes del próximo commit, ejecuta:\n' +
|
|
109
|
+
' node scripts/generar-inventario.js\n' +
|
|
110
|
+
' y verifica con:\n' +
|
|
111
|
+
' node scripts/verificar-release.js\n' +
|
|
112
|
+
' (silenciar con SWL_SUGERIR_REGEN_INVENTARIO=0)\n'
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function extraerRuta(toolInput) {
|
|
117
|
+
if (!toolInput || typeof toolInput !== 'object') return null;
|
|
118
|
+
return (
|
|
119
|
+
toolInput.file_path ||
|
|
120
|
+
toolInput.path ||
|
|
121
|
+
toolInput.notebook_path ||
|
|
122
|
+
null
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function ejecutarComoHook() {
|
|
127
|
+
let inputRaw = '';
|
|
128
|
+
|
|
129
|
+
process.stdin.on('data', chunk => { inputRaw += chunk; });
|
|
130
|
+
|
|
131
|
+
process.stdin.on('end', () => {
|
|
132
|
+
try {
|
|
133
|
+
if (process.env.SWL_SUGERIR_REGEN_INVENTARIO === '0') return;
|
|
134
|
+
|
|
135
|
+
const data = JSON.parse(inputRaw || '{}');
|
|
136
|
+
const toolName = String(data.tool_name || data.tool?.name || '');
|
|
137
|
+
const toolInput = data.tool_input || data.tool?.input || {};
|
|
138
|
+
|
|
139
|
+
if (!['Write', 'Edit', 'MultiEdit'].includes(toolName)) return;
|
|
140
|
+
|
|
141
|
+
const ruta = extraerRuta(toolInput);
|
|
142
|
+
if (!ruta) return;
|
|
143
|
+
|
|
144
|
+
const etiqueta = detectarCarpeta(ruta);
|
|
145
|
+
if (!etiqueta) return;
|
|
146
|
+
|
|
147
|
+
const estado = leerEstado();
|
|
148
|
+
if (dentroDeCooldown(estado, etiqueta)) return;
|
|
149
|
+
|
|
150
|
+
process.stdout.write(construirMensaje(etiqueta));
|
|
151
|
+
marcarAviso(estado, etiqueta);
|
|
152
|
+
} catch {
|
|
153
|
+
// Errores internos nunca bloquean
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Solo escuchar stdin cuando corre como entrypoint: directo o wrapper
|
|
159
|
+
// `node -e "require(...)"` (require.main undefined). No al importar para tests.
|
|
160
|
+
if (!require.main || require.main === module) {
|
|
161
|
+
ejecutarComoHook();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Para tests unitarios
|
|
165
|
+
module.exports = {
|
|
166
|
+
CARPETAS_INVENTARIADAS,
|
|
167
|
+
detectarCarpeta,
|
|
168
|
+
construirMensaje,
|
|
169
|
+
dentroDeCooldown,
|
|
170
|
+
COOLDOWN_MS,
|
|
171
|
+
};
|