@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,306 @@
|
|
|
1
|
+
# Vector Stores — Referencia completa
|
|
2
|
+
|
|
3
|
+
Guía de selección, configuración e integración de vector stores para aplicaciones RAG.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Comparativa de vector stores
|
|
8
|
+
|
|
9
|
+
| Vector Store | Despliegue | Escala | Búsqueda híbrida | Ideal para |
|
|
10
|
+
|-------------|-----------|--------|-----------------|-----------|
|
|
11
|
+
| pgvector | On-premise / Cloud | < 10M vectores | Manual (RRF) | Ya tienes PostgreSQL |
|
|
12
|
+
| Chroma | Local / Self-hosted | < 1M vectores | No | Prototipado rápido |
|
|
13
|
+
| Pinecone | Serverless | Sin límite práctico | Sí (nativo) | Producción sin DevOps |
|
|
14
|
+
| Weaviate | Self-hosted / Cloud | Millones | Sí (BM25 + vector) | Búsqueda semántica avanzada |
|
|
15
|
+
| Qdrant | Self-hosted / Cloud | Millones | Sí | Alta performance, tipado fuerte |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## pgvector con SQLAlchemy
|
|
20
|
+
|
|
21
|
+
### Instalación y configuración
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Extensión PostgreSQL
|
|
25
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
26
|
+
|
|
27
|
+
# Dependencias Python
|
|
28
|
+
pip install pgvector psycopg2-binary langchain-community
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Modelo SQLAlchemy con columna vector
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from pgvector.sqlalchemy import Vector
|
|
35
|
+
from sqlalchemy import Column, String, Text, Integer
|
|
36
|
+
from sqlalchemy.orm import DeclarativeBase
|
|
37
|
+
|
|
38
|
+
class Base(DeclarativeBase):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
class DocumentoChunk(Base):
|
|
42
|
+
__tablename__ = "documento_chunks"
|
|
43
|
+
|
|
44
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
45
|
+
contenido = Column(Text, nullable=False)
|
|
46
|
+
fuente = Column(String(500))
|
|
47
|
+
pagina = Column(Integer)
|
|
48
|
+
# 1536 dimensiones para text-embedding-3-small de OpenAI
|
|
49
|
+
# 768 para all-MiniLM-L6-v2 de HuggingFace
|
|
50
|
+
embedding = Column(Vector(1536))
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Índice HNSW — obligatorio para producción
|
|
54
|
+
|
|
55
|
+
```sql
|
|
56
|
+
-- Crear índice HNSW DESPUÉS de cargar los datos iniciales
|
|
57
|
+
-- m=16, ef_construction=64 son valores seguros para empezar
|
|
58
|
+
CREATE INDEX idx_chunks_embedding_hnsw
|
|
59
|
+
ON documento_chunks
|
|
60
|
+
USING hnsw (embedding vector_cosine_ops)
|
|
61
|
+
WITH (m = 16, ef_construction = 64);
|
|
62
|
+
|
|
63
|
+
-- Para distancia euclidiana
|
|
64
|
+
CREATE INDEX idx_chunks_embedding_euclidean
|
|
65
|
+
ON documento_chunks
|
|
66
|
+
USING hnsw (embedding vector_l2_ops)
|
|
67
|
+
WITH (m = 16, ef_construction = 64);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Por qué HNSW y no IVFFlat**: HNSW tiene mejor performance en queries individuales
|
|
71
|
+
y no requiere pre-entrenamiento con `lists`. IVFFlat es mejor si el dataset es enorme
|
|
72
|
+
(> 10M) y hay tiempo para el clustering inicial.
|
|
73
|
+
|
|
74
|
+
### Consultas de similitud con LangChain
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from langchain_community.vectorstores import PGVector
|
|
78
|
+
from langchain_openai import OpenAIEmbeddings
|
|
79
|
+
|
|
80
|
+
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
|
|
81
|
+
|
|
82
|
+
# Crear o conectar a store existente
|
|
83
|
+
vectorstore = PGVector(
|
|
84
|
+
embeddings=embeddings,
|
|
85
|
+
collection_name="documentos_empresa",
|
|
86
|
+
connection=DATABASE_URL, # postgresql+psycopg2://...
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Búsqueda semántica simple
|
|
90
|
+
docs = vectorstore.similarity_search("política de vacaciones", k=4)
|
|
91
|
+
|
|
92
|
+
# Búsqueda con score de relevancia (1.0 = idéntico, 0.0 = sin relación)
|
|
93
|
+
docs_con_score = vectorstore.similarity_search_with_score("política de vacaciones", k=4)
|
|
94
|
+
for doc, score in docs_con_score:
|
|
95
|
+
print(f"Score: {score:.3f} | {doc.page_content[:100]}")
|
|
96
|
+
|
|
97
|
+
# Búsqueda con filtro de metadata
|
|
98
|
+
docs_filtrados = vectorstore.similarity_search(
|
|
99
|
+
"instrucciones de seguridad",
|
|
100
|
+
k=4,
|
|
101
|
+
filter={"fuente": "manual_seguridad_2024.pdf"},
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Búsqueda híbrida manual con pgvector
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
-- Combinar búsqueda vectorial + full-text search con Reciprocal Rank Fusion (RRF)
|
|
109
|
+
WITH vectorial AS (
|
|
110
|
+
SELECT id, contenido, fuente,
|
|
111
|
+
1 - (embedding <=> $1::vector) AS score_vector,
|
|
112
|
+
ROW_NUMBER() OVER (ORDER BY embedding <=> $1::vector) AS rank_vector
|
|
113
|
+
FROM documento_chunks
|
|
114
|
+
ORDER BY embedding <=> $1::vector
|
|
115
|
+
LIMIT 20
|
|
116
|
+
),
|
|
117
|
+
textual AS (
|
|
118
|
+
SELECT id, contenido, fuente,
|
|
119
|
+
ts_rank(to_tsvector('spanish', contenido), plainto_tsquery('spanish', $2)) AS score_texto,
|
|
120
|
+
ROW_NUMBER() OVER (ORDER BY ts_rank(to_tsvector('spanish', contenido), plainto_tsquery('spanish', $2)) DESC) AS rank_texto
|
|
121
|
+
FROM documento_chunks
|
|
122
|
+
WHERE to_tsvector('spanish', contenido) @@ plainto_tsquery('spanish', $2)
|
|
123
|
+
LIMIT 20
|
|
124
|
+
)
|
|
125
|
+
SELECT
|
|
126
|
+
COALESCE(v.id, t.id) AS id,
|
|
127
|
+
COALESCE(v.contenido, t.contenido) AS contenido,
|
|
128
|
+
-- RRF score: 1/(k + rank) donde k=60 es estándar
|
|
129
|
+
COALESCE(1.0 / (60 + v.rank_vector), 0) + COALESCE(1.0 / (60 + t.rank_texto), 0) AS score_rrf
|
|
130
|
+
FROM vectorial v
|
|
131
|
+
FULL OUTER JOIN textual t ON v.id = t.id
|
|
132
|
+
ORDER BY score_rrf DESC
|
|
133
|
+
LIMIT 5;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Chroma — uso local
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
import chromadb
|
|
142
|
+
from langchain_community.vectorstores import Chroma
|
|
143
|
+
from langchain_openai import OpenAIEmbeddings
|
|
144
|
+
|
|
145
|
+
# Persistente en disco (desarrollo)
|
|
146
|
+
cliente = chromadb.PersistentClient(path="./chroma_db")
|
|
147
|
+
|
|
148
|
+
vectorstore = Chroma(
|
|
149
|
+
client=cliente,
|
|
150
|
+
collection_name="documentos",
|
|
151
|
+
embedding_function=OpenAIEmbeddings(),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Agregar documentos
|
|
155
|
+
vectorstore.add_documents(chunks)
|
|
156
|
+
|
|
157
|
+
# Buscar
|
|
158
|
+
docs = vectorstore.similarity_search("consulta", k=4)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Limitaciones de Chroma**: no tiene transacciones ACID, rendimiento degrada con
|
|
162
|
+
colecciones > 500k vectores, no tiene búsqueda híbrida nativa. Usar solo en desarrollo.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Pinecone — serverless
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from pinecone import Pinecone
|
|
170
|
+
from langchain_pinecone import PineconeVectorStore
|
|
171
|
+
from langchain_openai import OpenAIEmbeddings
|
|
172
|
+
|
|
173
|
+
# Inicializar cliente
|
|
174
|
+
pc = Pinecone(api_key=settings.PINECONE_API_KEY)
|
|
175
|
+
|
|
176
|
+
# Crear índice si no existe
|
|
177
|
+
if "documentos" not in pc.list_indexes().names():
|
|
178
|
+
pc.create_index(
|
|
179
|
+
name="documentos",
|
|
180
|
+
dimension=1536, # debe coincidir con el modelo de embedding
|
|
181
|
+
metric="cosine",
|
|
182
|
+
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
indice = pc.Index("documentos")
|
|
186
|
+
vectorstore = PineconeVectorStore(index=indice, embedding=OpenAIEmbeddings())
|
|
187
|
+
|
|
188
|
+
# Upsert con metadata
|
|
189
|
+
vectorstore.add_documents(chunks)
|
|
190
|
+
|
|
191
|
+
# Búsqueda con filtro de namespace
|
|
192
|
+
docs = vectorstore.similarity_search(
|
|
193
|
+
"consulta",
|
|
194
|
+
k=4,
|
|
195
|
+
namespace="empresa-x", # para multi-tenancy
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Weaviate — búsqueda híbrida
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
import weaviate
|
|
205
|
+
from langchain_weaviate.vectorstores import WeaviateVectorStore
|
|
206
|
+
|
|
207
|
+
cliente_weaviate = weaviate.connect_to_local() # o connect_to_weaviate_cloud(...)
|
|
208
|
+
|
|
209
|
+
vectorstore = WeaviateVectorStore(
|
|
210
|
+
client=cliente_weaviate,
|
|
211
|
+
index_name="Documentos",
|
|
212
|
+
text_key="contenido",
|
|
213
|
+
embedding=OpenAIEmbeddings(),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Búsqueda híbrida (combina BM25 + vector automáticamente)
|
|
217
|
+
docs = vectorstore.similarity_search(
|
|
218
|
+
"consulta sobre vacaciones",
|
|
219
|
+
k=4,
|
|
220
|
+
search_type="hybrid",
|
|
221
|
+
alpha=0.5, # 0 = solo BM25, 1 = solo vector, 0.5 = equilibrado
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Estrategia de actualización del vector store
|
|
228
|
+
|
|
229
|
+
### Re-embedding completo — cuándo hacerlo
|
|
230
|
+
|
|
231
|
+
- Cambio de modelo de embedding (dimensiones o distribución diferentes).
|
|
232
|
+
- Cambio radical en la base de documentos (> 50% de contenido nuevo).
|
|
233
|
+
- Degradación de métricas RAGAS detectada en evaluación periódica.
|
|
234
|
+
|
|
235
|
+
### Actualización incremental — el caso más común
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
import hashlib
|
|
239
|
+
|
|
240
|
+
def hash_documento(contenido: str) -> str:
|
|
241
|
+
"""Fingerprint del contenido para detectar cambios."""
|
|
242
|
+
return hashlib.sha256(contenido.encode()).hexdigest()
|
|
243
|
+
|
|
244
|
+
async def sincronizar_documento(doc_id: str, contenido: str, vectorstore: PGVector):
|
|
245
|
+
"""Solo re-embebede si el contenido cambió."""
|
|
246
|
+
hash_nuevo = hash_documento(contenido)
|
|
247
|
+
|
|
248
|
+
# Verificar hash almacenado en metadata
|
|
249
|
+
docs_existentes = vectorstore.similarity_search(
|
|
250
|
+
"", k=1, filter={"doc_id": doc_id}
|
|
251
|
+
)
|
|
252
|
+
if docs_existentes and docs_existentes[0].metadata.get("hash") == hash_nuevo:
|
|
253
|
+
return # Sin cambios — omitir re-embedding
|
|
254
|
+
|
|
255
|
+
# Eliminar chunks anteriores del documento
|
|
256
|
+
vectorstore.delete(ids=obtener_ids_por_doc(doc_id))
|
|
257
|
+
|
|
258
|
+
# Re-embebeder y guardar
|
|
259
|
+
chunks_nuevos = splitter.split_text(contenido)
|
|
260
|
+
vectorstore.add_texts(
|
|
261
|
+
texts=chunks_nuevos,
|
|
262
|
+
metadatas=[{"doc_id": doc_id, "hash": hash_nuevo}] * len(chunks_nuevos),
|
|
263
|
+
)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Costos de embeddings — referencia de precios
|
|
269
|
+
|
|
270
|
+
| Modelo | Proveedor | Costo / 1M tokens | Dimensiones | Notas |
|
|
271
|
+
|--------|-----------|-------------------|-------------|-------|
|
|
272
|
+
| text-embedding-3-small | OpenAI | $0.020 | 1536 | Mejor relación costo/calidad |
|
|
273
|
+
| text-embedding-3-large | OpenAI | $0.130 | 3072 | Mayor precisión |
|
|
274
|
+
| text-embedding-ada-002 | OpenAI | $0.100 | 1536 | Obsoleto — migrar a v3 |
|
|
275
|
+
| voyage-3 | Anthropic | $0.060 | 1024 | Óptimo con Claude |
|
|
276
|
+
| all-MiniLM-L6-v2 | HuggingFace | Gratis (local) | 384 | Sin costo de API |
|
|
277
|
+
| nomic-embed-text | Ollama | Gratis (local) | 768 | 100% on-premise |
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
def estimar_costo_corpus(rutas_pdf: list[str], modelo: str = "text-embedding-3-small") -> dict:
|
|
281
|
+
"""Estima el costo antes de embeber un corpus completo."""
|
|
282
|
+
import tiktoken
|
|
283
|
+
from langchain_community.document_loaders import PyPDFLoader
|
|
284
|
+
|
|
285
|
+
enc = tiktoken.get_encoding("cl100k_base")
|
|
286
|
+
total_tokens = 0
|
|
287
|
+
|
|
288
|
+
for ruta in rutas_pdf:
|
|
289
|
+
loader = PyPDFLoader(ruta)
|
|
290
|
+
docs = loader.load()
|
|
291
|
+
for doc in docs:
|
|
292
|
+
total_tokens += len(enc.encode(doc.page_content))
|
|
293
|
+
|
|
294
|
+
precios = {
|
|
295
|
+
"text-embedding-3-small": 0.020,
|
|
296
|
+
"text-embedding-3-large": 0.130,
|
|
297
|
+
"voyage-3": 0.060,
|
|
298
|
+
}
|
|
299
|
+
costo_usd = total_tokens / 1_000_000 * precios.get(modelo, 0.020)
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
"total_tokens": total_tokens,
|
|
303
|
+
"modelo": modelo,
|
|
304
|
+
"costo_estimado_usd": round(costo_usd, 4),
|
|
305
|
+
}
|
|
306
|
+
```
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: legacy-code-rescue
|
|
3
|
+
description: >
|
|
4
|
+
Técnicas para trabajar con código heredado sin tests, siguiendo la metodología
|
|
5
|
+
de Michael Feathers ("Working Effectively with Legacy Code"). Cubre
|
|
6
|
+
identificación de seams, characterization tests para capturar comportamiento
|
|
7
|
+
real (no el deseado), patrones para introducir cambios sin romper
|
|
8
|
+
(sprout method, sprout class, wrap method, wrap class), técnicas para romper
|
|
9
|
+
dependencias problemáticas, y orden de prioridad cuando se hereda código
|
|
10
|
+
sin cobertura. Cargar cuando se herede código sin tests, cuando un módulo
|
|
11
|
+
crítico tenga cobertura <30%, o cuando se planee refactoring de un sistema
|
|
12
|
+
heredado.
|
|
13
|
+
version: "1.0.0"
|
|
14
|
+
evolved: false
|
|
15
|
+
herramientasPermitidas: [Read]
|
|
16
|
+
exclusiones:
|
|
17
|
+
- "No cargar para refactoring de código moderno con buena cobertura — si los tests existen y cubren el área a refactorear, basta con `tdd-workflow`. Este skill es específico para código sin red de seguridad."
|
|
18
|
+
- "No cargar para migración entre versiones de framework — usar `deprecacion-migracion`. Este skill cubre rescate de código heredado en general, no actualizaciones de stack."
|
|
19
|
+
- "No cargar para deprecación planificada de features — usar `deprecacion-migracion`. Este skill cubre el problema inverso: código que NO se quiere deprecar pero hay que cambiar con seguridad."
|
|
20
|
+
- "No cargar para optimización de rendimiento de código moderno — los patrones aquí (especialmente characterization tests) priorizan seguridad sobre velocidad. Si la prioridad es perf, usar `performance-baseline` y profilers."
|
|
21
|
+
evolvable: true
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Legacy Code Rescue
|
|
25
|
+
|
|
26
|
+
Adaptado de "Working Effectively with Legacy Code" (Michael Feathers, 2004).
|
|
27
|
+
Definición operativa de Feathers: **legacy code es código sin tests**, sin
|
|
28
|
+
importar su edad o calidad aparente.
|
|
29
|
+
|
|
30
|
+
## Cuándo cargar
|
|
31
|
+
|
|
32
|
+
- Se hereda un módulo crítico con cobertura <30% y hay que cambiarlo.
|
|
33
|
+
- Se diagnostica un bug en código que nadie ha tocado en meses/años.
|
|
34
|
+
- Se planea un refactor de un sistema sin red de seguridad de tests.
|
|
35
|
+
- Se necesita agregar una feature en código que actualmente no se puede
|
|
36
|
+
testear de forma aislada.
|
|
37
|
+
- Se reciben quejas tipo "tengo miedo de tocar X porque puede romper Y".
|
|
38
|
+
|
|
39
|
+
## Cuándo NO cargar
|
|
40
|
+
|
|
41
|
+
- El código tiene cobertura ≥80% y los tests pasan — usar `tdd-workflow`.
|
|
42
|
+
- Se está migrando entre versiones de framework — usar `deprecacion-migracion`.
|
|
43
|
+
- Se está deprecando una feature intencionalmente — usar `deprecacion-migracion`.
|
|
44
|
+
- El objetivo es optimizar rendimiento — los patrones aquí priorizan seguridad
|
|
45
|
+
sobre velocidad; usar `performance-baseline` y profilers.
|
|
46
|
+
|
|
47
|
+
## Directiva primaria
|
|
48
|
+
|
|
49
|
+
**Antes de cambiar código heredado, capturar lo que hace**, no lo que se
|
|
50
|
+
supone que debe hacer. El comportamiento actual (incluidos sus bugs) es
|
|
51
|
+
la fuente de verdad — algún caller probablemente depende de cada peculiaridad.
|
|
52
|
+
|
|
53
|
+
Orden estricto:
|
|
54
|
+
1. **Caracterizar** el comportamiento actual con tests.
|
|
55
|
+
2. **Romper dependencias** lo mínimo necesario para que los tests sean posibles.
|
|
56
|
+
3. **Cambiar** el código.
|
|
57
|
+
4. **Refactorizar** ya con red de seguridad.
|
|
58
|
+
|
|
59
|
+
NO empezar refactorizando "porque el código está feo". Sin tests, cada cambio
|
|
60
|
+
es una apuesta.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Identificar seams (costuras)
|
|
65
|
+
|
|
66
|
+
Un **seam** es un punto donde el comportamiento del programa puede cambiarse
|
|
67
|
+
sin editar el código original. Los seams son la palanca para introducir
|
|
68
|
+
tests sin romper nada.
|
|
69
|
+
|
|
70
|
+
### Tipos de seams
|
|
71
|
+
|
|
72
|
+
| Tipo | Cuándo aplica | Cómo se activa |
|
|
73
|
+
|------|---------------|----------------|
|
|
74
|
+
| **Object seam** | OOP con polimorfismo | Inyectar una subclase/mock que herede |
|
|
75
|
+
| **Preprocessing seam** | C/C++ con `#define` | Macros o preprocesador |
|
|
76
|
+
| **Link seam** | Lenguajes compilados con linker | Sustituir librería en build |
|
|
77
|
+
| **Method seam** (Python/JS) | Lenguajes dinámicos | Monkeypatching, importlib |
|
|
78
|
+
|
|
79
|
+
En Python/TypeScript modernos, el object seam es el predominante:
|
|
80
|
+
inyectar dependencias en lugar de instanciarlas dentro del constructor.
|
|
81
|
+
|
|
82
|
+
### Identificar seams en código existente
|
|
83
|
+
|
|
84
|
+
Buscar:
|
|
85
|
+
- `new SomeClass()` dentro de constructores → object seam latente al refactorizar.
|
|
86
|
+
- Llamadas estáticas a clases globales → buscar wrappers o usar dependency injection.
|
|
87
|
+
- Imports de módulos con efectos secundarios → candidato a method seam.
|
|
88
|
+
- Funciones puras escondidas dentro de métodos largos → extraer es seam barato.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Characterization tests — capturar el comportamiento real
|
|
93
|
+
|
|
94
|
+
Un **characterization test** documenta lo que el código HACE, no lo que
|
|
95
|
+
debería hacer. Son la red de seguridad mínima antes de cualquier cambio.
|
|
96
|
+
|
|
97
|
+
### Receta
|
|
98
|
+
|
|
99
|
+
1. Tomar el código y ejecutarlo con un input concreto.
|
|
100
|
+
2. Capturar el output exacto (incluido errores, side effects, state final).
|
|
101
|
+
3. Escribir un test que assert ese output específico.
|
|
102
|
+
4. Repetir con varios inputs representativos: caso típico, edge cases
|
|
103
|
+
conocidos, inputs malformados, valores extremos.
|
|
104
|
+
5. Cuando el test pasa, **es la verdad** — incluso si revela un bug.
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# Ejemplo: función legacy sin tests
|
|
108
|
+
def calcular_descuento(precio, tipo_cliente):
|
|
109
|
+
# ... 80 líneas de if/else, redondeos extraños, edge cases ocultos
|
|
110
|
+
return total
|
|
111
|
+
|
|
112
|
+
# Characterization test — captura el comportamiento ACTUAL
|
|
113
|
+
def test_caracterizacion_descuento():
|
|
114
|
+
# Input típico
|
|
115
|
+
assert calcular_descuento(100, "VIP") == 85.0
|
|
116
|
+
# Edge case observado: tipo_cliente vacío
|
|
117
|
+
assert calcular_descuento(100, "") == 100.0
|
|
118
|
+
# Bug aparente, pero callers pueden depender de él
|
|
119
|
+
assert calcular_descuento(0, "VIP") == 0.0
|
|
120
|
+
# Negativos: el código devuelve negativos sin validar — documentarlo
|
|
121
|
+
assert calcular_descuento(-50, "VIP") == -42.5
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Reglas para characterization tests
|
|
125
|
+
|
|
126
|
+
- **No "arreglar" bugs** mientras se caracteriza — eso viene después.
|
|
127
|
+
- Si el comportamiento parece incorrecto, escribir un test que lo
|
|
128
|
+
documente Y abrir un ticket separado para discutir el cambio.
|
|
129
|
+
- Apuntar a cubrir los flujos que se van a tocar — no toda la base de
|
|
130
|
+
código.
|
|
131
|
+
- Tests rápidos > tests perfectos. Un test feo que corre es mejor que
|
|
132
|
+
uno elegante que no se escribió.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Patrones para cambio seguro
|
|
137
|
+
|
|
138
|
+
Cuando hay que agregar comportamiento sin tocar código existente.
|
|
139
|
+
|
|
140
|
+
### Sprout Method
|
|
141
|
+
|
|
142
|
+
Si necesitas lógica nueva dentro de un método legacy difícil de testear,
|
|
143
|
+
**escribe la lógica nueva como método aparte** (con tests propios) y
|
|
144
|
+
llámalo desde el método legacy.
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
# Antes — quieres agregar validación al método legacy
|
|
148
|
+
def procesar_orden(orden):
|
|
149
|
+
# 200 líneas legacy intocables
|
|
150
|
+
...
|
|
151
|
+
|
|
152
|
+
# Después — la nueva validación vive aparte y SÍ es testeable
|
|
153
|
+
def procesar_orden(orden):
|
|
154
|
+
# 200 líneas legacy intocables
|
|
155
|
+
if not _validar_disponibilidad_inventario(orden): # nuevo
|
|
156
|
+
return ResultadoOrden.fallo("sin stock")
|
|
157
|
+
...
|
|
158
|
+
|
|
159
|
+
def _validar_disponibilidad_inventario(orden):
|
|
160
|
+
"""Nuevo método con tests propios (no toca el legacy)."""
|
|
161
|
+
return all(item.cantidad <= item.producto.stock for item in orden.items)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Sprout Class
|
|
165
|
+
|
|
166
|
+
Cuando la lógica nueva es suficientemente grande, va en una **clase nueva**
|
|
167
|
+
en lugar de un método. Misma idea: lógica nueva con tests, llamada desde
|
|
168
|
+
el legacy.
|
|
169
|
+
|
|
170
|
+
### Wrap Method
|
|
171
|
+
|
|
172
|
+
Si necesitas ejecutar algo ANTES o DESPUÉS de un método legacy, renombra
|
|
173
|
+
el original a algo interno (`_procesar_orden_original`) y crea uno nuevo
|
|
174
|
+
con la firma original que llame al wrap + el original.
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
def procesar_orden(orden): # firma pública intacta
|
|
178
|
+
_registrar_intento(orden) # nueva pre-acción, testeable
|
|
179
|
+
resultado = _procesar_orden_original(orden)
|
|
180
|
+
_registrar_resultado(resultado) # nueva post-acción, testeable
|
|
181
|
+
return resultado
|
|
182
|
+
|
|
183
|
+
def _procesar_orden_original(orden):
|
|
184
|
+
# 200 líneas legacy intocables, ahora son privadas
|
|
185
|
+
...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Wrap Class
|
|
189
|
+
|
|
190
|
+
Para wrap de un sistema más grande: una clase nueva con la misma interfaz
|
|
191
|
+
delega al legacy y agrega comportamiento alrededor (decorator pattern).
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Romper dependencias
|
|
196
|
+
|
|
197
|
+
Algunos legacy methods son intratables por dependencias:
|
|
198
|
+
- Conexiones a BD/red en el constructor.
|
|
199
|
+
- Singletons globales que se acceden en cualquier parte.
|
|
200
|
+
- Llamadas a `time.now()`, `random()`, filesystem.
|
|
201
|
+
|
|
202
|
+
Técnicas (en orden de invasividad creciente):
|
|
203
|
+
|
|
204
|
+
1. **Subclass and Override Method**: hereda de la clase legacy, sobreescribe
|
|
205
|
+
el método problemático con un mock para los tests.
|
|
206
|
+
2. **Extract Interface / Extract Class**: extrae una interfaz pequeña con
|
|
207
|
+
solo los métodos que el código usa, e inyecta una implementación de prueba.
|
|
208
|
+
3. **Parameterize Method/Constructor**: inyecta como parámetro lo que antes
|
|
209
|
+
se obtenía globalmente (clock, random, IO).
|
|
210
|
+
4. **Replace Function with Function Pointer / Strategy**: cambiar funciones
|
|
211
|
+
estáticas por callables inyectables.
|
|
212
|
+
|
|
213
|
+
Aplicar la técnica MENOS invasiva que resuelva el problema. Cuanto más
|
|
214
|
+
invasiva, más riesgo de romper algo durante el rescate.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Anti-patrones
|
|
219
|
+
|
|
220
|
+
- **Refactorizar antes de tener characterization tests**: cualquier cambio
|
|
221
|
+
estructural sin red de seguridad es una apuesta.
|
|
222
|
+
- **"Mejorar" el comportamiento mientras se caracteriza**: si parece un
|
|
223
|
+
bug, documéntalo en un ticket y déjalo intacto en el characterization
|
|
224
|
+
test. Cambios funcionales van en commits separados con su propia revisión.
|
|
225
|
+
- **Apuntar a 100% de cobertura del módulo entero**: el objetivo es
|
|
226
|
+
cubrir lo que se va a tocar. Cobertura completa puede tomar meses;
|
|
227
|
+
cubrir el slice de cambio toma horas.
|
|
228
|
+
- **Borrar código "muerto" sin verificar**: en legacy, algo que parece
|
|
229
|
+
muerto puede ser invocado por reflection o cron. Buscar referencias
|
|
230
|
+
con `grep -r` antes de borrar.
|
|
231
|
+
- **Sustituir "todo" con un mock**: si el test pasa solo porque mockeaste
|
|
232
|
+
todas las dependencias, ya no testea nada. Mockear solo lo necesario
|
|
233
|
+
para aislar el código bajo prueba.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Gotchas / Errores comunes no obvios
|
|
238
|
+
|
|
239
|
+
- **Characterization test "perfecto" que se rompe en CI por orden no determinista**: el código legacy depende del orden de iteración de un dict (Python <3.7) o del timezone del servidor. Causa: comportamiento dependiente de entorno. Solución: capturar la dependencia (forzar timezone UTC en el test, ordenar collections antes de assert) y documentar la dependencia ambiental como bug a discutir.
|
|
240
|
+
- **Sprout Method que sí toca el legacy "solo un poquito"**: el desarrollador agrega un `if condicion_nueva` dentro del legacy en lugar de extraer. Causa: parece más simple. Solución: si tocas el legacy, ya no es sprout; o caracterizas primero, o aplicas wrap method que NO modifica el cuerpo original.
|
|
241
|
+
- **Inyectar dependencia con un default que llama al global**: `def __init__(self, db=None): self.db = db or get_global_db()`. Causa: querer mantener compatibilidad con callers viejos. Solución: el default escondido invalida la inyección — los tests acaban tocando el global. Aceptar que romper la firma es parte del rescate; agregar wrappers de compatibilidad fuera de la clase si es necesario.
|
|
242
|
+
- **Cobertura como métrica engañosa**: 80% de cobertura de líneas pero los asserts solo verifican que "no lanza excepción". Causa: tests escritos para subir el número, no para capturar comportamiento. Solución: cada characterization test debe tener al menos un assert sobre el output o side effect concreto, no solo `assert resultado is not None`.
|
|
243
|
+
- **Mock de la BD que devuelve datos perfectos donde el legacy maneja datos sucios**: el código legacy tiene defensas contra datos inconsistentes que el mock no reproduce. Causa: el mock idealiza la realidad. Solución: el mock debe reproducir la sucidad observada en producción (NULLs inesperados, encodings raros, duplicados) — caracterizar la entrada real es parte del rescate.
|
|
244
|
+
|
|
245
|
+
## Orden de prioridad cuando se hereda código
|
|
246
|
+
|
|
247
|
+
1. **Estabilizar**: identificar el módulo más crítico, escribir
|
|
248
|
+
characterization tests sobre los flujos que se van a tocar pronto.
|
|
249
|
+
2. **Aislar**: romper dependencias problemáticas con seams para que el
|
|
250
|
+
módulo crítico pueda testearse en isolation.
|
|
251
|
+
3. **Cubrir**: agregar tests sobre código nuevo (Sprout/Wrap) y sobre
|
|
252
|
+
regresiones detectadas.
|
|
253
|
+
4. **Cambiar**: hacer el cambio funcional pedido, ya con red de seguridad.
|
|
254
|
+
5. **Refactorizar**: mejorar la estructura ya que está cubierta. NO antes.
|
|
255
|
+
|
|
256
|
+
NO refactorices código que no piensas tocar. La cobertura no es un fin
|
|
257
|
+
en sí mismo — es palanca para cambios futuros.
|
|
258
|
+
|
|
259
|
+
## Checklist antes de tocar código heredado
|
|
260
|
+
|
|
261
|
+
- [ ] ¿Existen characterization tests sobre la zona de cambio?
|
|
262
|
+
- [ ] Si no: ¿se escribieron antes de cualquier modificación?
|
|
263
|
+
- [ ] ¿Las dependencias bloqueantes (DB, red, time, random) están aisladas?
|
|
264
|
+
- [ ] ¿El cambio funcional va en un commit separado del refactor estructural?
|
|
265
|
+
- [ ] ¿Se documentaron en tickets los bugs detectados durante la caracterización?
|
|
266
|
+
- [ ] ¿La cobertura nueva es del slice tocado, no del módulo completo?
|
|
267
|
+
- [ ] ¿El sprout/wrap se queda fuera del cuerpo legacy original?
|