@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,366 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: proteccion-rutas.js
|
|
6
|
+
* Tipo: PreToolUse (aplica a: Write, Edit)
|
|
7
|
+
*
|
|
8
|
+
* Protege el sistema de archivos verificando que la ruta de destino sea segura:
|
|
9
|
+
*
|
|
10
|
+
* 1. Sin path traversal:
|
|
11
|
+
* - Secuencias "../" o "..\\" (relativas que suben directorios)
|
|
12
|
+
* - Rutas que comienzan con "~/" (directorio home del usuario)
|
|
13
|
+
* - Secuencias percent-encoded: "%2e%2e", "%2E%2E", "%2e%2E" y combinaciones
|
|
14
|
+
* - Rutas que comienzan con "/" o una letra de drive Windows seguida de ":\\"
|
|
15
|
+
* apuntando fuera del CWD
|
|
16
|
+
*
|
|
17
|
+
* 2. Destino dentro del directorio de trabajo actual (CWD):
|
|
18
|
+
* La ruta resuelta (path.resolve) debe comenzar con el CWD normalizado.
|
|
19
|
+
* Si apunta fuera, se bloquea.
|
|
20
|
+
*
|
|
21
|
+
* Resultado:
|
|
22
|
+
* - Violación detectada → razón en stdout + exit code 2 (block)
|
|
23
|
+
* - Ruta segura → sin output, proceso termina naturalmente
|
|
24
|
+
* - Error interno → sin output (nunca bloquear por fallo del hook)
|
|
25
|
+
*
|
|
26
|
+
* Limitaciones conocidas:
|
|
27
|
+
* - No detecta symlinks que apuntan fuera del CWD (requeriría fs.realpathSync).
|
|
28
|
+
* - En Windows las rutas UNC (\\server\share) no se analizan completamente.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const path = require('path');
|
|
32
|
+
const os = require('os');
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Patrones de path traversal
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Lista de patrones que indican intento de traversal.
|
|
40
|
+
* Se evalúan contra la ruta RAW recibida (antes de normalizar),
|
|
41
|
+
* para capturar intentos de evasión por encoding.
|
|
42
|
+
*/
|
|
43
|
+
const PATRONES_TRAVERSAL = [
|
|
44
|
+
{
|
|
45
|
+
descripcion: 'Secuencia "../" (subida de directorio POSIX)',
|
|
46
|
+
patron: /(?:^|\/)\.\.(?:\/|$)/,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
descripcion: 'Secuencia "..\\" (subida de directorio Windows)',
|
|
50
|
+
patron: /(?:^|\\)\.\.(?:\\|$)/,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
descripcion: 'Percent-encoding de ".." (%2e%2e, %2E%2E, etc.)',
|
|
54
|
+
patron: /%2[eE]%2[eE]/i,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
descripcion: 'Percent-encoding de "/" (%2f, %2F)',
|
|
58
|
+
// Combinado con ".." es traversal: "..%2f"
|
|
59
|
+
patron: /\.\.%2[fF]/i,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
descripcion: 'Percent-encoding de "\\" (%5c, %5C)',
|
|
63
|
+
patron: /\.\.%5[cC]/i,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
descripcion: 'Ruta de directorio home (~/ o ~\\)',
|
|
67
|
+
patron: /^~[/\\]/,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
descripcion: 'Doble barra que puede usarse para evasión (//)',
|
|
71
|
+
// Rutas como "//etc/passwd"
|
|
72
|
+
patron: /^\/\//,
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Funciones auxiliares
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Normaliza separadores de ruta a "/" para comparaciones consistentes
|
|
82
|
+
* entre POSIX y Windows.
|
|
83
|
+
* @param {string} p
|
|
84
|
+
* @returns {string}
|
|
85
|
+
*/
|
|
86
|
+
function normalizarSeparadores(p) {
|
|
87
|
+
return String(p).replace(/\\/g, '/');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Archivos de configuración protegidos (config protection)
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Archivos de configuración de linters, formatters y compiladores que NO deben
|
|
96
|
+
* ser modificados por el agente. Cuando el agente intenta "resolver" errores
|
|
97
|
+
* de lint/formato debilitando la configuración, este check lo redirige a
|
|
98
|
+
* corregir el código en su lugar.
|
|
99
|
+
*
|
|
100
|
+
* Inspirado en ECC config-protection.js.
|
|
101
|
+
*/
|
|
102
|
+
const ARCHIVOS_CONFIG_PROTEGIDOS = [
|
|
103
|
+
// Linters
|
|
104
|
+
'.eslintrc', '.eslintrc.js', '.eslintrc.json', '.eslintrc.yml', '.eslintrc.cjs',
|
|
105
|
+
'eslint.config.js', 'eslint.config.mjs', 'eslint.config.ts',
|
|
106
|
+
'biome.json', 'biome.jsonc',
|
|
107
|
+
'.pylintrc', 'pylintrc', '.flake8', '.ruff.toml', 'ruff.toml',
|
|
108
|
+
'.rubocop.yml',
|
|
109
|
+
// Formatters
|
|
110
|
+
'.prettierrc', '.prettierrc.js', '.prettierrc.json', '.prettierrc.yml',
|
|
111
|
+
'.prettierrc.cjs', '.prettierrc.mjs', 'prettier.config.js', 'prettier.config.mjs',
|
|
112
|
+
'.editorconfig',
|
|
113
|
+
// TypeScript / compiladores
|
|
114
|
+
'tsconfig.json', 'tsconfig.build.json', 'tsconfig.app.json', 'tsconfig.spec.json',
|
|
115
|
+
// Testing
|
|
116
|
+
'jest.config.js', 'jest.config.ts', 'vitest.config.ts', 'vitest.config.js',
|
|
117
|
+
'pytest.ini', 'setup.cfg', 'pyproject.toml',
|
|
118
|
+
// CI/CD
|
|
119
|
+
'.github/workflows', '.gitlab-ci.yml',
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Verifica si la ruta apunta a un archivo de configuración protegido.
|
|
124
|
+
* @param {string} rutaRaw
|
|
125
|
+
* @returns {{ protegido: boolean, archivo: string }}
|
|
126
|
+
*/
|
|
127
|
+
function verificarConfigProtegido(rutaRaw) {
|
|
128
|
+
const nombre = path.basename(rutaRaw);
|
|
129
|
+
const rutaNorm = normalizarSeparadores(rutaRaw);
|
|
130
|
+
|
|
131
|
+
for (const cfg of ARCHIVOS_CONFIG_PROTEGIDOS) {
|
|
132
|
+
if (nombre === cfg || rutaNorm.endsWith('/' + cfg) || rutaNorm === cfg) {
|
|
133
|
+
return { protegido: true, archivo: cfg };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { protegido: false, archivo: '' };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Construye mensaje de advertencia para archivos de config protegidos.
|
|
141
|
+
* @param {string} archivo
|
|
142
|
+
* @param {string} rutaRaw
|
|
143
|
+
* @returns {string}
|
|
144
|
+
*/
|
|
145
|
+
function construirMensajeConfigProtegido(archivo, rutaRaw) {
|
|
146
|
+
return [
|
|
147
|
+
`Advertencia: modificacion de archivo de configuracion protegido.`,
|
|
148
|
+
``,
|
|
149
|
+
`Archivo: ${archivo}`,
|
|
150
|
+
`Ruta: ${rutaRaw}`,
|
|
151
|
+
``,
|
|
152
|
+
`Los archivos de linters, formatters y compiladores NO deben modificarse`,
|
|
153
|
+
`para resolver errores. En su lugar:`,
|
|
154
|
+
` 1. Corrige el codigo que causa el error de lint/formato`,
|
|
155
|
+
` 2. Si el error es un falso positivo, usa un comentario inline de supresion`,
|
|
156
|
+
` (// eslint-disable-next-line, # noqa, #[allow(...)], etc.)`,
|
|
157
|
+
` 3. Solo modifica la config si es un requisito explicito del plan`,
|
|
158
|
+
``,
|
|
159
|
+
`Si realmente necesitas modificar este archivo, documenta la razon en el commit.`,
|
|
160
|
+
].join('\n');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Funciones de verificación de traversal
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Verifica que la ruta RAW no contenga patrones de traversal conocidos.
|
|
169
|
+
* @param {string} rutaRaw - Ruta tal como la entregó Claude Code.
|
|
170
|
+
* @returns {{ segura: boolean, descripcion: string }}
|
|
171
|
+
*/
|
|
172
|
+
function verificarPatronesTraversal(rutaRaw) {
|
|
173
|
+
for (const { patron, descripcion } of PATRONES_TRAVERSAL) {
|
|
174
|
+
if (patron.test(rutaRaw)) {
|
|
175
|
+
return { segura: false, descripcion };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return { segura: true, descripcion: '' };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Verifica que la ruta resuelta esté dentro del directorio de trabajo actual.
|
|
183
|
+
*
|
|
184
|
+
* Se usa path.resolve() para expandir rutas relativas y eliminar ".." que
|
|
185
|
+
* pudieran haber pasado los filtros anteriores. La comparación se hace con
|
|
186
|
+
* ambas rutas normalizadas a minúsculas en Windows (case-insensitive FS).
|
|
187
|
+
*
|
|
188
|
+
* @param {string} rutaRaw - Ruta recibida del hook.
|
|
189
|
+
* @param {string} cwdActual - Directorio de trabajo actual del proceso.
|
|
190
|
+
* @returns {{ dentro: boolean, rutaResuelta: string }}
|
|
191
|
+
*/
|
|
192
|
+
function verificarDentroDeCwd(rutaRaw, cwdActual) {
|
|
193
|
+
const rutaResuelta = path.resolve(cwdActual, rutaRaw);
|
|
194
|
+
|
|
195
|
+
// Normalizar separadores y agregar "/" al final del CWD para evitar
|
|
196
|
+
// falsos positivos con directorios que comparten prefijo.
|
|
197
|
+
// Ej: CWD=/proyecto y ruta=/proyecto-extra no debe pasar.
|
|
198
|
+
const cwdNorm = normalizarSeparadores(cwdActual).replace(/\/?$/, '/');
|
|
199
|
+
const rutaNorm = normalizarSeparadores(rutaResuelta);
|
|
200
|
+
|
|
201
|
+
// En Windows el sistema de archivos es case-insensitive
|
|
202
|
+
const esDentroDeCwd = process.platform === 'win32'
|
|
203
|
+
? rutaNorm.toLowerCase().startsWith(cwdNorm.toLowerCase())
|
|
204
|
+
: rutaNorm.startsWith(cwdNorm);
|
|
205
|
+
|
|
206
|
+
return { dentro: esDentroDeCwd, rutaResuelta };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Rutas permitidas fuera del CWD.
|
|
211
|
+
* Estas rutas son legítimas para el funcionamiento de Claude Code
|
|
212
|
+
* (memoria persistente, configuración de proyecto, etc.).
|
|
213
|
+
*
|
|
214
|
+
* Se comparan con startsWith case-insensitive en Windows.
|
|
215
|
+
*/
|
|
216
|
+
const RUTAS_PERMITIDAS_EXTERNAS = [
|
|
217
|
+
// Directorio de memoria persistente de Claude Code (auto memory)
|
|
218
|
+
path.join(os.homedir(), '.claude', 'projects'),
|
|
219
|
+
// Configuración global de Claude Code
|
|
220
|
+
path.join(os.homedir(), '.claude', 'settings.json'),
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Verifica si una ruta resuelta está en la lista de rutas externas permitidas.
|
|
225
|
+
* @param {string} rutaResuelta
|
|
226
|
+
* @returns {boolean}
|
|
227
|
+
*/
|
|
228
|
+
function esRutaExternaPermitida(rutaResuelta) {
|
|
229
|
+
const rutaNorm = normalizarSeparadores(rutaResuelta);
|
|
230
|
+
for (const permitida of RUTAS_PERMITIDAS_EXTERNAS) {
|
|
231
|
+
const permitidaNorm = normalizarSeparadores(permitida);
|
|
232
|
+
const coincide = process.platform === 'win32'
|
|
233
|
+
? rutaNorm.toLowerCase().startsWith(permitidaNorm.toLowerCase())
|
|
234
|
+
: rutaNorm.startsWith(permitidaNorm);
|
|
235
|
+
if (coincide) return true;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Extrae el file_path del payload del hook.
|
|
242
|
+
* Soporta las variantes que Claude Code puede enviar.
|
|
243
|
+
*
|
|
244
|
+
* @param {object} toolInput
|
|
245
|
+
* @returns {string|null}
|
|
246
|
+
*/
|
|
247
|
+
function extraerRuta(toolInput) {
|
|
248
|
+
const candidatos = [
|
|
249
|
+
toolInput.file_path,
|
|
250
|
+
toolInput.path,
|
|
251
|
+
toolInput.filename,
|
|
252
|
+
toolInput.dest,
|
|
253
|
+
];
|
|
254
|
+
for (const c of candidatos) {
|
|
255
|
+
if (typeof c === 'string' && c.trim() !== '') return c.trim();
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
// Construcción de mensaje de bloqueo
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Construye el mensaje de error para devolver a Claude Code.
|
|
266
|
+
* @param {string} tipoViolacion - Descripción corta del tipo de violación.
|
|
267
|
+
* @param {string} rutaRaw - Ruta original recibida.
|
|
268
|
+
* @param {string} rutaResuelta - Ruta resuelta por path.resolve.
|
|
269
|
+
* @param {string} cwdActual - CWD del proceso.
|
|
270
|
+
* @returns {string}
|
|
271
|
+
*/
|
|
272
|
+
function construirMensajeBloqueo(tipoViolacion, rutaRaw, rutaResuelta, cwdActual) {
|
|
273
|
+
return [
|
|
274
|
+
`Escritura bloqueada por política de seguridad de rutas.`,
|
|
275
|
+
``,
|
|
276
|
+
`Violación: ${tipoViolacion}`,
|
|
277
|
+
`Ruta recibida: ${rutaRaw}`,
|
|
278
|
+
`Ruta resuelta: ${rutaResuelta || '(no calculada)'}`,
|
|
279
|
+
`Directorio CWD: ${cwdActual}`,
|
|
280
|
+
``,
|
|
281
|
+
`Reglas de seguridad:`,
|
|
282
|
+
` - La ruta de destino debe estar dentro del directorio de trabajo actual.`,
|
|
283
|
+
` - No se permiten secuencias de path traversal (../, ~/, %2e%2e, etc.).`,
|
|
284
|
+
` - No se permiten rutas absolutas fuera del proyecto.`,
|
|
285
|
+
``,
|
|
286
|
+
`Si necesitas escribir fuera del CWD, ajusta el directorio de trabajo`,
|
|
287
|
+
`o utiliza una ruta relativa dentro del proyecto.`,
|
|
288
|
+
].join('\n');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// ---------------------------------------------------------------------------
|
|
292
|
+
// Entrypoint principal
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
|
|
295
|
+
let inputRaw = '';
|
|
296
|
+
|
|
297
|
+
process.stdin.on('data', chunk => {
|
|
298
|
+
inputRaw += chunk;
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
process.stdin.on('end', () => {
|
|
302
|
+
try {
|
|
303
|
+
const data = JSON.parse(inputRaw);
|
|
304
|
+
|
|
305
|
+
const toolName = String(data.tool_name || data.tool?.name || '');
|
|
306
|
+
const toolInput = data.tool_input || data.tool?.input || {};
|
|
307
|
+
const sessionId = String(data.session_id || 'default');
|
|
308
|
+
|
|
309
|
+
// Este hook solo aplica a Write y Edit
|
|
310
|
+
if (!['Write', 'Edit'].includes(toolName)) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Extraer la ruta de destino
|
|
315
|
+
const rutaRaw = extraerRuta(toolInput);
|
|
316
|
+
if (!rutaRaw) {
|
|
317
|
+
// Sin ruta, nada que verificar — dejar que Claude Code maneje el error
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const cwdActual = process.cwd();
|
|
322
|
+
|
|
323
|
+
// --- Verificación 1: patrones de traversal en la ruta raw ---
|
|
324
|
+
const { segura, descripcion } = verificarPatronesTraversal(rutaRaw);
|
|
325
|
+
if (!segura) {
|
|
326
|
+
const { rutaResuelta } = verificarDentroDeCwd(rutaRaw, cwdActual);
|
|
327
|
+
const razon = construirMensajeBloqueo(
|
|
328
|
+
`Path traversal detectado — ${descripcion}`,
|
|
329
|
+
rutaRaw,
|
|
330
|
+
rutaResuelta,
|
|
331
|
+
cwdActual
|
|
332
|
+
);
|
|
333
|
+
process.stderr.write(razon);
|
|
334
|
+
try { require('./lib/guardrail-metrics').recordActivation('proteccion-rutas.js', sessionId, true); } catch (_) {}
|
|
335
|
+
process.exit(2);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// --- Verificación 2: destino dentro del CWD o en rutas externas permitidas ---
|
|
339
|
+
const { dentro, rutaResuelta } = verificarDentroDeCwd(rutaRaw, cwdActual);
|
|
340
|
+
if (!dentro && !esRutaExternaPermitida(rutaResuelta)) {
|
|
341
|
+
const razon = construirMensajeBloqueo(
|
|
342
|
+
`Destino fuera del directorio de trabajo actual`,
|
|
343
|
+
rutaRaw,
|
|
344
|
+
rutaResuelta,
|
|
345
|
+
cwdActual
|
|
346
|
+
);
|
|
347
|
+
process.stderr.write(razon);
|
|
348
|
+
try { require('./lib/guardrail-metrics').recordActivation('proteccion-rutas.js', sessionId, true); } catch (_) {}
|
|
349
|
+
process.exit(2);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// --- Verificación 3: archivos de configuración protegidos ---
|
|
353
|
+
const { protegido, archivo } = verificarConfigProtegido(rutaRaw);
|
|
354
|
+
if (protegido) {
|
|
355
|
+
const advertencia = construirMensajeConfigProtegido(archivo, rutaRaw);
|
|
356
|
+
process.stdout.write(advertencia);
|
|
357
|
+
// Exit 0 (advertencia, no bloqueo) — el agente ve el mensaje pero puede continuar
|
|
358
|
+
// si tiene justificacion explicita. Para bloquear, cambiar a process.exit(2).
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Ruta segura — permitir la operación
|
|
362
|
+
|
|
363
|
+
} catch (err) {
|
|
364
|
+
// El hook nunca bloquea por errores internos propios
|
|
365
|
+
}
|
|
366
|
+
});
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: registro-turnos.js
|
|
6
|
+
* Tipo: PostToolUse (todas las herramientas)
|
|
7
|
+
*
|
|
8
|
+
* Persiste cada tool call (turno) en .planning/sessions/{session_id}/turns.jsonl
|
|
9
|
+
* para auditoría granular y futuro replay/fork de sesiones.
|
|
10
|
+
*
|
|
11
|
+
* Patrón inspirado en `temp/claudian-main/src/core/bootstrap/SessionStorage.ts`
|
|
12
|
+
* (plugin Obsidian Claudian, Yishen Tu, MIT). Diferencias respecto al
|
|
13
|
+
* original:
|
|
14
|
+
* - Claudian persiste SessionMetadata + transcripts en JSONL del provider.
|
|
15
|
+
* SWL persiste turn-by-turn en formato propio compatible con
|
|
16
|
+
* .planning/sessions/.
|
|
17
|
+
* - Sanitización agresiva de entrada/salida antes de persistir
|
|
18
|
+
* (riesgo PII/secretos en argumentos de tools).
|
|
19
|
+
*
|
|
20
|
+
* Estado: OPT-IN. Inactivo por defecto. Activar con SWL_REGISTRO_TURNOS=1.
|
|
21
|
+
*
|
|
22
|
+
* Razones del default OFF:
|
|
23
|
+
* - Volumen alto: cada tool call genera entrada (decenas por sesión).
|
|
24
|
+
* - Riesgo PII: tool_input de Bash/Write/Edit puede contener tokens,
|
|
25
|
+
* contraseñas pegadas accidentalmente, paths privados.
|
|
26
|
+
* - El usuario debe decidir explícitamente activarlo en su entorno.
|
|
27
|
+
*
|
|
28
|
+
* Schema de cada turno (JSONL append-only):
|
|
29
|
+
* {
|
|
30
|
+
* ts: ISO timestamp,
|
|
31
|
+
* session_id: string,
|
|
32
|
+
* tool: string,
|
|
33
|
+
* input_resumen: string, // preview ≤ 200 chars, secrets sanitizados
|
|
34
|
+
* output_resumen: string, // preview ≤ 500 chars, secrets sanitizados
|
|
35
|
+
* duracion_ms?: number,
|
|
36
|
+
* agente?: string, // si tool=Agent, subagent_type
|
|
37
|
+
* error?: boolean
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* NUNCA persiste:
|
|
41
|
+
* - tool_input completo (truncado a 200 chars)
|
|
42
|
+
* - tool_response completo (truncado a 500 chars)
|
|
43
|
+
* - Patrones que parezcan tokens/secretos (sanitizados a [REDACTED])
|
|
44
|
+
*
|
|
45
|
+
* Variables de entorno:
|
|
46
|
+
* SWL_REGISTRO_TURNOS=1 - activa el hook (default: OFF)
|
|
47
|
+
* SWL_REGISTRO_TURNOS_LIMITE - máximo turns por sesión (default: 1000)
|
|
48
|
+
*
|
|
49
|
+
* Helper de inspección:
|
|
50
|
+
* /swl:sesiones --turnos=<session_id>
|
|
51
|
+
*
|
|
52
|
+
* @see hooks/lib/atomic-write.js
|
|
53
|
+
* @see hooks/lib/privacy-filter.js (si existe; fallback inline si no)
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
const fs = require('fs');
|
|
57
|
+
const path = require('path');
|
|
58
|
+
|
|
59
|
+
const LIMITE_TURNOS = parseInt(process.env.SWL_REGISTRO_TURNOS_LIMITE || '1000', 10);
|
|
60
|
+
const MAX_INPUT_CHARS = 200;
|
|
61
|
+
const MAX_OUTPUT_CHARS = 500;
|
|
62
|
+
const DIR_BASE = path.join(process.cwd(), '.planning', 'sessions');
|
|
63
|
+
|
|
64
|
+
// Patrones de sanitización conservadores: tokens largos, llaves API, JWT,
|
|
65
|
+
// password en URLs, paths con .env. Si aparece un match, se reemplaza con
|
|
66
|
+
// [REDACTED].
|
|
67
|
+
const PATRONES_REDACT = [
|
|
68
|
+
/\b[A-Za-z0-9_-]{32,}\b/g, // tokens largos
|
|
69
|
+
/(?:sk|pk|key|token|secret|password|pwd|api[_-]?key)["':\s=]+[A-Za-z0-9_\-./]{8,}/gi,
|
|
70
|
+
/\bey[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/g, // JWT
|
|
71
|
+
/https?:\/\/[^:]+:[^@\s]+@/g, // basic auth en URL
|
|
72
|
+
/-----BEGIN [A-Z ]+-----[\s\S]*?-----END [A-Z ]+-----/g, // PEM blocks
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
function sanitizar(texto) {
|
|
76
|
+
if (!texto) return '';
|
|
77
|
+
let r = String(texto);
|
|
78
|
+
for (const re of PATRONES_REDACT) {
|
|
79
|
+
r = r.replace(re, '[REDACTED]');
|
|
80
|
+
}
|
|
81
|
+
return r;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function truncar(texto, max) {
|
|
85
|
+
const s = sanitizar(texto);
|
|
86
|
+
if (s.length <= max) return s;
|
|
87
|
+
return s.slice(0, max - 3) + '...';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function ensureDir(dir) {
|
|
91
|
+
try { fs.mkdirSync(dir, { recursive: true }); } catch { /* ignore */ }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function contarTurnos(rutaArchivo) {
|
|
95
|
+
try {
|
|
96
|
+
if (!fs.existsSync(rutaArchivo)) return 0;
|
|
97
|
+
const contenido = fs.readFileSync(rutaArchivo, 'utf8');
|
|
98
|
+
return contenido.split(/\r?\n/).filter(Boolean).length;
|
|
99
|
+
} catch {
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function extraerInfoTurno(data) {
|
|
105
|
+
const toolName = String(data.tool_name || data.tool?.name || '');
|
|
106
|
+
if (!toolName) return null;
|
|
107
|
+
|
|
108
|
+
const sessionId = String(data.session_id || 'default').slice(0, 64);
|
|
109
|
+
|
|
110
|
+
const toolInput = data.tool_input || data.tool?.input || {};
|
|
111
|
+
const toolResponse = data.tool_response || data.tool_result || {};
|
|
112
|
+
|
|
113
|
+
// Resumen de input: serializar y truncar
|
|
114
|
+
let inputStr = '';
|
|
115
|
+
try {
|
|
116
|
+
inputStr = typeof toolInput === 'string'
|
|
117
|
+
? toolInput
|
|
118
|
+
: JSON.stringify(toolInput);
|
|
119
|
+
} catch { inputStr = '[unserializable]'; }
|
|
120
|
+
|
|
121
|
+
// Resumen de output: extraer campos comunes
|
|
122
|
+
let outputStr = '';
|
|
123
|
+
try {
|
|
124
|
+
if (typeof toolResponse === 'string') {
|
|
125
|
+
outputStr = toolResponse;
|
|
126
|
+
} else if (toolResponse && typeof toolResponse === 'object') {
|
|
127
|
+
const campos = ['output', 'content', 'stdout', 'text', 'result', 'message', 'error'];
|
|
128
|
+
for (const c of campos) {
|
|
129
|
+
if (typeof toolResponse[c] === 'string') {
|
|
130
|
+
outputStr = toolResponse[c];
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (!outputStr) outputStr = JSON.stringify(toolResponse);
|
|
135
|
+
}
|
|
136
|
+
} catch { outputStr = '[unserializable]'; }
|
|
137
|
+
|
|
138
|
+
const esError = !!(toolResponse && (toolResponse.is_error || toolResponse.status === 'failed'));
|
|
139
|
+
|
|
140
|
+
const turno = {
|
|
141
|
+
ts: new Date().toISOString(),
|
|
142
|
+
session_id: sessionId,
|
|
143
|
+
tool: toolName,
|
|
144
|
+
input_resumen: truncar(inputStr, MAX_INPUT_CHARS),
|
|
145
|
+
output_resumen: truncar(outputStr, MAX_OUTPUT_CHARS),
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
if (data.duration_ms || toolResponse.duration_ms) {
|
|
149
|
+
turno.duracion_ms = data.duration_ms || toolResponse.duration_ms;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (toolName === 'Agent') {
|
|
153
|
+
const subType = toolInput.subagent_type || toolInput.type;
|
|
154
|
+
if (subType) turno.agente = String(subType).slice(0, 60);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (esError) turno.error = true;
|
|
158
|
+
|
|
159
|
+
return turno;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Solo registrar listeners de stdin en modo CLI. Cuando se importa como
|
|
163
|
+
// módulo (tests), registrar listeners mantiene el event loop vivo
|
|
164
|
+
// indefinidamente porque stdin nunca emite 'end' en ese contexto, lo que
|
|
165
|
+
// hace que la suite de tests cuelgue hasta el timeout. El hook real
|
|
166
|
+
// invocado por Claude Code siempre se ejecuta como require.main.
|
|
167
|
+
//
|
|
168
|
+
// El opt-in via SWL_REGISTRO_TURNOS también se evalúa aquí adentro: si
|
|
169
|
+
// estuviera en el top-level del archivo, importar el módulo desde un
|
|
170
|
+
// test sin la env var mataría al test runner via process.exit(0).
|
|
171
|
+
if (require.main === module) {
|
|
172
|
+
if (process.env.SWL_REGISTRO_TURNOS !== '1') {
|
|
173
|
+
// OPT-IN: hook inactivo por default. Salir silencioso sin leer stdin.
|
|
174
|
+
process.exit(0);
|
|
175
|
+
}
|
|
176
|
+
let inputRaw = '';
|
|
177
|
+
process.stdin.on('data', chunk => { inputRaw += chunk; });
|
|
178
|
+
|
|
179
|
+
process.stdin.on('end', () => {
|
|
180
|
+
try {
|
|
181
|
+
const data = JSON.parse(inputRaw);
|
|
182
|
+
const turno = extraerInfoTurno(data);
|
|
183
|
+
if (!turno) return;
|
|
184
|
+
|
|
185
|
+
const dirSesion = path.join(DIR_BASE, turno.session_id);
|
|
186
|
+
ensureDir(dirSesion);
|
|
187
|
+
const rutaArchivo = path.join(dirSesion, 'turns.jsonl');
|
|
188
|
+
|
|
189
|
+
if (contarTurnos(rutaArchivo) >= LIMITE_TURNOS) {
|
|
190
|
+
// Hard cap: no seguir creciendo. El usuario decide rotar/limpiar.
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fs.appendFileSync(rutaArchivo, JSON.stringify(turno) + '\n', 'utf8');
|
|
195
|
+
} catch (err) {
|
|
196
|
+
// Hook nunca bloquea Claude Code, pero deja una traza diagnóstica
|
|
197
|
+
// para no perder regresiones silenciosas (ver feedback memoria
|
|
198
|
+
// sobre errores silenciados).
|
|
199
|
+
process.stderr.write(`[registro-turnos] error interno: ${String(err.message || err).slice(0, 120)}\n`);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
module.exports = {
|
|
204
|
+
extraerInfoTurno,
|
|
205
|
+
sanitizar,
|
|
206
|
+
truncar,
|
|
207
|
+
_internals: { PATRONES_REDACT, MAX_INPUT_CHARS, MAX_OUTPUT_CHARS, LIMITE_TURNOS },
|
|
208
|
+
};
|
|
209
|
+
}
|