@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,167 @@
|
|
|
1
|
+
# Testing Python — Ejemplos completos y referencia
|
|
2
|
+
|
|
3
|
+
## Mocking con unittest.mock y pytest-mock
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from unittest.mock import MagicMock, AsyncMock, patch
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
# Mock de una función de módulo
|
|
10
|
+
def test_crear_factura_llama_servicio_timbre(factura_service, mock_timbre):
|
|
11
|
+
with patch("app.services.factura_service.timbre_service") as mock_timbre:
|
|
12
|
+
mock_timbre.timbrar = MagicMock(return_value={"uuid": "abc-123"})
|
|
13
|
+
|
|
14
|
+
factura = factura_service.crear(datos_validos)
|
|
15
|
+
|
|
16
|
+
mock_timbre.timbrar.assert_called_once_with(factura)
|
|
17
|
+
assert factura.uuid_timbre == "abc-123"
|
|
18
|
+
|
|
19
|
+
# Con pytest-mock (más limpio)
|
|
20
|
+
def test_notificacion_enviada(mocker, factura_service):
|
|
21
|
+
mock_email = mocker.patch("app.services.email_service.enviar")
|
|
22
|
+
|
|
23
|
+
factura_service.emitir(factura_id="fac-123")
|
|
24
|
+
|
|
25
|
+
mock_email.assert_called_once()
|
|
26
|
+
llamada = mock_email.call_args
|
|
27
|
+
assert llamada.kwargs["destinatario"] == "cliente@empresa.com"
|
|
28
|
+
|
|
29
|
+
# Mock de async
|
|
30
|
+
async def test_obtener_usuario_llama_api_externa(mocker):
|
|
31
|
+
mock_get = mocker.patch("httpx.AsyncClient.get", new_callable=AsyncMock)
|
|
32
|
+
mock_get.return_value.json.return_value = {"id": "u1", "nombre": "Ana"}
|
|
33
|
+
mock_get.return_value.status_code = 200
|
|
34
|
+
|
|
35
|
+
usuario = await servicio.obtener_usuario("u1")
|
|
36
|
+
|
|
37
|
+
assert usuario.nombre == "Ana"
|
|
38
|
+
mock_get.assert_awaited_once()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Testing async con pytest-asyncio
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
# pyproject.toml
|
|
47
|
+
# [tool.pytest.ini_options]
|
|
48
|
+
# asyncio_mode = "auto" # Marcar todos los tests async automáticamente
|
|
49
|
+
|
|
50
|
+
import pytest
|
|
51
|
+
from httpx import AsyncClient, ASGITransport
|
|
52
|
+
|
|
53
|
+
@pytest.mark.asyncio
|
|
54
|
+
async def test_crear_factura_endpoint(async_client: AsyncClient):
|
|
55
|
+
respuesta = await async_client.post(
|
|
56
|
+
"/api/v1/facturas/",
|
|
57
|
+
json={
|
|
58
|
+
"folio": "F-001",
|
|
59
|
+
"fecha": "2026-03-25",
|
|
60
|
+
"subtotal": "1000.00",
|
|
61
|
+
"cliente_id": "cliente-123",
|
|
62
|
+
},
|
|
63
|
+
headers={"Authorization": "Bearer token-test"},
|
|
64
|
+
)
|
|
65
|
+
assert respuesta.status_code == 201
|
|
66
|
+
data = respuesta.json()
|
|
67
|
+
assert data["estatus"] == "borrador"
|
|
68
|
+
assert "id" in data
|
|
69
|
+
|
|
70
|
+
@pytest.fixture
|
|
71
|
+
async def async_client(app, async_db):
|
|
72
|
+
async with AsyncClient(
|
|
73
|
+
transport=ASGITransport(app=app),
|
|
74
|
+
base_url="http://test",
|
|
75
|
+
) as client:
|
|
76
|
+
yield client
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Factories con factory_boy
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
# tests/factories.py
|
|
85
|
+
import factory
|
|
86
|
+
from decimal import Decimal
|
|
87
|
+
from datetime import date
|
|
88
|
+
from app.models import Factura, Cliente, Item
|
|
89
|
+
|
|
90
|
+
class ClienteFactory(factory.Factory):
|
|
91
|
+
class Meta:
|
|
92
|
+
model = Cliente
|
|
93
|
+
|
|
94
|
+
id = factory.Sequence(lambda n: f"cliente-{n:05d}")
|
|
95
|
+
nombre = factory.Faker("company", locale="es_MX")
|
|
96
|
+
rfc = factory.LazyFunction(lambda: f"RFC{factory.Faker('numerify', text='######')}")
|
|
97
|
+
activo = True
|
|
98
|
+
|
|
99
|
+
class ItemFactory(factory.Factory):
|
|
100
|
+
class Meta:
|
|
101
|
+
model = Item
|
|
102
|
+
|
|
103
|
+
descripcion = factory.Faker("sentence", nb_words=4, locale="es_MX")
|
|
104
|
+
cantidad = factory.Faker("pyint", min_value=1, max_value=10)
|
|
105
|
+
precio_unitario = factory.Faker("pydecimal", min_value=10, max_value=1000,
|
|
106
|
+
right_digits=2)
|
|
107
|
+
|
|
108
|
+
class FacturaFactory(factory.Factory):
|
|
109
|
+
class Meta:
|
|
110
|
+
model = Factura
|
|
111
|
+
|
|
112
|
+
id = factory.Sequence(lambda n: f"fac-{n:05d}")
|
|
113
|
+
folio = factory.Sequence(lambda n: f"F-{n:05d}")
|
|
114
|
+
fecha = factory.LazyFunction(date.today)
|
|
115
|
+
estatus = "borrador"
|
|
116
|
+
cliente = factory.SubFactory(ClienteFactory)
|
|
117
|
+
items = factory.List([factory.SubFactory(ItemFactory)])
|
|
118
|
+
|
|
119
|
+
# Uso en tests
|
|
120
|
+
def test_calcular_total():
|
|
121
|
+
items = [ItemFactory(cantidad=2, precio_unitario=Decimal("100.00"))]
|
|
122
|
+
factura = FacturaFactory(items=items)
|
|
123
|
+
assert factura.calcular_total() == Decimal("200.00")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Anti-patrones en tests
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# MAL: test que verifica demasiado
|
|
132
|
+
def test_factura():
|
|
133
|
+
f = Factura(...)
|
|
134
|
+
assert f.folio == "F-001"
|
|
135
|
+
assert f.estatus == "borrador"
|
|
136
|
+
assert f.total == 1160
|
|
137
|
+
assert f.cliente.nombre == "Acme"
|
|
138
|
+
assert f.puede_cancelar() == True
|
|
139
|
+
# ... 10 asserts más
|
|
140
|
+
|
|
141
|
+
# BIEN: un comportamiento por test
|
|
142
|
+
def test_factura_nueva_tiene_estatus_borrador():
|
|
143
|
+
factura = FacturaFactory()
|
|
144
|
+
assert factura.estatus == "borrador"
|
|
145
|
+
|
|
146
|
+
def test_factura_calcula_total_con_iva():
|
|
147
|
+
factura = FacturaFactory(subtotal=Decimal("1000.00"), tasa_iva=0.16)
|
|
148
|
+
assert factura.total == Decimal("1160.00")
|
|
149
|
+
|
|
150
|
+
# MAL: lógica de negocio en los tests
|
|
151
|
+
def test_calcular_descuento():
|
|
152
|
+
if monto > 1000: # lógica duplicada del código de producción
|
|
153
|
+
esperado = monto * 0.1
|
|
154
|
+
else:
|
|
155
|
+
esperado = 0
|
|
156
|
+
assert calcular_descuento(monto) == esperado
|
|
157
|
+
|
|
158
|
+
# BIEN: valores concretos y explícitos
|
|
159
|
+
@pytest.mark.parametrize("monto,descuento_esperado", [
|
|
160
|
+
(500, Decimal("0.00")),
|
|
161
|
+
(1000, Decimal("0.00")),
|
|
162
|
+
(1001, Decimal("100.10")),
|
|
163
|
+
(2000, Decimal("200.00")),
|
|
164
|
+
])
|
|
165
|
+
def test_calcular_descuento(monto, descuento_esperado):
|
|
166
|
+
assert calcular_descuento(monto) == descuento_esperado
|
|
167
|
+
```
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: threat-model-lite
|
|
3
|
+
description: Modelado de amenazas ligero basado en STRIDE simplificado. Identifica la superficie de ataque del sistema, los activos críticos, los flujos de datos sensibles y genera mitigaciones priorizadas. Diseñado para completarse en una sesión de trabajo, no en semanas.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
herramientasPermitidas: [Read, Grep]
|
|
6
|
+
evolvable: true # default para skill estandar
|
|
7
|
+
nist_csf: [ID.RA-01, ID.RA-03, ID.RA-04]
|
|
8
|
+
nist_ai_rmf: [MAP-1.1, MAP-5.1, MAP-5.2]
|
|
9
|
+
exclusiones:
|
|
10
|
+
- "No cargar para implementar las mitigaciones técnicas identificadas (RBAC, rate limiting, TLS) — threat model produce el diagnóstico; para implementación cargar el skill del stack correspondiente."
|
|
11
|
+
- "No cargar para auditoría de código buscando vulnerabilidades específicas (SQL injection, XSS en código) — para revisión de código de seguridad cargar `checklist-seguridad` o el skill de revisión del lenguaje."
|
|
12
|
+
- "No cargar para análisis de cumplimiento normativo (PCI-DSS, SOC 2, ISO 27001) — el threat model es una entrada para el compliance, no el análisis de cumplimiento completo."
|
|
13
|
+
- "No cargar para red-teaming o pruebas de penetración activas — threat model es análisis estático; para pentest activo usar herramientas especializadas con autorización explícita."
|
|
14
|
+
---
|
|
15
|
+
# Habilidad: Threat Model Lite
|
|
16
|
+
|
|
17
|
+
## Cuándo NO cargar
|
|
18
|
+
|
|
19
|
+
- La tarea es implementar las mitigaciones identificadas (RBAC, rate limiting, TLS): usar el skill del stack correspondiente para la implementación.
|
|
20
|
+
- La tarea es revisión de código buscando vulnerabilidades: cargar `checklist-seguridad`.
|
|
21
|
+
- La tarea es análisis de cumplimiento normativo (PCI-DSS, SOC 2): el threat model es una entrada, no el análisis completo.
|
|
22
|
+
- La tarea es pentest activo o red-teaming: usar herramientas especializadas con autorización explícita.
|
|
23
|
+
|
|
24
|
+
## Propósito
|
|
25
|
+
|
|
26
|
+
Un threat model completo toma semanas. Esta versión toma entre 2 y 4 horas y
|
|
27
|
+
cubre el 80% de los riesgos reales. El objetivo no es ser exhaustivo — es
|
|
28
|
+
identificar las amenazas de mayor impacto antes de que lleguen a producción.
|
|
29
|
+
|
|
30
|
+
## Cuándo activar
|
|
31
|
+
|
|
32
|
+
- Al diseñar un nuevo sistema o módulo crítico
|
|
33
|
+
- Antes del primer deploy a producción de una aplicación nueva
|
|
34
|
+
- Cuando el sistema maneja datos PII, financieros o de salud
|
|
35
|
+
- Cuando se añade una nueva integración con sistemas externos
|
|
36
|
+
- Como parte de la revisión de seguridad trimestral
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Paso 1 — Definir el alcance en 15 minutos
|
|
41
|
+
|
|
42
|
+
Responder estas 4 preguntas antes de proceder:
|
|
43
|
+
|
|
44
|
+
1. **¿Qué estamos protegiendo?** (activos: datos, dinero, reputación, disponibilidad)
|
|
45
|
+
2. **¿De quién lo protegemos?** (actores: usuarios maliciosos, atacantes externos,
|
|
46
|
+
empleados deshonestos, errores accidentales)
|
|
47
|
+
3. **¿Cuál sería el peor escenario?** (impacto: pérdida de datos, fraude, downtime)
|
|
48
|
+
4. **¿Cuál es el perímetro del análisis?** (módulo específico, sistema completo,
|
|
49
|
+
integración puntual)
|
|
50
|
+
|
|
51
|
+
Si no puedes responder estas preguntas, detente y habla con el stakeholder antes
|
|
52
|
+
de continuar.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Paso 2 — Mapear la superficie de ataque
|
|
57
|
+
|
|
58
|
+
### Diagrama de flujo de datos (DFD simplificado)
|
|
59
|
+
|
|
60
|
+
Identificar y documentar:
|
|
61
|
+
|
|
62
|
+
**Puntos de entrada** (donde datos externos entran al sistema):
|
|
63
|
+
- [ ] Endpoints HTTP/REST públicos
|
|
64
|
+
- [ ] Endpoints autenticados
|
|
65
|
+
- [ ] Webhooks recibidos de sistemas externos
|
|
66
|
+
- [ ] Archivos cargados por usuarios
|
|
67
|
+
- [ ] Variables de entorno y configuración
|
|
68
|
+
- [ ] Mensajes de colas (Kafka, RabbitMQ, SQS)
|
|
69
|
+
- [ ] Interfaces de línea de comandos (CLI)
|
|
70
|
+
|
|
71
|
+
**Flujos de datos sensibles** (donde los datos críticos viajan):
|
|
72
|
+
- [ ] Datos de usuario en tránsito (login, sesión)
|
|
73
|
+
- [ ] Datos financieros (pagos, montos, cuentas)
|
|
74
|
+
- [ ] PII en requests/responses
|
|
75
|
+
- [ ] Tokens y credenciales en headers
|
|
76
|
+
- [ ] Datos en logs
|
|
77
|
+
- [ ] Datos exportados (CSV, PDF, reportes)
|
|
78
|
+
|
|
79
|
+
**Límites de confianza** (dónde cambia el nivel de confianza):
|
|
80
|
+
- [ ] Internet → API Gateway / Load Balancer
|
|
81
|
+
- [ ] API → Base de datos
|
|
82
|
+
- [ ] Microservicio A → Microservicio B
|
|
83
|
+
- [ ] Sistema interno → Sistema externo
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Paso 3 — STRIDE simplificado
|
|
88
|
+
|
|
89
|
+
Para cada punto de entrada y flujo de datos, evaluar las 6 categorías STRIDE:
|
|
90
|
+
|
|
91
|
+
### S — Spoofing (Suplantación de identidad)
|
|
92
|
+
**Pregunta**: ¿Puede un atacante hacerse pasar por un usuario legítimo?
|
|
93
|
+
- Autenticación débil o ausente en algún endpoint
|
|
94
|
+
- Tokens sin expiración o sin firma válida
|
|
95
|
+
- No verificación de origen en webhooks
|
|
96
|
+
- Reset de contraseña sin validación de identidad
|
|
97
|
+
|
|
98
|
+
### T — Tampering (Manipulación de datos)
|
|
99
|
+
**Pregunta**: ¿Puede un atacante modificar datos en tránsito o en reposo?
|
|
100
|
+
- Comunicación HTTP (no HTTPS) entre componentes internos
|
|
101
|
+
- HMAC ausente en mensajes de colas
|
|
102
|
+
- Validación insuficiente de inputs antes de persistir
|
|
103
|
+
- Archivos subidos sin verificación de integridad
|
|
104
|
+
|
|
105
|
+
### R — Repudiation (Repudio)
|
|
106
|
+
**Pregunta**: ¿Puede un actor negar haber realizado una acción?
|
|
107
|
+
- Acciones críticas sin audit log
|
|
108
|
+
- Logs sin timestamp confiable o sin integridad garantizada
|
|
109
|
+
- Sin registro de IP/agente en acciones de alto riesgo
|
|
110
|
+
|
|
111
|
+
### I — Information Disclosure (Divulgación de información)
|
|
112
|
+
**Pregunta**: ¿Puede un atacante acceder a información que no debería ver?
|
|
113
|
+
- Stack traces expuestos en respuestas de error
|
|
114
|
+
- Datos sensibles en logs
|
|
115
|
+
- Respuestas de API que revelan más de lo necesario
|
|
116
|
+
- Endpoints de debug accesibles en producción
|
|
117
|
+
- IDOR: acceso a recursos de otros usuarios
|
|
118
|
+
|
|
119
|
+
### D — Denial of Service (Denegación de servicio)
|
|
120
|
+
**Pregunta**: ¿Puede un atacante degradar o eliminar el servicio?
|
|
121
|
+
- Sin rate limiting en endpoints públicos
|
|
122
|
+
- Queries sin límite de resultados (full table scan por input del usuario)
|
|
123
|
+
- Archivos de tamaño ilimitado aceptados
|
|
124
|
+
- Operaciones costosas sin throttling
|
|
125
|
+
|
|
126
|
+
### E — Elevation of Privilege (Escalación de privilegios)
|
|
127
|
+
**Pregunta**: ¿Puede un usuario normal obtener permisos de administrador?
|
|
128
|
+
- RBAC incompleto o con brechas
|
|
129
|
+
- Endpoints de admin sin verificación de rol
|
|
130
|
+
- Parámetros de rol aceptados del cliente sin validación del servidor
|
|
131
|
+
- Tokens JWT con claims manipulables
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Paso 4 — Identificar activos críticos
|
|
136
|
+
|
|
137
|
+
Clasificar los activos del sistema por impacto si se comprometen:
|
|
138
|
+
|
|
139
|
+
| Activo | Tipo | Impacto si comprometido | Nivel |
|
|
140
|
+
|--------|------|------------------------|-------|
|
|
141
|
+
| Contraseñas de usuarios | PII + Auth | Acceso no autorizado a cuentas | CRÍTICO |
|
|
142
|
+
| Datos financieros | Financiero | Pérdida monetaria / fraude | CRÍTICO |
|
|
143
|
+
| PII (nombre, email, RFC) | PII | Violación de privacidad / LFPDPPP | ALTO |
|
|
144
|
+
| Tokens JWT | Auth | Suplantación de identidad | ALTO |
|
|
145
|
+
| Logs de acceso | Operacional | Pérdida de auditoría | MEDIO |
|
|
146
|
+
| Datos de configuración | Operacional | Exposición de infraestructura | MEDIO |
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Paso 5 — Generar mitigaciones priorizadas
|
|
151
|
+
|
|
152
|
+
Usar la matriz de riesgo para priorizar:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
Riesgo = Probabilidad × Impacto
|
|
156
|
+
|
|
157
|
+
Probabilidad: 1 (baja) → 5 (casi seguro)
|
|
158
|
+
Impacto: 1 (insignificante) → 5 (crítico)
|
|
159
|
+
Prioridad: [1-5] Baja | [6-14] Media | [15-25] Alta
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Para cada amenaza STRIDE encontrada, generar:
|
|
163
|
+
|
|
164
|
+
```markdown
|
|
165
|
+
### [ID-001] [Nombre de la amenaza]
|
|
166
|
+
- **Categoría STRIDE**: [S/T/R/I/D/E]
|
|
167
|
+
- **Activo afectado**: [nombre del activo]
|
|
168
|
+
- **Flujo de datos**: [de dónde a dónde]
|
|
169
|
+
- **Descripción del ataque**: [cómo un atacante lo exploraría]
|
|
170
|
+
- **Probabilidad**: [1-5] | **Impacto**: [1-5] | **Riesgo**: [producto]
|
|
171
|
+
- **Mitigación propuesta**: [solución técnica específica]
|
|
172
|
+
- **Costo de mitigación**: [Bajo/Medio/Alto]
|
|
173
|
+
- **Estado**: Pendiente / En progreso / Mitigado / Aceptado
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Plantilla de salida: `THREAT-MODEL.md`
|
|
179
|
+
|
|
180
|
+
```markdown
|
|
181
|
+
# THREAT-MODEL.md — [Nombre del Sistema]
|
|
182
|
+
**Fecha**: [fecha] **Versión**: [N] **Autor**: [agente/persona]
|
|
183
|
+
|
|
184
|
+
## Alcance
|
|
185
|
+
[Descripción del sistema y qué está dentro/fuera del análisis]
|
|
186
|
+
|
|
187
|
+
## Activos críticos
|
|
188
|
+
| Activo | Nivel | Propietario |
|
|
189
|
+
|--------|-------|------------|
|
|
190
|
+
| | | |
|
|
191
|
+
|
|
192
|
+
## Superficie de ataque
|
|
193
|
+
### Puntos de entrada
|
|
194
|
+
- [lista]
|
|
195
|
+
|
|
196
|
+
### Flujos de datos sensibles
|
|
197
|
+
- [lista]
|
|
198
|
+
|
|
199
|
+
### Límites de confianza
|
|
200
|
+
- [lista]
|
|
201
|
+
|
|
202
|
+
## Amenazas identificadas
|
|
203
|
+
[Para cada amenaza, la ficha del formato anterior]
|
|
204
|
+
|
|
205
|
+
## Resumen de riesgos
|
|
206
|
+
| ID | Amenaza | Riesgo | Estado |
|
|
207
|
+
|----|---------|--------|--------|
|
|
208
|
+
| | | | |
|
|
209
|
+
|
|
210
|
+
## Plan de mitigación (priorizado)
|
|
211
|
+
| Prioridad | ID | Acción | Responsable | Fecha límite |
|
|
212
|
+
|-----------|---|--------|-------------|-------------|
|
|
213
|
+
| 1 (ALTO) | | | | |
|
|
214
|
+
| 2 (MEDIO) | | | | |
|
|
215
|
+
|
|
216
|
+
## Amenazas aceptadas (con justificación)
|
|
217
|
+
| ID | Amenaza | Justificación | Quién aceptó |
|
|
218
|
+
|----|---------|--------------|-------------|
|
|
219
|
+
| | | | |
|
|
220
|
+
|
|
221
|
+
## Próxima revisión
|
|
222
|
+
**Fecha**: [fecha de revisión] o cuando ocurra: [evento trigger]
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Triggers para actualizar el modelo
|
|
228
|
+
|
|
229
|
+
El threat model debe revisarse cuando:
|
|
230
|
+
- Se añade un nuevo punto de entrada al sistema
|
|
231
|
+
- Se integra un servicio externo nuevo
|
|
232
|
+
- Se cambia el mecanismo de autenticación
|
|
233
|
+
- Los datos que maneja el sistema cambian de clasificación
|
|
234
|
+
- Se detecta una vulnerabilidad en producción
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Gotchas / Errores comunes no obvios
|
|
239
|
+
|
|
240
|
+
**El STRIDE simplificado de este skill omite sistemáticamente amenazas de "confused deputy" donde un servicio interno con privilegios elevados ejecuta acciones en nombre de un actor de menor privilegio sin verificar la identidad original**: en un microservicio de reportes que llama al microservicio de pagos usando credenciales de servicio (no del usuario), un atacante que compromete el microservicio de reportes puede consultar pagos de cualquier usuario. Causa: STRIDE evalúa cada componente aisladamente; las amenazas confused deputy emergen en la interacción entre dos límites de confianza. Fix: al mapear límites de confianza en el Paso 2, agregar explícitamente la pregunta: "¿Este servicio actúa en nombre de un actor? ¿Verifica que la acción solicitada está autorizada para ese actor específico?" Documentar la identidad que fluye entre servicios en el DFD.
|
|
241
|
+
|
|
242
|
+
**Las mitigaciones de prioridad calculadas con `Probabilidad × Impacto` son inconsistentes entre revisores porque la escala 1-5 es subjetiva y dos ingenieros pueden asignar probabilidad 2 vs 4 a la misma amenaza según su experiencia personal**: un equipo que usa el threat model sin calibración previa genera matrices de riesgo donde "SQL injection en el endpoint de búsqueda" tiene riesgo 6 para un revisor (Prob=2, Imp=3) y riesgo 20 para otro (Prob=4, Imp=5). Causa: las escalas ordinales sin anclas concretas son inherentemente subjetivas. Fix: antes de la sesión, calibrar la escala con 2-3 amenazas históricas conocidas del sector: "CVE-XXXX-YYYY tuvo Probabilidad=4 porque fue explotado activamente en los 6 meses anteriores al parche". Las anclas históricas reducen la varianza entre revisores.
|
|
243
|
+
|
|
244
|
+
**El THREAT-MODEL.md marcado como "Mitigado" para una amenaza de IDOR queda obsoleto en 3 meses cuando se agrega un nuevo endpoint de API que expone el mismo recurso sin la verificación de autorización implementada en los endpoints originales**: el threat model registra que "IDOR en `/api/v1/pedidos/{id}`" fue mitigado, pero el endpoint nuevo `/api/v2/orders/{id}` (agregado en sprint 14) no fue evaluado y tiene el mismo vector. Causa: el threat model es un documento puntual; los cambios incrementales al sistema no lo actualizan automáticamente. Fix: en el mapa de propagación de cambios del proyecto, agregar una regla: "nuevo endpoint en `api/` → verificar si el THREAT-MODEL.md cubre el nuevo recurso expuesto". Revisar las amenazas de tipo I (Information Disclosure) y E (Elevation of Privilege) del modelo cada vez que se añade un endpoint.
|
|
245
|
+
|
|
246
|
+
**La categoría S (Spoofing) suele generar mitigaciones de "agregar autenticación" que quedan como ítems en el backlog indefinidamente porque no tienen criterio de aceptación técnico medible**: la mitigación "implementar autenticación JWT en el endpoint" sin especificar qué claims verificar, qué algoritmo usar, qué TTL del token, ni cómo manejar revocación es inaccionable. El ticket se cierra cuando se agrega "cualquier autenticación" aunque sea trivialmente bypasseable. Causa: las mitigaciones STRIDE son descripciones de objetivo, no especificaciones técnicas. Fix: para cada mitigación en el plan de acción, agregar los criterios de aceptación mínimos: "Verificar firma RS256, audience claim = 'api.mi-sistema.com', exp < now() + 1h, validar contra JWKS endpoint del IdP. Test: request sin token retorna 401, request con token expirado retorna 401, request con audience incorrecta retorna 401."
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tracing-processor
|
|
3
|
+
description: Documenta el patrón TracingProcessor para el sistema de trazabilidad SWL. Cómo crear exportadores de trazas (Langfuse, Jaeger, consola) sin modificar el núcleo, usando la interfaz formal en scripts/lib/tracing-processor-interface.js. Cargar cuando se implementa un exportador de trazas nuevo, se integra observabilidad externa, o se usa MultiProcessor.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
herramientasPermitidas: [Read, Write]
|
|
6
|
+
exclusiones:
|
|
7
|
+
- "No cargar para leer trazas ya generadas en `.planning/traces/` — eso es lectura directa de JSONL con el Read tool o con `drift-detection`; este skill documenta cómo implementar nuevos exportadores, no cómo consumir trazas."
|
|
8
|
+
- "No cargar para agregar observabilidad a hooks que no son parte del pipeline de trazabilidad — los hooks que registran eventos en `nudges.jsonl`, `alertas-persistentes.json` o archivos de estado no son TracingProcessors; este skill es exclusivo para exportadores de spans del ciclo de vida de agentes."
|
|
9
|
+
- "No cargar para depurar por qué un agente falla — las trazas son observabilidad, no diagnóstico de bugs; para bugs usar `depurador-swl` o revisar los logs del hook directamente."
|
|
10
|
+
- "No cargar si el exportador objetivo ya está implementado en `hooks/lib/otlp-exporter.js` y solo necesita configuración vía variable de entorno — los exportadores existentes se activan con variables opt-in, no requieren código nuevo."
|
|
11
|
+
evolvable: true
|
|
12
|
+
evolvable_scope:
|
|
13
|
+
- content
|
|
14
|
+
- examples
|
|
15
|
+
- anti-patterns
|
|
16
|
+
---
|
|
17
|
+
# Habilidad: TracingProcessor — Exportadores de Trazas
|
|
18
|
+
|
|
19
|
+
## Propósito del patrón
|
|
20
|
+
|
|
21
|
+
El sistema SWL ya registra spans en `.planning/traces/YYYY-MM-DD.jsonl` vía
|
|
22
|
+
`hooks/lib/otlp-exporter.js`. Sin la interfaz formal, agregar un segundo
|
|
23
|
+
destino de exportación (Langfuse, Jaeger, consola) requeriría modificar ese
|
|
24
|
+
archivo — violando el principio Open/Closed.
|
|
25
|
+
|
|
26
|
+
**TracingProcessor** resuelve esto: define un contrato que cualquier exportador
|
|
27
|
+
debe cumplir. El núcleo (`hooks/telemetria-agentes.js`) solo conoce la interfaz;
|
|
28
|
+
los destinos concretos son plugins intercambiables.
|
|
29
|
+
|
|
30
|
+
Beneficios:
|
|
31
|
+
- Agregar destinos sin tocar código existente.
|
|
32
|
+
- Combinar múltiples destinos con `MultiProcessor` (patrón Composite).
|
|
33
|
+
- Testear exportadores de forma aislada.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Contrato de la interfaz
|
|
38
|
+
|
|
39
|
+
Archivo: `scripts/lib/tracing-processor-interface.js`
|
|
40
|
+
|
|
41
|
+
| Método | Cuándo se invoca | Responsabilidad |
|
|
42
|
+
|--------|-----------------|----------------|
|
|
43
|
+
| `onTraceStart(traza)` | Al iniciar una traza de alto nivel | Registrar inicio, crear buffer si aplica |
|
|
44
|
+
| `onTraceEnd(traza)` | Al finalizar una traza completa | Exportar la traza completa, liberar buffer |
|
|
45
|
+
| `onSpanStart(span)` | Al iniciar un span individual | Registrar inicio del span |
|
|
46
|
+
| `onSpanEnd(span)` | Al finalizar un span (datos completos disponibles) | Punto principal de exportación |
|
|
47
|
+
| `shutdown()` | Al detener la aplicación | Vaciar buffers, cerrar archivos/conexiones |
|
|
48
|
+
| `forceFlush()` | Antes de shutdown o cuando se necesita garantía | Forzar volcado de colas internas |
|
|
49
|
+
|
|
50
|
+
Reglas del contrato:
|
|
51
|
+
- Los métodos deben retornar rápidamente. Usar colas internas para I/O lento.
|
|
52
|
+
- Los errores internos no deben propagarse al caller.
|
|
53
|
+
- Todos los métodos son síncronos por contrato; las subclases usan colas async internamente.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Cómo crear un exportador alterno
|
|
58
|
+
|
|
59
|
+
### Paso 1 — Extender la clase abstracta
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
'use strict';
|
|
63
|
+
const { TracingProcessor } = require('../../scripts/lib/tracing-processor-interface');
|
|
64
|
+
|
|
65
|
+
class MiExportador extends TracingProcessor {
|
|
66
|
+
constructor(opciones = {}) {
|
|
67
|
+
super();
|
|
68
|
+
this._buffer = [];
|
|
69
|
+
this._destino = opciones.destino || 'https://mi-backend.example.com/traces';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
onTraceStart(traza) { /* opcional: registrar inicio */ }
|
|
73
|
+
onTraceEnd(traza) { this._enviarBatch(); }
|
|
74
|
+
onSpanStart(span) { /* opcional */ }
|
|
75
|
+
|
|
76
|
+
onSpanEnd(span) {
|
|
77
|
+
this._buffer.push(span);
|
|
78
|
+
if (this._buffer.length >= 50) this._enviarBatch();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
shutdown() { this._enviarBatch(); }
|
|
82
|
+
forceFlush() { this._enviarBatch(); }
|
|
83
|
+
|
|
84
|
+
_enviarBatch() {
|
|
85
|
+
const lote = this._buffer.splice(0);
|
|
86
|
+
if (!lote.length) return;
|
|
87
|
+
// Envío HTTP fire-and-forget
|
|
88
|
+
try {
|
|
89
|
+
const https = require('https');
|
|
90
|
+
const body = JSON.stringify(lote);
|
|
91
|
+
const req = https.request(this._destino, { method: 'POST',
|
|
92
|
+
headers: { 'Content-Type': 'application/json' } });
|
|
93
|
+
req.on('error', () => {});
|
|
94
|
+
req.write(body);
|
|
95
|
+
req.end();
|
|
96
|
+
} catch (_) {}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = { MiExportador };
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Paso 2 — Verificar la implementación
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const { TracingProcessor } = require('../../scripts/lib/tracing-processor-interface');
|
|
107
|
+
const { MiExportador } = require('./mi-exportador');
|
|
108
|
+
|
|
109
|
+
console.log(TracingProcessor.esProcesadorValido(new MiExportador())); // → true
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Paso 3 — Registrar en el pipeline (opcional)
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
const { MultiProcessor } = require('../../scripts/lib/tracing-processor-interface');
|
|
116
|
+
const { OtlpLocalProcessor } = require('../../hooks/lib/otlp-exporter');
|
|
117
|
+
const { MiExportador } = require('./mi-exportador');
|
|
118
|
+
|
|
119
|
+
const pipeline = new MultiProcessor([
|
|
120
|
+
new OtlpLocalProcessor(process.cwd()), // siempre activo
|
|
121
|
+
new MiExportador({ destino: process.env.TRACES_ENDPOINT }),
|
|
122
|
+
]);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Patrón Composite con MultiProcessor
|
|
128
|
+
|
|
129
|
+
`MultiProcessor` implementa `TracingProcessor` y propaga cada evento a N hijos.
|
|
130
|
+
|
|
131
|
+
**Cuándo usarlo:**
|
|
132
|
+
- Necesitas enviar spans a más de un destino simultáneamente.
|
|
133
|
+
- Quieres activar un exportador de consola durante debugging sin modificar el pipeline.
|
|
134
|
+
- Construyes un pipeline configurable donde los destinos se leen de variables de entorno.
|
|
135
|
+
|
|
136
|
+
**Comportamiento ante errores:** si un hijo lanza en `onSpanEnd`, `MultiProcessor`
|
|
137
|
+
captura la excepción y continúa con los demás hijos. Ningún fallo individual
|
|
138
|
+
interrumpe el pipeline completo.
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
const multi = new MultiProcessor([exportadorA, exportadorB]);
|
|
142
|
+
multi.addProcessor(exportadorC); // agregar en tiempo de ejecución
|
|
143
|
+
multi.removeProcessor(exportadorB); // eliminar por referencia
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Casos de uso reales
|
|
149
|
+
|
|
150
|
+
### Exportador a Langfuse (mediano plazo)
|
|
151
|
+
|
|
152
|
+
Langfuse acepta trazas vía HTTP. Crear `scripts/lib/langfuse-processor.js`
|
|
153
|
+
extendiendo `TracingProcessor`. En `onSpanEnd`, formatear el span al schema
|
|
154
|
+
de Langfuse y encolarlo. En `shutdown`, vaciar la cola con `forceFlush`.
|
|
155
|
+
|
|
156
|
+
Variables de entorno necesarias: `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`,
|
|
157
|
+
`LANGFUSE_HOST`. El procesador solo se activa si `LANGFUSE_PUBLIC_KEY` está
|
|
158
|
+
definida (patrón opt-in de `CLAUDE.md`).
|
|
159
|
+
|
|
160
|
+
### Exportador a Jaeger
|
|
161
|
+
|
|
162
|
+
Jaeger acepta spans en formato OpenTelemetry JSON. Los spans de swl-ses ya
|
|
163
|
+
tienen la estructura correcta (`traceId`, `spanId`, `nombre`, `duracionMs`).
|
|
164
|
+
El exportador debe mapear `estado: 'ERROR'` al código de status OTLP `2`.
|
|
165
|
+
|
|
166
|
+
Endpoint: `JAEGER_OTLP_ENDPOINT` (por defecto `http://localhost:4318/v1/traces`).
|
|
167
|
+
|
|
168
|
+
### Exportador para métricas agregadas
|
|
169
|
+
|
|
170
|
+
En lugar de persistir spans crudos, un exportador puede agregar en memoria:
|
|
171
|
+
contar spans por tipo, sumar duraciones, detectar anomalías. En `onTraceEnd`
|
|
172
|
+
emite las métricas agregadas a `.planning/evolucion/metricas.json` usando
|
|
173
|
+
`atomicWriteJSON` de `hooks/lib/atomic-write.js`.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Anti-patrones
|
|
178
|
+
|
|
179
|
+
| Anti-patrón | Problema | Solución |
|
|
180
|
+
|-------------|----------|---------|
|
|
181
|
+
| Exportador que bloquea `onSpanEnd` con I/O síncrono lento | Ralentiza todos los agentes | Usar cola interna y enviar en batch desde `onTraceEnd` o un setInterval |
|
|
182
|
+
| Exportador que relanza excepciones de red | Interrumpe el pipeline completo | Capturar con try/catch, registrar el error internamente |
|
|
183
|
+
| Exportador sin `shutdown` / `forceFlush` implementados | Spans en buffer se pierden al cerrar el proceso | Implementar ambos métodos; `shutdown` debe vaciar el buffer |
|
|
184
|
+
| Exportador que modifica el span recibido | Efectos secundarios para otros procesadores en el pipeline | Clonar el span antes de mutarlo: `const s = { ...span }` |
|
|
185
|
+
| Exportador activado incondicionalmente en producción | Agrega latencia sin config del usuario | Patrón opt-in: `if (!process.env.MI_ENDPOINT) return` al inicio |
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Relación con el resto del sistema
|
|
190
|
+
|
|
191
|
+
| Componente | Relación |
|
|
192
|
+
|-----------|----------|
|
|
193
|
+
| `scripts/lib/tracing-processor-interface.js` | Define las clases abstractas `TracingProcessor`, `TracingExporter` y `MultiProcessor` |
|
|
194
|
+
| `hooks/lib/otlp-exporter.js` | Implementación concreta `OtlpLocalProcessor` + funciones sueltas (compatibilidad) |
|
|
195
|
+
| `scripts/lib/span-schema.js` | Taxonomía de 13 tipos de span; los spans que llegan a `onSpanEnd` siguen este schema |
|
|
196
|
+
| `hooks/telemetria-agentes.js` | Produce los spans del ciclo de vida de agentes; es el emisor principal |
|
|
197
|
+
| `.planning/traces/YYYY-MM-DD.jsonl` | Destino por defecto del `OtlpLocalProcessor` |
|
|
198
|
+
| `hooks/lib/atomic-write.js` | Para exportadores que persisten estado (métricas, índices) — no usar para JSONL |
|
|
199
|
+
|
|
200
|
+
## Cuándo NO cargar
|
|
201
|
+
|
|
202
|
+
- Se leen o analizan trazas ya generadas en `.planning/traces/` — usar Read tool o `drift-detection`; este skill describe cómo construir exportadores nuevos, no cómo consumir el JSONL existente.
|
|
203
|
+
- Se agrega observabilidad a hooks que no emiten spans del ciclo de vida de agentes (hooks de perfilado, guardrails, auditoría) — esos hooks registran en sus propios archivos JSONL; `TracingProcessor` es para el pipeline de spans de `telemetria-agentes.js`.
|
|
204
|
+
- El exportador objetivo ya existe en `hooks/lib/otlp-exporter.js` y solo necesita activarse — los exportadores implementados se activan con la variable de entorno correspondiente (patrón opt-in); no requieren código nuevo.
|
|
205
|
+
- Se diagnostica por qué un agente produjo un resultado incorrecto — las trazas miden ciclo de vida y duración, no lógica; para bugs usar `depurador-swl` o los logs del hook directamente.
|
|
206
|
+
|
|
207
|
+
## Gotchas / Errores comunes no obvios
|
|
208
|
+
|
|
209
|
+
- **`onSpanEnd` con I/O síncrono bloquea el pipeline completo**: el exportador llama a `fetch()` o `fs.writeFileSync()` directamente en `onSpanEnd` y ralentiza todos los agentes porque cada span espera al I/O antes de continuar. Causa: `onSpanEnd` se ejecuta síncronamente en el mismo event loop. Solución: encolar los spans en un buffer interno y vaciar el buffer en `onTraceEnd` o con un `setInterval` — el anti-patrón está documentado explícitamente en la tabla del skill.
|
|
210
|
+
- **Exportador que mutua el span recibido afecta a otros procesadores en el pipeline**: un exportador agrega un campo `exportado: true` al span y el siguiente procesador en el `MultiProcessor` recibe el span modificado. Causa: los procesadores comparten el mismo objeto span por referencia. Solución: clonar el span antes de mutarlo (`const s = { ...span }`) — regla documentada en los anti-patrones del skill.
|
|
211
|
+
- **`shutdown()` no implementado provoca pérdida de spans en buffer al cerrar el proceso**: el proceso del hook termina y los spans acumulados en la cola interna se descartan. Causa: implementar solo `onSpanEnd` y `onTraceEnd` sin `shutdown`. Solución: `shutdown` debe vaciar el buffer síncronamente (o retornar una Promise que resuelve al vaciar); Claude Code llama a `shutdown` en el proceso de cierre del hook.
|
|
212
|
+
- **Exportador activado sin variable de entorno opt-in en todos los entornos**: el exportador a Langfuse se activa incluso en proyectos que no configuraron `LANGFUSE_PUBLIC_KEY`, añadiendo latencia de red sin beneficio. Causa: no implementar el guard de opt-in al inicio de `onSpanEnd`. Solución: todo exportador externo debe comenzar con `if (!process.env.MI_ENDPOINT) return` — el patrón opt-in de CLAUDE.md es obligatorio para integraciones enterprise.
|