@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,763 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: extraccion-aprendizajes.js
|
|
6
|
+
* Tipo: PostToolUse (aplica a: Bash, Write, Edit — al finalizar acciones del agente)
|
|
7
|
+
*
|
|
8
|
+
* Lee el output de herramientas del agente buscando patrones que indiquen
|
|
9
|
+
* un aprendizaje significativo: errores resueltos, bugs encontrados, decisiones
|
|
10
|
+
* arquitectónicas, descubrimientos de comportamiento inesperado.
|
|
11
|
+
*
|
|
12
|
+
* Si detecta un aprendizaje potencial:
|
|
13
|
+
* 1. Clasifica el tipo: anti-patrón | patrón | gotcha | decisión | bug-fix
|
|
14
|
+
* 2. Extrae el contexto (±3 líneas alrededor del keyword)
|
|
15
|
+
* 3. Verifica que no sea un duplicado de aprendizajes ya registrados
|
|
16
|
+
* 4. Escribe la entrada en .planning/APRENDIZAJES.md
|
|
17
|
+
*
|
|
18
|
+
* El hook nunca bloquea (siempre exit 0).
|
|
19
|
+
* Los errores internos se reportan en stderr y se ignoran silenciosamente.
|
|
20
|
+
*
|
|
21
|
+
* Formato de entrada en APRENDIZAJES.md:
|
|
22
|
+
* ─────────────────────────────────────────────────────────
|
|
23
|
+
* ## [YYYY-MM-DD] tipo — descripción corta
|
|
24
|
+
* **Agente**: nombre-del-agente
|
|
25
|
+
* **Contexto**: extracto del output que originó el aprendizaje
|
|
26
|
+
* ─────────────────────────────────────────────────────────
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const fs = require('fs');
|
|
30
|
+
const path = require('path');
|
|
31
|
+
const os = require('os');
|
|
32
|
+
|
|
33
|
+
const { atomicWriteSync } = require('./lib/atomic-write');
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Constantes de configuración
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Ruta del archivo donde se acumulan los aprendizajes.
|
|
41
|
+
* Se resuelve relativa al CWD del proceso (raíz del proyecto).
|
|
42
|
+
*/
|
|
43
|
+
const RUTA_APRENDIZAJES = path.join(process.cwd(), '.planning', 'APRENDIZAJES.md');
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Número de líneas de contexto a extraer alrededor del keyword detectado.
|
|
47
|
+
* El extracto será de hasta (LINEAS_CONTEXTO * 2 + 1) líneas.
|
|
48
|
+
*/
|
|
49
|
+
const LINEAS_CONTEXTO = 3;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Longitud máxima del extracto de contexto a guardar (en caracteres).
|
|
53
|
+
* Evita que contextos muy largos inflen el archivo de aprendizajes.
|
|
54
|
+
*/
|
|
55
|
+
const MAX_CHARS_CONTEXTO = 500;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Longitud mínima de la descripción extraída para considerarla significativa.
|
|
59
|
+
* Extractos muy cortos (< N chars) se descartan como ruido.
|
|
60
|
+
*/
|
|
61
|
+
const MIN_CHARS_DESCRIPCION = 40;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Umbral de similitud para deduplicación (Jaccard sobre bigramas de palabras).
|
|
65
|
+
* Valores entre 0 y 1. Un aprendizaje con similitud >= este umbral se considera
|
|
66
|
+
* duplicado y no se escribe.
|
|
67
|
+
*/
|
|
68
|
+
const UMBRAL_SIMILITUD = 0.75;
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Keywords y clasificación de aprendizajes
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Keywords que indican un aprendizaje potencial.
|
|
76
|
+
* Cada entrada define:
|
|
77
|
+
* - keywords: términos a buscar (case-insensitive) en el output
|
|
78
|
+
* - tipo: categoría del aprendizaje
|
|
79
|
+
* - peso: prioridad al elegir entre múltiples matches en la misma línea
|
|
80
|
+
*/
|
|
81
|
+
const REGLAS_CLASIFICACION = [
|
|
82
|
+
{
|
|
83
|
+
keywords: ['anti-patrón', 'antipatron', 'anti patrón', 'nunca hacer', 'never do', 'bad practice'],
|
|
84
|
+
tipo: 'anti-patrón',
|
|
85
|
+
peso: 5,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
keywords: ['bug fix', 'bugfix', 'corrección', 'corregido', 'fixed', 'se corrigió', 'arreglado'],
|
|
89
|
+
tipo: 'bug-fix',
|
|
90
|
+
peso: 5,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
keywords: ['gotcha', 'trampa', 'cuidado con', 'ojo con', 'footgun', 'pitfall'],
|
|
94
|
+
tipo: 'gotcha',
|
|
95
|
+
peso: 4,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
keywords: ['decisión', 'decision', 'decidimos', 'elegimos', 'optamos por', 'trade-off', 'tradeoff'],
|
|
99
|
+
tipo: 'decisión',
|
|
100
|
+
peso: 3,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
keywords: ['patrón', 'patron', 'best practice', 'buena práctica', 'recomendado', 'siempre usar'],
|
|
104
|
+
tipo: 'patrón',
|
|
105
|
+
peso: 3,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
keywords: ['descubrimiento', 'discovery', 'encontramos', 'hallazgo', 'aprendizaje', 'lección'],
|
|
109
|
+
tipo: 'descubrimiento',
|
|
110
|
+
peso: 2,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
keywords: ['error', 'fallo', 'failure', 'exception', 'traceback'],
|
|
114
|
+
tipo: 'bug-fix',
|
|
115
|
+
peso: 1,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
keywords: ['bug', 'issue', 'problema resuelto'],
|
|
119
|
+
tipo: 'bug-fix',
|
|
120
|
+
peso: 1,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
keywords: ['fix', 'solucion', 'solución', 'resuelto', 'resolved'],
|
|
124
|
+
tipo: 'bug-fix',
|
|
125
|
+
peso: 1,
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// Utilidades de texto
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Trunca un texto respetando bordes naturales: prefiere cortar al final de
|
|
135
|
+
* una oración (`. ! ?`) y si no hay, al final de una palabra (último espacio).
|
|
136
|
+
* Jamás corta a mitad de palabra ni en medio de un caracter multibyte.
|
|
137
|
+
*
|
|
138
|
+
* @param {string} texto
|
|
139
|
+
* @param {number} maxChars Límite duro superior.
|
|
140
|
+
* @param {object} [opts]
|
|
141
|
+
* @param {number} [opts.minRatio=0.6] Proporción mínima de maxChars que debe
|
|
142
|
+
* alcanzar el punto de corte. Si un corte
|
|
143
|
+
* de oración caería antes de este ratio,
|
|
144
|
+
* preferimos cortar en espacio.
|
|
145
|
+
* @returns {string} Texto truncado con '…' si se acortó.
|
|
146
|
+
*/
|
|
147
|
+
function truncarElegante(texto, maxChars, opts = {}) {
|
|
148
|
+
const s = String(texto || '');
|
|
149
|
+
if (s.length <= maxChars) return s;
|
|
150
|
+
|
|
151
|
+
const minRatio = typeof opts.minRatio === 'number' ? opts.minRatio : 0.6;
|
|
152
|
+
const minCorte = Math.floor(maxChars * minRatio);
|
|
153
|
+
const ventana = s.slice(0, maxChars);
|
|
154
|
+
|
|
155
|
+
// 1. Intentar corte en fin de oración (`. ! ?` seguido de espacio o fin)
|
|
156
|
+
const reOracion = /[.!?](?=\s|$)/g;
|
|
157
|
+
let ultimaOracion = -1;
|
|
158
|
+
let m;
|
|
159
|
+
while ((m = reOracion.exec(ventana)) !== null) {
|
|
160
|
+
ultimaOracion = m.index + 1; // incluir el signo de puntuación
|
|
161
|
+
}
|
|
162
|
+
if (ultimaOracion >= minCorte) {
|
|
163
|
+
return s.slice(0, ultimaOracion).trimEnd() + ' …';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 2. Intentar corte en `,` o `;` seguido de espacio
|
|
167
|
+
const reClausula = /[,;:](?=\s)/g;
|
|
168
|
+
let ultimaClausula = -1;
|
|
169
|
+
while ((m = reClausula.exec(ventana)) !== null) {
|
|
170
|
+
ultimaClausula = m.index + 1;
|
|
171
|
+
}
|
|
172
|
+
if (ultimaClausula >= minCorte) {
|
|
173
|
+
return s.slice(0, ultimaClausula).trimEnd() + ' …';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 3. Último recurso: último espacio antes del límite
|
|
177
|
+
const ultimoEspacio = ventana.lastIndexOf(' ');
|
|
178
|
+
if (ultimoEspacio >= minCorte) {
|
|
179
|
+
return s.slice(0, ultimoEspacio).trimEnd() + ' …';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 4. Si la "palabra" es enorme (URL, ruta), cortar duro pero no en
|
|
183
|
+
// medio de un code-point (trimEnd no ayuda con surrogates; usar Array.from).
|
|
184
|
+
const chars = Array.from(ventana);
|
|
185
|
+
return chars.slice(0, maxChars).join('').trimEnd() + ' …';
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Construye el conjunto de bigramas de palabras de un texto.
|
|
190
|
+
* Usado para la deduplicación por similitud Jaccard.
|
|
191
|
+
*
|
|
192
|
+
* @param {string} texto
|
|
193
|
+
* @returns {Set<string>}
|
|
194
|
+
*/
|
|
195
|
+
function bigramasTexto(texto) {
|
|
196
|
+
const palabras = texto
|
|
197
|
+
.toLowerCase()
|
|
198
|
+
.replace(/[^\w\s]/g, ' ')
|
|
199
|
+
.split(/\s+/)
|
|
200
|
+
.filter(p => p.length > 2); // Ignorar palabras muy cortas
|
|
201
|
+
|
|
202
|
+
const bigramas = new Set();
|
|
203
|
+
for (let i = 0; i < palabras.length - 1; i++) {
|
|
204
|
+
bigramas.add(`${palabras[i]}|${palabras[i + 1]}`);
|
|
205
|
+
}
|
|
206
|
+
return bigramas;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Calcula la similitud de Jaccard entre dos conjuntos.
|
|
211
|
+
*
|
|
212
|
+
* @param {Set<string>} a
|
|
213
|
+
* @param {Set<string>} b
|
|
214
|
+
* @returns {number} Valor entre 0 (sin similitud) y 1 (idénticos).
|
|
215
|
+
*/
|
|
216
|
+
function similitudJaccard(a, b) {
|
|
217
|
+
if (a.size === 0 && b.size === 0) return 1;
|
|
218
|
+
if (a.size === 0 || b.size === 0) return 0;
|
|
219
|
+
|
|
220
|
+
let interseccion = 0;
|
|
221
|
+
for (const elem of a) {
|
|
222
|
+
if (b.has(elem)) interseccion++;
|
|
223
|
+
}
|
|
224
|
+
const union = a.size + b.size - interseccion;
|
|
225
|
+
return interseccion / union;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Extrae un identificador hash simple de un texto para comparación rápida
|
|
230
|
+
* antes de calcular Jaccard completo (optimización).
|
|
231
|
+
*
|
|
232
|
+
* @param {string} texto
|
|
233
|
+
* @returns {string}
|
|
234
|
+
*/
|
|
235
|
+
function hashTexto(texto) {
|
|
236
|
+
let hash = 0;
|
|
237
|
+
for (let i = 0; i < texto.length; i++) {
|
|
238
|
+
hash = ((hash << 5) - hash + texto.charCodeAt(i)) | 0;
|
|
239
|
+
}
|
|
240
|
+
return String(hash >>> 0);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// Normalización de fechas relativas (patrón autoDream)
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Mapa de expresiones relativas en español a funciones de cálculo.
|
|
249
|
+
* Convierte "ayer", "hace 2 días", etc. a fechas absolutas YYYY-MM-DD.
|
|
250
|
+
*/
|
|
251
|
+
const PATRONES_FECHA_RELATIVA = [
|
|
252
|
+
{ regex: /\bhoy\b/gi, calc: () => 0 },
|
|
253
|
+
{ regex: /\bayer\b/gi, calc: () => -1 },
|
|
254
|
+
{ regex: /\banteayer\b/gi, calc: () => -2 },
|
|
255
|
+
{ regex: /\bhace\s+(\d+)\s+días?\b/gi, calc: (m) => -parseInt(m[1], 10) },
|
|
256
|
+
{ regex: /\bhace\s+(\d+)\s+semanas?\b/gi, calc: (m) => -parseInt(m[1], 10) * 7 },
|
|
257
|
+
{ regex: /\bla\s+semana\s+pasada\b/gi, calc: () => -7 },
|
|
258
|
+
{ regex: /\bhace\s+(\d+)\s+meses?\b/gi, calc: (m) => -parseInt(m[1], 10) * 30 },
|
|
259
|
+
{ regex: /\bel\s+mes\s+pasado\b/gi, calc: () => -30 },
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Reemplaza fechas relativas en un texto por fechas absolutas YYYY-MM-DD.
|
|
264
|
+
* Preserva el texto original si no hay coincidencias.
|
|
265
|
+
*
|
|
266
|
+
* @param {string} texto - Texto con posibles fechas relativas.
|
|
267
|
+
* @param {Date} [ahora] - Fecha de referencia (default: Date.now()).
|
|
268
|
+
* @returns {string} Texto con fechas absolutas.
|
|
269
|
+
*/
|
|
270
|
+
function normalizarFechas(texto, ahora = new Date()) {
|
|
271
|
+
let resultado = texto;
|
|
272
|
+
|
|
273
|
+
for (const { regex, calc } of PATRONES_FECHA_RELATIVA) {
|
|
274
|
+
resultado = resultado.replace(regex, (...args) => {
|
|
275
|
+
const diasOffset = calc(args);
|
|
276
|
+
const fecha = new Date(ahora);
|
|
277
|
+
fecha.setDate(fecha.getDate() + diasOffset);
|
|
278
|
+
return fecha.toISOString().slice(0, 10); // YYYY-MM-DD
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return resultado;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
// Extracción del texto a analizar
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Extrae el texto relevante del payload del hook para analizar en busca
|
|
291
|
+
* de aprendizajes. Soporta múltiples estructuras que Claude Code puede enviar.
|
|
292
|
+
*
|
|
293
|
+
* @param {object} data - Payload JSON del hook.
|
|
294
|
+
* @returns {{ texto: string, agente: string }}
|
|
295
|
+
*/
|
|
296
|
+
function extraerTextoYAgente(data) {
|
|
297
|
+
const toolName = String(data.tool_name || data.tool?.name || '');
|
|
298
|
+
const toolResult = data.tool_result || data.tool?.result || {};
|
|
299
|
+
const toolInput = data.tool_input || data.tool?.input || {};
|
|
300
|
+
|
|
301
|
+
// Nombre del agente: preferir session_id o model; fallback a tool_name
|
|
302
|
+
const agente = String(
|
|
303
|
+
data.agent_name ||
|
|
304
|
+
data.session_id ||
|
|
305
|
+
data.model ||
|
|
306
|
+
toolName ||
|
|
307
|
+
'agente-desconocido'
|
|
308
|
+
).slice(0, 60);
|
|
309
|
+
|
|
310
|
+
// Recolectar fragmentos de texto del resultado de la herramienta
|
|
311
|
+
const fragmentos = [];
|
|
312
|
+
|
|
313
|
+
// Resultado puede ser string directo
|
|
314
|
+
if (typeof toolResult === 'string') {
|
|
315
|
+
fragmentos.push(toolResult);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Resultado puede ser objeto con campo "output", "content", "stdout", etc.
|
|
319
|
+
if (toolResult && typeof toolResult === 'object') {
|
|
320
|
+
const camposResultado = ['output', 'content', 'stdout', 'text', 'result', 'message'];
|
|
321
|
+
for (const campo of camposResultado) {
|
|
322
|
+
if (typeof toolResult[campo] === 'string') {
|
|
323
|
+
fragmentos.push(toolResult[campo]);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Para herramientas Write/Edit, analizar el contenido que se escribió
|
|
329
|
+
if (['Write', 'Edit'].includes(toolName)) {
|
|
330
|
+
const contenido = toolInput.content || toolInput.new_string || '';
|
|
331
|
+
if (typeof contenido === 'string' && contenido.length > 0) {
|
|
332
|
+
// Solo analizar comentarios y docstrings del código, no el código mismo
|
|
333
|
+
const lineasComentario = contenido
|
|
334
|
+
.split('\n')
|
|
335
|
+
.filter(l => /^\s*(#|\/\/|\/\*|\*|"""|''')/.test(l))
|
|
336
|
+
.join('\n');
|
|
337
|
+
if (lineasComentario) fragmentos.push(lineasComentario);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Leer también de stdin si hay datos adicionales (modo pipe directo)
|
|
342
|
+
const texto = fragmentos.join('\n\n').slice(0, 50_000); // Límite de 50KB para análisis
|
|
343
|
+
|
|
344
|
+
return { texto, agente };
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
// Detección y clasificación de aprendizajes
|
|
349
|
+
// ---------------------------------------------------------------------------
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Resultado de analizar el texto en busca de aprendizajes.
|
|
353
|
+
* @typedef {{ tipo: string, contexto: string, descripcion: string }} Aprendizaje
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Analiza el texto del output del agente buscando aprendizajes significativos.
|
|
358
|
+
* Retorna el aprendizaje más relevante encontrado, o null si no hay ninguno.
|
|
359
|
+
*
|
|
360
|
+
* Estrategia:
|
|
361
|
+
* 1. Buscar keywords de mayor peso primero.
|
|
362
|
+
* 2. Para cada match, extraer contexto de ±LINEAS_CONTEXTO líneas.
|
|
363
|
+
* 3. Verificar longitud mínima del contexto.
|
|
364
|
+
* 4. Clasificar por el tipo de keyword que disparó la detección.
|
|
365
|
+
*
|
|
366
|
+
* @param {string} texto
|
|
367
|
+
* @returns {Aprendizaje|null}
|
|
368
|
+
*/
|
|
369
|
+
function detectarAprendizaje(texto) {
|
|
370
|
+
if (!texto || texto.trim().length < MIN_CHARS_DESCRIPCION) return null;
|
|
371
|
+
|
|
372
|
+
const lineas = texto.split('\n');
|
|
373
|
+
|
|
374
|
+
// Ordenar reglas de mayor a menor peso para priorizar los más significativos
|
|
375
|
+
const reglasPorPeso = [...REGLAS_CLASIFICACION].sort((a, b) => b.peso - a.peso);
|
|
376
|
+
|
|
377
|
+
for (const { keywords, tipo } of reglasPorPeso) {
|
|
378
|
+
for (const keyword of keywords) {
|
|
379
|
+
const patronKeyword = new RegExp(keyword, 'i');
|
|
380
|
+
|
|
381
|
+
for (let i = 0; i < lineas.length; i++) {
|
|
382
|
+
if (!patronKeyword.test(lineas[i])) continue;
|
|
383
|
+
|
|
384
|
+
// Extraer contexto alrededor de la línea con el keyword
|
|
385
|
+
const inicio = Math.max(0, i - LINEAS_CONTEXTO);
|
|
386
|
+
const fin = Math.min(lineas.length, i + LINEAS_CONTEXTO + 1);
|
|
387
|
+
const contexto = lineas.slice(inicio, fin).join('\n').trim();
|
|
388
|
+
|
|
389
|
+
// Verificar longitud mínima significativa
|
|
390
|
+
if (contexto.length < MIN_CHARS_DESCRIPCION) continue;
|
|
391
|
+
|
|
392
|
+
// Truncar el contexto respetando bordes de oración/palabra
|
|
393
|
+
const contextoFinal = truncarElegante(contexto, MAX_CHARS_CONTEXTO);
|
|
394
|
+
|
|
395
|
+
// Descripción: la línea del keyword, limpiada de símbolos de código.
|
|
396
|
+
// Preferir cortar al final de la primera oración si cabe en 120 chars;
|
|
397
|
+
// si no, al último espacio antes del límite.
|
|
398
|
+
const lineaLimpia = lineas[i]
|
|
399
|
+
.trim()
|
|
400
|
+
.replace(/^[#*\/\-–•]+\s*/, '') // Quitar prefijos de comentario/lista
|
|
401
|
+
.replace(/\*\*/g, '') // Quitar marcadores de negrita Markdown
|
|
402
|
+
.replace(/`+/g, ''); // Quitar backticks
|
|
403
|
+
|
|
404
|
+
// Si la línea tiene un punto temprano, usarlo como fin natural
|
|
405
|
+
const matchOracion = lineaLimpia.match(/^[^.!?]*[.!?]/);
|
|
406
|
+
const descripcionBase = matchOracion
|
|
407
|
+
? matchOracion[0].trim()
|
|
408
|
+
: lineaLimpia;
|
|
409
|
+
|
|
410
|
+
const descripcion = truncarElegante(descripcionBase, 120, { minRatio: 0.4 });
|
|
411
|
+
|
|
412
|
+
if (descripcion.length < 10) continue;
|
|
413
|
+
|
|
414
|
+
return { tipo, contexto: contextoFinal, descripcion };
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
423
|
+
// Gestión del archivo APRENDIZAJES.md
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Lee las entradas existentes en APRENDIZAJES.md.
|
|
428
|
+
* Retorna el contenido completo y una lista de descripciones para deduplicar.
|
|
429
|
+
*
|
|
430
|
+
* @returns {{ contenidoExistente: string, descripciones: string[] }}
|
|
431
|
+
*/
|
|
432
|
+
function leerAprendizajesExistentes() {
|
|
433
|
+
try {
|
|
434
|
+
const contenido = fs.readFileSync(RUTA_APRENDIZAJES, 'utf8');
|
|
435
|
+
// Extraer las líneas de descripción corta (las que empiezan con "##")
|
|
436
|
+
const descripciones = contenido
|
|
437
|
+
.split('\n')
|
|
438
|
+
.filter(l => l.startsWith('## '))
|
|
439
|
+
.map(l => l.replace(/^##\s+\[\d{4}-\d{2}-\d{2}\]\s+\w+[-\w]*\s+—\s+/, '').trim());
|
|
440
|
+
|
|
441
|
+
return { contenidoExistente: contenido, descripciones };
|
|
442
|
+
} catch (_) {
|
|
443
|
+
// El archivo no existe aún — primera ejecución
|
|
444
|
+
return { contenidoExistente: '', descripciones: [] };
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Verifica si un aprendizaje candidato ya existe en el archivo,
|
|
450
|
+
* usando similitud de Jaccard sobre bigramas para detectar duplicados
|
|
451
|
+
* semánticamente similares aunque no idénticos.
|
|
452
|
+
*
|
|
453
|
+
* @param {string} descripcion - Descripción del aprendizaje candidato.
|
|
454
|
+
* @param {string[]} descripciones - Descripciones existentes en el archivo.
|
|
455
|
+
* @returns {boolean} true si el aprendizaje ya existe (o es muy similar).
|
|
456
|
+
*/
|
|
457
|
+
function esDuplicado(descripcion, descripciones) {
|
|
458
|
+
if (descripciones.length === 0) return false;
|
|
459
|
+
|
|
460
|
+
const bigramasNuevo = bigramasTexto(descripcion);
|
|
461
|
+
|
|
462
|
+
for (const desc of descripciones) {
|
|
463
|
+
const bigramasExistente = bigramasTexto(desc);
|
|
464
|
+
const similitud = similitudJaccard(bigramasNuevo, bigramasExistente);
|
|
465
|
+
if (similitud >= UMBRAL_SIMILITUD) return true;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Asegura que el directorio padre de RUTA_APRENDIZAJES existe.
|
|
473
|
+
* Crea el directorio .planning/ si no existe.
|
|
474
|
+
*/
|
|
475
|
+
function asegurarDirectorio() {
|
|
476
|
+
const dir = path.dirname(RUTA_APRENDIZAJES);
|
|
477
|
+
if (!fs.existsSync(dir)) {
|
|
478
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Escribe el encabezado inicial del archivo APRENDIZAJES.md si está vacío.
|
|
484
|
+
*
|
|
485
|
+
* @param {string} contenidoExistente
|
|
486
|
+
* @returns {string} Contenido actualizado con encabezado.
|
|
487
|
+
*/
|
|
488
|
+
function asegurarEncabezado(contenidoExistente) {
|
|
489
|
+
if (contenidoExistente.length > 0) return contenidoExistente;
|
|
490
|
+
|
|
491
|
+
return [
|
|
492
|
+
'# Aprendizajes del Sistema',
|
|
493
|
+
'',
|
|
494
|
+
'Registro automático de aprendizajes extraídos por el hook `extraccion-aprendizajes.js`.',
|
|
495
|
+
'Cada entrada describe un anti-patrón, patrón, gotcha, bug-fix o decisión detectada',
|
|
496
|
+
'durante la ejecución de agentes en el proyecto.',
|
|
497
|
+
'',
|
|
498
|
+
'---',
|
|
499
|
+
'',
|
|
500
|
+
].join('\n');
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Formatea una entrada de aprendizaje para insertar en el archivo.
|
|
505
|
+
*
|
|
506
|
+
* @param {string} fecha - Fecha en formato YYYY-MM-DD.
|
|
507
|
+
* @param {string} tipo - Tipo del aprendizaje.
|
|
508
|
+
* @param {string} descripcion - Descripción corta.
|
|
509
|
+
* @param {string} agente - Nombre/ID del agente que generó el aprendizaje.
|
|
510
|
+
* @param {string} contexto - Extracto del output del agente.
|
|
511
|
+
* @returns {string}
|
|
512
|
+
*/
|
|
513
|
+
function formatearEntrada(fecha, tipo, descripcion, agente, contexto) {
|
|
514
|
+
// Indentar el contexto para que se muestre como blockquote en Markdown
|
|
515
|
+
const contextoIndentado = contexto
|
|
516
|
+
.split('\n')
|
|
517
|
+
.map(l => `> ${l}`)
|
|
518
|
+
.join('\n');
|
|
519
|
+
|
|
520
|
+
// Markdown válido requiere líneas en blanco antes de ## y antes/después de ---
|
|
521
|
+
return [
|
|
522
|
+
'',
|
|
523
|
+
`## [${fecha}] ${tipo} — ${descripcion}`,
|
|
524
|
+
'',
|
|
525
|
+
`**Agente**: \`${agente}\``,
|
|
526
|
+
'',
|
|
527
|
+
`**Contexto**:`,
|
|
528
|
+
'',
|
|
529
|
+
contextoIndentado,
|
|
530
|
+
'',
|
|
531
|
+
'---',
|
|
532
|
+
'',
|
|
533
|
+
].join('\n');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Escribe un nuevo aprendizaje al final del archivo APRENDIZAJES.md.
|
|
538
|
+
*
|
|
539
|
+
* @param {Aprendizaje} aprendizaje
|
|
540
|
+
* @param {string} agente
|
|
541
|
+
*/
|
|
542
|
+
function escribirAprendizaje(aprendizaje, agente) {
|
|
543
|
+
asegurarDirectorio();
|
|
544
|
+
|
|
545
|
+
const { contenidoExistente, descripciones } = leerAprendizajesExistentes();
|
|
546
|
+
|
|
547
|
+
// Verificar duplicado antes de escribir
|
|
548
|
+
if (esDuplicado(aprendizaje.descripcion, descripciones)) {
|
|
549
|
+
// Aprendizaje duplicado — omitido silenciosamente
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
const fecha = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
|
|
554
|
+
const contenidoBase = asegurarEncabezado(contenidoExistente);
|
|
555
|
+
|
|
556
|
+
// Normalizar fechas relativas a absolutas (patrón autoDream)
|
|
557
|
+
const descripcionNorm = normalizarFechas(aprendizaje.descripcion);
|
|
558
|
+
const contextoNorm = normalizarFechas(aprendizaje.contexto);
|
|
559
|
+
|
|
560
|
+
const entrada = formatearEntrada(
|
|
561
|
+
fecha,
|
|
562
|
+
aprendizaje.tipo,
|
|
563
|
+
descripcionNorm,
|
|
564
|
+
agente,
|
|
565
|
+
contextoNorm
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
atomicWriteSync(RUTA_APRENDIZAJES, contenidoBase + entrada);
|
|
569
|
+
|
|
570
|
+
// Aprendizaje registrado silenciosamente
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// ---------------------------------------------------------------------------
|
|
574
|
+
// Filtros de señal vs. ruido
|
|
575
|
+
// ---------------------------------------------------------------------------
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Determina si el evento del hook proviene de una herramienta cuyo output
|
|
579
|
+
* vale la pena analizar para extraer aprendizajes.
|
|
580
|
+
*
|
|
581
|
+
* Se excluyen herramientas puramente de lectura y de estado
|
|
582
|
+
* que generan mucho ruido sin información nueva.
|
|
583
|
+
*
|
|
584
|
+
* @param {string} toolName
|
|
585
|
+
* @returns {boolean}
|
|
586
|
+
*/
|
|
587
|
+
function esHerramientaRelevante(toolName) {
|
|
588
|
+
const HERRAMIENTAS_EXCLUIDAS = new Set([
|
|
589
|
+
'Read', // Lectura pura — sin aprendizajes del agente
|
|
590
|
+
'Glob', // Listado de archivos
|
|
591
|
+
'Grep', // Búsqueda — output técnico sin narrativa
|
|
592
|
+
]);
|
|
593
|
+
return !HERRAMIENTAS_EXCLUIDAS.has(toolName);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Rutas de archivos SWL donde Write/Edit NO debe generar aprendizajes.
|
|
598
|
+
* Editar contenido de skills, reglas, APRENDIZAJES, ADRs, etc. es
|
|
599
|
+
* mantenimiento del sistema SWL, no descubrimiento en tiempo de ejecución.
|
|
600
|
+
* Capturar fragmentos de esos archivos produce ruido auto-referente.
|
|
601
|
+
*/
|
|
602
|
+
const PATRONES_ARCHIVO_SWL_EXCLUIDO = [
|
|
603
|
+
/[\\/]habilidades[\\/]/,
|
|
604
|
+
/[\\/]agentes[\\/]/,
|
|
605
|
+
/[\\/]reglas[\\/]/,
|
|
606
|
+
/[\\/]comandos[\\/]swl[\\/]/,
|
|
607
|
+
/[\\/]hooks[\\/]/,
|
|
608
|
+
/[\\/]scripts[\\/]/,
|
|
609
|
+
/[\\/]schemas[\\/]/,
|
|
610
|
+
/[\\/]manifiestos[\\/]/,
|
|
611
|
+
/[\\/]plantillas[\\/]/,
|
|
612
|
+
/[\\/]contextos[\\/]/,
|
|
613
|
+
/[\\/]instintos[\\/]/,
|
|
614
|
+
// Todo .planning/ salvo wiki/ (que puede contener conocimiento del proyecto usuario).
|
|
615
|
+
// En swl-ses .planning/ es meta del sistema; los aprendizajes se gestionan manualmente.
|
|
616
|
+
/[\\/]\.planning[\\/](?!wiki[\\/])/,
|
|
617
|
+
/[\\/]CHANGELOG\.md$/i,
|
|
618
|
+
/[\\/]CLAUDE\.md$/i,
|
|
619
|
+
/[\\/]AGENTS\.md$/i,
|
|
620
|
+
/[\\/]README\.md$/i,
|
|
621
|
+
/[\\/]MANUAL_USO\.md$/i,
|
|
622
|
+
/[\\/]COMANDOS\.md$/i,
|
|
623
|
+
/[\\/]INSTALACION\.md$/i,
|
|
624
|
+
/[\\/]INVENTARIO\.md$/i,
|
|
625
|
+
/[\\/]SALUD\.md$/i,
|
|
626
|
+
/[\\/]package\.json$/,
|
|
627
|
+
/[\\/]plugin\.json$/,
|
|
628
|
+
/[\\/]package-lock\.json$/,
|
|
629
|
+
];
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Determina si el target de Write/Edit es un archivo del sistema SWL
|
|
633
|
+
* donde la edición es mantenimiento, no descubrimiento. Previene ruido
|
|
634
|
+
* auto-referente (capturar fragmentos de SKILL.md propios como "aprendizajes").
|
|
635
|
+
*
|
|
636
|
+
* @param {string} filePath
|
|
637
|
+
* @returns {boolean}
|
|
638
|
+
*/
|
|
639
|
+
function esArchivoSwlExcluido(filePath) {
|
|
640
|
+
if (!filePath || typeof filePath !== 'string') return false;
|
|
641
|
+
return PATRONES_ARCHIVO_SWL_EXCLUIDO.some(rx => rx.test(filePath));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Detecta si un fragmento parece ser contenido estructurado de skill/regla
|
|
646
|
+
* (frontmatter YAML, encabezados ## NN, tablas markdown grandes) en vez de
|
|
647
|
+
* un aprendizaje narrativo genuino. Filtro final antes de persistir.
|
|
648
|
+
*
|
|
649
|
+
* @param {string} contexto
|
|
650
|
+
* @returns {boolean} true si el fragmento parece estructural (descartar)
|
|
651
|
+
*/
|
|
652
|
+
function pareceContenidoEstructuralSwl(contexto) {
|
|
653
|
+
if (!contexto) return false;
|
|
654
|
+
const lineas = contexto.split('\n');
|
|
655
|
+
|
|
656
|
+
// Frontmatter YAML: ---\nname: ...\ndescription: ...\n---
|
|
657
|
+
if (lineas.some(l => /^---\s*$/.test(l)) && lineas.some(l => /^(name|description|version|evolved):/i.test(l))) {
|
|
658
|
+
return true;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Tabla markdown dominante: más del 50% de líneas no vacías son filas de tabla
|
|
662
|
+
const noVacias = lineas.filter(l => l.trim().length > 0);
|
|
663
|
+
const filas = noVacias.filter(l => /^\|.*\|/.test(l));
|
|
664
|
+
if (noVacias.length > 0 && filas.length / noVacias.length > 0.5) {
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Enumeración de encabezados sin cuerpo sustantivo
|
|
669
|
+
// (3+ líneas tipo "## [fecha] tipo — descripción" juntas)
|
|
670
|
+
const encabezadosFecha = lineas.filter(l => /^##\s+\[\d{4}-\d{2}-\d{2}\]/.test(l));
|
|
671
|
+
if (encabezadosFecha.length >= 2) {
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Determina si el texto tiene suficiente contenido narrativo para contener
|
|
680
|
+
* un aprendizaje significativo (vs. output técnico puro como stack traces
|
|
681
|
+
* o listados de archivos).
|
|
682
|
+
*
|
|
683
|
+
* Heurística: el ratio de palabras largas (>4 chars) sobre el total
|
|
684
|
+
* indica prosa vs. código/rutas.
|
|
685
|
+
*
|
|
686
|
+
* @param {string} texto
|
|
687
|
+
* @returns {boolean}
|
|
688
|
+
*/
|
|
689
|
+
function tieneContenidoNarrativo(texto) {
|
|
690
|
+
if (texto.length < MIN_CHARS_DESCRIPCION) return false;
|
|
691
|
+
|
|
692
|
+
const palabras = texto.split(/\s+/).filter(p => p.length > 0);
|
|
693
|
+
const palabrasLargas = palabras.filter(p => p.length > 4);
|
|
694
|
+
const ratioNarrativo = palabras.length > 0 ? palabrasLargas.length / palabras.length : 0;
|
|
695
|
+
|
|
696
|
+
// Al menos 30% de palabras largas sugiere prosa con contenido semántico
|
|
697
|
+
return ratioNarrativo >= 0.30 && palabras.length >= 10;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// ---------------------------------------------------------------------------
|
|
701
|
+
// Entrypoint principal
|
|
702
|
+
// ---------------------------------------------------------------------------
|
|
703
|
+
|
|
704
|
+
let inputRaw = '';
|
|
705
|
+
|
|
706
|
+
process.stdin.on('data', chunk => {
|
|
707
|
+
inputRaw += chunk;
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
process.stdin.on('end', () => {
|
|
711
|
+
try {
|
|
712
|
+
const data = JSON.parse(inputRaw);
|
|
713
|
+
|
|
714
|
+
const toolName = String(data.tool_name || data.tool?.name || '');
|
|
715
|
+
|
|
716
|
+
// Filtrar herramientas que generan ruido sin aprendizajes
|
|
717
|
+
if (!esHerramientaRelevante(toolName)) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Filtrar Write/Edit sobre archivos del sistema SWL (auto-referencia).
|
|
722
|
+
// Editar habilidades/, agentes/, reglas/, CHANGELOG, CLAUDE.md, etc. es
|
|
723
|
+
// mantenimiento del sistema, no descubrimiento en tiempo de ejecución.
|
|
724
|
+
if (toolName === 'Write' || toolName === 'Edit' || toolName === 'MultiEdit') {
|
|
725
|
+
const toolInput = data.tool_input || data.tool?.input || {};
|
|
726
|
+
const filePath = String(toolInput.file_path || toolInput.path || '');
|
|
727
|
+
if (esArchivoSwlExcluido(filePath)) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// Extraer texto y nombre del agente del payload
|
|
733
|
+
const { texto, agente } = extraerTextoYAgente(data);
|
|
734
|
+
|
|
735
|
+
// Verificar que el texto tiene contenido narrativo suficiente
|
|
736
|
+
if (!tieneContenidoNarrativo(texto)) {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Detectar aprendizaje en el texto
|
|
741
|
+
const aprendizaje = detectarAprendizaje(texto);
|
|
742
|
+
|
|
743
|
+
if (!aprendizaje) {
|
|
744
|
+
// Sin aprendizaje detectado — salir silenciosamente
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Filtro final: descartar si el contexto parece estructural (frontmatter
|
|
749
|
+
// YAML, tablas markdown, enumeración de encabezados sin cuerpo). Previene
|
|
750
|
+
// que fragmentos de skills/reglas se persistan como aprendizajes.
|
|
751
|
+
if (pareceContenidoEstructuralSwl(aprendizaje.contexto)) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Escribir el aprendizaje (incluye deduplicación interna)
|
|
756
|
+
escribirAprendizaje(aprendizaje, agente);
|
|
757
|
+
|
|
758
|
+
// PostToolUse: no escribir a stdout — salida limpia.
|
|
759
|
+
|
|
760
|
+
} catch (err) {
|
|
761
|
+
// No escribir a stderr — Claude Code lo reporta como hook error
|
|
762
|
+
}
|
|
763
|
+
});
|