@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,688 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: tracking-costos.js
|
|
6
|
+
* Tipo: PostToolUse
|
|
7
|
+
*
|
|
8
|
+
* Registra el consumo estimado de tokens y costo en USD por sesión.
|
|
9
|
+
* Cada invocación acumula los datos en un archivo bridge por sesión en /tmp/
|
|
10
|
+
* y actualiza .planning/METRICAS.md cada INTERVALO_ACTUALIZACION tool calls.
|
|
11
|
+
*
|
|
12
|
+
* Umbrales de presupuesto (configurables en hooks-config.json):
|
|
13
|
+
* - alertAt (defecto 0.80): emite WARNING en stderr al superar el 80%
|
|
14
|
+
* - 100%: emite ALERTA CRITICA en stderr
|
|
15
|
+
*
|
|
16
|
+
* El presupuesto base se lee de hooks-config.json (costBudget).
|
|
17
|
+
* Fallback si no existe: $10.00 USD / 500,000 tokens.
|
|
18
|
+
*
|
|
19
|
+
* El hook nunca bloquea (siempre exit 0). Es PostToolUse informativo.
|
|
20
|
+
* Los mensajes de alerta se emiten en stderr con prefijo [tracking-costos].
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const fs = require('fs');
|
|
24
|
+
const path = require('path');
|
|
25
|
+
const os = require('os');
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Dependencias internas
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
estimarToolCall,
|
|
33
|
+
formatearCosto,
|
|
34
|
+
formatearNumero,
|
|
35
|
+
inferirFamiliaModelo,
|
|
36
|
+
} = require('./lib/token-estimator');
|
|
37
|
+
|
|
38
|
+
const bus = require('./lib/event-bus');
|
|
39
|
+
const runLog = require('./lib/run-log');
|
|
40
|
+
const { quota } = require('./lib/resource-quota');
|
|
41
|
+
|
|
42
|
+
// Importar modelo de uso con guard de robustez — el hook no debe fallar
|
|
43
|
+
// si el módulo aún no existe en instalaciones anteriores del sistema.
|
|
44
|
+
let usageModel = null;
|
|
45
|
+
try {
|
|
46
|
+
usageModel = require('./lib/usage-model');
|
|
47
|
+
} catch (_) {
|
|
48
|
+
// Módulo no disponible — usar estimación heurística como fallback
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Constantes de configuración
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Cada cuántas tool calls se actualiza METRICAS.md.
|
|
57
|
+
* Reducir este valor genera más I/O; aumentarlo hace el reporte menos frecuente.
|
|
58
|
+
*/
|
|
59
|
+
const INTERVALO_ACTUALIZACION = 20;
|
|
60
|
+
|
|
61
|
+
/** Presupuesto por defecto si no hay hooks-config.json. */
|
|
62
|
+
const PRESUPUESTO_DEFAULT = {
|
|
63
|
+
maxUsd: 10.0,
|
|
64
|
+
maxTokens: 500_000,
|
|
65
|
+
alertAt: 0.80,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** Ruta del manifesto de configuración de hooks. */
|
|
69
|
+
const RUTA_HOOKS_CONFIG = path.join(process.cwd(), 'manifiestos', 'hooks-config.json');
|
|
70
|
+
|
|
71
|
+
/** Ruta del archivo de métricas de sesión. */
|
|
72
|
+
const RUTA_METRICS = path.join(process.cwd(), '.planning', 'METRICAS.md');
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Utilidades de configuración
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Lee el presupuesto configurado en hooks-config.json.
|
|
80
|
+
* Si el archivo no existe o está malformado, devuelve el presupuesto por defecto.
|
|
81
|
+
*
|
|
82
|
+
* @returns {{ maxUsd: number, maxTokens: number, alertAt: number }}
|
|
83
|
+
*/
|
|
84
|
+
function leerPresupuesto() {
|
|
85
|
+
try {
|
|
86
|
+
const raw = fs.readFileSync(RUTA_HOOKS_CONFIG, 'utf8');
|
|
87
|
+
const config = JSON.parse(raw);
|
|
88
|
+
const budget = config.costBudget || {};
|
|
89
|
+
return {
|
|
90
|
+
maxUsd: typeof budget.maxUsd === 'number' ? budget.maxUsd : PRESUPUESTO_DEFAULT.maxUsd,
|
|
91
|
+
maxTokens: typeof budget.maxTokens === 'number' ? budget.maxTokens : PRESUPUESTO_DEFAULT.maxTokens,
|
|
92
|
+
alertAt: typeof budget.alertAt === 'number' ? budget.alertAt : PRESUPUESTO_DEFAULT.alertAt,
|
|
93
|
+
};
|
|
94
|
+
} catch (_) {
|
|
95
|
+
return { ...PRESUPUESTO_DEFAULT };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Bridge de estado de sesión (/tmp)
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Devuelve la ruta del archivo bridge para la sesión dada.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} sessionId
|
|
107
|
+
* @returns {string}
|
|
108
|
+
*/
|
|
109
|
+
function rutaBridge(sessionId) {
|
|
110
|
+
return path.join(os.tmpdir(), `swl-costs-${sessionId}.json`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Estado inicial vacío para una nueva sesión.
|
|
115
|
+
*
|
|
116
|
+
* @returns {object}
|
|
117
|
+
*/
|
|
118
|
+
function estadoInicial() {
|
|
119
|
+
return {
|
|
120
|
+
sessionId: '',
|
|
121
|
+
toolCalls: 0,
|
|
122
|
+
tokensTotal: 0,
|
|
123
|
+
costoTotal: 0,
|
|
124
|
+
modeloPredominante: 'sonnet',
|
|
125
|
+
inicio: new Date().toISOString(),
|
|
126
|
+
ultimaActualizacion: new Date().toISOString(),
|
|
127
|
+
// Desglose por herramienta: { NombreTool: { llamadas, tokens } }
|
|
128
|
+
desglosePorHerramienta: {},
|
|
129
|
+
// Contador de usos por modelo para determinar el predominante
|
|
130
|
+
conteoPorModelo: {},
|
|
131
|
+
// Componentes SWL usados en la sesión
|
|
132
|
+
componentesSWL: {
|
|
133
|
+
agentes: [], // agentes invocados via Agent tool
|
|
134
|
+
skills: [], // skills cargados via Skill tool
|
|
135
|
+
scripts: [], // scripts/ modificados o ejecutados
|
|
136
|
+
hooks: [], // hooks que se ejecutaron (auto-registrado)
|
|
137
|
+
reglas: [], // reglas/ tocadas
|
|
138
|
+
comandos: [], // comandos /swl:* invocados
|
|
139
|
+
},
|
|
140
|
+
// Métricas por agente: { agentName: { llamadas, tokens, costo } }
|
|
141
|
+
// Permite calcular costo-por-resolución y detectar agentes costosos.
|
|
142
|
+
costePorAgente: {},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Lee el estado acumulado del bridge de la sesión.
|
|
148
|
+
* Si el archivo no existe, devuelve un estado inicial limpio.
|
|
149
|
+
*
|
|
150
|
+
* @param {string} bridgePath
|
|
151
|
+
* @returns {object}
|
|
152
|
+
*/
|
|
153
|
+
function leerEstado(bridgePath) {
|
|
154
|
+
try {
|
|
155
|
+
const raw = fs.readFileSync(bridgePath, 'utf8');
|
|
156
|
+
const datos = JSON.parse(raw);
|
|
157
|
+
// Asegurar que los campos opcionales existen (compatibilidad con versiones previas)
|
|
158
|
+
datos.desglosePorHerramienta = datos.desglosePorHerramienta || {};
|
|
159
|
+
datos.conteoPorModelo = datos.conteoPorModelo || {};
|
|
160
|
+
datos.costePorAgente = datos.costePorAgente || {};
|
|
161
|
+
return datos;
|
|
162
|
+
} catch (_) {
|
|
163
|
+
return estadoInicial();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Persiste el estado de la sesión en el archivo bridge.
|
|
169
|
+
*
|
|
170
|
+
* @param {string} bridgePath
|
|
171
|
+
* @param {object} estado
|
|
172
|
+
*/
|
|
173
|
+
function guardarEstado(bridgePath, estado) {
|
|
174
|
+
try {
|
|
175
|
+
fs.writeFileSync(bridgePath, JSON.stringify(estado, null, 2), 'utf8');
|
|
176
|
+
} catch (err) {
|
|
177
|
+
// Error al escribir bridge — ignorar silenciosamente
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
// Actualización de estado acumulado
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Acumula los datos de la invocación actual en el estado de sesión.
|
|
187
|
+
*
|
|
188
|
+
* @param {object} estado - Estado actual leído del bridge.
|
|
189
|
+
* @param {string} toolName - Nombre de la herramienta invocada.
|
|
190
|
+
* @param {string} modelLabel - Etiqueta corta del modelo.
|
|
191
|
+
* @param {string} sessionId - ID de sesión.
|
|
192
|
+
* @param {object} toolInput - Parámetros de entrada de la herramienta.
|
|
193
|
+
* @returns {object} Estado actualizado (muta y devuelve la misma referencia).
|
|
194
|
+
*/
|
|
195
|
+
/**
|
|
196
|
+
* Extrae tokens reales del payload PostToolUse si están disponibles.
|
|
197
|
+
* Claude Code puede exponer campos de uso en tool_result para llamadas LLM.
|
|
198
|
+
*
|
|
199
|
+
* @param {object} data - Payload completo del evento PostToolUse.
|
|
200
|
+
* @returns {{ inputTokens: number, outputTokens: number, cachedTokens: number, reasoningTokens: number }|null}
|
|
201
|
+
* Datos reales o null si no están disponibles en el payload.
|
|
202
|
+
*/
|
|
203
|
+
function extraerTokensReales(data) {
|
|
204
|
+
// Claude Code expone usage en varios lugares según la versión del evento
|
|
205
|
+
const uso = data.usage
|
|
206
|
+
|| (data.tool_result && data.tool_result.usage)
|
|
207
|
+
|| (data.result && data.result.usage)
|
|
208
|
+
|| null;
|
|
209
|
+
if (!uso) return null;
|
|
210
|
+
|
|
211
|
+
const inputTokens = Number(uso.input_tokens || uso.inputTokens || 0);
|
|
212
|
+
const outputTokens = Number(uso.output_tokens || uso.outputTokens || 0);
|
|
213
|
+
const cachedTokens = Number(uso.cache_read_input_tokens || uso.cached_tokens || uso.cachedTokens || 0);
|
|
214
|
+
const reasoningTokens = Number(uso.reasoning_tokens || uso.reasoningTokens || 0);
|
|
215
|
+
|
|
216
|
+
if (inputTokens === 0 && outputTokens === 0) return null;
|
|
217
|
+
return { inputTokens, outputTokens, cachedTokens, reasoningTokens };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function acumularInvocacion(estado, toolName, modelLabel, sessionId, toolInput, dataCompleto) {
|
|
221
|
+
// Intentar usar tokens reales del payload antes de recurrir a estimación
|
|
222
|
+
let tokensEstimados;
|
|
223
|
+
let costoEstimado;
|
|
224
|
+
let tokensRealesUsados = false;
|
|
225
|
+
|
|
226
|
+
const tokensReales = dataCompleto ? extraerTokensReales(dataCompleto) : null;
|
|
227
|
+
|
|
228
|
+
if (tokensReales && usageModel) {
|
|
229
|
+
// Datos reales disponibles — usar Usage model para tracking preciso
|
|
230
|
+
if (!estado.usageModel) {
|
|
231
|
+
estado.usageModel = usageModel.crearUsage().serialize();
|
|
232
|
+
}
|
|
233
|
+
const usoActual = usageModel.fromJSON(estado.usageModel);
|
|
234
|
+
usoActual.addEntrada({
|
|
235
|
+
inputTokens: tokensReales.inputTokens,
|
|
236
|
+
outputTokens: tokensReales.outputTokens,
|
|
237
|
+
cachedTokens: tokensReales.cachedTokens,
|
|
238
|
+
reasoningTokens: tokensReales.reasoningTokens,
|
|
239
|
+
modelo: modelLabel,
|
|
240
|
+
});
|
|
241
|
+
estado.usageModel = usoActual.serialize();
|
|
242
|
+
|
|
243
|
+
tokensEstimados = tokensReales.inputTokens + tokensReales.outputTokens;
|
|
244
|
+
tokensRealesUsados = true;
|
|
245
|
+
// Estimar costo desde tokens reales con la misma función de precios
|
|
246
|
+
const { costoEstimado: costoBase } = estimarToolCall(toolName, modelLabel);
|
|
247
|
+
// Escalar el costo estimado proporcionalmente a los tokens reales
|
|
248
|
+
const { tokensEstimados: tokensBase } = estimarToolCall(toolName, modelLabel);
|
|
249
|
+
costoEstimado = tokensBase > 0
|
|
250
|
+
? (costoBase / tokensBase) * tokensEstimados
|
|
251
|
+
: costoBase;
|
|
252
|
+
} else {
|
|
253
|
+
// Fallback a estimación heurística (comportamiento original)
|
|
254
|
+
const estimacion = estimarToolCall(toolName, modelLabel);
|
|
255
|
+
tokensEstimados = estimacion.tokensEstimados;
|
|
256
|
+
costoEstimado = estimacion.costoEstimado;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
estado.sessionId = sessionId;
|
|
260
|
+
estado.toolCalls += 1;
|
|
261
|
+
estado.tokensTotal += tokensEstimados;
|
|
262
|
+
estado.costoTotal += costoEstimado;
|
|
263
|
+
// Indicar si la entrada tiene tokens reales (para auditabilidad)
|
|
264
|
+
if (tokensRealesUsados) estado.ultimaEntradaConTokensReales = true;
|
|
265
|
+
estado.ultimaActualizacion = new Date().toISOString();
|
|
266
|
+
|
|
267
|
+
// Desglose por herramienta
|
|
268
|
+
if (!estado.desglosePorHerramienta[toolName]) {
|
|
269
|
+
estado.desglosePorHerramienta[toolName] = { llamadas: 0, tokens: 0 };
|
|
270
|
+
}
|
|
271
|
+
estado.desglosePorHerramienta[toolName].llamadas += 1;
|
|
272
|
+
estado.desglosePorHerramienta[toolName].tokens += tokensEstimados;
|
|
273
|
+
|
|
274
|
+
// Conteo por modelo para determinar el predominante
|
|
275
|
+
if (!estado.conteoPorModelo[modelLabel]) {
|
|
276
|
+
estado.conteoPorModelo[modelLabel] = 0;
|
|
277
|
+
}
|
|
278
|
+
estado.conteoPorModelo[modelLabel] += 1;
|
|
279
|
+
|
|
280
|
+
// Actualizar modelo predominante (el que tiene más llamadas)
|
|
281
|
+
const modeloPred = Object.entries(estado.conteoPorModelo)
|
|
282
|
+
.sort(([, a], [, b]) => b - a)[0];
|
|
283
|
+
estado.modeloPredominante = modeloPred ? modeloPred[0] : modelLabel;
|
|
284
|
+
|
|
285
|
+
// Rastrear componentes SWL usados
|
|
286
|
+
rastrearComponentesSWL(estado, toolName, toolInput);
|
|
287
|
+
|
|
288
|
+
// Registrar en resource-quota para verificación de límites rolling
|
|
289
|
+
try {
|
|
290
|
+
quota.registrar({ tokens: tokensEstimados, costoUsd: costoEstimado, agente: toolName });
|
|
291
|
+
const check = quota.verificar();
|
|
292
|
+
if (check.excedido) {
|
|
293
|
+
process.stderr.write(`[tracking-costos] ALERTA QUOTA: ${check.mensaje}\n`);
|
|
294
|
+
} else if (check.warnings.length > 0) {
|
|
295
|
+
process.stderr.write(`[tracking-costos] ${check.mensaje}\n`);
|
|
296
|
+
}
|
|
297
|
+
} catch { /* no bloquear por fallo de quota */ }
|
|
298
|
+
|
|
299
|
+
return estado;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Detecta y registra componentes SWL usados a partir de la herramienta y sus parámetros.
|
|
304
|
+
* También acumula métricas de costo por agente para análisis de rendimiento.
|
|
305
|
+
*/
|
|
306
|
+
function rastrearComponentesSWL(estado, toolName, toolInput) {
|
|
307
|
+
if (!estado.componentesSWL) {
|
|
308
|
+
estado.componentesSWL = { agentes: [], skills: [], scripts: [], hooks: [], reglas: [], comandos: [] };
|
|
309
|
+
}
|
|
310
|
+
if (!estado.costePorAgente) {
|
|
311
|
+
estado.costePorAgente = {};
|
|
312
|
+
}
|
|
313
|
+
const c = estado.componentesSWL;
|
|
314
|
+
const input = toolInput || {};
|
|
315
|
+
|
|
316
|
+
// Agent tool → registrar agente invocado y acumular costo estimado
|
|
317
|
+
if (toolName === 'Agent') {
|
|
318
|
+
const tipo = String(input.subagent_type || input.description || '').slice(0, 60);
|
|
319
|
+
if (tipo) {
|
|
320
|
+
if (!c.agentes.includes(tipo)) c.agentes.push(tipo);
|
|
321
|
+
// Acumular costo/tokens para este agente
|
|
322
|
+
// Los subagentes son llamadas "Agent" cuyo costo es proporcional al de la herramienta.
|
|
323
|
+
const { tokensEstimados, costoEstimado } = estimarToolCall('Agent', estado.modeloPredominante || 'sonnet');
|
|
324
|
+
if (!estado.costePorAgente[tipo]) {
|
|
325
|
+
estado.costePorAgente[tipo] = { llamadas: 0, tokens: 0, costo: 0 };
|
|
326
|
+
}
|
|
327
|
+
estado.costePorAgente[tipo].llamadas += 1;
|
|
328
|
+
estado.costePorAgente[tipo].tokens += tokensEstimados;
|
|
329
|
+
estado.costePorAgente[tipo].costo += costoEstimado;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Skill tool → registrar skill cargado
|
|
334
|
+
if (toolName === 'Skill') {
|
|
335
|
+
const nombre = String(input.skill || '').trim();
|
|
336
|
+
if (nombre && !c.skills.includes(nombre)) c.skills.push(nombre);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Bash tool → detectar comandos /swl:* y ejecución de scripts
|
|
340
|
+
if (toolName === 'Bash') {
|
|
341
|
+
const cmd = String(input.command || '');
|
|
342
|
+
// Detectar /swl:* invocados via skill
|
|
343
|
+
const swlMatch = cmd.match(/swl:([a-z-]+)/);
|
|
344
|
+
if (swlMatch && !c.comandos.includes(`/swl:${swlMatch[1]}`)) {
|
|
345
|
+
c.comandos.push(`/swl:${swlMatch[1]}`);
|
|
346
|
+
}
|
|
347
|
+
// Detectar ejecución de scripts SWL
|
|
348
|
+
const scriptMatch = cmd.match(/node\s+(?:scripts|bin)\/([^\s]+)/);
|
|
349
|
+
if (scriptMatch && !c.scripts.includes(scriptMatch[1])) {
|
|
350
|
+
c.scripts.push(scriptMatch[1]);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Write/Edit → detectar archivos SWL modificados
|
|
355
|
+
if (toolName === 'Write' || toolName === 'Edit') {
|
|
356
|
+
const filePath = String(input.file_path || '');
|
|
357
|
+
// Detectar scripts modificados
|
|
358
|
+
const scriptMatch = filePath.match(/scripts\/(?:lib\/)?([^/]+\.js)/);
|
|
359
|
+
if (scriptMatch && !c.scripts.includes(scriptMatch[1])) {
|
|
360
|
+
c.scripts.push(scriptMatch[1]);
|
|
361
|
+
}
|
|
362
|
+
// Detectar hooks modificados
|
|
363
|
+
const hookMatch = filePath.match(/hooks\/([^/]+\.js)/);
|
|
364
|
+
if (hookMatch && !c.hooks.includes(hookMatch[1])) {
|
|
365
|
+
c.hooks.push(hookMatch[1]);
|
|
366
|
+
}
|
|
367
|
+
// Detectar reglas modificadas
|
|
368
|
+
const reglaMatch = filePath.match(/reglas\/([^/]+\.md)/);
|
|
369
|
+
if (reglaMatch && !c.reglas.includes(reglaMatch[1])) {
|
|
370
|
+
c.reglas.push(reglaMatch[1]);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
// Generación de METRICAS.md
|
|
377
|
+
// ---------------------------------------------------------------------------
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Calcula la duración estimada de la sesión en minutos.
|
|
381
|
+
* Heurística: cada tool call toma ~30 segundos en promedio.
|
|
382
|
+
*
|
|
383
|
+
* @param {string} inicio - ISO timestamp de inicio de sesión.
|
|
384
|
+
* @param {number} toolCalls - Número total de tool calls.
|
|
385
|
+
* @returns {number} Minutos estimados.
|
|
386
|
+
*/
|
|
387
|
+
function estimarDuracionMinutos(inicio, toolCalls) {
|
|
388
|
+
try {
|
|
389
|
+
const ms = Date.now() - new Date(inicio).getTime();
|
|
390
|
+
const minutosPorTiempo = ms / 60_000;
|
|
391
|
+
const minutosPorCalls = toolCalls * 0.5; // 30 seg por call
|
|
392
|
+
// Usar el mayor de los dos para ser conservadores
|
|
393
|
+
return Math.round(Math.max(minutosPorTiempo, minutosPorCalls));
|
|
394
|
+
} catch (_) {
|
|
395
|
+
return Math.round(toolCalls * 0.5);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Genera la sección de componentes SWL usados en la sesión.
|
|
401
|
+
* Solo incluye categorías con al menos un componente.
|
|
402
|
+
*/
|
|
403
|
+
function generarSeccionComponentesSWL(componentesSWL) {
|
|
404
|
+
if (!componentesSWL) return '';
|
|
405
|
+
|
|
406
|
+
const categorias = [
|
|
407
|
+
{ clave: 'agentes', titulo: 'Agentes' },
|
|
408
|
+
{ clave: 'skills', titulo: 'Skills' },
|
|
409
|
+
{ clave: 'scripts', titulo: 'Scripts' },
|
|
410
|
+
{ clave: 'hooks', titulo: 'Hooks' },
|
|
411
|
+
{ clave: 'reglas', titulo: 'Reglas' },
|
|
412
|
+
{ clave: 'comandos', titulo: 'Comandos' },
|
|
413
|
+
];
|
|
414
|
+
|
|
415
|
+
const filas = categorias
|
|
416
|
+
.filter(cat => (componentesSWL[cat.clave] || []).length > 0)
|
|
417
|
+
.map(cat => `| ${cat.titulo.padEnd(10)} | ${componentesSWL[cat.clave].join(', ')} |`);
|
|
418
|
+
|
|
419
|
+
if (filas.length === 0) return '';
|
|
420
|
+
|
|
421
|
+
return [
|
|
422
|
+
'## Componentes SWL Utilizados',
|
|
423
|
+
'| Tipo | Componentes |',
|
|
424
|
+
'|------------|-------------|',
|
|
425
|
+
...filas,
|
|
426
|
+
'',
|
|
427
|
+
].join('\n');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Genera la sección de rendimiento por agente.
|
|
432
|
+
* Muestra llamadas, tokens, costo y costo promedio por invocación.
|
|
433
|
+
*
|
|
434
|
+
* @param {object} costePorAgente - Mapa { agentName: { llamadas, tokens, costo } }
|
|
435
|
+
* @param {number} costoTotal - Costo total de la sesión (para calcular % por agente).
|
|
436
|
+
* @returns {string}
|
|
437
|
+
*/
|
|
438
|
+
function generarSeccionAgentes(costePorAgente, costoTotal) {
|
|
439
|
+
if (!costePorAgente || Object.keys(costePorAgente).length === 0) return '';
|
|
440
|
+
|
|
441
|
+
// Ordenar por costo descendente
|
|
442
|
+
const filas = Object.entries(costePorAgente)
|
|
443
|
+
.sort(([, a], [, b]) => b.costo - a.costo)
|
|
444
|
+
.map(([nombre, datos]) => {
|
|
445
|
+
const pctCosto = costoTotal > 0 ? Math.round((datos.costo / costoTotal) * 100) : 0;
|
|
446
|
+
const costoPorInv = datos.llamadas > 0 ? (datos.costo / datos.llamadas) : 0;
|
|
447
|
+
const nombreCorto = nombre.length > 30 ? nombre.slice(0, 27) + '...' : nombre;
|
|
448
|
+
return `| ${nombreCorto.padEnd(32)} | ${String(datos.llamadas).padStart(8)} | ${formatearCosto(datos.costo).padStart(10)} | ${String(pctCosto + '%').padStart(8)} | ${formatearCosto(costoPorInv).padStart(12)} |`;
|
|
449
|
+
})
|
|
450
|
+
.join('\n');
|
|
451
|
+
|
|
452
|
+
return [
|
|
453
|
+
'## Rendimiento por Agente',
|
|
454
|
+
'| Agente | Llamadas | Costo est. | % total | Costo/llamada |',
|
|
455
|
+
'|----------------------------------|----------|------------|---------|---------------|',
|
|
456
|
+
filas,
|
|
457
|
+
'',
|
|
458
|
+
].join('\n');
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Genera el contenido completo de METRICAS.md a partir del estado actual.
|
|
463
|
+
*
|
|
464
|
+
* @param {object} estado - Estado acumulado de la sesión.
|
|
465
|
+
* @param {object} presupuesto - Presupuesto configurado.
|
|
466
|
+
* @returns {string} Contenido markdown completo.
|
|
467
|
+
*/
|
|
468
|
+
function generarMetrics(estado, presupuesto) {
|
|
469
|
+
const {
|
|
470
|
+
toolCalls,
|
|
471
|
+
tokensTotal,
|
|
472
|
+
costoTotal,
|
|
473
|
+
modeloPredominante,
|
|
474
|
+
inicio,
|
|
475
|
+
ultimaActualizacion,
|
|
476
|
+
desglosePorHerramienta,
|
|
477
|
+
componentesSWL,
|
|
478
|
+
costePorAgente,
|
|
479
|
+
} = estado;
|
|
480
|
+
|
|
481
|
+
const duracion = estimarDuracionMinutos(inicio, toolCalls);
|
|
482
|
+
const pctCosto = presupuesto.maxUsd > 0 ? (costoTotal / presupuesto.maxUsd) * 100 : 0;
|
|
483
|
+
const pctTokens = presupuesto.maxTokens > 0 ? (tokensTotal / presupuesto.maxTokens) * 100 : 0;
|
|
484
|
+
|
|
485
|
+
// Estado del presupuesto
|
|
486
|
+
let estadoPresupuesto;
|
|
487
|
+
if (pctCosto >= 100 || pctTokens >= 100) {
|
|
488
|
+
estadoPresupuesto = 'PRESUPUESTO SUPERADO';
|
|
489
|
+
} else if (pctCosto >= presupuesto.alertAt * 100 || pctTokens >= presupuesto.alertAt * 100) {
|
|
490
|
+
estadoPresupuesto = 'CERCA DEL LIMITE';
|
|
491
|
+
} else {
|
|
492
|
+
estadoPresupuesto = 'DENTRO DE PRESUPUESTO';
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Tabla de desglose por herramienta (ordenada por tokens desc)
|
|
496
|
+
const filasDesglose = Object.entries(desglosePorHerramienta)
|
|
497
|
+
.sort(([, a], [, b]) => b.tokens - a.tokens)
|
|
498
|
+
.map(([herramienta, datos]) => {
|
|
499
|
+
const pct = tokensTotal > 0
|
|
500
|
+
? Math.round((datos.tokens / tokensTotal) * 100)
|
|
501
|
+
: 0;
|
|
502
|
+
return `| ${herramienta.padEnd(16)} | ${String(datos.llamadas).padStart(8)} | ${formatearNumero(datos.tokens).padStart(11)} | ${String(pct + '%').padStart(11)} |`;
|
|
503
|
+
})
|
|
504
|
+
.join('\n');
|
|
505
|
+
|
|
506
|
+
const tablaDesglose = filasDesglose.length > 0
|
|
507
|
+
? filasDesglose
|
|
508
|
+
: '| (sin datos) | 0 | 0 | 0% |';
|
|
509
|
+
|
|
510
|
+
return [
|
|
511
|
+
'# Metricas de Sesion',
|
|
512
|
+
'',
|
|
513
|
+
`**Ultima actualizacion**: ${ultimaActualizacion}`,
|
|
514
|
+
'',
|
|
515
|
+
'## Resumen',
|
|
516
|
+
'| Metrica | Valor |',
|
|
517
|
+
'|---------|-------|',
|
|
518
|
+
`| Tool calls totales | ${formatearNumero(toolCalls)} |`,
|
|
519
|
+
`| Tokens estimados | ~${formatearNumero(tokensTotal)} |`,
|
|
520
|
+
`| Costo estimado | ~${formatearCosto(costoTotal)} USD |`,
|
|
521
|
+
`| Modelo predominante | ${modeloPredominante} |`,
|
|
522
|
+
`| Duracion estimada | ~${duracion} min |`,
|
|
523
|
+
'',
|
|
524
|
+
'## Desglose por Herramienta',
|
|
525
|
+
'| Herramienta | Llamadas | Tokens est. | % del total |',
|
|
526
|
+
'|------------------|----------|-------------|-------------|',
|
|
527
|
+
tablaDesglose,
|
|
528
|
+
'',
|
|
529
|
+
generarSeccionAgentes(costePorAgente, costoTotal),
|
|
530
|
+
generarSeccionComponentesSWL(componentesSWL),
|
|
531
|
+
'',
|
|
532
|
+
'## Presupuesto',
|
|
533
|
+
'',
|
|
534
|
+
`- Limite: ${formatearCosto(presupuesto.maxUsd)} USD / ${formatearNumero(presupuesto.maxTokens)} tokens`,
|
|
535
|
+
`- Consumido: ${formatearCosto(costoTotal)} USD (${pctCosto.toFixed(1)}%) / ${formatearNumero(tokensTotal)} tokens (${pctTokens.toFixed(1)}%)`,
|
|
536
|
+
`- Estado: ${estadoPresupuesto}`,
|
|
537
|
+
'',
|
|
538
|
+
].join('\n');
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Escribe el archivo METRICAS.md en .planning/.
|
|
543
|
+
* Crea el directorio si no existe.
|
|
544
|
+
*
|
|
545
|
+
* @param {object} estado - Estado acumulado.
|
|
546
|
+
* @param {object} presupuesto - Presupuesto configurado.
|
|
547
|
+
*/
|
|
548
|
+
function escribirMetrics(estado, presupuesto) {
|
|
549
|
+
try {
|
|
550
|
+
const dir = path.dirname(RUTA_METRICS);
|
|
551
|
+
if (!fs.existsSync(dir)) {
|
|
552
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
553
|
+
}
|
|
554
|
+
const contenido = generarMetrics(estado, presupuesto);
|
|
555
|
+
fs.writeFileSync(RUTA_METRICS, contenido, 'utf8');
|
|
556
|
+
} catch (err) {
|
|
557
|
+
// Error al escribir METRICAS.md — ignorar silenciosamente
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// ---------------------------------------------------------------------------
|
|
562
|
+
// Alertas de presupuesto
|
|
563
|
+
// ---------------------------------------------------------------------------
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Emite advertencias de presupuesto en stderr si se superan los umbrales.
|
|
567
|
+
* WARNING al superar alertAt (defecto 80%). CRITICO al superar el 100%.
|
|
568
|
+
*
|
|
569
|
+
* @param {number} costoTotal - Costo acumulado en USD.
|
|
570
|
+
* @param {number} tokensTotal - Tokens acumulados.
|
|
571
|
+
* @param {object} presupuesto - Presupuesto configurado.
|
|
572
|
+
*/
|
|
573
|
+
function verificarPresupuesto(costoTotal, tokensTotal, presupuesto) {
|
|
574
|
+
const pctCosto = presupuesto.maxUsd > 0 ? costoTotal / presupuesto.maxUsd : 0;
|
|
575
|
+
const pctTokens = presupuesto.maxTokens > 0 ? tokensTotal / presupuesto.maxTokens : 0;
|
|
576
|
+
const pctMax = Math.max(pctCosto, pctTokens);
|
|
577
|
+
|
|
578
|
+
// Las alertas de presupuesto se manejan silenciosamente en el bridge.
|
|
579
|
+
// Claude Code reporta stderr como hook error, así que no se emiten alertas aquí.
|
|
580
|
+
// El estado se refleja en METRICAS.md que se actualiza periódicamente.
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// ---------------------------------------------------------------------------
|
|
584
|
+
// Entrypoint principal
|
|
585
|
+
// ---------------------------------------------------------------------------
|
|
586
|
+
|
|
587
|
+
let inputRaw = '';
|
|
588
|
+
|
|
589
|
+
process.stdin.on('data', chunk => {
|
|
590
|
+
inputRaw += chunk;
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
process.stdin.on('end', () => {
|
|
594
|
+
try {
|
|
595
|
+
const data = JSON.parse(inputRaw);
|
|
596
|
+
|
|
597
|
+
// Extraer campos del evento PostToolUse
|
|
598
|
+
const sessionId = String(data.session_id || 'default');
|
|
599
|
+
const modelId = String(data.model || '');
|
|
600
|
+
const toolName = String(data.tool_name || 'Unknown');
|
|
601
|
+
const toolInput = data.tool_input || {};
|
|
602
|
+
|
|
603
|
+
// Inferir etiqueta del modelo para el estimador
|
|
604
|
+
const modelLabel = inferirFamiliaModelo(modelId);
|
|
605
|
+
|
|
606
|
+
// Leer presupuesto configurado
|
|
607
|
+
const presupuesto = leerPresupuesto();
|
|
608
|
+
|
|
609
|
+
// Leer estado acumulado del bridge
|
|
610
|
+
const bridge = rutaBridge(sessionId);
|
|
611
|
+
const estado = leerEstado(bridge);
|
|
612
|
+
|
|
613
|
+
// Acumular invocación actual (incluye rastreo de componentes SWL)
|
|
614
|
+
// Se pasa `data` completo para extraer tokens reales si están disponibles.
|
|
615
|
+
acumularInvocacion(estado, toolName, modelLabel, sessionId, toolInput, data);
|
|
616
|
+
|
|
617
|
+
// Persistir estado actualizado
|
|
618
|
+
guardarEstado(bridge, estado);
|
|
619
|
+
|
|
620
|
+
// -----------------------------------------------------------------------
|
|
621
|
+
// Publicar evento al bus (observabilidad desacoplada)
|
|
622
|
+
// -----------------------------------------------------------------------
|
|
623
|
+
const esNuevaSession = estado.toolCalls === 1;
|
|
624
|
+
if (esNuevaSession) {
|
|
625
|
+
// Primera invocación: registrar inicio de sesión en JSONL
|
|
626
|
+
runLog.sessionStart(sessionId, { cwd: process.cwd(), model: modelLabel });
|
|
627
|
+
runLog.limpiarRunsAntiguos();
|
|
628
|
+
bus.publish({ type: 'session-start', runId: sessionId, cwd: process.cwd(), model: modelLabel });
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Publicar evento de tool-call al bus
|
|
632
|
+
bus.publish({
|
|
633
|
+
type: 'tool-call',
|
|
634
|
+
runId: sessionId,
|
|
635
|
+
toolName: toolName,
|
|
636
|
+
modelLabel: modelLabel,
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// Registrar en JSONL de run cada 5 tool calls (balance entre trazabilidad e I/O)
|
|
640
|
+
if (estado.toolCalls % 5 === 0 || esNuevaSession) {
|
|
641
|
+
runLog.toolCall(sessionId, toolName, { callNumber: estado.toolCalls });
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Registrar agentes y skills detectados en JSONL
|
|
645
|
+
const c = estado.componentesSWL || {};
|
|
646
|
+
if (toolName === 'Agent') {
|
|
647
|
+
const agName = String((toolInput || {}).subagent_type || (toolInput || {}).description || '').slice(0, 60);
|
|
648
|
+
if (agName) runLog.agentInvoked(sessionId, agName);
|
|
649
|
+
}
|
|
650
|
+
if (toolName === 'Skill') {
|
|
651
|
+
const skName = String((toolInput || {}).skill || '').trim();
|
|
652
|
+
if (skName) runLog.skillLoaded(sessionId, skName);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Verificar alertas de presupuesto en cada invocación
|
|
656
|
+
verificarPresupuesto(estado.costoTotal, estado.tokensTotal, presupuesto);
|
|
657
|
+
|
|
658
|
+
// Actualizar METRICAS.md cada INTERVALO_ACTUALIZACION tool calls
|
|
659
|
+
if (estado.toolCalls % INTERVALO_ACTUALIZACION === 0) {
|
|
660
|
+
escribirMetrics(estado, presupuesto);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Sincronizar con session-store cada INTERVALO_ACTUALIZACION
|
|
664
|
+
if (estado.toolCalls % INTERVALO_ACTUALIZACION === 0) {
|
|
665
|
+
try {
|
|
666
|
+
const { actualizarSesion } = require('./lib/session-store');
|
|
667
|
+
const cwd = process.cwd();
|
|
668
|
+
actualizarSesion(cwd, {
|
|
669
|
+
toolCall: toolName,
|
|
670
|
+
tokensEstimated: estado.tokensTotal,
|
|
671
|
+
costEstimated: estado.costoTotal,
|
|
672
|
+
});
|
|
673
|
+
// Registrar agentes y skills detectados
|
|
674
|
+
const c = estado.componentesSWL || {};
|
|
675
|
+
for (const ag of (c.agentes || [])) {
|
|
676
|
+
actualizarSesion(cwd, { agentInvoked: ag });
|
|
677
|
+
}
|
|
678
|
+
} catch (_) {
|
|
679
|
+
// session-store no disponible — continuar sin sincronizar
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// PostToolUse: no escribir a stdout — salida limpia.
|
|
684
|
+
|
|
685
|
+
} catch (err) {
|
|
686
|
+
// No escribir a stderr — Claude Code lo reporta como hook error
|
|
687
|
+
}
|
|
688
|
+
});
|