@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,511 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: calidad-typescript.js
|
|
6
|
+
* Tipo: PreToolUse (aplica a: Bash — comandos git commit)
|
|
7
|
+
*
|
|
8
|
+
* Verifica calidad TypeScript en archivos staged ANTES de que Claude Code
|
|
9
|
+
* ejecute un `git commit`. Complementa a calidad-pre-commit.js con
|
|
10
|
+
* verificaciones específicas del sistema de tipos de TypeScript.
|
|
11
|
+
*
|
|
12
|
+
* Verificaciones (sin dependencias externas):
|
|
13
|
+
* 1. Nuevas introducciones de `any` explícito en el diff
|
|
14
|
+
* 2. @ts-ignore sin comentario de justificación en la línea anterior
|
|
15
|
+
* 3. `as unknown as T` (double cast para evadir el type system)
|
|
16
|
+
* 4. Funciones async sin tipo de retorno cuando el retorno no es void/any
|
|
17
|
+
* 5. Errores de tsc --noEmit si el proyecto tiene tsconfig.json
|
|
18
|
+
*
|
|
19
|
+
* Verificaciones con ts-morph (si está instalado en el proyecto):
|
|
20
|
+
* 6. Imports no usados (más precisos que grep)
|
|
21
|
+
* 7. Variables declaradas con `var` en archivos TypeScript
|
|
22
|
+
*
|
|
23
|
+
* Resultado:
|
|
24
|
+
* - Violaciones CRÍTICAS → stdout + exit code 2 (bloquea el commit)
|
|
25
|
+
* - Advertencias → stdout + exit code 0 (no bloquea)
|
|
26
|
+
* - Sin violaciones → sin output, exit natural
|
|
27
|
+
* - Error interno → sin output (nunca bloquear por fallo del hook)
|
|
28
|
+
*
|
|
29
|
+
* Escenario C — integración con ts-morph:
|
|
30
|
+
* Si el proyecto tiene ts-morph instalado (`node_modules/ts-morph`),
|
|
31
|
+
* este hook lo usa automáticamente para análisis más profundo.
|
|
32
|
+
* Si no está disponible, las verificaciones básicas de grep siguen funcionando.
|
|
33
|
+
*
|
|
34
|
+
* Performance:
|
|
35
|
+
* Usa hooks/lib/performance-marks.js para medir tiempos de cada verificación.
|
|
36
|
+
* El reporte de tiempos se incluye en el output cuando hay violaciones.
|
|
37
|
+
*
|
|
38
|
+
* @module hooks/calidad-typescript
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
const fs = require('fs');
|
|
42
|
+
const path = require('path');
|
|
43
|
+
const { execSync } = require('child_process');
|
|
44
|
+
const perf = require('./lib/performance-marks');
|
|
45
|
+
const { normalizeForDetection } = require('./lib/normalize-input');
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Configuración
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
const CWD = process.cwd();
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Directorios excluidos de verificación.
|
|
55
|
+
* Los archivos en estos paths no se verifican aunque estén en el diff.
|
|
56
|
+
*/
|
|
57
|
+
const EXCLUIR_DIRS = [
|
|
58
|
+
'node_modules', '.next', 'dist', 'build', 'out', 'coverage',
|
|
59
|
+
'.planning', 'temp', '.cache',
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// Utilidades
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Verifica si el comando actual es un git commit.
|
|
68
|
+
* @param {string} cmd
|
|
69
|
+
* @returns {boolean}
|
|
70
|
+
*/
|
|
71
|
+
function esGitCommit(cmd) {
|
|
72
|
+
return /\bgit\s+commit\b/.test(cmd);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Obtiene los archivos TypeScript staged para commit.
|
|
77
|
+
* @returns {string[]} rutas de archivos .ts/.tsx staged
|
|
78
|
+
*/
|
|
79
|
+
function obtenerArchivosTSStagged() {
|
|
80
|
+
try {
|
|
81
|
+
const out = execSync('git diff --cached --name-only --diff-filter=ACMR', {
|
|
82
|
+
cwd: CWD, encoding: 'utf8', stdio: ['pipe','pipe','pipe'],
|
|
83
|
+
});
|
|
84
|
+
return out.trim().split('\n')
|
|
85
|
+
.filter(f => f && (f.endsWith('.ts') || f.endsWith('.tsx')))
|
|
86
|
+
.filter(f => !EXCLUIR_DIRS.some(d => f.startsWith(d + '/')))
|
|
87
|
+
.filter(f => !f.includes('.d.ts'));
|
|
88
|
+
} catch (_) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Obtiene el contenido del diff staged para los archivos TS.
|
|
95
|
+
* @returns {string}
|
|
96
|
+
*/
|
|
97
|
+
function obtenerDiffTS() {
|
|
98
|
+
try {
|
|
99
|
+
return execSync('git diff --cached -- "*.ts" "*.tsx"', {
|
|
100
|
+
cwd: CWD, encoding: 'utf8', stdio: ['pipe','pipe','pipe'],
|
|
101
|
+
});
|
|
102
|
+
} catch (_) {
|
|
103
|
+
return '';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Extrae solo las líneas añadidas del diff (líneas con + al inicio).
|
|
109
|
+
* Excluye encabezados de archivos (+++ ...).
|
|
110
|
+
* @param {string} diff
|
|
111
|
+
* @returns {{ archivo: string, linea: number, contenido: string }[]}
|
|
112
|
+
*/
|
|
113
|
+
function extraerLineasAgregadas(diff) {
|
|
114
|
+
const resultado = [];
|
|
115
|
+
let archivoActual = '';
|
|
116
|
+
let lineaActual = 0;
|
|
117
|
+
|
|
118
|
+
for (const linea of diff.split('\n')) {
|
|
119
|
+
// Encabezado de archivo nuevo
|
|
120
|
+
const matchArchivo = linea.match(/^\+\+\+ b\/(.+)/);
|
|
121
|
+
if (matchArchivo) {
|
|
122
|
+
archivoActual = matchArchivo[1];
|
|
123
|
+
lineaActual = 0;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Número de línea en el nuevo archivo
|
|
128
|
+
const matchHunk = linea.match(/^@@.*\+(\d+)/);
|
|
129
|
+
if (matchHunk) {
|
|
130
|
+
lineaActual = parseInt(matchHunk[1], 10) - 1;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (linea.startsWith('+') && !linea.startsWith('+++')) {
|
|
135
|
+
lineaActual++;
|
|
136
|
+
resultado.push({
|
|
137
|
+
archivo: archivoActual,
|
|
138
|
+
linea: lineaActual,
|
|
139
|
+
contenido: linea.slice(1), // quitar el + del diff
|
|
140
|
+
});
|
|
141
|
+
} else if (!linea.startsWith('-')) {
|
|
142
|
+
lineaActual++;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return resultado;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
// Verificaciones de calidad TypeScript
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 1. Detecta introducciones nuevas de `any` explícito sin justificación.
|
|
155
|
+
* Busca en líneas agregadas del diff.
|
|
156
|
+
*
|
|
157
|
+
* @param {Array} lineasAgregadas
|
|
158
|
+
* @returns {{ archivo: string, linea: number, descripcion: string }[]}
|
|
159
|
+
*/
|
|
160
|
+
function verificarAnyExplicito(lineasAgregadas) {
|
|
161
|
+
perf.mark('anyCheck_start');
|
|
162
|
+
const violaciones = [];
|
|
163
|
+
|
|
164
|
+
const patronAny = /(?<!\/\/.*)(?<!\w)(?::\s*any\b|as\s+any\b|<any>|Array<any>|Promise<any>|Record<string,\s*any>)/;
|
|
165
|
+
const patronJustificado = /\/\/\s*(eslint-disable|ts-ignore|any justificado|FIXME|TODO|hack)/i;
|
|
166
|
+
|
|
167
|
+
for (const { archivo, linea, contenido } of lineasAgregadas) {
|
|
168
|
+
if (!patronAny.test(contenido)) continue;
|
|
169
|
+
// Si la línea tiene un comentario de justificación, no es violación
|
|
170
|
+
if (patronJustificado.test(contenido)) continue;
|
|
171
|
+
// Si es en un archivo de test, es advertencia no crítica
|
|
172
|
+
const esTest = archivo.includes('.test.') || archivo.includes('.spec.') || archivo.includes('__tests__');
|
|
173
|
+
violaciones.push({
|
|
174
|
+
archivo, linea,
|
|
175
|
+
descripcion: `'any' introducido sin justificación${esTest ? ' (en test)' : ''}`,
|
|
176
|
+
severidad: esTest ? 'advertencia' : 'critica',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
perf.mark('anyCheck_end');
|
|
181
|
+
perf.measure('anyCheck', 'anyCheck_start', 'anyCheck_end');
|
|
182
|
+
return violaciones;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 2. Detecta @ts-ignore sin comentario explicativo en la línea anterior.
|
|
187
|
+
*
|
|
188
|
+
* @param {string[]} archivos — lista de rutas relativas
|
|
189
|
+
* @returns {{ archivo: string, linea: number, descripcion: string }[]}
|
|
190
|
+
*/
|
|
191
|
+
function verificarTsIgnore(archivos) {
|
|
192
|
+
perf.mark('tsIgnoreCheck_start');
|
|
193
|
+
const violaciones = [];
|
|
194
|
+
|
|
195
|
+
for (const archivo of archivos) {
|
|
196
|
+
let contenido;
|
|
197
|
+
try {
|
|
198
|
+
contenido = fs.readFileSync(path.join(CWD, archivo), 'utf8');
|
|
199
|
+
} catch (_) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const lineas = contenido.split('\n');
|
|
204
|
+
for (let i = 0; i < lineas.length; i++) {
|
|
205
|
+
const linea = lineas[i];
|
|
206
|
+
if (!/@ts-ignore/.test(linea)) continue;
|
|
207
|
+
|
|
208
|
+
// Verificar que la línea actual o la anterior tiene un comentario explicativo
|
|
209
|
+
const lineaAnterior = i > 0 ? lineas[i - 1] : '';
|
|
210
|
+
const tieneJustificacion =
|
|
211
|
+
/\/\/\s*.{5,}/.test(lineaAnterior) || // comentario con texto en línea anterior
|
|
212
|
+
/\/\/\s*.{5,}/.test(linea.replace('@ts-ignore', '').trim()); // comentario en misma línea
|
|
213
|
+
|
|
214
|
+
if (!tieneJustificacion) {
|
|
215
|
+
violaciones.push({
|
|
216
|
+
archivo, linea: i + 1,
|
|
217
|
+
descripcion: '@ts-ignore sin comentario de justificación (¿por qué no se puede tipar correctamente?)',
|
|
218
|
+
severidad: 'critica',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
perf.mark('tsIgnoreCheck_end');
|
|
225
|
+
perf.measure('tsIgnoreCheck', 'tsIgnoreCheck_start', 'tsIgnoreCheck_end');
|
|
226
|
+
return violaciones;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* 3. Detecta double cast `as unknown as T` para evadir el type system.
|
|
231
|
+
*
|
|
232
|
+
* @param {Array} lineasAgregadas
|
|
233
|
+
* @returns {{ archivo: string, linea: number, descripcion: string }[]}
|
|
234
|
+
*/
|
|
235
|
+
function verificarDoubleCast(lineasAgregadas) {
|
|
236
|
+
perf.mark('doubleCastCheck_start');
|
|
237
|
+
const violaciones = [];
|
|
238
|
+
const patron = /as\s+unknown\s+as\s+\w/;
|
|
239
|
+
|
|
240
|
+
for (const { archivo, linea, contenido } of lineasAgregadas) {
|
|
241
|
+
if (!patron.test(contenido)) continue;
|
|
242
|
+
violaciones.push({
|
|
243
|
+
archivo, linea,
|
|
244
|
+
descripcion: "'as unknown as T' — double cast para evadir el type system. Tipar la fuente correctamente o usar type guard",
|
|
245
|
+
severidad: 'critica',
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
perf.mark('doubleCastCheck_end');
|
|
250
|
+
perf.measure('doubleCastCheck', 'doubleCastCheck_start', 'doubleCastCheck_end');
|
|
251
|
+
return violaciones;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 4. Detecta catch blocks con tipo any o Error en lugar de unknown.
|
|
256
|
+
*
|
|
257
|
+
* @param {Array} lineasAgregadas
|
|
258
|
+
* @returns {{ archivo: string, linea: number, descripcion: string }[]}
|
|
259
|
+
*/
|
|
260
|
+
function verificarCatchTipos(lineasAgregadas) {
|
|
261
|
+
perf.mark('catchCheck_start');
|
|
262
|
+
const violaciones = [];
|
|
263
|
+
|
|
264
|
+
const patronCatchAny = /catch\s*\(\s*\w+\s*:\s*any\s*\)/;
|
|
265
|
+
const patronCatchError = /catch\s*\(\s*\w+\s*:\s*Error\s*\)/;
|
|
266
|
+
|
|
267
|
+
for (const { archivo, linea, contenido } of lineasAgregadas) {
|
|
268
|
+
if (patronCatchAny.test(contenido)) {
|
|
269
|
+
violaciones.push({
|
|
270
|
+
archivo, linea,
|
|
271
|
+
descripcion: "catch (e: any) — usar 'unknown' y narrowing con instanceof",
|
|
272
|
+
severidad: 'critica',
|
|
273
|
+
});
|
|
274
|
+
} else if (patronCatchError.test(contenido)) {
|
|
275
|
+
violaciones.push({
|
|
276
|
+
archivo, linea,
|
|
277
|
+
descripcion: "catch (e: Error) — el tipo en catch es siempre 'unknown' en TS moderno. Usar instanceof Error para narrowing",
|
|
278
|
+
severidad: 'mayor',
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
perf.mark('catchCheck_end');
|
|
284
|
+
perf.measure('catchCheck', 'catchCheck_start', 'catchCheck_end');
|
|
285
|
+
return violaciones;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 5. Ejecuta tsc --noEmit si el proyecto tiene tsconfig.json.
|
|
290
|
+
* Captura los primeros errores (no bloquea si tsc no está disponible).
|
|
291
|
+
*
|
|
292
|
+
* @returns {{ errores: string[], tiempoMs: number }}
|
|
293
|
+
*/
|
|
294
|
+
function ejecutarTsc() {
|
|
295
|
+
perf.mark('tsc_start');
|
|
296
|
+
const resultado = { errores: [], tiempoMs: 0 };
|
|
297
|
+
|
|
298
|
+
const tsconfigPath = path.join(CWD, 'tsconfig.json');
|
|
299
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
300
|
+
perf.mark('tsc_end');
|
|
301
|
+
perf.measure('tsc', 'tsc_start', 'tsc_end');
|
|
302
|
+
return resultado;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
execSync('npx tsc --noEmit 2>&1', {
|
|
307
|
+
cwd: CWD, encoding: 'utf8', stdio: ['pipe','pipe','pipe'], timeout: 60_000,
|
|
308
|
+
});
|
|
309
|
+
} catch (err) {
|
|
310
|
+
const output = (err.stdout || err.stderr || '').toString();
|
|
311
|
+
// Extraer solo los primeros 10 errores — evitar output masivo
|
|
312
|
+
const lineas = output.split('\n').filter(l => l.includes(': error TS'));
|
|
313
|
+
resultado.errores = lineas.slice(0, 10);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
perf.mark('tsc_end');
|
|
317
|
+
perf.measure('tsc', 'tsc_start', 'tsc_end');
|
|
318
|
+
return resultado;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 6. Verificaciones con ts-morph si está disponible.
|
|
323
|
+
* Graceful degradation: si no está instalado, retorna vacío.
|
|
324
|
+
*
|
|
325
|
+
* @param {string[]} archivos
|
|
326
|
+
* @returns {{ violaciones: Array, disponible: boolean }}
|
|
327
|
+
*/
|
|
328
|
+
function verificarConTsMorph(archivos) {
|
|
329
|
+
perf.mark('tsMorph_start');
|
|
330
|
+
const resultado = { violaciones: [], disponible: false };
|
|
331
|
+
|
|
332
|
+
// Verificar si ts-morph está disponible
|
|
333
|
+
const tsMorphPath = path.join(CWD, 'node_modules', 'ts-morph');
|
|
334
|
+
if (!fs.existsSync(tsMorphPath)) {
|
|
335
|
+
perf.mark('tsMorph_end');
|
|
336
|
+
perf.measure('tsMorph', 'tsMorph_start', 'tsMorph_end');
|
|
337
|
+
return resultado;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
try {
|
|
341
|
+
const { Project } = require(tsMorphPath);
|
|
342
|
+
resultado.disponible = true;
|
|
343
|
+
|
|
344
|
+
const project = new Project({
|
|
345
|
+
tsConfigFilePath: path.join(CWD, 'tsconfig.json'),
|
|
346
|
+
skipAddingFilesFromTsConfig: true,
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
for (const rutaRelativa of archivos.slice(0, 20)) { // Limitar a 20 archivos
|
|
350
|
+
const rutaAbsoluta = path.join(CWD, rutaRelativa);
|
|
351
|
+
if (!fs.existsSync(rutaAbsoluta)) continue;
|
|
352
|
+
|
|
353
|
+
const sourceFile = project.addSourceFileAtPath(rutaAbsoluta);
|
|
354
|
+
|
|
355
|
+
// Detectar variables declaradas con `var`
|
|
356
|
+
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
357
|
+
const declarationList = decl.getParent();
|
|
358
|
+
if (declarationList && declarationList.getDeclarationKind &&
|
|
359
|
+
declarationList.getDeclarationKind().toString() === 'var') {
|
|
360
|
+
resultado.violaciones.push({
|
|
361
|
+
archivo: rutaRelativa,
|
|
362
|
+
linea: decl.getStartLineNumber(),
|
|
363
|
+
descripcion: `var '${decl.getName()}' — usar const o let`,
|
|
364
|
+
severidad: 'menor',
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// Detectar console.log en producción (refuerza calidad-pre-commit)
|
|
370
|
+
sourceFile.getDescendantsOfKind(274 /* CallExpression */).forEach(call => {
|
|
371
|
+
const expr = call.getExpression();
|
|
372
|
+
if (expr && expr.getText && /^console\.(log|debug|warn)/.test(expr.getText())) {
|
|
373
|
+
const ruta = call.getSourceFile().getFilePath();
|
|
374
|
+
if (!ruta.includes('.test.') && !ruta.includes('.spec.')) {
|
|
375
|
+
resultado.violaciones.push({
|
|
376
|
+
archivo: rutaRelativa,
|
|
377
|
+
linea: call.getStartLineNumber(),
|
|
378
|
+
descripcion: `${expr.getText()}() — eliminar debug output en producción`,
|
|
379
|
+
severidad: 'menor',
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
} catch (_) {
|
|
386
|
+
// ts-morph disponible pero error al analizar — no bloquear
|
|
387
|
+
resultado.disponible = true;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
perf.mark('tsMorph_end');
|
|
391
|
+
perf.measure('tsMorph', 'tsMorph_start', 'tsMorph_end');
|
|
392
|
+
return resultado;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ---------------------------------------------------------------------------
|
|
396
|
+
// Punto de entrada
|
|
397
|
+
// ---------------------------------------------------------------------------
|
|
398
|
+
|
|
399
|
+
function main() {
|
|
400
|
+
// Leer el input de Claude Code (JSON en stdin)
|
|
401
|
+
let input = '';
|
|
402
|
+
try {
|
|
403
|
+
input = fs.readFileSync('/dev/stdin', 'utf8');
|
|
404
|
+
} catch (_) {
|
|
405
|
+
try {
|
|
406
|
+
// Fallback para Windows
|
|
407
|
+
const buf = [];
|
|
408
|
+
const fd = require('fs').openSync('\\\\.\\pipe\\CONIN$', 'r');
|
|
409
|
+
// Si falla, simplemente no hay input — salir silenciosamente
|
|
410
|
+
} catch (_2) {}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
let datos = {};
|
|
414
|
+
try { datos = JSON.parse(input); } catch (_) { process.exit(0); }
|
|
415
|
+
|
|
416
|
+
const cmd = normalizeForDetection(datos?.tool_input?.command || '');
|
|
417
|
+
if (!esGitCommit(cmd)) process.exit(0);
|
|
418
|
+
|
|
419
|
+
perf.mark('hook_start');
|
|
420
|
+
|
|
421
|
+
// Obtener archivos TypeScript staged
|
|
422
|
+
const archivosTS = obtenerArchivosTSStagged();
|
|
423
|
+
if (archivosTS.length === 0) {
|
|
424
|
+
// No hay archivos TypeScript en el commit — no aplica este hook
|
|
425
|
+
process.exit(0);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Obtener diff de archivos TS
|
|
429
|
+
const diff = obtenerDiffTS();
|
|
430
|
+
const lineasAgregadas = extraerLineasAgregadas(diff);
|
|
431
|
+
|
|
432
|
+
// Ejecutar todas las verificaciones
|
|
433
|
+
const todasViolaciones = [];
|
|
434
|
+
|
|
435
|
+
todasViolaciones.push(...verificarAnyExplicito(lineasAgregadas));
|
|
436
|
+
todasViolaciones.push(...verificarTsIgnore(archivosTS));
|
|
437
|
+
todasViolaciones.push(...verificarDoubleCast(lineasAgregadas));
|
|
438
|
+
todasViolaciones.push(...verificarCatchTipos(lineasAgregadas));
|
|
439
|
+
|
|
440
|
+
// tsc --noEmit
|
|
441
|
+
const { errores: erroresTsc } = ejecutarTsc();
|
|
442
|
+
|
|
443
|
+
// ts-morph (opcional)
|
|
444
|
+
const { violaciones: violacionesMorph } = verificarConTsMorph(archivosTS);
|
|
445
|
+
todasViolaciones.push(...violacionesMorph);
|
|
446
|
+
|
|
447
|
+
perf.mark('hook_end');
|
|
448
|
+
perf.measure('hook_total', 'hook_start', 'hook_end');
|
|
449
|
+
|
|
450
|
+
// Separar críticos de advertencias
|
|
451
|
+
const criticos = todasViolaciones.filter(v => v.severidad === 'critica');
|
|
452
|
+
const mayores = todasViolaciones.filter(v => v.severidad === 'mayor');
|
|
453
|
+
const advertencias = todasViolaciones.filter(v => v.severidad === 'advertencia' || v.severidad === 'menor');
|
|
454
|
+
|
|
455
|
+
const hayProblemas = criticos.length > 0 || mayores.length > 0 || erroresTsc.length > 0;
|
|
456
|
+
|
|
457
|
+
if (!hayProblemas && advertencias.length === 0) process.exit(0);
|
|
458
|
+
|
|
459
|
+
// Generar output
|
|
460
|
+
const lineasOutput = [
|
|
461
|
+
`\n[calidad-typescript] ${archivosTS.length} archivo(s) TypeScript en el commit\n`,
|
|
462
|
+
];
|
|
463
|
+
|
|
464
|
+
if (criticos.length > 0) {
|
|
465
|
+
lineasOutput.push('CRÍTICOS (bloquean el commit):');
|
|
466
|
+
criticos.forEach(v => lineasOutput.push(` ${v.archivo}:${v.linea} — ${v.descripcion}`));
|
|
467
|
+
lineasOutput.push('');
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (mayores.length > 0) {
|
|
471
|
+
lineasOutput.push('MAYORES:');
|
|
472
|
+
mayores.forEach(v => lineasOutput.push(` ${v.archivo}:${v.linea} — ${v.descripcion}`));
|
|
473
|
+
lineasOutput.push('');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (erroresTsc.length > 0) {
|
|
477
|
+
lineasOutput.push(`Errores de tsc --noEmit (${erroresTsc.length} primeros):`);
|
|
478
|
+
erroresTsc.forEach(e => lineasOutput.push(` ${e}`));
|
|
479
|
+
lineasOutput.push('');
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (advertencias.length > 0) {
|
|
483
|
+
lineasOutput.push('Advertencias (no bloquean):');
|
|
484
|
+
advertencias.forEach(v => lineasOutput.push(` ${v.archivo}:${v.linea} — ${v.descripcion}`));
|
|
485
|
+
lineasOutput.push('');
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Agregar reporte de performance si tardó más de 3 segundos
|
|
489
|
+
const durTotal = perf.getDuration('hook_total');
|
|
490
|
+
if (durTotal > 3000) {
|
|
491
|
+
lineasOutput.push(perf.formatReporte({ umbralMs: 50 }));
|
|
492
|
+
lineasOutput.push('');
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// stderr: visible al usuario siempre y enviado a Claude si se usa exit 2.
|
|
496
|
+
// stdout solo se muestra en modo transcript (CTRL-R), no llega al modelo.
|
|
497
|
+
process.stderr.write(lineasOutput.join('\n'));
|
|
498
|
+
|
|
499
|
+
// Bloquear solo si hay críticos, mayores o errores de tsc
|
|
500
|
+
if (criticos.length > 0 || erroresTsc.length > 0) {
|
|
501
|
+
process.exit(2);
|
|
502
|
+
}
|
|
503
|
+
// Mayores: bloquear si hay más de 2
|
|
504
|
+
if (mayores.length > 2) {
|
|
505
|
+
process.exit(2);
|
|
506
|
+
}
|
|
507
|
+
// Si solo hay advertencias o 1-2 mayores: warning sin bloqueo
|
|
508
|
+
process.exit(0);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
main();
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: captura-feedback-usuario.js
|
|
6
|
+
* Tipo: UserPromptSubmit
|
|
7
|
+
*
|
|
8
|
+
* Detecta correcciones explícitas del usuario ("no hagas X", "recuerda Y",
|
|
9
|
+
* "prefiero Z") y las encola en .planning/evolucion/feedback-queue.jsonl
|
|
10
|
+
* para que el perfilador-usuario-swl, el ciclo AGP y /swl:aprender puedan
|
|
11
|
+
* consumirlas sin depender de que el usuario ejecute comandos manualmente.
|
|
12
|
+
*
|
|
13
|
+
* Inspirado en claude-reflect (capture_learning.py). Zero-deps, patrones
|
|
14
|
+
* regex en español e inglés.
|
|
15
|
+
*
|
|
16
|
+
* A diferencia del clasificador-mensajes.js (que hace routing de modelos),
|
|
17
|
+
* este hook captura SEÑALES DE MEMORIA persistente del usuario.
|
|
18
|
+
*
|
|
19
|
+
* Resultado:
|
|
20
|
+
* - Señal detectada → append a feedback-queue.jsonl (no bloquea ni muestra al modelo)
|
|
21
|
+
* - Sin señal → exit 0 silencioso
|
|
22
|
+
* - Error → exit 0 silencioso (nunca bloquea)
|
|
23
|
+
*
|
|
24
|
+
* Opt-out: SWL_CAPTURAR_FEEDBACK=0
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
const path = require('path');
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Patrones de detección
|
|
32
|
+
//
|
|
33
|
+
// Clasificación por tipo de señal:
|
|
34
|
+
// correccion: el usuario corrige un comportamiento ("no hagas X", "no uses Y")
|
|
35
|
+
// preferencia: el usuario declara una preferencia ("prefiero X", "siempre usa Y")
|
|
36
|
+
// memoria: el usuario pide recordar ("recuerda que X", "guarda X")
|
|
37
|
+
// prohibicion: el usuario prohíbe ("nunca X", "jamás Y")
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
const PATRONES = [
|
|
41
|
+
// Correcciones explícitas
|
|
42
|
+
{ tipo: 'correccion', re: /\b(no\s+(?:hagas|uses|escribas|incluyas|agregues)\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
43
|
+
{ tipo: 'correccion', re: /\b(don['´]?t\s+(?:do|use|write|include|add)\s+[a-z][^.!?\n]{3,100})/i },
|
|
44
|
+
{ tipo: 'correccion', re: /\b(eso\s+(?:está|esta)\s+mal[^.!?\n]{0,100})/i },
|
|
45
|
+
{ tipo: 'correccion', re: /\b(that['´]?s\s+wrong[^.!?\n]{0,100})/i },
|
|
46
|
+
{ tipo: 'correccion', re: /\b(corrige\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
47
|
+
|
|
48
|
+
// Preferencias
|
|
49
|
+
{ tipo: 'preferencia', re: /\b(prefiero\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
50
|
+
{ tipo: 'preferencia', re: /\b(i\s+prefer\s+[a-z][^.!?\n]{3,100})/i },
|
|
51
|
+
{ tipo: 'preferencia', re: /\b(mejor\s+usa\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
52
|
+
{ tipo: 'preferencia', re: /\b(siempre\s+(?:usa|haz|escribe|incluye)\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
53
|
+
{ tipo: 'preferencia', re: /\b(always\s+(?:use|do|write|include)\s+[a-z][^.!?\n]{3,100})/i },
|
|
54
|
+
|
|
55
|
+
// Memoria explícita
|
|
56
|
+
{ tipo: 'memoria', re: /\b(recuerda(?:\s+que)?\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
57
|
+
{ tipo: 'memoria', re: /\b(guarda\s+(?:esto|que)\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
58
|
+
{ tipo: 'memoria', re: /\b(remember\s+(?:that\s+)?[a-z][^.!?\n]{3,100})/i },
|
|
59
|
+
|
|
60
|
+
// Prohibiciones absolutas
|
|
61
|
+
{ tipo: 'prohibicion', re: /\b(nunca\s+(?:hagas|uses|escribas|incluyas|agregues)\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
62
|
+
{ tipo: 'prohibicion', re: /\b(jamás\s+(?:hagas|uses|escribas|incluyas|agregues)\s+[a-záéíóúñ][^.!?\n]{3,100})/i },
|
|
63
|
+
{ tipo: 'prohibicion', re: /\b(never\s+(?:do|use|write|include|add)\s+[a-z][^.!?\n]{3,100})/i },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Longitud mínima del prompt completo para considerarlo como feedback
|
|
67
|
+
// (evita capturar "no" suelto o prompts ultra-cortos de navegación).
|
|
68
|
+
const MIN_PROMPT_LEN = 12;
|
|
69
|
+
|
|
70
|
+
// Longitud máxima del fragmento capturado (para no saturar la cola con pastes largos)
|
|
71
|
+
const MAX_FRAGMENTO_LEN = 280;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Analiza un prompt y extrae señales de feedback.
|
|
75
|
+
* @param {string} prompt
|
|
76
|
+
* @returns {Array<{tipo: string, fragmento: string}>}
|
|
77
|
+
*/
|
|
78
|
+
function detectarFeedback(prompt) {
|
|
79
|
+
if (!prompt || prompt.length < MIN_PROMPT_LEN) return [];
|
|
80
|
+
|
|
81
|
+
// Omitir si el prompt es claramente un comando slash
|
|
82
|
+
if (prompt.trim().startsWith('/')) return [];
|
|
83
|
+
|
|
84
|
+
const hallazgos = [];
|
|
85
|
+
for (const { tipo, re } of PATRONES) {
|
|
86
|
+
const m = prompt.match(re);
|
|
87
|
+
if (!m) continue;
|
|
88
|
+
const fragmento = m[1].trim().slice(0, MAX_FRAGMENTO_LEN);
|
|
89
|
+
hallazgos.push({ tipo, fragmento });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Deduplicar por fragmento idéntico
|
|
93
|
+
const vistos = new Set();
|
|
94
|
+
return hallazgos.filter(h => {
|
|
95
|
+
const clave = `${h.tipo}::${h.fragmento.toLowerCase()}`;
|
|
96
|
+
if (vistos.has(clave)) return false;
|
|
97
|
+
vistos.add(clave);
|
|
98
|
+
return true;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Encola un hallazgo en feedback-queue.jsonl.
|
|
104
|
+
*/
|
|
105
|
+
function encolar(hallazgo, meta) {
|
|
106
|
+
try {
|
|
107
|
+
const dir = path.join(process.cwd(), '.planning', 'evolucion');
|
|
108
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
109
|
+
|
|
110
|
+
const entrada = {
|
|
111
|
+
ts: new Date().toISOString(),
|
|
112
|
+
sessionId: meta.sessionId,
|
|
113
|
+
tipo: hallazgo.tipo,
|
|
114
|
+
fragmento: hallazgo.fragmento,
|
|
115
|
+
cwd: meta.cwd,
|
|
116
|
+
procesado: false,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const jsonlPath = path.join(dir, 'feedback-queue.jsonl');
|
|
120
|
+
fs.appendFileSync(jsonlPath, JSON.stringify(entrada) + '\n');
|
|
121
|
+
} catch (_) { /* nunca bloquear */ }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Entrypoint
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
let inputRaw = '';
|
|
129
|
+
process.stdin.on('data', c => { inputRaw += c; });
|
|
130
|
+
|
|
131
|
+
process.stdin.on('end', () => {
|
|
132
|
+
try {
|
|
133
|
+
if (process.env.SWL_CAPTURAR_FEEDBACK === '0') return;
|
|
134
|
+
|
|
135
|
+
const data = JSON.parse(inputRaw);
|
|
136
|
+
const prompt = data.prompt || '';
|
|
137
|
+
const sessionId = String(data.session_id || 'default');
|
|
138
|
+
|
|
139
|
+
const hallazgos = detectarFeedback(prompt);
|
|
140
|
+
if (hallazgos.length === 0) return;
|
|
141
|
+
|
|
142
|
+
for (const h of hallazgos) {
|
|
143
|
+
encolar(h, { sessionId, cwd: process.cwd() });
|
|
144
|
+
}
|
|
145
|
+
} catch (_) { /* silencioso */ }
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
module.exports = { detectarFeedback };
|