@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,305 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: go-experto
|
|
3
|
+
description: >
|
|
4
|
+
Go idiomático: concurrencia con goroutines y channels, context propagation,
|
|
5
|
+
error handling, HTTP servers con chi/gin y graceful shutdown. Cargar cuando
|
|
6
|
+
se implementen servicios Go, handlers HTTP o lógica concurrente.
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
herramientasPermitidas: [Read, Grep]
|
|
9
|
+
exclusiones:
|
|
10
|
+
- "No cargar para diagnosticar errores de compilación Go o problemas de módulos — para build errors cargar `build-errors-go`."
|
|
11
|
+
- "No cargar para diseñar la arquitectura de paquetes Go (interfaces, patrones) — para eso cargar `go-patrones`."
|
|
12
|
+
- "No cargar para escribir tests en Go — para testing cargar `go-testing`."
|
|
13
|
+
- "No cargar para lógica de backend que no sea Go — si el stack es Python, Java o Node.js cargar el skill correspondiente."
|
|
14
|
+
evolvable: true # default para skill estandar
|
|
15
|
+
---
|
|
16
|
+
# Go Experto — Go Idiomático y Concurrencia
|
|
17
|
+
|
|
18
|
+
Cubre el desarrollo Go idiomático: net/http con routers, middleware, manejo
|
|
19
|
+
de context.Context, concurrencia con goroutines y channels, error handling
|
|
20
|
+
con wrapping, logging estructurado y graceful shutdown.
|
|
21
|
+
|
|
22
|
+
## Cuándo cargar este skill
|
|
23
|
+
|
|
24
|
+
Invoca `Skill("go-experto")` cuando:
|
|
25
|
+
|
|
26
|
+
- Se implementen HTTP handlers o middleware en Go
|
|
27
|
+
- Se use concurrencia con goroutines, channels o errgroup
|
|
28
|
+
- Se propague context.Context a través de capas
|
|
29
|
+
- Se diseñe el manejo de errores con sentinel errors o custom types
|
|
30
|
+
- Se configure graceful shutdown de un servidor HTTP
|
|
31
|
+
- Se implemente dependency injection sin frameworks
|
|
32
|
+
|
|
33
|
+
## Cuándo NO cargar
|
|
34
|
+
|
|
35
|
+
- La pregunta es sobre errores de compilación Go o problemas de `go.mod`/`go.sum` — para build errors cargar `build-errors-go`.
|
|
36
|
+
- La pregunta es sobre diseñar interfaces, patrones de paquetes o arquitectura — para diseño cargar `go-patrones`.
|
|
37
|
+
- La tarea es escribir tests unitarios o de integración en Go — cargar `go-testing`.
|
|
38
|
+
- El backend usa Python, Java, Node.js u otro lenguaje — este skill cubre Go específicamente.
|
|
39
|
+
|
|
40
|
+
## Conceptos clave
|
|
41
|
+
|
|
42
|
+
### context.Context es el primer parámetro — siempre
|
|
43
|
+
|
|
44
|
+
Context propaga cancelación, deadlines y valores a través de goroutines. Se
|
|
45
|
+
pasa como primer parámetro named `ctx context.Context`. Nunca almacenar en structs.
|
|
46
|
+
|
|
47
|
+
### Error handling explícito
|
|
48
|
+
|
|
49
|
+
Go no tiene excepciones. Cada error se verifica en el punto donde ocurre.
|
|
50
|
+
`errors.Is` compara por valor (sentinel), `errors.As` extrae por tipo.
|
|
51
|
+
`fmt.Errorf("operación: %w", err)` envuelve conservando la cadena.
|
|
52
|
+
|
|
53
|
+
### Goroutine leak prevention
|
|
54
|
+
|
|
55
|
+
Una goroutine sin mecanismo de terminación es un leak. Siempre proporcionar
|
|
56
|
+
forma de cancelar: context con cancel, channel de done o errgroup.
|
|
57
|
+
|
|
58
|
+
### Dependency injection por constructor
|
|
59
|
+
|
|
60
|
+
Los servicios reciben sus dependencias por constructor, no las instancian.
|
|
61
|
+
Favorece testabilidad e intercambiabilidad de implementaciones.
|
|
62
|
+
|
|
63
|
+
## Reglas obligatorias
|
|
64
|
+
|
|
65
|
+
### Verificar TODOS los errores — NUNCA ignorar con _
|
|
66
|
+
|
|
67
|
+
```go
|
|
68
|
+
// MAL
|
|
69
|
+
result, _ := db.Query(ctx, sql)
|
|
70
|
+
|
|
71
|
+
// BIEN
|
|
72
|
+
result, err := db.Query(ctx, sql)
|
|
73
|
+
if err != nil {
|
|
74
|
+
return fmt.Errorf("consultar pedidos: %w", err)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Cancelar SIEMPRE el context derivado
|
|
79
|
+
|
|
80
|
+
```go
|
|
81
|
+
// MAL — context con timeout sin defer cancel
|
|
82
|
+
ctx, _ := context.WithTimeout(parent, 5*time.Second)
|
|
83
|
+
|
|
84
|
+
// BIEN
|
|
85
|
+
ctx, cancel := context.WithTimeout(parent, 5*time.Second)
|
|
86
|
+
defer cancel()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Usar errgroup para goroutines con errores
|
|
90
|
+
|
|
91
|
+
```go
|
|
92
|
+
// MAL — WaitGroup no propaga errores
|
|
93
|
+
var wg sync.WaitGroup
|
|
94
|
+
wg.Add(1)
|
|
95
|
+
go func() {
|
|
96
|
+
defer wg.Done()
|
|
97
|
+
if err := hacerAlgo(); err != nil {
|
|
98
|
+
log.Println(err) // error perdido
|
|
99
|
+
}
|
|
100
|
+
}()
|
|
101
|
+
|
|
102
|
+
// BIEN — errgroup cancela todas al primer error
|
|
103
|
+
g, ctx := errgroup.WithContext(ctx)
|
|
104
|
+
g.Go(func() error { return hacerAlgo(ctx) })
|
|
105
|
+
g.Go(func() error { return hacerOtraCosa(ctx) })
|
|
106
|
+
if err := g.Wait(); err != nil {
|
|
107
|
+
return fmt.Errorf("procesamiento paralelo: %w", err)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### context.Background() solo en main — NUNCA en handlers
|
|
112
|
+
|
|
113
|
+
Los handlers reciben el context del request (`r.Context()`). Crear
|
|
114
|
+
`context.Background()` en un handler rompe la propagacion de cancelacion
|
|
115
|
+
del cliente.
|
|
116
|
+
|
|
117
|
+
## Patrones recomendados
|
|
118
|
+
|
|
119
|
+
### HTTP server con chi y middleware
|
|
120
|
+
|
|
121
|
+
```go
|
|
122
|
+
func NuevoRouter(pedidoHandler *PedidoHandler, auth Middleware) http.Handler {
|
|
123
|
+
r := chi.NewRouter()
|
|
124
|
+
r.Use(middleware.RequestID)
|
|
125
|
+
r.Use(middleware.RealIP)
|
|
126
|
+
r.Use(middleware.Logger)
|
|
127
|
+
r.Use(middleware.Recoverer)
|
|
128
|
+
|
|
129
|
+
r.Route("/v1", func(r chi.Router) {
|
|
130
|
+
r.Use(auth.Verificar)
|
|
131
|
+
r.Route("/pedidos", func(r chi.Router) {
|
|
132
|
+
r.Get("/", pedidoHandler.Listar)
|
|
133
|
+
r.Post("/", pedidoHandler.Crear)
|
|
134
|
+
r.Get("/{id}", pedidoHandler.Obtener)
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
return r
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Handler con context y error handling
|
|
142
|
+
|
|
143
|
+
```go
|
|
144
|
+
func (h *PedidoHandler) Crear(w http.ResponseWriter, r *http.Request) {
|
|
145
|
+
var req CrearPedidoRequest
|
|
146
|
+
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
147
|
+
responderError(w, http.StatusBadRequest, "body inválido")
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
pedido, err := h.service.Crear(r.Context(), req)
|
|
152
|
+
if err != nil {
|
|
153
|
+
var notFound *NotFoundError
|
|
154
|
+
switch {
|
|
155
|
+
case errors.As(err, ¬Found):
|
|
156
|
+
responderError(w, http.StatusNotFound, notFound.Error())
|
|
157
|
+
default:
|
|
158
|
+
slog.ErrorContext(r.Context(), "crear pedido", "error", err)
|
|
159
|
+
responderError(w, http.StatusInternalServerError, "error interno")
|
|
160
|
+
}
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
w.Header().Set("Content-Type", "application/json")
|
|
165
|
+
w.WriteHeader(http.StatusCreated)
|
|
166
|
+
json.NewEncoder(w).Encode(pedido)
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Error types con sentinel y wrapping
|
|
171
|
+
|
|
172
|
+
```go
|
|
173
|
+
// Sentinel errors para comparación con errors.Is
|
|
174
|
+
var (
|
|
175
|
+
ErrNotFound = errors.New("recurso no encontrado")
|
|
176
|
+
ErrUnauthorized = errors.New("no autorizado")
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
// Custom type para contexto con errors.As
|
|
180
|
+
type ValidationError struct {
|
|
181
|
+
Campo string
|
|
182
|
+
Mensaje string
|
|
183
|
+
}
|
|
184
|
+
func (e *ValidationError) Error() string {
|
|
185
|
+
return fmt.Sprintf("validación fallida en %s: %s", e.Campo, e.Mensaje)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Wrapping que preserva la cadena
|
|
189
|
+
func (s *PedidoService) Crear(ctx context.Context, req CrearPedidoRequest) (*Pedido, error) {
|
|
190
|
+
cliente, err := s.clienteRepo.Obtener(ctx, req.ClienteID)
|
|
191
|
+
if err != nil {
|
|
192
|
+
return nil, fmt.Errorf("obtener cliente %s: %w", req.ClienteID, err)
|
|
193
|
+
}
|
|
194
|
+
// ...
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Graceful shutdown
|
|
199
|
+
|
|
200
|
+
```go
|
|
201
|
+
func main() {
|
|
202
|
+
srv := &http.Server{Addr: ":8080", Handler: nuevoRouter()}
|
|
203
|
+
|
|
204
|
+
go func() {
|
|
205
|
+
if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
|
|
206
|
+
slog.Error("servidor fallo", "error", err)
|
|
207
|
+
os.Exit(1)
|
|
208
|
+
}
|
|
209
|
+
}()
|
|
210
|
+
|
|
211
|
+
quit := make(chan os.Signal, 1)
|
|
212
|
+
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
213
|
+
<-quit
|
|
214
|
+
|
|
215
|
+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
216
|
+
defer cancel()
|
|
217
|
+
if err := srv.Shutdown(ctx); err != nil {
|
|
218
|
+
slog.Error("shutdown forzado", "error", err)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Structured logging con slog
|
|
224
|
+
|
|
225
|
+
```go
|
|
226
|
+
// Configuración en main
|
|
227
|
+
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
|
228
|
+
Level: slog.LevelInfo,
|
|
229
|
+
}))
|
|
230
|
+
slog.SetDefault(logger)
|
|
231
|
+
|
|
232
|
+
// Uso en handlers y services
|
|
233
|
+
slog.InfoContext(ctx, "pedido creado",
|
|
234
|
+
"pedido_id", pedido.ID,
|
|
235
|
+
"cliente_id", pedido.ClienteID,
|
|
236
|
+
"total", pedido.Total,
|
|
237
|
+
)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Anti-patrones conocidos
|
|
241
|
+
|
|
242
|
+
### Goroutine sin mecanismo de cancelación
|
|
243
|
+
|
|
244
|
+
```go
|
|
245
|
+
// MAL — goroutine que vive para siempre
|
|
246
|
+
go func() {
|
|
247
|
+
for {
|
|
248
|
+
procesarCola()
|
|
249
|
+
time.Sleep(time.Second)
|
|
250
|
+
}
|
|
251
|
+
}()
|
|
252
|
+
|
|
253
|
+
// BIEN — goroutine controlada por context
|
|
254
|
+
go func() {
|
|
255
|
+
ticker := time.NewTicker(time.Second)
|
|
256
|
+
defer ticker.Stop()
|
|
257
|
+
for {
|
|
258
|
+
select {
|
|
259
|
+
case <-ticker.C:
|
|
260
|
+
procesarCola(ctx)
|
|
261
|
+
case <-ctx.Done():
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}()
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Panic en lugar de error return
|
|
269
|
+
|
|
270
|
+
```go
|
|
271
|
+
// MAL — panic en lógica de negocio
|
|
272
|
+
func dividir(a, b float64) float64 {
|
|
273
|
+
if b == 0 { panic("división por cero") }
|
|
274
|
+
return a / b
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// BIEN — error explícito
|
|
278
|
+
func dividir(a, b float64) (float64, error) {
|
|
279
|
+
if b == 0 { return 0, errors.New("división por cero") }
|
|
280
|
+
return a / b, nil
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Checklist de verificación
|
|
285
|
+
|
|
286
|
+
- [ ] Todos los errores verificados, ningún `_` descartando error
|
|
287
|
+
- [ ] context.Context como primer parámetro en funciones que hacen I/O
|
|
288
|
+
- [ ] Toda goroutine tiene mecanismo de terminación (context, done channel)
|
|
289
|
+
- [ ] defer cancel() inmediatamente después de WithTimeout/WithCancel
|
|
290
|
+
- [ ] context.Background() solo en main o tests
|
|
291
|
+
- [ ] errgroup en lugar de WaitGroup cuando hay errores que propagar
|
|
292
|
+
- [ ] Graceful shutdown implementado en el servidor principal
|
|
293
|
+
|
|
294
|
+
## Gotchas / Errores comunes no obvios
|
|
295
|
+
|
|
296
|
+
**`defer cancel()` después de `context.WithTimeout` pero antes de verificar el error**: poner `ctx, cancel := context.WithTimeout(parent, 5*time.Second)` y llamar `defer cancel()` es correcto, pero si `cancel()` se llama antes de que la operación termine porque la función retornó por otro camino (un error temprano), el contexto se cancela innecesariamente para tareas downstream que aún lo usan. Fix: llamar `defer cancel()` inmediatamente después de `WithTimeout` — eso es correcto e intencional; lo que se debe evitar es pasar `ctx` a goroutines que viven más que la función que creó el contexto.
|
|
297
|
+
|
|
298
|
+
**Goroutine leak cuando el channel receptor termina antes de enviar**: `for _, item := range items { go func() { results <- procesar(item) }() }` — si el goroutine principal sale (por error o cancelación) mientras los goroutines aún intentan enviar a `results`, los goroutines quedan bloqueados para siempre. Fix: usar `select { case results <- r: case <-ctx.Done(): return }` dentro de cada goroutine para que puedan salir cuando se cancela el contexto.
|
|
299
|
+
|
|
300
|
+
**`errors.Is` no detecta errores envueltos con `fmt.Errorf("%v", err)`**: usar `%v` en el format string descarta la cadena de wrapping — el error resultante es un string, no un error envuelto. Solo `%w` preserva la cadena para `errors.Is`/`errors.As`. Fix: siempre usar `fmt.Errorf("operación falló: %w", err)` cuando se quiera que el error sea inspeccionable con `errors.Is` o `errors.As`.
|
|
301
|
+
|
|
302
|
+
**`sync.WaitGroup.Add()` llamado dentro de la goroutine en lugar de antes de lanzarla**: si `Add(1)` se llama dentro de `go func() { wg.Add(1); defer wg.Done(); ... }()`, existe una condición de carrera donde `wg.Wait()` puede retornar antes de que las goroutines hayan hecho `Add`. Fix: llamar siempre `wg.Add(1)` en el goroutine padre, justo antes de `go func()`.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
*Skill creado con swl:crear-skill el 2026-03-31. Versión 1.0.0.*
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: go-patrones
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: >
|
|
5
|
+
Patrones idiomáticos de Go: functional options, interfaces pequeñas, error
|
|
6
|
+
wrapping, middleware chain, repository pattern y generics básicos (Go 1.18+).
|
|
7
|
+
Cargar cuando se diseñe arquitectura Go o se revise código existente.
|
|
8
|
+
herramientasPermitidas: [Read, Glob, Grep]
|
|
9
|
+
exclusiones:
|
|
10
|
+
- "No cargar para implementar handlers HTTP o lógica concurrente en Go — para implementación concreta cargar `go-experto`; este skill cubre diseño de arquitectura de paquetes."
|
|
11
|
+
- "No cargar para escribir tests en Go — para testing cargar `go-testing`."
|
|
12
|
+
- "No cargar para errores de compilación Go — para build errors cargar `build-errors-go`."
|
|
13
|
+
- "No cargar para patrones de diseño en otros lenguajes — las interfaces pequeñas y functional options son patrones específicos del idioma Go."
|
|
14
|
+
evolvable: true # default para skill estandar
|
|
15
|
+
---
|
|
16
|
+
# Go Patrones — Diseño Idiomático Go
|
|
17
|
+
|
|
18
|
+
Cubre los patrones que producen código Go mantenible y testeable: functional
|
|
19
|
+
options para configuración, interfaces de 1-3 métodos, error handling avanzado,
|
|
20
|
+
middleware chain, repository pattern y generics básicos.
|
|
21
|
+
|
|
22
|
+
## Cuándo cargar este skill
|
|
23
|
+
|
|
24
|
+
Invoca `Skill("go-patrones")` cuando:
|
|
25
|
+
|
|
26
|
+
- Se diseñe una nueva API pública de un paquete Go
|
|
27
|
+
- Se refactorice código con structs de configuración complejos
|
|
28
|
+
- Se implemente un middleware chain HTTP
|
|
29
|
+
- Se diseñe la capa de acceso a datos (repository pattern)
|
|
30
|
+
- Se evalúen los anti-patrones de global state o init() abuse
|
|
31
|
+
|
|
32
|
+
## Cuándo NO cargar
|
|
33
|
+
|
|
34
|
+
- La pregunta es sobre implementar handlers HTTP concretos o lógica concurrente — para implementación cargar `go-experto`; este skill cubre decisiones de diseño de paquetes.
|
|
35
|
+
- La tarea es escribir tests unitarios o de integración en Go — cargar `go-testing`.
|
|
36
|
+
- La pregunta es sobre errores de compilación Go — cargar `build-errors-go`.
|
|
37
|
+
- Los patrones buscados son de otro lenguaje (Java, Python) — las interfaces pequeñas y functional options son patrones idiomáticos de Go, no directamente aplicables en otros lenguajes.
|
|
38
|
+
|
|
39
|
+
## Conceptos clave
|
|
40
|
+
|
|
41
|
+
### Interfaces pequeñas — cuanto más chica, más reutilizable
|
|
42
|
+
|
|
43
|
+
La interfaz de Go se satisface implícitamente. Una interfaz de 1-2 métodos
|
|
44
|
+
puede ser satisfecha por muchas más implementaciones y es más fácil de testear.
|
|
45
|
+
La regla: aceptar interfaces, retornar tipos concretos.
|
|
46
|
+
|
|
47
|
+
### Functional Options Pattern
|
|
48
|
+
|
|
49
|
+
Permite configuración opcional con valores default sin romper la firma del
|
|
50
|
+
constructor cuando se agregan opciones nuevas. Elimina structs Config con
|
|
51
|
+
campos opcionales difíciles de distinguir.
|
|
52
|
+
|
|
53
|
+
### Zero Value Util
|
|
54
|
+
|
|
55
|
+
El zero value de un tipo debe ser útil o al menos seguro de usar. Un struct
|
|
56
|
+
con zero value inválido es un bug en espera.
|
|
57
|
+
|
|
58
|
+
## Reglas obligatorias
|
|
59
|
+
|
|
60
|
+
### Interfaces de máximo 3 métodos — dividir si crece más
|
|
61
|
+
|
|
62
|
+
Una interfaz con 10 métodos raramente puede ser implementada limpiamente.
|
|
63
|
+
Si crece, dividirla en interfaces específicas que se componen.
|
|
64
|
+
|
|
65
|
+
```go
|
|
66
|
+
// MAL — difícil de mockear, acopla demasiado
|
|
67
|
+
type PedidoStore interface {
|
|
68
|
+
Crear(ctx, req) (*Pedido, error)
|
|
69
|
+
Actualizar(ctx, id, req) (*Pedido, error)
|
|
70
|
+
Eliminar(ctx, id) error
|
|
71
|
+
Buscar(ctx, filtro) ([]*Pedido, error)
|
|
72
|
+
BuscarPorCliente(ctx, clienteID) ([]*Pedido, error)
|
|
73
|
+
Contar(ctx, filtro) (int, error)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// BIEN — interfaces por responsabilidad
|
|
77
|
+
type PedidoWriter interface {
|
|
78
|
+
Crear(ctx context.Context, req CrearPedidoRequest) (*Pedido, error)
|
|
79
|
+
Actualizar(ctx context.Context, id uuid.UUID, req ActualizarRequest) (*Pedido, error)
|
|
80
|
+
}
|
|
81
|
+
type PedidoReader interface {
|
|
82
|
+
Buscar(ctx context.Context, filtro Filtro) ([]*Pedido, error)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### NUNCA usar init() para logica de negocio
|
|
87
|
+
|
|
88
|
+
`init()` se ejecuta antes de main, en orden no garantizado entre paquetes.
|
|
89
|
+
Solo para registro de drivers o validación de configuración obligatoria.
|
|
90
|
+
|
|
91
|
+
### NUNCA usar variables globales mutables en paquetes de biblioteca
|
|
92
|
+
|
|
93
|
+
El estado global impide tests paralelos y hace el comportamiento dependiente
|
|
94
|
+
del orden de inicialización. Usar inyección de dependencias.
|
|
95
|
+
|
|
96
|
+
## Patrones recomendados
|
|
97
|
+
|
|
98
|
+
### Functional options
|
|
99
|
+
|
|
100
|
+
```go
|
|
101
|
+
type Server struct {
|
|
102
|
+
addr string
|
|
103
|
+
timeout time.Duration
|
|
104
|
+
maxConn int
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
type Option func(*Server)
|
|
108
|
+
|
|
109
|
+
func ConAddr(addr string) Option {
|
|
110
|
+
return func(s *Server) { s.addr = addr }
|
|
111
|
+
}
|
|
112
|
+
func ConTimeout(d time.Duration) Option {
|
|
113
|
+
return func(s *Server) { s.timeout = d }
|
|
114
|
+
}
|
|
115
|
+
func ConMaxConn(n int) Option {
|
|
116
|
+
return func(s *Server) { s.maxConn = n }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
func NuevoServer(opts ...Option) *Server {
|
|
120
|
+
s := &Server{ // defaults seguros
|
|
121
|
+
addr: ":8080",
|
|
122
|
+
timeout: 30 * time.Second,
|
|
123
|
+
maxConn: 100,
|
|
124
|
+
}
|
|
125
|
+
for _, opt := range opts {
|
|
126
|
+
opt(s)
|
|
127
|
+
}
|
|
128
|
+
return s
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Uso — solo se pasan las opciones que cambian
|
|
132
|
+
srv := NuevoServer(
|
|
133
|
+
ConAddr(":9090"),
|
|
134
|
+
ConTimeout(60 * time.Second),
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Middleware chain
|
|
139
|
+
|
|
140
|
+
```go
|
|
141
|
+
type Middleware func(http.Handler) http.Handler
|
|
142
|
+
|
|
143
|
+
func Cadena(h http.Handler, middlewares ...Middleware) http.Handler {
|
|
144
|
+
for i := len(middlewares) - 1; i >= 0; i-- {
|
|
145
|
+
h = middlewares[i](h)
|
|
146
|
+
}
|
|
147
|
+
return h
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
func LoggingMiddleware(next http.Handler) http.Handler {
|
|
151
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
152
|
+
start := time.Now()
|
|
153
|
+
next.ServeHTTP(w, r)
|
|
154
|
+
slog.InfoContext(r.Context(), "request",
|
|
155
|
+
"method", r.Method,
|
|
156
|
+
"path", r.URL.Path,
|
|
157
|
+
"duracion", time.Since(start),
|
|
158
|
+
)
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Repository pattern
|
|
164
|
+
|
|
165
|
+
```go
|
|
166
|
+
// Interfaz en el paquete de dominio
|
|
167
|
+
type PedidoRepository interface {
|
|
168
|
+
Obtener(ctx context.Context, id uuid.UUID) (*Pedido, error)
|
|
169
|
+
Guardar(ctx context.Context, p *Pedido) error
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Implementación en paquete de infraestructura
|
|
173
|
+
type postgresPedidoRepo struct {
|
|
174
|
+
db *pgxpool.Pool
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
func NuevoPedidoRepo(db *pgxpool.Pool) PedidoRepository {
|
|
178
|
+
return &postgresPedidoRepo{db: db}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
func (r *postgresPedidoRepo) Obtener(ctx context.Context, id uuid.UUID) (*Pedido, error) {
|
|
182
|
+
var p Pedido
|
|
183
|
+
err := r.db.QueryRow(ctx,
|
|
184
|
+
"SELECT id, cliente_id, total FROM pedidos WHERE id = $1", id,
|
|
185
|
+
).Scan(&p.ID, &p.ClienteID, &p.Total)
|
|
186
|
+
if errors.Is(err, pgx.ErrNoRows) {
|
|
187
|
+
return nil, ErrNotFound
|
|
188
|
+
}
|
|
189
|
+
return &p, err
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Generics para contenedores tipados (Go 1.18+)
|
|
194
|
+
|
|
195
|
+
```go
|
|
196
|
+
// Mapa con default value
|
|
197
|
+
func ObtenerODefault[K comparable, V any](m map[K]V, key K, def V) V {
|
|
198
|
+
if v, ok := m[key]; ok {
|
|
199
|
+
return v
|
|
200
|
+
}
|
|
201
|
+
return def
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Filter generico
|
|
205
|
+
func Filtrar[T any](slice []T, pred func(T) bool) []T {
|
|
206
|
+
resultado := make([]T, 0)
|
|
207
|
+
for _, v := range slice {
|
|
208
|
+
if pred(v) {
|
|
209
|
+
resultado = append(resultado, v)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return resultado
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Embed para recursos estaticos
|
|
217
|
+
|
|
218
|
+
```go
|
|
219
|
+
//go:embed templates/*.html
|
|
220
|
+
var templateFS embed.FS
|
|
221
|
+
|
|
222
|
+
//go:embed migrations/*.sql
|
|
223
|
+
var migrationsFS embed.FS
|
|
224
|
+
|
|
225
|
+
// Uso en producción y tests — sin path absolutos
|
|
226
|
+
tmpl, err := template.ParseFS(templateFS, "templates/email.html")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Anti-patrones conocidos
|
|
230
|
+
|
|
231
|
+
### Global state mutable
|
|
232
|
+
|
|
233
|
+
```go
|
|
234
|
+
// MAL — estado global que rompe tests paralelos
|
|
235
|
+
var dbConnection *sql.DB
|
|
236
|
+
func init() {
|
|
237
|
+
dbConnection, _ = sql.Open("postgres", os.Getenv("DB_URL"))
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// BIEN — inyección por constructor
|
|
241
|
+
type App struct { db *sql.DB }
|
|
242
|
+
func NewApp(db *sql.DB) *App { return &App{db: db} }
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Interfaz definida por el productor, no el consumidor
|
|
246
|
+
|
|
247
|
+
```go
|
|
248
|
+
// MAL — el paquete "pedidos" define una interfaz grande que
|
|
249
|
+
// obliga a los consumidores a implementar todo
|
|
250
|
+
package pedidos
|
|
251
|
+
type Repositorio interface { /* 8 métodos */ }
|
|
252
|
+
|
|
253
|
+
// BIEN — cada consumidor define la interfaz mínima que necesita
|
|
254
|
+
package service
|
|
255
|
+
type pedidoLector interface { // solo lo que este servicio usa
|
|
256
|
+
Obtener(ctx context.Context, id uuid.UUID) (*Pedido, error)
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Panic para control de flujo normal
|
|
261
|
+
|
|
262
|
+
```go
|
|
263
|
+
// MAL
|
|
264
|
+
func obtenerConfig(key string) string {
|
|
265
|
+
v, ok := configs[key]
|
|
266
|
+
if !ok { panic("config no encontrada: " + key) }
|
|
267
|
+
return v
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// BIEN
|
|
271
|
+
func obtenerConfig(key string) (string, error) {
|
|
272
|
+
v, ok := configs[key]
|
|
273
|
+
if !ok { return "", fmt.Errorf("config no encontrada: %s", key) }
|
|
274
|
+
return v, nil
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Checklist de verificación
|
|
279
|
+
|
|
280
|
+
- [ ] Interfaces de máximo 3 métodos; interfaces más grandes divididas
|
|
281
|
+
- [ ] Interfaces definidas en el paquete consumidor, no en el productor
|
|
282
|
+
- [ ] Functional options para structs con más de 3 campos opcionales
|
|
283
|
+
- [ ] Sin variables globales mutables en paquetes de biblioteca
|
|
284
|
+
- [ ] init() solo para registro de drivers, no lógica de negocio
|
|
285
|
+
- [ ] Repository pattern separa interfaz (dominio) de implementación (infra)
|
|
286
|
+
- [ ] Generics usados para contenedores, no para simular herencia
|
|
287
|
+
|
|
288
|
+
## Gotchas / Errores comunes no obvios
|
|
289
|
+
|
|
290
|
+
**Functional options que modifican el struct después de la inicialización no tienen efecto si el struct fue copiado**: si `WithTimeout(5 * time.Second)` modifica un campo del struct por puntero pero la función `New()` retorna el struct por valor (no `*MiStruct`), la opción modifica una copia temporal. Fix: siempre retornar puntero `*T` en funciones `New()` que aceptan functional options, y asegurarse que las opciones reciben `*T`, no `T`.
|
|
291
|
+
|
|
292
|
+
**Interface implementada en puntero receptor pero usada con valor receiver causa error de compilación difícil de leer**: si `func (s *Servidor) ServeHTTP(...)` implementa `http.Handler`, pasar `Servidor{}` (valor) donde se espera `http.Handler` falla con "does not implement interface". El mensaje de error no indica el puntero claramente. Fix: siempre usar `&Servidor{}` cuando el método de interfaz está en el puntero receptor, o definir los métodos en value receiver si el tipo no necesita mutación.
|
|
293
|
+
|
|
294
|
+
**Embebido de interface en struct para "implementación parcial" causa panic en runtime**: embeber una interfaz en un struct para satisfacer el type system sin implementar todos los métodos `type MockRepo struct { RepositorioInterface }` compila pero llama nil en runtime si se invoca el método no implementado. Fix: implementar todos los métodos de la interfaz explícitamente, o usar un framework de mocking que genere el mock completo.
|
|
295
|
+
|
|
296
|
+
**`init()` con efectos secundarios globales rompe la testabilidad del paquete**: usar `init()` para registrar handlers, conectar a BD o inicializar loggers globales hace que importar el paquete en tests ejecute esos efectos. Fix: exponer una función `Setup()` o `New()` explícita que el llamador invoca cuando quiere los efectos secundarios; reservar `init()` solo para registro de drivers (`sql.Register`).
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
*Skill creado con swl:crear-skill el 2026-03-31. Versión 1.0.0.*
|