@saulwade/swl-ses 1.0.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 +238 -0
- package/README.md +560 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/.evolved.json +9 -0
- package/agentes/accesibilidad-wcag-swl.md +692 -0
- package/agentes/arquitecto-swl.md +238 -0
- package/agentes/auto-evolucion-swl.md +854 -0
- package/agentes/backend-api-swl.md +470 -0
- package/agentes/backend-csharp-swl.md +418 -0
- package/agentes/backend-go-swl.md +388 -0
- package/agentes/backend-java-swl.md +279 -0
- package/agentes/backend-node-swl.md +477 -0
- package/agentes/backend-python-swl.md +608 -0
- package/agentes/backend-rust-swl.md +362 -0
- package/agentes/backend-workers-swl.md +480 -0
- package/agentes/cloud-infra-swl.md +485 -0
- package/agentes/consolidador-swl.md +539 -0
- package/agentes/datos-swl.md +584 -0
- package/agentes/depurador-swl.md +349 -0
- package/agentes/devops-ci-swl.md +374 -0
- package/agentes/disenador-ui-swl.md +558 -0
- package/agentes/documentador-swl.md +343 -0
- package/agentes/evals/arquitecto-swl.evals.json +56 -0
- package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
- package/agentes/evals/implementador-swl.evals.json +56 -0
- package/agentes/evals/orquestador-swl.evals.json +60 -0
- package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
- package/agentes/evals/red-team-swl.evals.json +59 -0
- package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
- package/agentes/frontend-angular-swl.md +627 -0
- package/agentes/frontend-css-swl.md +720 -0
- package/agentes/frontend-react-swl.md +696 -0
- package/agentes/frontend-swl.md +500 -0
- package/agentes/frontend-tailwind-swl.md +830 -0
- package/agentes/implementador-swl.md +328 -0
- package/agentes/investigador-swl.md +430 -0
- package/agentes/investigador-ux-swl.md +500 -0
- package/agentes/llm-apps-swl.md +276 -0
- package/agentes/migrador-swl.md +417 -0
- package/agentes/mobile-android-swl.md +509 -0
- package/agentes/mobile-cross-swl.md +539 -0
- package/agentes/mobile-ios-swl.md +500 -0
- package/agentes/mobile-testing-swl.md +300 -0
- package/agentes/notificador-swl.md +916 -0
- package/agentes/observabilidad-swl.md +436 -0
- package/agentes/orquestador-swl.md +884 -0
- package/agentes/pagos-swl.md +283 -0
- package/agentes/perfilador-usuario-swl.md +306 -0
- package/agentes/planificador-swl.md +402 -0
- package/agentes/producto-prd-swl.md +587 -0
- package/agentes/red-team-swl.md +216 -0
- package/agentes/release-manager-swl.md +568 -0
- package/agentes/rendimiento-swl.md +714 -0
- package/agentes/resolutor-build-swl.md +243 -0
- package/agentes/revisor-angular-swl.md +276 -0
- package/agentes/revisor-codigo-swl.md +348 -0
- package/agentes/revisor-csharp-swl.md +262 -0
- package/agentes/revisor-go-swl.md +257 -0
- package/agentes/revisor-java-swl.md +255 -0
- package/agentes/revisor-kotlin-swl.md +271 -0
- package/agentes/revisor-nextjs-swl.md +279 -0
- package/agentes/revisor-php-swl.md +269 -0
- package/agentes/revisor-react-swl.md +276 -0
- package/agentes/revisor-rust-swl.md +344 -0
- package/agentes/revisor-seguridad-swl.md +390 -0
- package/agentes/revisor-swift-swl.md +266 -0
- package/agentes/revisor-typescript-swl.md +344 -0
- package/agentes/sre-swl.md +265 -0
- package/agentes/tdd-qa-swl.md +354 -0
- package/agentes/ux-disenador-swl.md +501 -0
- package/bin/lib/bot-comandos.js +1030 -0
- package/bin/lib/bot-discovery.js +182 -0
- package/bin/lib/bot-git.js +142 -0
- package/bin/swl-ses.js +325 -0
- package/bin/swl-telegram-bot.js +442 -0
- package/bin/swl-telegram-bot.plist +21 -0
- package/bin/swl-telegram-bot.service +14 -0
- package/comandos/swl/.evolved.json +23 -0
- package/comandos/swl/actualizar.md +174 -0
- package/comandos/swl/adoptar-proyecto.md +207 -0
- package/comandos/swl/aprender.md +701 -0
- package/comandos/swl/auditar-deps.md +134 -0
- package/comandos/swl/autoresearch.md +170 -0
- package/comandos/swl/ayuda.md +224 -0
- package/comandos/swl/brainstorm.md +50 -0
- package/comandos/swl/checkpoint.md +330 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/configurar-ci.md +227 -0
- package/comandos/swl/contexto.md +112 -0
- package/comandos/swl/contribuir.md +233 -0
- package/comandos/swl/crear-skill.md +292 -0
- package/comandos/swl/cron.md +196 -0
- package/comandos/swl/dashboard.md +146 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +135 -0
- package/comandos/swl/evaluar-skill.md +487 -0
- package/comandos/swl/evolucion-estado.md +142 -0
- package/comandos/swl/evolucionar.md +259 -0
- package/comandos/swl/exportar-vault.md +189 -0
- package/comandos/swl/gateway.md +158 -0
- package/comandos/swl/inbox.md +116 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/instintos.md +86 -0
- package/comandos/swl/mapear-codebase.md +312 -0
- package/comandos/swl/mcp-status.md +175 -0
- package/comandos/swl/metricas.md +270 -0
- package/comandos/swl/modelo.md +102 -0
- package/comandos/swl/notificaciones.md +396 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/plugins.md +256 -0
- package/comandos/swl/reflect-skills.md +125 -0
- package/comandos/swl/release.md +217 -0
- package/comandos/swl/revisar-impacto.md +206 -0
- package/comandos/swl/revisar.md +330 -0
- package/comandos/swl/salud.md +363 -0
- package/comandos/swl/sesiones.md +200 -0
- package/comandos/swl/skill-search.md +113 -0
- package/comandos/swl/verificar.md +585 -0
- package/comandos/swl/wiki.md +620 -0
- package/contextos/dev.md +32 -0
- package/contextos/research.md +30 -0
- package/contextos/review.md +31 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
- package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
- package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
- package/habilidades/agent-browser/SKILL.md +218 -0
- package/habilidades/agentes-como-servicio/SKILL.md +218 -0
- package/habilidades/ai-runtime-security/SKILL.md +273 -0
- package/habilidades/angular-avanzado/SKILL.md +164 -0
- package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
- package/habilidades/angular-moderno/SKILL.md +186 -0
- package/habilidades/angular-moderno/evals/evals.json +45 -0
- package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
- package/habilidades/api-rest-diseno/SKILL.md +191 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
- package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
- package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
- package/habilidades/async-python/SKILL.md +149 -0
- package/habilidades/async-python/evals/evals.json +47 -0
- package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
- package/habilidades/auth-patrones/.evolved.json +9 -0
- package/habilidades/auth-patrones/SKILL.md +413 -0
- package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
- package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
- package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
- package/habilidades/autoresearch/SKILL.md +268 -0
- package/habilidades/autoresearch/evals/evals.json +41 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/azure-cloud/SKILL.md +308 -0
- package/habilidades/azure-cloud/recursos/aks.md +327 -0
- package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
- package/habilidades/backend-production-resilience/SKILL.md +288 -0
- package/habilidades/brainstorming/SKILL.md +295 -0
- package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
- package/habilidades/build-errors-cpp/SKILL.md +270 -0
- package/habilidades/build-errors-csharp/SKILL.md +265 -0
- package/habilidades/build-errors-go/SKILL.md +306 -0
- package/habilidades/build-errors-java/SKILL.md +278 -0
- package/habilidades/build-errors-kotlin/SKILL.md +303 -0
- package/habilidades/build-errors-nextjs/SKILL.md +312 -0
- package/habilidades/build-errors-php/SKILL.md +270 -0
- package/habilidades/build-errors-python/SKILL.md +292 -0
- package/habilidades/build-errors-rust/SKILL.md +284 -0
- package/habilidades/build-errors-swift/SKILL.md +272 -0
- package/habilidades/build-errors-typescript/SKILL.md +369 -0
- package/habilidades/checklist-calidad/SKILL.md +271 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +285 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
- package/habilidades/cloud-aws/SKILL.md +142 -0
- package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
- package/habilidades/compactacion-contexto/SKILL.md +247 -0
- package/habilidades/contenedores-docker/SKILL.md +137 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
- package/habilidades/context-builder/SKILL.md +170 -0
- package/habilidades/control-profundidad/SKILL.md +128 -0
- package/habilidades/csharp-experto/SKILL.md +322 -0
- package/habilidades/csharp-patrones/SKILL.md +316 -0
- package/habilidades/csharp-testing/SKILL.md +286 -0
- package/habilidades/css-moderno/SKILL.md +166 -0
- package/habilidades/css-moderno/evals/evals.json +43 -0
- package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
- package/habilidades/datos-etl/SKILL.md +129 -0
- package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
- package/habilidades/dbml-experto/SKILL.md +339 -0
- package/habilidades/dbml-experto/evals/evals.json +56 -0
- package/habilidades/dependencias-auditoria/SKILL.md +320 -0
- package/habilidades/deprecacion-migracion/SKILL.md +169 -0
- package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
- package/habilidades/design-tokens/SKILL.md +158 -0
- package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
- package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
- package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
- package/habilidades/discutir-fase/SKILL.md +188 -0
- package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
- package/habilidades/diseno-responsivo/SKILL.md +186 -0
- package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
- package/habilidades/django-experto/SKILL.md +205 -0
- package/habilidades/django-experto/recursos/async-django.md +390 -0
- package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
- package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
- package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
- package/habilidades/django-experto/recursos/testing-django.md +415 -0
- package/habilidades/doc-sync/SKILL.md +280 -0
- package/habilidades/drift-detection/SKILL.md +179 -0
- package/habilidades/ejecutar-fase/SKILL.md +468 -0
- package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
- package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
- package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/evaluacion-agentes/SKILL.md +314 -0
- package/habilidades/event-driven/SKILL.md +153 -0
- package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
- package/habilidades/extraccion-documentos/SKILL.md +221 -0
- package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
- package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
- package/habilidades/fastapi-experto/SKILL.md +221 -0
- package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
- package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
- package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
- package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
- package/habilidades/filament-admin/SKILL.md +290 -0
- package/habilidades/frontend-avanzado/SKILL.md +257 -0
- package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
- package/habilidades/gcp-cloud/SKILL.md +260 -0
- package/habilidades/gcp-cloud/recursos/gke.md +234 -0
- package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
- package/habilidades/generacion-mermaid/SKILL.md +229 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
- package/habilidades/go-experto/SKILL.md +305 -0
- package/habilidades/go-patrones/SKILL.md +299 -0
- package/habilidades/go-testing/SKILL.md +291 -0
- package/habilidades/graphql-experto/SKILL.md +323 -0
- package/habilidades/guardrail-semantico/SKILL.md +282 -0
- package/habilidades/harness-claude-code/SKILL.md +299 -0
- package/habilidades/iam-secretos/SKILL.md +265 -0
- package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
- package/habilidades/infra-github-actions/SKILL.md +166 -0
- package/habilidades/instalar-sistema/.evolved.json +9 -0
- package/habilidades/instalar-sistema/SKILL.md +221 -0
- package/habilidades/java-experto/SKILL.md +290 -0
- package/habilidades/java-patrones/SKILL.md +275 -0
- package/habilidades/java-testing/SKILL.md +288 -0
- package/habilidades/kotlin-compose/SKILL.md +278 -0
- package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
- package/habilidades/kotlin-experto/SKILL.md +318 -0
- package/habilidades/kotlin-testing/SKILL.md +267 -0
- package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
- package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
- package/habilidades/langchain-langraph/SKILL.md +386 -0
- package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
- package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
- package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
- package/habilidades/legacy-code-rescue/SKILL.md +267 -0
- package/habilidades/likec4-experto/SKILL.md +412 -0
- package/habilidades/likec4-experto/evals/evals.json +69 -0
- package/habilidades/manejo-errores/.evolved.json +9 -0
- package/habilidades/manejo-errores/SKILL.md +407 -0
- package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
- package/habilidades/mapear-codebase/SKILL.md +275 -0
- package/habilidades/memoria-busqueda/SKILL.md +194 -0
- package/habilidades/memoria-busqueda/evals/evals.json +44 -0
- package/habilidades/meta-skills-estandar/SKILL.md +298 -0
- package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
- package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
- package/habilidades/microservicios/SKILL.md +155 -0
- package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
- package/habilidades/mobile-flutter/SKILL.md +199 -0
- package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
- package/habilidades/mobile-react-native/SKILL.md +176 -0
- package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
- package/habilidades/mongodb-experto/SKILL.md +302 -0
- package/habilidades/monitoring-alertas/SKILL.md +201 -0
- package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
- package/habilidades/nestjs-experto/SKILL.md +307 -0
- package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
- package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
- package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
- package/habilidades/nextjs-experto/SKILL.md +335 -0
- package/habilidades/nextjs-patrones/SKILL.md +303 -0
- package/habilidades/nextjs-testing/SKILL.md +331 -0
- package/habilidades/node-experto/.evolved.json +9 -0
- package/habilidades/node-experto/SKILL.md +266 -0
- package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
- package/habilidades/nuevo-proyecto/SKILL.md +204 -0
- package/habilidades/orquestacion-async/SKILL.md +303 -0
- package/habilidades/paid-media-tracking/SKILL.md +269 -0
- package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
- package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
- package/habilidades/patrones-python/SKILL.md +228 -0
- package/habilidades/patrones-python/evals/evals.json +56 -0
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
- package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
- package/habilidades/perfil-usuario/SKILL.md +200 -0
- package/habilidades/perfil-usuario/evals/evals.json +55 -0
- package/habilidades/performance-baseline/SKILL.md +297 -0
- package/habilidades/php-experto/SKILL.md +291 -0
- package/habilidades/php-patrones/SKILL.md +306 -0
- package/habilidades/php-testing/SKILL.md +280 -0
- package/habilidades/planear-fase/SKILL.md +269 -0
- package/habilidades/postgresql-experto/SKILL.md +151 -0
- package/habilidades/postgresql-experto/evals/evals.json +53 -0
- package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
- package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
- package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
- package/habilidades/privacy-memoria/SKILL.md +141 -0
- package/habilidades/privacy-memoria/evals/evals.json +43 -0
- package/habilidades/prompt-engineering/SKILL.md +518 -0
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
- package/habilidades/rag-arquitectura/SKILL.md +338 -0
- package/habilidades/rails-experto/SKILL.md +237 -0
- package/habilidades/rails-experto/recursos/active-record.md +260 -0
- package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
- package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
- package/habilidades/react-experto/SKILL.md +209 -0
- package/habilidades/react-experto/evals/evals.json +55 -0
- package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
- package/habilidades/react-optimizacion/SKILL.md +174 -0
- package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
- package/habilidades/redis-experto/SKILL.md +305 -0
- package/habilidades/release-semver/.evolved.json +9 -0
- package/habilidades/release-semver/SKILL.md +248 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/rust-experto/SKILL.md +400 -0
- package/habilidades/rust-patrones/SKILL.md +296 -0
- package/habilidades/rust-testing/SKILL.md +311 -0
- package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
- package/habilidades/sql-optimizacion/SKILL.md +200 -0
- package/habilidades/sql-optimizacion/evals/evals.json +54 -0
- package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
- package/habilidades/sre-patrones/SKILL.md +333 -0
- package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
- package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
- package/habilidades/stripe-pagos/SKILL.md +550 -0
- package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
- package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
- package/habilidades/structured-outputs/SKILL.md +343 -0
- package/habilidades/swift-experto/SKILL.md +320 -0
- package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
- package/habilidades/swift-patrones/SKILL.md +313 -0
- package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
- package/habilidades/swift-testing/SKILL.md +254 -0
- package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
- package/habilidades/swl-dashboard/SKILL.md +370 -0
- package/habilidades/swl-markitdown/SKILL.md +285 -0
- package/habilidades/swl-markitdown/evals/evals.json +52 -0
- package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
- package/habilidades/tailwind-experto/SKILL.md +240 -0
- package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
- package/habilidades/tdd-workflow/SKILL.md +293 -0
- package/habilidades/terraform-experto/SKILL.md +321 -0
- package/habilidades/testing-python/SKILL.md +340 -0
- package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
- package/habilidades/threat-model-lite/SKILL.md +246 -0
- package/habilidades/tracing-processor/SKILL.md +212 -0
- package/habilidades/tracking-measurement/SKILL.md +239 -0
- package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
- package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
- package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
- package/habilidades/typescript-avanzado/SKILL.md +144 -0
- package/habilidades/typescript-avanzado/evals/evals.json +55 -0
- package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
- package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
- package/habilidades/ux-diseno/SKILL.md +116 -0
- package/habilidades/ux-diseno/evals/evals.json +43 -0
- package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificacion-evidencia/SKILL.md +160 -0
- package/habilidades/verificar-trabajo/SKILL.md +303 -0
- package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
- package/habilidades/wiki-conocimiento/SKILL.md +276 -0
- package/habilidades/wireframes-flujos/SKILL.md +212 -0
- package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
- package/habilidades/workflow-claude-code/SKILL.md +260 -0
- package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
- package/hooks/_run-hook.sh +57 -0
- package/hooks/actualizar-perfil-usuario.js +364 -0
- package/hooks/agente-lifecycle.js +71 -0
- package/hooks/aiisms-detector.js +173 -0
- package/hooks/audit-trail.js +204 -0
- package/hooks/auto-background.js +97 -0
- package/hooks/auto-consolidacion.js +178 -0
- package/hooks/auto-evolucion.js +666 -0
- package/hooks/auto-restaurar-settings.js +360 -0
- package/hooks/calidad-pre-commit.js +929 -0
- package/hooks/calidad-typescript.js +511 -0
- package/hooks/captura-feedback-usuario.js +148 -0
- package/hooks/check-update.js +211 -0
- package/hooks/clasificador-mensajes.js +271 -0
- package/hooks/degradacion-instintos.js +272 -0
- package/hooks/escaneo-secretos.js +389 -0
- package/hooks/extraccion-aprendizajes.js +763 -0
- package/hooks/grafo-contexto.js +129 -0
- package/hooks/graph-update.js +67 -0
- package/hooks/guardrail-modelo.js +247 -0
- package/hooks/inbox-aviso.js +75 -0
- package/hooks/inyeccion-contexto.js +246 -0
- package/hooks/lib/abort-registry.js +214 -0
- package/hooks/lib/agent-backend.js +210 -0
- package/hooks/lib/agent-comms.js +263 -0
- package/hooks/lib/agent-issue-codes.js +284 -0
- package/hooks/lib/agent-matcher.js +189 -0
- package/hooks/lib/async-hook-registry.js +252 -0
- package/hooks/lib/atomic-write.js +130 -0
- package/hooks/lib/auto-consolidator.js +335 -0
- package/hooks/lib/canary-skills.js +187 -0
- package/hooks/lib/consolidation-lock.js +291 -0
- package/hooks/lib/context-builder.js +430 -0
- package/hooks/lib/context-compressor.js +657 -0
- package/hooks/lib/convergence-detector.js +105 -0
- package/hooks/lib/delegation-tracker.js +198 -0
- package/hooks/lib/detectar-package-manager.js +423 -0
- package/hooks/lib/edit-accumulator.js +171 -0
- package/hooks/lib/error-classifier.js +308 -0
- package/hooks/lib/event-bus.js +112 -0
- package/hooks/lib/evolution-tracker.js +442 -0
- package/hooks/lib/execution-state.js +316 -0
- package/hooks/lib/fingerprint-id.js +135 -0
- package/hooks/lib/gateway-notify.js +116 -0
- package/hooks/lib/graph-security.js +75 -0
- package/hooks/lib/guardrail-metrics.js +202 -0
- package/hooks/lib/hook-circuit-breaker.js +206 -0
- package/hooks/lib/loop-detector.js +267 -0
- package/hooks/lib/mcp-health.js +184 -0
- package/hooks/lib/mcp-pool.js +436 -0
- package/hooks/lib/memory-search.js +506 -0
- package/hooks/lib/merkle-audit.js +96 -0
- package/hooks/lib/model-router.js +222 -0
- package/hooks/lib/normalize-error.js +324 -0
- package/hooks/lib/normalize-input.js +65 -0
- package/hooks/lib/nudge-tracker.js +306 -0
- package/hooks/lib/otlp-exporter.js +365 -0
- package/hooks/lib/performance-marks.js +239 -0
- package/hooks/lib/privacy-filter.js +128 -0
- package/hooks/lib/prompt-injection-scanner.js +209 -0
- package/hooks/lib/provenance-tracker.js +183 -0
- package/hooks/lib/rate-limit-tracker.js +253 -0
- package/hooks/lib/reflect-classifier.js +164 -0
- package/hooks/lib/resource-quota.js +122 -0
- package/hooks/lib/retry-jitter.js +165 -0
- package/hooks/lib/risk-engine.js +368 -0
- package/hooks/lib/run-log.js +408 -0
- package/hooks/lib/session-fts.js +379 -0
- package/hooks/lib/session-store.js +293 -0
- package/hooks/lib/singleton-guard.js +159 -0
- package/hooks/lib/skill-auditor.js +588 -0
- package/hooks/lib/sync-status.js +228 -0
- package/hooks/lib/taint-tracker.js +107 -0
- package/hooks/lib/task-service.js +295 -0
- package/hooks/lib/tech-skills-map.js +146 -0
- package/hooks/lib/telegram-cliente.js +159 -0
- package/hooks/lib/telegram-config.js +170 -0
- package/hooks/lib/token-budget.js +156 -0
- package/hooks/lib/token-estimator.js +420 -0
- package/hooks/lib/toon-compressor.js +245 -0
- package/hooks/lib/usage-model.js +183 -0
- package/hooks/lib/variable-resolver.js +230 -0
- package/hooks/linea-estado.js +324 -0
- package/hooks/metricas-evolucion.js +209 -0
- package/hooks/monitor-contexto.js +325 -0
- package/hooks/notificacion-sesion-stop.js +198 -0
- package/hooks/notificacion-telegram-notification.js +4 -0
- package/hooks/notificacion-telegram-subagent.js +4 -0
- package/hooks/notificacion-telegram.js +267 -0
- package/hooks/preservar-estado-pre-compact.js +150 -0
- package/hooks/proteccion-rutas.js +366 -0
- package/hooks/registro-turnos.js +209 -0
- package/hooks/resumen-sesion.js +249 -0
- package/hooks/risk-scoring.js +323 -0
- package/hooks/rotar-audit-auto.js +122 -0
- package/hooks/sugerir-regenerar-inventario.js +170 -0
- package/hooks/telemetria-agentes.js +167 -0
- package/hooks/tracking-costos.js +688 -0
- package/instintos/global.yaml +8 -0
- package/instintos/perfil-usuario.yaml +53 -0
- package/instintos/prompt-appendices.yaml +57 -0
- package/instintos/proyecto.yaml +372 -0
- package/manifiestos/gateway-config.json +77 -0
- package/manifiestos/handoff-context.json +223 -0
- package/manifiestos/hook-profiles.json +44 -0
- package/manifiestos/hooks-config.json +360 -0
- package/manifiestos/modulos.json +1173 -0
- package/manifiestos/perfiles.json +404 -0
- package/package.json +86 -0
- package/plantillas/ESTADO.md +109 -0
- package/plantillas/HOJA-RUTA.md +143 -0
- package/plantillas/PROYECTO.md +122 -0
- package/plantillas/REQUISITOS.md +132 -0
- package/plantillas/auditor-veto-template.md +105 -0
- package/plantillas/github-workflows/README.md +47 -0
- package/plantillas/github-workflows/release-please.yml +44 -0
- package/plantillas/github-workflows/swl-ci.yml +107 -0
- package/plantillas/github-workflows/swl-security.yml +51 -0
- package/plantillas/mcp-mineru.json +13 -0
- package/plantillas/research/ARQUITECTURA.md +220 -0
- package/plantillas/research/FUNCIONALIDADES.md +175 -0
- package/plantillas/research/RESUMEN.md +165 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/TRAMPAS.md +299 -0
- package/plantillas/skill-evals-template.json +44 -0
- package/plugin.json +343 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +352 -0
- package/reglas/brevedad-output.md +124 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +201 -0
- package/reglas/git-workflow.md +245 -0
- package/reglas/gobernanza.md +271 -0
- package/reglas/harness-claude-code.md +213 -0
- package/reglas/hooks.md +186 -0
- package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
- package/reglas/lenguajes/csharp/hooks.md +281 -0
- package/reglas/lenguajes/csharp/patrones.md +226 -0
- package/reglas/lenguajes/csharp/seguridad.md +258 -0
- package/reglas/lenguajes/csharp/testing.md +176 -0
- package/reglas/lenguajes/go/estilo-codigo.md +195 -0
- package/reglas/lenguajes/go/hooks.md +249 -0
- package/reglas/lenguajes/go/patrones.md +249 -0
- package/reglas/lenguajes/go/seguridad.md +225 -0
- package/reglas/lenguajes/go/testing.md +272 -0
- package/reglas/lenguajes/java/estilo-codigo.md +217 -0
- package/reglas/lenguajes/java/hooks.md +251 -0
- package/reglas/lenguajes/java/patrones.md +226 -0
- package/reglas/lenguajes/java/seguridad.md +233 -0
- package/reglas/lenguajes/java/testing.md +238 -0
- package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
- package/reglas/lenguajes/kotlin/hooks.md +245 -0
- package/reglas/lenguajes/kotlin/patrones.md +201 -0
- package/reglas/lenguajes/kotlin/seguridad.md +202 -0
- package/reglas/lenguajes/kotlin/testing.md +236 -0
- package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
- package/reglas/lenguajes/nextjs/hooks.md +186 -0
- package/reglas/lenguajes/nextjs/patrones.md +225 -0
- package/reglas/lenguajes/nextjs/seguridad.md +216 -0
- package/reglas/lenguajes/nextjs/testing.md +193 -0
- package/reglas/lenguajes/php/estilo-codigo.md +228 -0
- package/reglas/lenguajes/php/hooks.md +165 -0
- package/reglas/lenguajes/php/patrones.md +233 -0
- package/reglas/lenguajes/php/seguridad.md +186 -0
- package/reglas/lenguajes/php/testing.md +205 -0
- package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
- package/reglas/lenguajes/rust/hooks.md +240 -0
- package/reglas/lenguajes/rust/patrones.md +250 -0
- package/reglas/lenguajes/rust/seguridad.md +221 -0
- package/reglas/lenguajes/rust/testing.md +194 -0
- package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
- package/reglas/lenguajes/swift/hooks.md +257 -0
- package/reglas/lenguajes/swift/patrones.md +235 -0
- package/reglas/lenguajes/swift/seguridad.md +248 -0
- package/reglas/lenguajes/swift/testing.md +242 -0
- package/reglas/markitdown.md +60 -0
- package/reglas/memoria-consolidada.md +209 -0
- package/reglas/patrones.md +225 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad-agentes.md +351 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +373 -0
- package/reglas/testing.md +193 -0
- package/schemas/agent-contract.json +176 -0
- package/schemas/agent-frontmatter.schema.json +149 -0
- package/schemas/agent-message.schema.json +53 -0
- package/schemas/agent-output-implementacion.schema.json +85 -0
- package/schemas/agent-output-planificacion.schema.json +113 -0
- package/schemas/agent-output-review.schema.json +78 -0
- package/schemas/diary-entry.schema.json +80 -0
- package/schemas/hook-profiles.schema.json +39 -0
- package/schemas/hooks-config.schema.json +74 -0
- package/schemas/instinct.schema.json +115 -0
- package/schemas/modulos.schema.json +29 -0
- package/schemas/perfiles.schema.json +28 -0
- package/schemas/plugin.schema.json +64 -0
- package/schemas/skill-evals.schema.json +95 -0
- package/schemas/skill-frontmatter.schema.json +170 -0
- package/scripts/actualizar.js +145 -0
- package/scripts/audit-skills.sh +78 -0
- package/scripts/auditar-agentes-gaps.js +149 -0
- package/scripts/auditar-cobertura-frameworks.js +241 -0
- package/scripts/auditar-skills-gaps.js +206 -0
- package/scripts/bootstrap-instintos.js +259 -0
- package/scripts/check-update.js +109 -0
- package/scripts/comandos/agents.js +105 -0
- package/scripts/comandos/info.js +108 -0
- package/scripts/comandos/install-asistido.js +186 -0
- package/scripts/comandos/skills.js +211 -0
- package/scripts/configurar-branch-protection.js +418 -0
- package/scripts/daemon-swl.py +388 -0
- package/scripts/desinstalar.js +130 -0
- package/scripts/doctor.js +559 -0
- package/scripts/field-report.js +199 -0
- package/scripts/generar-inventario.js +317 -0
- package/scripts/inbox-tmux-inject.js +161 -0
- package/scripts/inferir-herramientas-permitidas.js +586 -0
- package/scripts/inicializar.js +133 -0
- package/scripts/instalador.js +1031 -0
- package/scripts/instalar-git-hook.js +122 -0
- package/scripts/lib/agp-frontmatter.js +222 -0
- package/scripts/lib/append-con-marcadores.js +199 -0
- package/scripts/lib/artefactos-python.js +43 -0
- package/scripts/lib/audit-query.js +221 -0
- package/scripts/lib/autostart-linux.js +347 -0
- package/scripts/lib/autostart-macos.js +360 -0
- package/scripts/lib/autostart-windows.js +307 -0
- package/scripts/lib/budget-enforcer.js +252 -0
- package/scripts/lib/claude-sessions.js +285 -0
- package/scripts/lib/configurar-ci.js +380 -0
- package/scripts/lib/console-span-exporter.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -0
- package/scripts/lib/dashboard-widgets.js +290 -0
- package/scripts/lib/detectar-runtime.js +279 -0
- package/scripts/lib/detectar-stack.js +187 -0
- package/scripts/lib/diary-entry.js +234 -0
- package/scripts/lib/drift-detector.js +545 -0
- package/scripts/lib/estado.js +124 -0
- package/scripts/lib/gestor-componentes.js +243 -0
- package/scripts/lib/gitignore-manifest.js +305 -0
- package/scripts/lib/graph-analyze.py +556 -0
- package/scripts/lib/graph-builder.py +485 -0
- package/scripts/lib/graph-cluster.py +259 -0
- package/scripts/lib/health-row.js +168 -0
- package/scripts/lib/hooks-settings.js +789 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/mc-client.js +137 -0
- package/scripts/lib/notificaciones-telegram.js +1107 -0
- package/scripts/lib/npm-version.js +261 -0
- package/scripts/lib/paquetes-conocidos.js +50 -0
- package/scripts/lib/preservar-usuario.js +586 -0
- package/scripts/lib/prompt-builder.js +264 -0
- package/scripts/lib/resolver-externo.js +332 -0
- package/scripts/lib/schedule-parser.js +305 -0
- package/scripts/lib/scoring-instintos.js +240 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/lib/selector-interactivo.js +152 -0
- package/scripts/lib/semantic-search.js +242 -0
- package/scripts/lib/skill-discovery.js +234 -0
- package/scripts/lib/skill-metrics.js +246 -0
- package/scripts/lib/skill-normalizer.js +112 -0
- package/scripts/lib/skills-hub.js +340 -0
- package/scripts/lib/span-schema.js +134 -0
- package/scripts/lib/tool-cost-analyzer.js +255 -0
- package/scripts/lib/tracing-processor-interface.js +286 -0
- package/scripts/lib/transformadores/base.js +80 -0
- package/scripts/lib/transformadores/claude.js +124 -0
- package/scripts/lib/transformadores/codex.js +115 -0
- package/scripts/lib/transformadores/copilot.js +106 -0
- package/scripts/lib/transformadores/gemini.js +74 -0
- package/scripts/lib/transformadores/index.js +35 -0
- package/scripts/lib/transformadores/opencode.js +75 -0
- package/scripts/lib/ui.js +259 -0
- package/scripts/limpiar-artefactos-python.js +131 -0
- package/scripts/mcp-orchestrator.py +386 -0
- package/scripts/mcp-pool-manager.py +352 -0
- package/scripts/mcp-telemetry.py +378 -0
- package/scripts/poblar-evolvable.js +226 -0
- package/scripts/publicar.js +287 -0
- package/scripts/reflect-skills.js +403 -0
- package/scripts/rotar-audit-logs.js +185 -0
- package/scripts/run-skill-evals.js +242 -0
- package/scripts/smoke-test.js +374 -0
- package/scripts/token-analysis.py +471 -0
- package/scripts/validar-manifest.js +195 -0
- package/scripts/validar-memoria.js +321 -0
- package/scripts/validar-tests-aislamiento.js +184 -0
- package/scripts/validar-tokens-test.js +208 -0
- package/scripts/validar.js +147 -0
- package/scripts/validate-markdown.py +339 -0
- package/scripts/validate-skills.py +385 -0
- package/scripts/vendor/claude-usage/README.md +116 -0
- package/scripts/vendor/claude-usage/cli.py +334 -0
- package/scripts/vendor/claude-usage/dashboard.py +795 -0
- package/scripts/vendor/claude-usage/scanner.py +467 -0
- package/scripts/vendor/markitdown/cli.py +194 -0
- package/scripts/verificar-evolucion.js +289 -0
- package/scripts/verificar-release.js +494 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* guardrail-metrics.js — Métricas de activación y bloqueo de guardrails (hooks).
|
|
5
|
+
*
|
|
6
|
+
* Registra cuántas veces se activa y cuántas bloquea cada hook por sesión.
|
|
7
|
+
* Los datos se persisten en /tmp/swl-guardrail-metrics-{sessionId}.json para
|
|
8
|
+
* sobrevivir entre invocaciones del mismo hook.
|
|
9
|
+
*
|
|
10
|
+
* Principio adoptado del PDF "A Practical Guide to Building Agents":
|
|
11
|
+
* "Monitorear guardrail effectiveness basado en real-world data.
|
|
12
|
+
* Guardrails no son set-and-forget; evolucionan con el agente."
|
|
13
|
+
*
|
|
14
|
+
* API pública:
|
|
15
|
+
* recordActivation(hookName, sessionId, blocked) — registra una activación
|
|
16
|
+
* getMetrics(sessionId) — lee métricas de la sesión
|
|
17
|
+
* formatearResumen(metricas) — formatea para mostrar al usuario
|
|
18
|
+
*
|
|
19
|
+
* Zero-dependencies: solo usa fs, path, os del runtime de Node.
|
|
20
|
+
*
|
|
21
|
+
* @module hooks/lib/guardrail-metrics
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
const os = require('os');
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Internos
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Devuelve la ruta del bridge de métricas para la sesión dada.
|
|
34
|
+
* @param {string} sessionId
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
function rutaBridge(sessionId) {
|
|
38
|
+
const sid = (sessionId || 'default').replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
39
|
+
return path.join(os.tmpdir(), `swl-guardrail-metrics-${sid}.json`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Lee el estado actual del bridge o devuelve uno vacío.
|
|
44
|
+
* @param {string} bridgePath
|
|
45
|
+
* @returns {object}
|
|
46
|
+
*/
|
|
47
|
+
function leerBridge(bridgePath) {
|
|
48
|
+
try {
|
|
49
|
+
const raw = fs.readFileSync(bridgePath, 'utf8');
|
|
50
|
+
const datos = JSON.parse(raw);
|
|
51
|
+
datos.hooks = datos.hooks || {};
|
|
52
|
+
return datos;
|
|
53
|
+
} catch (_) {
|
|
54
|
+
return { sessionId: '', hooks: {} };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Persiste el bridge de métricas.
|
|
60
|
+
* @param {string} bridgePath
|
|
61
|
+
* @param {object} datos
|
|
62
|
+
*/
|
|
63
|
+
function guardarBridge(bridgePath, datos) {
|
|
64
|
+
try {
|
|
65
|
+
fs.writeFileSync(bridgePath, JSON.stringify(datos, null, 2), 'utf8');
|
|
66
|
+
} catch (_) {
|
|
67
|
+
// I/O error — silencioso para no interrumpir hooks
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// API pública
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Registra una activación de guardrail.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} hookName - Nombre del archivo del hook (ej: "escaneo-secretos.js").
|
|
79
|
+
* @param {string} sessionId - ID de la sesión activa.
|
|
80
|
+
* @param {boolean} blocked - true si el hook bloqueó (exit code 2), false si fue warning.
|
|
81
|
+
*/
|
|
82
|
+
function recordActivation(hookName, sessionId, blocked) {
|
|
83
|
+
const bridgePath = rutaBridge(sessionId);
|
|
84
|
+
const datos = leerBridge(bridgePath);
|
|
85
|
+
|
|
86
|
+
datos.sessionId = sessionId || datos.sessionId || 'default';
|
|
87
|
+
|
|
88
|
+
if (!datos.hooks[hookName]) {
|
|
89
|
+
datos.hooks[hookName] = {
|
|
90
|
+
activaciones: 0,
|
|
91
|
+
bloqueos: 0,
|
|
92
|
+
warnings: 0,
|
|
93
|
+
ultimaActivacion: null,
|
|
94
|
+
ultimoBloqueo: null,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const entrada = datos.hooks[hookName];
|
|
99
|
+
entrada.activaciones += 1;
|
|
100
|
+
entrada.ultimaActivacion = new Date().toISOString();
|
|
101
|
+
|
|
102
|
+
if (blocked) {
|
|
103
|
+
entrada.bloqueos += 1;
|
|
104
|
+
entrada.ultimoBloqueo = new Date().toISOString();
|
|
105
|
+
} else {
|
|
106
|
+
entrada.warnings += 1;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
guardarBridge(bridgePath, datos);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Lee las métricas de guardrails de la sesión actual.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} sessionId
|
|
116
|
+
* @returns {{ sessionId: string, hooks: object }}
|
|
117
|
+
*/
|
|
118
|
+
function getMetrics(sessionId) {
|
|
119
|
+
const bridgePath = rutaBridge(sessionId);
|
|
120
|
+
return leerBridge(bridgePath);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Formatea las métricas de guardrails como texto markdown para mostrar en reportes.
|
|
125
|
+
*
|
|
126
|
+
* @param {object} metricas - Resultado de getMetrics().
|
|
127
|
+
* @returns {string} Sección markdown con tabla de guardrails.
|
|
128
|
+
*/
|
|
129
|
+
function formatearResumen(metricas) {
|
|
130
|
+
const hooks = metricas.hooks || {};
|
|
131
|
+
const entradas = Object.entries(hooks);
|
|
132
|
+
|
|
133
|
+
if (entradas.length === 0) {
|
|
134
|
+
return '## Guardrails\n\n_Ningún guardrail se activó en esta sesión._\n\n';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Ordenar por bloqueos desc, luego por activaciones desc
|
|
138
|
+
entradas.sort(([, a], [, b]) => {
|
|
139
|
+
if (b.bloqueos !== a.bloqueos) return b.bloqueos - a.bloqueos;
|
|
140
|
+
return b.activaciones - a.activaciones;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const filas = entradas.map(([nombre, datos]) => {
|
|
144
|
+
const tasaBloqueo = datos.activaciones > 0
|
|
145
|
+
? Math.round((datos.bloqueos / datos.activaciones) * 100)
|
|
146
|
+
: 0;
|
|
147
|
+
const nombreCorto = nombre.replace('.js', '');
|
|
148
|
+
return `| ${nombreCorto.padEnd(28)} | ${String(datos.activaciones).padStart(11)} | ${String(datos.bloqueos).padStart(8)} | ${String(datos.warnings).padStart(8)} | ${String(tasaBloqueo + '%').padStart(12)} |`;
|
|
149
|
+
}).join('\n');
|
|
150
|
+
|
|
151
|
+
return [
|
|
152
|
+
'## Guardrails — Activaciones por Sesión',
|
|
153
|
+
'',
|
|
154
|
+
'> Basado en el principio de defensa multicapa: cada hook registra activaciones/bloqueos',
|
|
155
|
+
'> para detectar patrones de falso-positivo o sub-cobertura.',
|
|
156
|
+
'',
|
|
157
|
+
'| Hook | Activaciones | Bloqueos | Warnings | Tasa bloqueo |',
|
|
158
|
+
'|------------------------------|-------------|----------|----------|--------------|',
|
|
159
|
+
filas,
|
|
160
|
+
'',
|
|
161
|
+
].join('\n');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Genera un reporte de salud de guardrails.
|
|
166
|
+
* Detecta hooks con tasa de bloqueo anómalamente alta (>50%) o baja (<1%).
|
|
167
|
+
*
|
|
168
|
+
* @param {object} metricas - Resultado de getMetrics().
|
|
169
|
+
* @returns {string[]} Lista de advertencias (vacía si todo está bien).
|
|
170
|
+
*/
|
|
171
|
+
function diagnosticar(metricas) {
|
|
172
|
+
const hooks = metricas.hooks || {};
|
|
173
|
+
const advertencias = [];
|
|
174
|
+
|
|
175
|
+
for (const [nombre, datos] of Object.entries(hooks)) {
|
|
176
|
+
if (datos.activaciones < 5) continue; // necesita al menos 5 muestras
|
|
177
|
+
|
|
178
|
+
const tasa = datos.bloqueos / datos.activaciones;
|
|
179
|
+
|
|
180
|
+
if (tasa > 0.5) {
|
|
181
|
+
advertencias.push(
|
|
182
|
+
`${nombre}: tasa de bloqueo alta (${Math.round(tasa * 100)}%). ` +
|
|
183
|
+
`Posible falso-positivo recurrente — revisar umbrales en hooks-config.json.`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (tasa === 0 && datos.activaciones >= 20) {
|
|
187
|
+
advertencias.push(
|
|
188
|
+
`${nombre}: nunca bloqueó en ${datos.activaciones} activaciones. ` +
|
|
189
|
+
`Verificar que los umbrales estén correctamente configurados.`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return advertencias;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = {
|
|
198
|
+
recordActivation,
|
|
199
|
+
getMetrics,
|
|
200
|
+
formatearResumen,
|
|
201
|
+
diagnosticar,
|
|
202
|
+
};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook Circuit Breaker — Previene cascadas de fallos en hooks SWL.
|
|
5
|
+
*
|
|
6
|
+
* Inspirado en el patrón de Claude Code (denialTracking.ts):
|
|
7
|
+
* - Contador de fallos consecutivos por hook
|
|
8
|
+
* - Después de N fallos consecutivos, degrada el hook a modo warn
|
|
9
|
+
* - Un éxito resetea el contador consecutivo
|
|
10
|
+
* - Contador total como métrica (no bloquea, solo registra)
|
|
11
|
+
*
|
|
12
|
+
* Estado persistido en /tmp/swl-cb-{hookName}.json por sesión.
|
|
13
|
+
* Zero-dependencies — solo fs, path, os nativos.
|
|
14
|
+
*
|
|
15
|
+
* Uso:
|
|
16
|
+
* const cb = require('./hook-circuit-breaker');
|
|
17
|
+
* if (cb.isTripped('mi-hook')) return; // hook degradado, skip
|
|
18
|
+
* try { ... } catch (e) { cb.recordFailure('mi-hook'); }
|
|
19
|
+
* cb.recordSuccess('mi-hook');
|
|
20
|
+
*
|
|
21
|
+
* @module hooks/lib/hook-circuit-breaker
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
const os = require('os');
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Configuración por defecto
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
/** Fallos consecutivos antes de trip (degradar). */
|
|
33
|
+
const DEFAULT_MAX_CONSECUTIVE = 3;
|
|
34
|
+
|
|
35
|
+
/** Fallos totales en sesión para registrar en audit (no bloquea). */
|
|
36
|
+
const DEFAULT_AUDIT_THRESHOLD = 10;
|
|
37
|
+
|
|
38
|
+
/** Tiempo en ms antes de intentar recovery automático (half-open). */
|
|
39
|
+
const HALF_OPEN_COOLDOWN_MS = 5 * 60 * 1000; // 5 minutos
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Helpers de estado
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Ruta del archivo de estado del circuit breaker para un hook.
|
|
47
|
+
* @param {string} hookName - Nombre del hook (sin extensión .js).
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
function statePath(hookName) {
|
|
51
|
+
const sessionId = process.env.SWL_SESSION_ID || 'default';
|
|
52
|
+
return path.join(os.tmpdir(), `swl-cb-${hookName}-${sessionId}.json`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Lee el estado actual del breaker.
|
|
57
|
+
* @param {string} hookName
|
|
58
|
+
* @returns {{ consecutive: number, total: number, trippedAt: number|null, lastFailure: number }}
|
|
59
|
+
*/
|
|
60
|
+
function readState(hookName) {
|
|
61
|
+
const defaults = { consecutive: 0, total: 0, trippedAt: null, lastFailure: 0 };
|
|
62
|
+
try {
|
|
63
|
+
const raw = fs.readFileSync(statePath(hookName), 'utf8');
|
|
64
|
+
return { ...defaults, ...JSON.parse(raw) };
|
|
65
|
+
} catch {
|
|
66
|
+
return defaults;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Escribe el estado del breaker.
|
|
72
|
+
* @param {string} hookName
|
|
73
|
+
* @param {object} state
|
|
74
|
+
*/
|
|
75
|
+
function writeState(hookName, state) {
|
|
76
|
+
try {
|
|
77
|
+
fs.writeFileSync(statePath(hookName), JSON.stringify(state), 'utf8');
|
|
78
|
+
} catch {
|
|
79
|
+
// Fallo silencioso — no bloquear por no poder escribir estado
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// API Pública
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Verifica si el circuit breaker de un hook está "tripped" (abierto).
|
|
89
|
+
*
|
|
90
|
+
* Si está tripped pero pasó el cooldown, entra en half-open:
|
|
91
|
+
* permite un intento para verificar si el hook se recuperó.
|
|
92
|
+
*
|
|
93
|
+
* @param {string} hookName - Nombre del hook.
|
|
94
|
+
* @param {object} [opts]
|
|
95
|
+
* @param {number} [opts.maxConsecutive=3] - Fallos consecutivos para trip.
|
|
96
|
+
* @returns {boolean} true si el hook debe saltarse (degradado).
|
|
97
|
+
*/
|
|
98
|
+
function isTripped(hookName, opts = {}) {
|
|
99
|
+
const maxConsecutive = opts.maxConsecutive || DEFAULT_MAX_CONSECUTIVE;
|
|
100
|
+
const state = readState(hookName);
|
|
101
|
+
|
|
102
|
+
if (state.consecutive < maxConsecutive) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Está tripped — verificar half-open (cooldown pasado)
|
|
107
|
+
if (state.trippedAt && (Date.now() - state.trippedAt) >= HALF_OPEN_COOLDOWN_MS) {
|
|
108
|
+
// Half-open: permitir un intento
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Registra un fallo del hook.
|
|
117
|
+
*
|
|
118
|
+
* @param {string} hookName
|
|
119
|
+
* @param {object} [opts]
|
|
120
|
+
* @param {number} [opts.maxConsecutive=3]
|
|
121
|
+
* @returns {{ tripped: boolean, consecutive: number, total: number }}
|
|
122
|
+
*/
|
|
123
|
+
function recordFailure(hookName, opts = {}) {
|
|
124
|
+
const maxConsecutive = opts.maxConsecutive || DEFAULT_MAX_CONSECUTIVE;
|
|
125
|
+
const state = readState(hookName);
|
|
126
|
+
|
|
127
|
+
state.consecutive += 1;
|
|
128
|
+
state.total += 1;
|
|
129
|
+
state.lastFailure = Date.now();
|
|
130
|
+
|
|
131
|
+
if (state.consecutive >= maxConsecutive && !state.trippedAt) {
|
|
132
|
+
state.trippedAt = Date.now();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
writeState(hookName, state);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
tripped: state.consecutive >= maxConsecutive,
|
|
139
|
+
consecutive: state.consecutive,
|
|
140
|
+
total: state.total,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Registra un éxito del hook. Resetea el contador consecutivo.
|
|
146
|
+
*
|
|
147
|
+
* @param {string} hookName
|
|
148
|
+
*/
|
|
149
|
+
function recordSuccess(hookName) {
|
|
150
|
+
const state = readState(hookName);
|
|
151
|
+
state.consecutive = 0;
|
|
152
|
+
state.trippedAt = null;
|
|
153
|
+
writeState(hookName, state);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Obtiene las métricas del breaker sin modificar estado.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} hookName
|
|
160
|
+
* @returns {{ consecutive: number, total: number, trippedAt: number|null, isTripped: boolean }}
|
|
161
|
+
*/
|
|
162
|
+
function getMetrics(hookName, opts = {}) {
|
|
163
|
+
const maxConsecutive = opts.maxConsecutive || DEFAULT_MAX_CONSECUTIVE;
|
|
164
|
+
const state = readState(hookName);
|
|
165
|
+
return {
|
|
166
|
+
...state,
|
|
167
|
+
isTripped: state.consecutive >= maxConsecutive,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Resetea completamente el estado de un hook.
|
|
173
|
+
*
|
|
174
|
+
* @param {string} hookName
|
|
175
|
+
*/
|
|
176
|
+
function reset(hookName) {
|
|
177
|
+
try {
|
|
178
|
+
fs.unlinkSync(statePath(hookName));
|
|
179
|
+
} catch {
|
|
180
|
+
// No existe o no se puede borrar — ok
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Verifica si el total de fallos supera el umbral de audit.
|
|
186
|
+
*
|
|
187
|
+
* @param {string} hookName
|
|
188
|
+
* @param {number} [threshold=10]
|
|
189
|
+
* @returns {boolean}
|
|
190
|
+
*/
|
|
191
|
+
function shouldAudit(hookName, threshold = DEFAULT_AUDIT_THRESHOLD) {
|
|
192
|
+
const state = readState(hookName);
|
|
193
|
+
return state.total >= threshold;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = {
|
|
197
|
+
isTripped,
|
|
198
|
+
recordFailure,
|
|
199
|
+
recordSuccess,
|
|
200
|
+
getMetrics,
|
|
201
|
+
reset,
|
|
202
|
+
shouldAudit,
|
|
203
|
+
DEFAULT_MAX_CONSECUTIVE,
|
|
204
|
+
DEFAULT_AUDIT_THRESHOLD,
|
|
205
|
+
HALF_OPEN_COOLDOWN_MS,
|
|
206
|
+
};
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Loop Detector — Detección de agentes atascados en loops repetitivos.
|
|
5
|
+
*
|
|
6
|
+
* Usa sliding window para rastrear tool calls y outputs de texto.
|
|
7
|
+
* Cuando detecta N repeticiones consecutivas identicas, emite alerta
|
|
8
|
+
* y opcionalmente termina la ejecucion.
|
|
9
|
+
*
|
|
10
|
+
* Inspirado en open-multi-agent (LoopDetector), adaptado a zero-dependencies
|
|
11
|
+
* y al protocolo de hooks de SWL-SES.
|
|
12
|
+
*
|
|
13
|
+
* Integración:
|
|
14
|
+
* - risk-scoring.js puede consultar getStats() para factor de riesgo
|
|
15
|
+
* - delegation-tracker.js puede usar isLooping() como condicion de abort
|
|
16
|
+
*
|
|
17
|
+
* @module hooks/lib/loop-detector
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Constantes por defecto
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
/** Repeticiones consecutivas antes de detectar loop. */
|
|
25
|
+
const DEFAULT_MAX_REPETITIONS = 3;
|
|
26
|
+
|
|
27
|
+
/** Tamaño de la ventana de observación (turnos). */
|
|
28
|
+
const DEFAULT_WINDOW_SIZE = 6;
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Estado en memoria (por sesión, por agente)
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Map<agentName, { toolSignatures: string[], textOutputs: string[], loopsDetected: number }>
|
|
36
|
+
*/
|
|
37
|
+
const _agentWindows = new Map();
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Helpers internos
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Ordena keys recursivamente para que {b:1, a:2} y {a:2, b:1}
|
|
45
|
+
* produzcan el mismo JSON string.
|
|
46
|
+
* @param {*} value
|
|
47
|
+
* @returns {*}
|
|
48
|
+
*/
|
|
49
|
+
function sortKeys(value) {
|
|
50
|
+
if (value === null || typeof value !== 'object') return value;
|
|
51
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
52
|
+
const sorted = {};
|
|
53
|
+
for (const key of Object.keys(value).sort()) {
|
|
54
|
+
sorted[key] = sortKeys(value[key]);
|
|
55
|
+
}
|
|
56
|
+
return sorted;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Genera una firma determinista para un conjunto de tool calls.
|
|
61
|
+
* @param {Array<{name: string, input: object}>} toolCalls
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
64
|
+
function computeToolSignature(toolCalls) {
|
|
65
|
+
const items = toolCalls
|
|
66
|
+
.map(tc => ({ name: tc.name, input: sortKeys(tc.input) }))
|
|
67
|
+
.sort((a, b) => {
|
|
68
|
+
const cmp = a.name.localeCompare(b.name);
|
|
69
|
+
if (cmp !== 0) return cmp;
|
|
70
|
+
return JSON.stringify(a.input).localeCompare(JSON.stringify(b.input));
|
|
71
|
+
});
|
|
72
|
+
return JSON.stringify(items);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Cuenta repeticiones consecutivas identicas al final del buffer.
|
|
77
|
+
* @param {string[]} buffer
|
|
78
|
+
* @returns {number}
|
|
79
|
+
*/
|
|
80
|
+
function consecutiveRepeats(buffer) {
|
|
81
|
+
if (buffer.length === 0) return 0;
|
|
82
|
+
const last = buffer[buffer.length - 1];
|
|
83
|
+
let count = 0;
|
|
84
|
+
for (let i = buffer.length - 1; i >= 0; i--) {
|
|
85
|
+
if (buffer[i] === last) count++;
|
|
86
|
+
else break;
|
|
87
|
+
}
|
|
88
|
+
return count;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Agrega entrada al buffer y recorta al tamaño de ventana.
|
|
93
|
+
* @param {string[]} buffer
|
|
94
|
+
* @param {string} entry
|
|
95
|
+
* @param {number} windowSize
|
|
96
|
+
*/
|
|
97
|
+
function pushAndTrim(buffer, entry, windowSize) {
|
|
98
|
+
buffer.push(entry);
|
|
99
|
+
while (buffer.length > windowSize) {
|
|
100
|
+
buffer.shift();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Obtiene o crea el estado de ventana para un agente.
|
|
106
|
+
* @param {string} agentName
|
|
107
|
+
* @returns {{ toolSignatures: string[], textOutputs: string[], loopsDetected: number, lastAction: string|null }}
|
|
108
|
+
*/
|
|
109
|
+
function getWindow(agentName) {
|
|
110
|
+
if (!_agentWindows.has(agentName)) {
|
|
111
|
+
_agentWindows.set(agentName, {
|
|
112
|
+
toolSignatures: [],
|
|
113
|
+
textOutputs: [],
|
|
114
|
+
loopsDetected: 0,
|
|
115
|
+
lastAction: null,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return _agentWindows.get(agentName);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// API pública
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Registra tool calls de un turno y verifica si hay loop.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} agentName - Nombre del agente.
|
|
129
|
+
* @param {Array<{name: string, input: object}>} toolCalls - Tool calls del turno.
|
|
130
|
+
* @param {object} [options]
|
|
131
|
+
* @param {number} [options.maxRepetitions=3] - Umbral de repeticiones.
|
|
132
|
+
* @param {number} [options.windowSize=6] - Tamaño de ventana.
|
|
133
|
+
* @returns {{ detected: boolean, kind?: string, repetitions?: number, detail?: string }}
|
|
134
|
+
*/
|
|
135
|
+
function recordToolCalls(agentName, toolCalls, options = {}) {
|
|
136
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
137
|
+
return { detected: false };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const maxReps = options.maxRepetitions || DEFAULT_MAX_REPETITIONS;
|
|
141
|
+
const winSize = Math.max(options.windowSize || DEFAULT_WINDOW_SIZE, maxReps);
|
|
142
|
+
const win = getWindow(agentName);
|
|
143
|
+
|
|
144
|
+
const signature = computeToolSignature(toolCalls);
|
|
145
|
+
pushAndTrim(win.toolSignatures, signature, winSize);
|
|
146
|
+
|
|
147
|
+
const count = consecutiveRepeats(win.toolSignatures);
|
|
148
|
+
if (count >= maxReps) {
|
|
149
|
+
win.loopsDetected++;
|
|
150
|
+
const names = toolCalls.map(tc => tc.name).join(', ');
|
|
151
|
+
win.lastAction = 'tool_loop';
|
|
152
|
+
return {
|
|
153
|
+
detected: true,
|
|
154
|
+
kind: 'tool_repetition',
|
|
155
|
+
repetitions: count,
|
|
156
|
+
detail: `Tool call "${names}" con argumentos identicos se repitio ${count} veces consecutivas. El agente parece atascado.`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { detected: false };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Registra output de texto de un turno y verifica si hay loop.
|
|
165
|
+
*
|
|
166
|
+
* @param {string} agentName - Nombre del agente.
|
|
167
|
+
* @param {string} text - Texto del output.
|
|
168
|
+
* @param {object} [options]
|
|
169
|
+
* @param {number} [options.maxRepetitions=3] - Umbral de repeticiones.
|
|
170
|
+
* @param {number} [options.windowSize=6] - Tamaño de ventana.
|
|
171
|
+
* @returns {{ detected: boolean, kind?: string, repetitions?: number, detail?: string }}
|
|
172
|
+
*/
|
|
173
|
+
function recordTextOutput(agentName, text, options = {}) {
|
|
174
|
+
const normalized = (text || '').trim().replace(/\s+/g, ' ');
|
|
175
|
+
if (normalized.length === 0) {
|
|
176
|
+
return { detected: false };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const maxReps = options.maxRepetitions || DEFAULT_MAX_REPETITIONS;
|
|
180
|
+
const winSize = Math.max(options.windowSize || DEFAULT_WINDOW_SIZE, maxReps);
|
|
181
|
+
const win = getWindow(agentName);
|
|
182
|
+
|
|
183
|
+
pushAndTrim(win.textOutputs, normalized, winSize);
|
|
184
|
+
|
|
185
|
+
const count = consecutiveRepeats(win.textOutputs);
|
|
186
|
+
if (count >= maxReps) {
|
|
187
|
+
win.loopsDetected++;
|
|
188
|
+
win.lastAction = 'text_loop';
|
|
189
|
+
return {
|
|
190
|
+
detected: true,
|
|
191
|
+
kind: 'text_repetition',
|
|
192
|
+
repetitions: count,
|
|
193
|
+
detail: `El agente produjo la misma respuesta de texto ${count} veces consecutivas. Parece atascado en un loop.`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return { detected: false };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Verifica si un agente esta actualmente en un loop.
|
|
202
|
+
*
|
|
203
|
+
* @param {string} agentName
|
|
204
|
+
* @returns {boolean}
|
|
205
|
+
*/
|
|
206
|
+
function isLooping(agentName) {
|
|
207
|
+
const win = _agentWindows.get(agentName);
|
|
208
|
+
if (!win) return false;
|
|
209
|
+
return win.lastAction === 'tool_loop' || win.lastAction === 'text_loop';
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Resetea el estado de detección para un agente.
|
|
214
|
+
*
|
|
215
|
+
* @param {string} agentName
|
|
216
|
+
*/
|
|
217
|
+
function resetAgent(agentName) {
|
|
218
|
+
_agentWindows.delete(agentName);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Obtiene estadísticas de loops detectados.
|
|
223
|
+
*
|
|
224
|
+
* @returns {{ totalAgentsTracked: number, totalLoopsDetected: number, agentDetails: Array<{name: string, loops: number, lastAction: string|null}> }}
|
|
225
|
+
*/
|
|
226
|
+
function getStats() {
|
|
227
|
+
const agentDetails = [];
|
|
228
|
+
let totalLoops = 0;
|
|
229
|
+
|
|
230
|
+
for (const [name, win] of _agentWindows) {
|
|
231
|
+
agentDetails.push({
|
|
232
|
+
name,
|
|
233
|
+
loops: win.loopsDetected,
|
|
234
|
+
lastAction: win.lastAction,
|
|
235
|
+
});
|
|
236
|
+
totalLoops += win.loopsDetected;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
totalAgentsTracked: _agentWindows.size,
|
|
241
|
+
totalLoopsDetected: totalLoops,
|
|
242
|
+
agentDetails,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Resetea todo el estado del detector.
|
|
248
|
+
*/
|
|
249
|
+
function resetAll() {
|
|
250
|
+
_agentWindows.clear();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// Exports
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
|
|
257
|
+
module.exports = {
|
|
258
|
+
recordToolCalls,
|
|
259
|
+
recordTextOutput,
|
|
260
|
+
isLooping,
|
|
261
|
+
resetAgent,
|
|
262
|
+
resetAll,
|
|
263
|
+
getStats,
|
|
264
|
+
// Constantes para configuración externa
|
|
265
|
+
DEFAULT_MAX_REPETITIONS,
|
|
266
|
+
DEFAULT_WINDOW_SIZE,
|
|
267
|
+
};
|