@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,163 @@
|
|
|
1
|
+
# Skills as Agents — patrón técnico avanzado
|
|
2
|
+
|
|
3
|
+
Documenta el patrón Anthropic nativo de ejecutar un skill SWL en su propio
|
|
4
|
+
sub-agente con `agent: true` + `model:` en el frontmatter. Origen: artículo
|
|
5
|
+
"Claude Code's Limits Are Generous. The Problem Is Your Harness." sección 2.3.
|
|
6
|
+
|
|
7
|
+
## Concepto
|
|
8
|
+
|
|
9
|
+
Un SKILL.md normal es contenido que se carga al contexto del padre cuando
|
|
10
|
+
se invoca con `Skill("nombre")`. El skill aporta reglas, conocimiento o
|
|
11
|
+
guía al modelo del padre, que las usa al razonar.
|
|
12
|
+
|
|
13
|
+
Con el patrón skills as agents, el skill se vuelve **invocable como
|
|
14
|
+
sub-agente independiente**: tiene su propio modelo, su propio contexto,
|
|
15
|
+
y solo devuelve un resultado acotado al padre. Útil cuando el skill
|
|
16
|
+
procesa un input grande y debe entregar un resumen.
|
|
17
|
+
|
|
18
|
+
## Cuándo usar este patrón
|
|
19
|
+
|
|
20
|
+
- El skill procesa un archivo o input grande y debe devolver solo un
|
|
21
|
+
resumen al padre (ejemplo: extraer TLDR de un PDF de 50 páginas, sin
|
|
22
|
+
que el texto completo entre al contexto del padre).
|
|
23
|
+
- El skill ejecuta búsqueda exhaustiva o crawling de un codebase completo
|
|
24
|
+
y el resultado es un set acotado de findings.
|
|
25
|
+
- El skill necesita un modelo distinto al del padre por costo o latencia
|
|
26
|
+
(Haiku para trabajo mecánico cuando el padre es Opus).
|
|
27
|
+
- El trabajo del skill es paralelizable y se va a invocar varias veces en
|
|
28
|
+
la misma sesión.
|
|
29
|
+
|
|
30
|
+
## Cuándo NO usar
|
|
31
|
+
|
|
32
|
+
- El skill solo aporta reglas o conocimiento estático que se aplica al
|
|
33
|
+
razonamiento del padre — esos son skills "passive" normales y NO
|
|
34
|
+
necesitan `agent: true`. Su valor es justamente que cargan reglas al
|
|
35
|
+
contexto del padre.
|
|
36
|
+
- El skill es referenciado dentro de otro skill como contenido de apoyo
|
|
37
|
+
— el contexto del padre lo necesita ver.
|
|
38
|
+
- El skill requiere acceso al contexto activo del padre (decisiones
|
|
39
|
+
tomadas mid-session, archivos ya leídos) — `agent: true` aísla del
|
|
40
|
+
padre, así que el sub-agente no vería esa información.
|
|
41
|
+
- El skill es invocado una sola vez en la sesión y su output es pequeño
|
|
42
|
+
— el overhead de spawn de sub-agente puede dominar.
|
|
43
|
+
|
|
44
|
+
## Ejemplo de skill como agent
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
---
|
|
48
|
+
name: tldr-pdf
|
|
49
|
+
description: >
|
|
50
|
+
Extrae TLDR de 200 palabras de un PDF sin cargar el texto completo en
|
|
51
|
+
el contexto del padre. Cargar cuando se reciba ruta a un PDF que solo
|
|
52
|
+
necesita resumen ejecutivo.
|
|
53
|
+
agent: true
|
|
54
|
+
model: claude-haiku-4-5-20251001
|
|
55
|
+
herramientasPermitidas: [Bash, Read]
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
# tldr-pdf
|
|
59
|
+
|
|
60
|
+
Recibes la ruta de un PDF como input.
|
|
61
|
+
|
|
62
|
+
1. Ejecuta `pdftotext "$1" -` para extraer texto.
|
|
63
|
+
2. Lee la salida.
|
|
64
|
+
3. Devuelve SOLO:
|
|
65
|
+
- 5 bullets de TLDR
|
|
66
|
+
- 3 quotes que valga la pena conservar
|
|
67
|
+
- URLs citadas
|
|
68
|
+
|
|
69
|
+
Nunca devuelvas el texto completo. Nunca expandas más allá de la estructura.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Flujo: el padre invoca `Skill("tldr-pdf")` con la ruta del PDF; el
|
|
73
|
+
sub-agente Haiku ejecuta `pdftotext`, lee la salida (que llena su propio
|
|
74
|
+
contexto, no el del padre), y devuelve ~200 palabras estructuradas. El PDF
|
|
75
|
+
completo nunca toca el contexto del padre.
|
|
76
|
+
|
|
77
|
+
## Reglas del patrón
|
|
78
|
+
|
|
79
|
+
### Frontmatter
|
|
80
|
+
|
|
81
|
+
- `agent: true` activa el modo sub-agente.
|
|
82
|
+
- `model:` debe ser un modelo Anthropic válido. Para skills mecánicos,
|
|
83
|
+
preferir Haiku (5× más barato que Sonnet, 25× más barato que Opus 4.7).
|
|
84
|
+
- El frontmatter sigue siendo válido SWL: incluir `name`, `description`,
|
|
85
|
+
`herramientasPermitidas`, `exclusiones` y demás campos obligatorios.
|
|
86
|
+
|
|
87
|
+
### Cuerpo
|
|
88
|
+
|
|
89
|
+
- Debe ser **autocontenido**: el sub-agente NO tiene acceso al contexto
|
|
90
|
+
del padre (CLAUDE.md del proyecto, instintos cargados, sesión activa,
|
|
91
|
+
archivos previamente leídos). Todo lo que necesite saber tiene que
|
|
92
|
+
estar en el cuerpo del skill o en lo que reciba como input.
|
|
93
|
+
- El output debe ser **acotado**: si el sub-agente devuelve un dump
|
|
94
|
+
masivo, se pierde el beneficio (terminamos pasando lo mismo al padre,
|
|
95
|
+
solo con un round-trip extra). Especificar formato exacto en el
|
|
96
|
+
cuerpo del skill: número de bullets, longitud máxima, qué incluir y
|
|
97
|
+
qué no.
|
|
98
|
+
|
|
99
|
+
### Errores comunes a evitar
|
|
100
|
+
|
|
101
|
+
- **Usar Opus en `model:` para skills mecánicos**: invalida el ahorro de
|
|
102
|
+
costo. La mayoría de skills as agents deberían ser Haiku o Sonnet.
|
|
103
|
+
- **Devolver el texto crudo del input**: si el skill recibe un PDF y
|
|
104
|
+
devuelve el texto completo, no estamos aislando nada. Devuelve siempre
|
|
105
|
+
la transformación, no el material crudo.
|
|
106
|
+
- **Asumir que el skill verá el CLAUDE.md del proyecto**: no lo verá.
|
|
107
|
+
Si el skill necesita seguir convenciones del proyecto, hay que
|
|
108
|
+
explicárselas en el cuerpo.
|
|
109
|
+
|
|
110
|
+
## Skills SWL candidatos al patrón (no migración masiva)
|
|
111
|
+
|
|
112
|
+
Evaluación caso por caso. NO aplicar masivamente — el patrón aporta solo
|
|
113
|
+
cuando el skill consume input grande y devuelve output acotado.
|
|
114
|
+
|
|
115
|
+
| Skill SWL | Por qué encaja | Modelo recomendado |
|
|
116
|
+
|-----------|----------------|--------------------|
|
|
117
|
+
| `extraccion-documentos` | Procesa PDFs/Office grandes | Haiku |
|
|
118
|
+
| `mapear-codebase` | Procesa codebase entero, devuelve reporte | Sonnet |
|
|
119
|
+
| `wiki-conocimiento` (modo query) | Búsqueda en wiki con respuesta acotada | Sonnet |
|
|
120
|
+
|
|
121
|
+
Skills NO candidatos (son passive, su valor es cargar reglas al contexto del padre):
|
|
122
|
+
|
|
123
|
+
- `manejo-errores`, `auth-patrones`, `api-rest-diseno`, `accesibilidad-a11y`, etc.
|
|
124
|
+
- Toda regla de estilo o convención por lenguaje.
|
|
125
|
+
- Toda regla SWL en `reglas/`.
|
|
126
|
+
|
|
127
|
+
## Implicaciones operativas
|
|
128
|
+
|
|
129
|
+
### Costo
|
|
130
|
+
|
|
131
|
+
Spawn de sub-agente tiene overhead (system prompt + carga del skill +
|
|
132
|
+
contexto inicial). Para inputs chicos, el overhead supera el ahorro.
|
|
133
|
+
Regla práctica: usar el patrón si el input que el skill procesa es
|
|
134
|
+
≥3,000 tokens (o ≥10K caracteres).
|
|
135
|
+
|
|
136
|
+
### Latencia
|
|
137
|
+
|
|
138
|
+
El padre espera al sub-agente antes de continuar. Si el skill demora >10s,
|
|
139
|
+
considerar si la operación cabe en el padre directamente (sin spawn).
|
|
140
|
+
|
|
141
|
+
### Trazabilidad
|
|
142
|
+
|
|
143
|
+
Los sub-agentes spawneados aparecen en `claude-usage` (vendor SWL) como
|
|
144
|
+
invocaciones separadas con su propio modelo. Útil para entender qué
|
|
145
|
+
porcentaje del costo viene de sub-agentes vs. trabajo del padre.
|
|
146
|
+
|
|
147
|
+
### Compatibilidad con SWL
|
|
148
|
+
|
|
149
|
+
- El skill sigue registrado normalmente en `manifiestos/modulos.json`.
|
|
150
|
+
- El skill se invoca igual: `Skill("nombre")`. La diferencia es interna
|
|
151
|
+
(el harness Anthropic decide si lo carga al padre o lo ejecuta como
|
|
152
|
+
sub-agente según el frontmatter).
|
|
153
|
+
- Hooks SWL siguen aplicando: `linea-estado.js`, `monitor-contexto.js`,
|
|
154
|
+
`audit-trail.js` registran las invocaciones del sub-agente.
|
|
155
|
+
|
|
156
|
+
## Referencias
|
|
157
|
+
|
|
158
|
+
- Artículo de origen: "Claude Code's Limits Are Generous. The Problem Is
|
|
159
|
+
Your Harness." (sección 2.3 — Skills Can Also Be Invoked as Agents).
|
|
160
|
+
- Documentación oficial Anthropic sobre Claude Skills (cuando esté
|
|
161
|
+
disponible).
|
|
162
|
+
- `Skill("harness-claude-code")` — uso operativo del patrón en sesiones
|
|
163
|
+
largas, junto con sub-agentes via Task tool y delegación explícita.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: microservicios
|
|
3
|
+
description: Arquitectura de microservicios. Cuándo usar y cuándo NO. Circuit breakers, service mesh, API gateway, saga pattern, event sourcing, CQRS, distributed tracing, health checks, service discovery. Anti-patrones.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
herramientasPermitidas: [Read, Grep]
|
|
6
|
+
exclusiones:
|
|
7
|
+
- "No cargar para implementación de APIs REST o GraphQL individuales — para implementación de endpoints cargar `fastapi-experto`, `api-rest-diseno` o `graphql-experto`."
|
|
8
|
+
- "No cargar para infraestructura de Kubernetes, Docker o Terraform — para infra cargar `cloud-infra`."
|
|
9
|
+
- "No cargar para messaging/event streaming específico (Kafka, RabbitMQ) — este skill cubre los patrones de arquitectura; para implementación de brokers usar los recursos de infra."
|
|
10
|
+
- "No cargar para monolitos modulares o arquitectura hexagonal sin distribución — este skill asume distribución de red entre servicios."
|
|
11
|
+
evolvable: true # default para skill estandar
|
|
12
|
+
---
|
|
13
|
+
# Arquitectura de Microservicios
|
|
14
|
+
|
|
15
|
+
## Cuándo NO cargar
|
|
16
|
+
|
|
17
|
+
- La tarea es implementar endpoints REST o GraphQL individuales dentro de un servicio — cargar `fastapi-experto`, `api-rest-diseno` o `graphql-experto`.
|
|
18
|
+
- El trabajo es infraestructura: Kubernetes, Docker Compose, Terraform — cargar `cloud-infra`.
|
|
19
|
+
- La pregunta es sobre configuración específica de un broker de mensajes (Kafka, RabbitMQ, SQS) — este skill cubre los patrones de arquitectura, no la implementación del broker.
|
|
20
|
+
- El sistema es un monolito modular o arquitectura hexagonal sin distribución de red — este skill asume que los servicios se comunican por red.
|
|
21
|
+
|
|
22
|
+
Microservicios no es la respuesta por defecto — es una decisión de arquitectura con
|
|
23
|
+
costos reales. Este skill cubre cuándo aplicarlos, cómo implementarlos y cuándo evitarlos.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. Microservicios o Monolito — Decide primero
|
|
28
|
+
|
|
29
|
+
### Señales de que el MONOLITO es la respuesta correcta
|
|
30
|
+
|
|
31
|
+
- Equipo < 10 desarrolladores
|
|
32
|
+
- Dominio de negocio no bien definido aún
|
|
33
|
+
- Producto en fase de descubrimiento (pivots frecuentes)
|
|
34
|
+
- No hay equipos independientes que puedan ser dueños de servicios distintos
|
|
35
|
+
- Sin infraestructura de observabilidad madura
|
|
36
|
+
- SLA de < 99.9%
|
|
37
|
+
|
|
38
|
+
### Señales de que microservicios SUMAN valor
|
|
39
|
+
|
|
40
|
+
- Equipos independientes que necesitan deployar sin coordinación
|
|
41
|
+
- Módulos con requerimientos de escalado MUY distintos
|
|
42
|
+
- Diferentes requerimientos de seguridad o cumplimiento por módulo
|
|
43
|
+
- Módulos que necesitan tecnologías distintas (Python para ML, Go para performance)
|
|
44
|
+
- Más de 100 deploys por mes
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 2. Principios de Diseño de Servicios
|
|
49
|
+
|
|
50
|
+
### Bounded Context — Límites claros entre servicios
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
MONOLITO MODULAR (recomendado para empezar):
|
|
54
|
+
+-- modulo: empleados/
|
|
55
|
+
+-- modulo: nomina/
|
|
56
|
+
+-- modulo: asistencia/
|
|
57
|
+
+-- modulo: reportes/
|
|
58
|
+
|
|
59
|
+
MICROSERVICIOS (cuando los módulos necesitan escalar independientemente):
|
|
60
|
+
+-- servicio-empleados — equipo A, escala: bajo
|
|
61
|
+
+-- servicio-nomina — equipo B, escala: muy alto en quincena
|
|
62
|
+
+-- servicio-asistencia — equipo C, escala: alto en horario laboral
|
|
63
|
+
+-- servicio-reportes — equipo D, escala: bajo, alto en auditorías
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### High Cohesion, Loose Coupling
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
# MAL: servicio que hace demasiado (god service)
|
|
70
|
+
class ServicioRRHH:
|
|
71
|
+
def crear_empleado(self): ...
|
|
72
|
+
def calcular_nomina(self): ...
|
|
73
|
+
def registrar_asistencia(self): ...
|
|
74
|
+
|
|
75
|
+
# BIEN: servicios con responsabilidad única
|
|
76
|
+
class ServicioEmpleados:
|
|
77
|
+
def crear(self): ...
|
|
78
|
+
def actualizar(self): ...
|
|
79
|
+
def buscar(self): ...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 3. Reglas Obligatorias
|
|
85
|
+
|
|
86
|
+
1. **Cada servicio tiene su propia BD** — NUNCA compartir esquemas entre servicios.
|
|
87
|
+
2. **SIEMPRE implementar circuit breaker** para llamadas a otros servicios.
|
|
88
|
+
3. **SIEMPRE propagar `X-Correlation-ID`** en todas las llamadas salientes.
|
|
89
|
+
4. **SIEMPRE poner timeout** en TODAS las llamadas HTTP salientes.
|
|
90
|
+
5. **SIEMPRE implementar idempotency** en operaciones de escritura.
|
|
91
|
+
6. **Exponer health checks**: `/health/live`, `/health/ready`, `/health/startup`.
|
|
92
|
+
7. **Logs estructurados (JSON)** con nivel, servicio y correlationId.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 4. Anti-patrones Críticos
|
|
97
|
+
|
|
98
|
+
### Monolito Distribuido (el peor anti-patrón)
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Síntomas:
|
|
102
|
+
- Los servicios se llaman síncronamente en cadena para cada request
|
|
103
|
+
- Deploy de un servicio requiere deploy de otros (acoplamiento)
|
|
104
|
+
- Un fallo en el servicio A causa fallo en cascada a B, C, D
|
|
105
|
+
- La "base de datos compartida" entre servicios
|
|
106
|
+
|
|
107
|
+
MAL:
|
|
108
|
+
Request -> API Gateway -> ServicioA -> ServicioB -> ServicioC -> BD compartida
|
|
109
|
+
|
|
110
|
+
BIEN:
|
|
111
|
+
Request -> API Gateway -> ServicioA (BD propia)
|
|
112
|
+
-> (evento async) -> ServicioB (BD propia)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Otros Anti-patrones
|
|
116
|
+
|
|
117
|
+
| Anti-patrón | Problema | Solución |
|
|
118
|
+
|-------------|---------|---------|
|
|
119
|
+
| Chatty services (100s de llamadas síncronas) | Latencia acumulada | Agregar datos en el servicio o usar eventos |
|
|
120
|
+
| Compartir BD entre servicios | Acoplamiento fuerte | Una BD por servicio |
|
|
121
|
+
| Servicios demasiado pequeños (nanoservices) | Overhead operativo excesivo | Bounded context adecuado |
|
|
122
|
+
| Sin contrato de API versionado | Romper clientes al actualizar | Versioning en URL (/v1/, /v2/) |
|
|
123
|
+
| Logging sin correlation ID | Imposible tracing | `X-Correlation-ID` en headers |
|
|
124
|
+
| Sin idempotency en APIs | Doble procesamiento en reintentos | Idempotency keys en mutaciones |
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 5. Checklist de Microservicio Nuevo
|
|
129
|
+
|
|
130
|
+
- [ ] Tiene su propia BD (sin compartir esquemas con otros servicios)
|
|
131
|
+
- [ ] Expone `/health/live`, `/health/ready`, `/health/startup`
|
|
132
|
+
- [ ] Implementa circuit breaker para llamadas a otros servicios
|
|
133
|
+
- [ ] Propaga `X-Correlation-ID` en todas las llamadas salientes
|
|
134
|
+
- [ ] Tiene contrato de API documentado (OpenAPI spec)
|
|
135
|
+
- [ ] Versioning en URL (`/api/v1/...`)
|
|
136
|
+
- [ ] Idempotency implementada en operaciones de escritura
|
|
137
|
+
- [ ] Rate limiting configurado en el API Gateway
|
|
138
|
+
- [ ] Timeout configurado en TODAS las llamadas HTTP salientes
|
|
139
|
+
- [ ] Logs estructurados (JSON) con nivel, servicio, correlationId
|
|
140
|
+
- [ ] Métricas de negocio expuestas (Prometheus)
|
|
141
|
+
- [ ] Fallback o degradación elegante cuando dependencias fallan
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
Para ejemplos completos de API Gateway (NGINX), Circuit Breaker, Saga Pattern, Distributed Tracing (OpenTelemetry), Health Checks y Service Discovery (Consul), ver [recursos/patrones-y-ejemplos-completos.md](recursos/patrones-y-ejemplos-completos.md).
|
|
146
|
+
|
|
147
|
+
## Gotchas / Errores comunes no obvios
|
|
148
|
+
|
|
149
|
+
**Circuit breaker con estado en memoria del proceso no funciona en entornos multi-instancia**: si el circuit breaker abre en una instancia del servicio (por fallos detectados localmente), las otras instancias siguen enviando tráfico al servicio caído. Causa: el estado del circuit breaker en memoria es local al proceso. Fix: usar un circuit breaker respaldado por Redis o un service mesh (Istio, Linkerd) que administra el estado de circuit breaking a nivel de red, compartido entre todas las instancias.
|
|
150
|
+
|
|
151
|
+
**Saga con compensación no es equivalente a rollback de base de datos — los efectos secundarios ya ocurrieron**: en una Saga coreografada donde el paso 3 (envío de email) falla, la compensación no "no envía el email" — el email ya se envió en paso 1. La compensación solo puede enviar otro email que diga "la operación fue cancelada". Causa: la Saga es eventual y los pasos intermedios son commits locales irreversibles. Fix: diseñar las compensaciones como acciones de negocio válidas (no rollbacks), documentar explícitamente qué efectos no son compensables (emails enviados, notificaciones push) y diseñar el flujo de negocio para tolerar esos efectos.
|
|
152
|
+
|
|
153
|
+
**`X-Correlation-ID` propagado solo en llamadas HTTP se pierde cuando el flujo pasa por un queue (RabbitMQ, Kafka)**: si el servicio A llama al servicio B por HTTP con correlation ID y B publica un evento en Kafka sin incluir el correlation ID en el header del mensaje, el servicio C que consume el evento no puede correlacionar la traza. Causa: los mensajes async no propagan headers HTTP automáticamente. Fix: incluir el correlation ID en el payload del mensaje (o en los headers del mensaje de Kafka/RabbitMQ) como parte del contrato del evento, y extraerlo al crear el span de OpenTelemetry al consumir.
|
|
154
|
+
|
|
155
|
+
**El health check `/health/ready` que verifica la conexión a la BD puede causar restart en cascada**: si `/health/ready` falla cuando la BD tiene alta latencia (no caída), Kubernetes puede marcar el pod como unhealthy y reiniciarlo — pero el restart no resuelve el problema de latencia de BD y puede generar una cascada de reinicios. Causa: usar el health check de readiness para métricas de performance, no solo de disponibilidad. Fix: `/health/ready` debe verificar solo si el servicio puede aceptar tráfico (conexión básica a BD disponible), no la latencia — las métricas de performance van en el health de Prometheus/métricas, no en el readiness probe.
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# Microservicios — Patrones y Ejemplos Completos
|
|
2
|
+
|
|
3
|
+
Referencia extendida de la skill `microservicios`. Contiene ejemplos de implementación
|
|
4
|
+
completos para API Gateway, Circuit Breaker, Saga Pattern, Distributed Tracing,
|
|
5
|
+
Health Checks y Service Discovery.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## API Gateway — Configuración NGINX
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
# Kong, AWS API Gateway, o NGINX como gateway
|
|
13
|
+
# Responsabilidades del gateway:
|
|
14
|
+
# 1. Autenticación/autorización centralizada
|
|
15
|
+
# 2. Rate limiting
|
|
16
|
+
# 3. Request routing
|
|
17
|
+
# 4. SSL termination
|
|
18
|
+
# 5. Logging y métricas
|
|
19
|
+
# 6. Transformación de requests (versioning)
|
|
20
|
+
|
|
21
|
+
# Configuración NGINX como API Gateway básico
|
|
22
|
+
# nginx.conf
|
|
23
|
+
upstream servicio_empleados {
|
|
24
|
+
server empleados-svc:8001;
|
|
25
|
+
keepalive 32;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
upstream servicio_nomina {
|
|
29
|
+
server nomina-svc:8002;
|
|
30
|
+
keepalive 32;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
server {
|
|
34
|
+
listen 443 ssl;
|
|
35
|
+
server_name api.empresa.com.mx;
|
|
36
|
+
|
|
37
|
+
# Autenticación JWT en el gateway (todas las rutas protegidas)
|
|
38
|
+
auth_jwt "API RRHH";
|
|
39
|
+
auth_jwt_key_file /etc/nginx/jwt_public_key.pem;
|
|
40
|
+
|
|
41
|
+
location /api/v1/empleados/ {
|
|
42
|
+
proxy_pass http://servicio_empleados/;
|
|
43
|
+
proxy_set_header X-User-ID $jwt_claim_sub;
|
|
44
|
+
proxy_set_header X-User-Roles $jwt_claim_roles;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
location /api/v1/nomina/ {
|
|
48
|
+
proxy_pass http://servicio_nomina/;
|
|
49
|
+
limit_req zone=nomina_zone burst=20 nodelay; # Rate limiting
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Circuit Breaker — Implementación completa
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# pip install circuitbreaker
|
|
60
|
+
from circuitbreaker import circuit, CircuitBreakerError
|
|
61
|
+
import httpx
|
|
62
|
+
import asyncio
|
|
63
|
+
|
|
64
|
+
class ClienteServicioEmpleados:
|
|
65
|
+
def __init__(self, base_url: str):
|
|
66
|
+
self.base_url = base_url
|
|
67
|
+
self._client = httpx.AsyncClient(timeout=5.0)
|
|
68
|
+
|
|
69
|
+
@circuit(
|
|
70
|
+
failure_threshold=5, # Abrir después de 5 fallos consecutivos
|
|
71
|
+
recovery_timeout=30, # Intentar recuperar después de 30s
|
|
72
|
+
expected_exception=httpx.RequestError,
|
|
73
|
+
)
|
|
74
|
+
async def obtener_empleado(self, empleado_id: str) -> dict:
|
|
75
|
+
"""
|
|
76
|
+
Estados del circuit breaker:
|
|
77
|
+
- CLOSED: tráfico normal
|
|
78
|
+
- OPEN: rechaza requests (fallback inmediato)
|
|
79
|
+
- HALF-OPEN: prueba un request para ver si el servicio se recuperó
|
|
80
|
+
"""
|
|
81
|
+
response = await self._client.get(
|
|
82
|
+
f"{self.base_url}/empleados/{empleado_id}"
|
|
83
|
+
)
|
|
84
|
+
response.raise_for_status()
|
|
85
|
+
return response.json()
|
|
86
|
+
|
|
87
|
+
async def obtener_empleado_con_fallback(self, empleado_id: str) -> dict:
|
|
88
|
+
try:
|
|
89
|
+
return await self.obtener_empleado(empleado_id)
|
|
90
|
+
except CircuitBreakerError:
|
|
91
|
+
return await self._obtener_de_cache(empleado_id)
|
|
92
|
+
except httpx.RequestError as e:
|
|
93
|
+
raise ServicioNoDisponible(f"Servicio de empleados inaccesible: {e}")
|
|
94
|
+
|
|
95
|
+
async def _obtener_de_cache(self, empleado_id: str) -> dict:
|
|
96
|
+
datos = await redis.get(f"empleado:{empleado_id}")
|
|
97
|
+
if datos:
|
|
98
|
+
return json.loads(datos)
|
|
99
|
+
raise DatosNoEnCache(f"Empleado {empleado_id} no en caché")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Saga Pattern — Transacciones distribuidas (Orquestación)
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from dataclasses import dataclass
|
|
108
|
+
from enum import Enum
|
|
109
|
+
from typing import Callable, Awaitable
|
|
110
|
+
|
|
111
|
+
class EstadoSaga(str, Enum):
|
|
112
|
+
INICIADA = "INICIADA"
|
|
113
|
+
COMPLETADA = "COMPLETADA"
|
|
114
|
+
FALLIDA = "FALLIDA"
|
|
115
|
+
COMPENSANDO = "COMPENSANDO"
|
|
116
|
+
|
|
117
|
+
@dataclass
|
|
118
|
+
class PasoSaga:
|
|
119
|
+
nombre: str
|
|
120
|
+
ejecutar: Callable[..., Awaitable[dict]]
|
|
121
|
+
compensar: Callable[..., Awaitable[None]]
|
|
122
|
+
|
|
123
|
+
class SagaAltaDeEmpleado:
|
|
124
|
+
"""
|
|
125
|
+
Saga para el alta de un nuevo empleado.
|
|
126
|
+
Pasos:
|
|
127
|
+
1. Crear expediente en BD central
|
|
128
|
+
2. Configurar nómina en SAP
|
|
129
|
+
3. Crear cuenta en Active Directory
|
|
130
|
+
4. Enviar correo de bienvenida
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
def __init__(
|
|
134
|
+
self,
|
|
135
|
+
svc_expedientes,
|
|
136
|
+
svc_nomina,
|
|
137
|
+
svc_directorio,
|
|
138
|
+
svc_notificaciones,
|
|
139
|
+
):
|
|
140
|
+
self._pasos = [
|
|
141
|
+
PasoSaga(
|
|
142
|
+
nombre="crear_expediente",
|
|
143
|
+
ejecutar=svc_expedientes.crear,
|
|
144
|
+
compensar=svc_expedientes.eliminar,
|
|
145
|
+
),
|
|
146
|
+
PasoSaga(
|
|
147
|
+
nombre="configurar_nomina",
|
|
148
|
+
ejecutar=svc_nomina.configurar_empleado,
|
|
149
|
+
compensar=svc_nomina.eliminar_empleado,
|
|
150
|
+
),
|
|
151
|
+
PasoSaga(
|
|
152
|
+
nombre="crear_cuenta_directorio",
|
|
153
|
+
ejecutar=svc_directorio.crear_cuenta,
|
|
154
|
+
compensar=svc_directorio.desactivar_cuenta,
|
|
155
|
+
),
|
|
156
|
+
PasoSaga(
|
|
157
|
+
nombre="enviar_bienvenida",
|
|
158
|
+
ejecutar=svc_notificaciones.enviar_bienvenida,
|
|
159
|
+
compensar=lambda **_: None,
|
|
160
|
+
),
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
async def ejecutar(self, datos_empleado: dict) -> dict:
|
|
164
|
+
resultados: list[dict] = []
|
|
165
|
+
ejecutados: list[tuple[PasoSaga, dict]] = []
|
|
166
|
+
|
|
167
|
+
for paso in self._pasos:
|
|
168
|
+
try:
|
|
169
|
+
resultado = await paso.ejecutar(**datos_empleado, **{
|
|
170
|
+
f"resultado_{p.nombre}": r for p, r in ejecutados
|
|
171
|
+
})
|
|
172
|
+
resultados.append(resultado)
|
|
173
|
+
ejecutados.append((paso, resultado))
|
|
174
|
+
except Exception as e:
|
|
175
|
+
await self._compensar(ejecutados[::-1], datos_empleado)
|
|
176
|
+
raise SagaFallida(
|
|
177
|
+
f"Saga falló en paso '{paso.nombre}': {e}"
|
|
178
|
+
) from e
|
|
179
|
+
|
|
180
|
+
return {"resultados": resultados}
|
|
181
|
+
|
|
182
|
+
async def _compensar(
|
|
183
|
+
self,
|
|
184
|
+
pasos_ejecutados: list[tuple[PasoSaga, dict]],
|
|
185
|
+
datos: dict,
|
|
186
|
+
) -> None:
|
|
187
|
+
for paso, resultado in pasos_ejecutados:
|
|
188
|
+
try:
|
|
189
|
+
await paso.compensar(**datos, resultado_previo=resultado)
|
|
190
|
+
except Exception as e:
|
|
191
|
+
logger.error("Error compensando %s: %s", paso.nombre, e)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Distributed Tracing — OpenTelemetry
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from opentelemetry import trace
|
|
200
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
201
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
202
|
+
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
|
|
203
|
+
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
|
|
204
|
+
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
|
205
|
+
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
|
|
206
|
+
|
|
207
|
+
def configurar_tracing(servicio: str, jaeger_host: str = "jaeger") -> None:
|
|
208
|
+
provider = TracerProvider()
|
|
209
|
+
jaeger_exporter = JaegerExporter(
|
|
210
|
+
agent_host_name=jaeger_host,
|
|
211
|
+
agent_port=6831,
|
|
212
|
+
)
|
|
213
|
+
provider.add_span_processor(BatchSpanProcessor(jaeger_exporter))
|
|
214
|
+
trace.set_tracer_provider(provider)
|
|
215
|
+
|
|
216
|
+
FastAPIInstrumentor.instrument()
|
|
217
|
+
HTTPXClientInstrumentor.instrument()
|
|
218
|
+
SQLAlchemyInstrumentor.instrument()
|
|
219
|
+
|
|
220
|
+
tracer = trace.get_tracer(__name__)
|
|
221
|
+
|
|
222
|
+
async def calcular_nomina_quincenal(periodo_id: str) -> dict:
|
|
223
|
+
with tracer.start_as_current_span("calcular_nomina_quincenal") as span:
|
|
224
|
+
span.set_attribute("periodo.id", periodo_id)
|
|
225
|
+
|
|
226
|
+
with tracer.start_as_current_span("obtener_empleados_activos"):
|
|
227
|
+
empleados = await repo.obtener_empleados_activos()
|
|
228
|
+
span.set_attribute("empleados.count", len(empleados))
|
|
229
|
+
|
|
230
|
+
with tracer.start_as_current_span("calcular_percepciones"):
|
|
231
|
+
percepciones = await calcular_percepciones(empleados)
|
|
232
|
+
|
|
233
|
+
span.set_attribute("nomina.total", sum(p["total"] for p in percepciones))
|
|
234
|
+
return {"periodo_id": periodo_id, "percepciones": percepciones}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Health Checks — 3 endpoints estándar
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
from fastapi import APIRouter
|
|
243
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
244
|
+
|
|
245
|
+
router = APIRouter()
|
|
246
|
+
|
|
247
|
+
@router.get("/health/live")
|
|
248
|
+
async def liveness():
|
|
249
|
+
"""
|
|
250
|
+
Kubernetes liveness probe.
|
|
251
|
+
Responde 200 si el proceso está vivo.
|
|
252
|
+
NUNCA verificar dependencias externas aquí.
|
|
253
|
+
"""
|
|
254
|
+
return {"status": "alive"}
|
|
255
|
+
|
|
256
|
+
@router.get("/health/ready")
|
|
257
|
+
async def readiness(db: AsyncSession = Depends(get_db)):
|
|
258
|
+
"""
|
|
259
|
+
Kubernetes readiness probe.
|
|
260
|
+
Verifica dependencias críticas.
|
|
261
|
+
"""
|
|
262
|
+
checks = {}
|
|
263
|
+
try:
|
|
264
|
+
await db.execute(text("SELECT 1"))
|
|
265
|
+
checks["database"] = "ok"
|
|
266
|
+
except Exception as e:
|
|
267
|
+
checks["database"] = f"error: {e}"
|
|
268
|
+
|
|
269
|
+
try:
|
|
270
|
+
await redis.ping()
|
|
271
|
+
checks["cache"] = "ok"
|
|
272
|
+
except Exception as e:
|
|
273
|
+
checks["cache"] = f"error: {e}"
|
|
274
|
+
|
|
275
|
+
todo_ok = all(v == "ok" for v in checks.values())
|
|
276
|
+
return JSONResponse(
|
|
277
|
+
content={"status": "ready" if todo_ok else "not_ready", "checks": checks},
|
|
278
|
+
status_code=200 if todo_ok else 503,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
@router.get("/health/startup")
|
|
282
|
+
async def startup_probe():
|
|
283
|
+
"""
|
|
284
|
+
Kubernetes startup probe.
|
|
285
|
+
Permite más tiempo para servicios con arranque lento.
|
|
286
|
+
"""
|
|
287
|
+
head_revision = await obtener_revision_actual_db()
|
|
288
|
+
expected_revision = get_alembic_head()
|
|
289
|
+
if head_revision != expected_revision:
|
|
290
|
+
raise HTTPException(503, "Migraciones pendientes")
|
|
291
|
+
return {"status": "started", "revision": head_revision}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Service Discovery — Consul
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
import consul
|
|
300
|
+
|
|
301
|
+
class RegistroServicios:
|
|
302
|
+
def __init__(self):
|
|
303
|
+
self._consul = consul.aio.Consul(host="consul", port=8500)
|
|
304
|
+
|
|
305
|
+
async def registrar(self, nombre: str, puerto: int, tags: list[str]) -> None:
|
|
306
|
+
await self._consul.agent.service.register(
|
|
307
|
+
name=nombre,
|
|
308
|
+
service_id=f"{nombre}-{os.environ['HOSTNAME']}",
|
|
309
|
+
address=os.environ["POD_IP"],
|
|
310
|
+
port=puerto,
|
|
311
|
+
tags=tags,
|
|
312
|
+
check=consul.Check.http(
|
|
313
|
+
f"http://{os.environ['POD_IP']}:{puerto}/health/ready",
|
|
314
|
+
interval="10s",
|
|
315
|
+
deregister="30s",
|
|
316
|
+
),
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
async def descubrir(self, nombre: str) -> str:
|
|
320
|
+
_, servicios = await self._consul.health.service(nombre, passing=True)
|
|
321
|
+
if not servicios:
|
|
322
|
+
raise ServicioNoDisponible(f"No hay instancias de '{nombre}'")
|
|
323
|
+
servicio = servicios[0]["Service"]
|
|
324
|
+
return f"http://{servicio['Address']}:{servicio['Port']}"
|
|
325
|
+
```
|