@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,260 @@
|
|
|
1
|
+
# Active Record Avanzado
|
|
2
|
+
|
|
3
|
+
Referencia de patrones avanzados de Active Record para Rails 7+.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Concerns — comportamiento compartido entre modelos
|
|
8
|
+
|
|
9
|
+
Los concerns encapsulan lógica reutilizable que múltiples modelos comparten.
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
# app/models/concerns/trackable.rb
|
|
13
|
+
module Trackable
|
|
14
|
+
extend ActiveSupport::Concern
|
|
15
|
+
|
|
16
|
+
included do
|
|
17
|
+
belongs_to :created_by_user, class_name: 'User', optional: true
|
|
18
|
+
belongs_to :updated_by_user, class_name: 'User', optional: true
|
|
19
|
+
|
|
20
|
+
before_create { self.created_by_user = Current.user }
|
|
21
|
+
before_save { self.updated_by_user = Current.user }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# app/models/concerns/searchable.rb
|
|
26
|
+
module Searchable
|
|
27
|
+
extend ActiveSupport::Concern
|
|
28
|
+
|
|
29
|
+
included do
|
|
30
|
+
scope :buscar, ->(termino) {
|
|
31
|
+
where("titulo ILIKE :q OR descripcion ILIKE :q", q: "%#{sanitize_sql_like(termino)}%")
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Uso en modelo
|
|
37
|
+
class Post < ApplicationRecord
|
|
38
|
+
include Trackable
|
|
39
|
+
include Searchable
|
|
40
|
+
end
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Regla**: usar `sanitize_sql_like` siempre que el término de búsqueda viene del usuario.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Counter Cache — contadores automáticos
|
|
48
|
+
|
|
49
|
+
Evita `SELECT COUNT(*)` repetidos en vistas de listas.
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
# En la asociación (migration y modelo)
|
|
53
|
+
class Comment < ApplicationRecord
|
|
54
|
+
belongs_to :post, counter_cache: true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Migración para agregar la columna
|
|
58
|
+
class AddCommentsCountToPosts < ActiveRecord::Migration[7.1]
|
|
59
|
+
def change
|
|
60
|
+
add_column :posts, :comments_count, :integer, default: 0, null: false
|
|
61
|
+
# Inicializar contadores en datos existentes
|
|
62
|
+
Post.find_each { |p| Post.reset_counters(p.id, :comments) }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Uso — no ejecuta query adicional
|
|
67
|
+
post.comments_count # lee la columna, no hace COUNT(*)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Touch**: `belongs_to :post, counter_cache: true, touch: true` actualiza `updated_at` del post al crear/eliminar un comentario — útil para cache HTTP.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Optimistic Locking con lock_version
|
|
75
|
+
|
|
76
|
+
Previene actualizaciones concurrentes que sobreescriben datos.
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
# Migración
|
|
80
|
+
add_column :posts, :lock_version, :integer, default: 0
|
|
81
|
+
|
|
82
|
+
# Rails lo activa automáticamente al existir la columna.
|
|
83
|
+
# Cuando dos usuarios editan el mismo registro:
|
|
84
|
+
post_a = Post.find(1) # lock_version = 5
|
|
85
|
+
post_b = Post.find(1) # lock_version = 5
|
|
86
|
+
|
|
87
|
+
post_a.update!(titulo: "Versión A") # lock_version → 6, OK
|
|
88
|
+
post_b.update!(titulo: "Versión B") # lanza ActiveRecord::StaleObjectError
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
# En el controller, rescatar y reintentar
|
|
93
|
+
def update
|
|
94
|
+
@post.update!(post_params)
|
|
95
|
+
rescue ActiveRecord::StaleObjectError
|
|
96
|
+
@post.reload
|
|
97
|
+
flash.now[:alert] = 'Otro usuario modificó este registro. Revisa los cambios.'
|
|
98
|
+
render :edit, status: :conflict
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Soft Delete con paranoia / discard
|
|
105
|
+
|
|
106
|
+
Dos opciones idiomáticas:
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
# Opción A: gem 'discard' (más simple, recomendada para Rails 7+)
|
|
110
|
+
class Post < ApplicationRecord
|
|
111
|
+
include Discard::Model
|
|
112
|
+
default_scope -> { kept }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
post.discard # marca deleted_at, no elimina de BD
|
|
116
|
+
post.undiscard # restaura
|
|
117
|
+
|
|
118
|
+
# Migración necesaria
|
|
119
|
+
add_column :posts, :discarded_at, :datetime
|
|
120
|
+
add_index :posts, :discarded_at
|
|
121
|
+
|
|
122
|
+
# Opción B: gem 'paranoia' (más funcionalidad, más magia)
|
|
123
|
+
class Post < ApplicationRecord
|
|
124
|
+
acts_as_paranoid
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
post.destroy # soft delete (sets deleted_at)
|
|
128
|
+
post.really_destroy! # elimina permanentemente
|
|
129
|
+
Post.with_deleted # incluye registros eliminados
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Single Table Inheritance (STI)
|
|
135
|
+
|
|
136
|
+
**Cuándo usar STI**: subtipos con comportamiento distinto pero mismos atributos base.
|
|
137
|
+
**Cuándo NO**: subtipos con atributos muy distintos → usar polimorfismo o tablas separadas.
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
# Una sola tabla "vehicles" con columna "type"
|
|
141
|
+
class Vehicle < ApplicationRecord
|
|
142
|
+
validates :marca, presence: true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
class Car < Vehicle
|
|
146
|
+
validates :puertas, numericality: { greater_than: 0 }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
class Truck < Vehicle
|
|
150
|
+
validates :capacidad_toneladas, numericality: { greater_than: 0 }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Rails almacena el nombre de clase en la columna "type"
|
|
154
|
+
Car.create!(marca: "Toyota", puertas: 4)
|
|
155
|
+
Vehicle.all # devuelve Cars y Trucks
|
|
156
|
+
Car.all # solo Cars
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Anti-patrón**: columnas `null: true` en exceso por diferencias de atributos → señal de que STI no es la solución correcta.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Bulk Operations (Rails 6+)
|
|
164
|
+
|
|
165
|
+
Para insertar o actualizar grandes volúmenes sin instanciar modelos.
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
# insert_all — ignora duplicados por defecto
|
|
169
|
+
Post.insert_all([
|
|
170
|
+
{ titulo: "Post 1", status: "publicado", author_id: 1 },
|
|
171
|
+
{ titulo: "Post 2", status: "borrador", author_id: 2 }
|
|
172
|
+
])
|
|
173
|
+
|
|
174
|
+
# upsert_all — actualiza si existe conflicto en la PK
|
|
175
|
+
Post.upsert_all(
|
|
176
|
+
registros,
|
|
177
|
+
unique_by: :titulo,
|
|
178
|
+
update_only: [:status, :updated_at]
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# NOTA: insert_all/upsert_all NO ejecutan callbacks ni validaciones.
|
|
182
|
+
# Usar solo para importaciones masivas donde el origen es confiable.
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## ActiveRecord::Encryption (Rails 7+)
|
|
188
|
+
|
|
189
|
+
Cifrado transparente de columnas sensibles sin cambios en el código de negocio.
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
# config/application.rb
|
|
193
|
+
config.active_record.encryption.primary_key = Rails.application.credentials.ar_encryption[:primary_key]
|
|
194
|
+
config.active_record.encryption.deterministic_key = Rails.application.credentials.ar_encryption[:deterministic_key]
|
|
195
|
+
config.active_record.encryption.key_derivation_salt = Rails.application.credentials.ar_encryption[:salt]
|
|
196
|
+
|
|
197
|
+
# Modelo
|
|
198
|
+
class User < ApplicationRecord
|
|
199
|
+
encrypts :numero_tarjeta
|
|
200
|
+
encrypts :email, deterministic: true # permite búsquedas exactas
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Uso — transparente para el código
|
|
204
|
+
user.email # devuelve valor descifrado
|
|
205
|
+
User.find_by(email: "a@b.com") # funciona por ser deterministic: true
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Regla**: usar `deterministic: true` solo cuando necesitas buscar por el campo. Sin `deterministic`, el cifrado usa nonce aleatorio (más seguro).
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Callbacks — cuándo usar y anti-patrones
|
|
213
|
+
|
|
214
|
+
**Callbacks válidos:**
|
|
215
|
+
- `before_validation`: normalizar datos (`strip`, `downcase`)
|
|
216
|
+
- `before_save`: derivar valores calculados del mismo modelo
|
|
217
|
+
- `after_initialize`: valores default complejos
|
|
218
|
+
|
|
219
|
+
**Callbacks a evitar:**
|
|
220
|
+
```ruby
|
|
221
|
+
# MAL — request HTTP en callback (bloquea la transacción DB)
|
|
222
|
+
after_create :notificar_por_email # si el mailer falla, la TX puede quedar abierta
|
|
223
|
+
|
|
224
|
+
# BIEN — delegar a un job
|
|
225
|
+
after_create_commit -> { NotificarJob.perform_later(id) }
|
|
226
|
+
|
|
227
|
+
# MAL — lógica de negocio en callback (difícil de testear y reutilizar)
|
|
228
|
+
before_save :calcular_precio_total_con_impuestos_y_descuentos
|
|
229
|
+
|
|
230
|
+
# BIEN — service object que llama al modelo con el valor ya calculado
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Query cache y EXPLAIN
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
# Ver el plan de ejecución SQL de una query
|
|
239
|
+
Post.includes(:author).where(status: :publicado).explain
|
|
240
|
+
# Imprime EXPLAIN ANALYZE en PostgreSQL
|
|
241
|
+
|
|
242
|
+
# Query cache — Rails cachea queries idénticas dentro de la misma request
|
|
243
|
+
# Forzar recarga cuando el cache interfiere en tests:
|
|
244
|
+
ActiveRecord::Base.connection.clear_query_cache
|
|
245
|
+
|
|
246
|
+
# Índices que casi siempre se necesitan
|
|
247
|
+
add_index :posts, :status
|
|
248
|
+
add_index :posts, [:author_id, :created_at] # índice compuesto para order frecuente
|
|
249
|
+
add_index :posts, :discarded_at # si usas soft delete
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Referencias externas
|
|
255
|
+
|
|
256
|
+
- [Active Record Associations — Rails Guides](https://guides.rubyonrails.org/association_basics.html)
|
|
257
|
+
- [Active Record Query Interface](https://guides.rubyonrails.org/active_record_querying.html)
|
|
258
|
+
- [Active Record Encryption](https://guides.rubyonrails.org/active_record_encryption.html)
|
|
259
|
+
- [gem discard](https://github.com/jhawthorn/discard)
|
|
260
|
+
- [gem bullet (detección N+1)](https://github.com/flyerhzm/bullet)
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Hotwire: Turbo y Stimulus
|
|
2
|
+
|
|
3
|
+
Referencia completa de Hotwire para Rails 7+: Turbo Drive, Turbo Frames,
|
|
4
|
+
Turbo Streams, Stimulus y Action Cable.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Turbo Drive — navegación sin page reload
|
|
9
|
+
|
|
10
|
+
Turbo Drive intercepta clics en `<a>` y envíos de `<form>` para hacer
|
|
11
|
+
fetch en segundo plano y reemplazar solo `<body>`. Está activo por defecto.
|
|
12
|
+
|
|
13
|
+
```erb
|
|
14
|
+
<%# Deshabilitar Turbo Drive en un enlace específico %>
|
|
15
|
+
<%= link_to "Descargar PDF", reporte_path, data: { turbo: false } %>
|
|
16
|
+
|
|
17
|
+
<%# Deshabilitar en un formulario que redirecciona a URL externa %>
|
|
18
|
+
<%= form_with url: pago_externo_path, data: { turbo: false } do |f| %>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Regla**: no deshabilitar Turbo Drive globalmente. Si hay conflictos, resolver
|
|
22
|
+
usando `data-turbo="false"` selectivamente.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Turbo Frames — actualización parcial de la página
|
|
27
|
+
|
|
28
|
+
Un Turbo Frame delimita una región de la página. Los enlaces y formularios
|
|
29
|
+
dentro del frame solo actualizan ese frame, no toda la página.
|
|
30
|
+
|
|
31
|
+
```erb
|
|
32
|
+
<%# app/views/posts/index.html.erb %>
|
|
33
|
+
<%= turbo_frame_tag "lista-posts" do %>
|
|
34
|
+
<%= render @posts %>
|
|
35
|
+
<%= link_to "Cargar más", posts_path(page: @proxima_pagina) %>
|
|
36
|
+
<% end %>
|
|
37
|
+
|
|
38
|
+
<%# El controller debe devolver la misma etiqueta en la respuesta %>
|
|
39
|
+
<%# app/views/posts/index.html.erb (respuesta al frame) %>
|
|
40
|
+
<%= turbo_frame_tag "lista-posts" do %>
|
|
41
|
+
<%= render @posts %>
|
|
42
|
+
<% end %>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
# Edición inline sin modal — el formulario de edición está en su propio frame
|
|
47
|
+
# app/views/posts/_post.html.erb
|
|
48
|
+
<%= turbo_frame_tag dom_id(post) do %>
|
|
49
|
+
<h2><%= post.titulo %></h2>
|
|
50
|
+
<%= link_to "Editar", edit_post_path(post) %>
|
|
51
|
+
<% end %>
|
|
52
|
+
|
|
53
|
+
# app/views/posts/edit.html.erb
|
|
54
|
+
<%= turbo_frame_tag dom_id(@post) do %>
|
|
55
|
+
<%= render "form", post: @post %>
|
|
56
|
+
<% end %>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Regla**: el `id` del `turbo_frame_tag` en la respuesta debe coincidir exactamente
|
|
60
|
+
con el del frame que hizo la solicitud. Si no coincide, Turbo lo descarta.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Turbo Streams desde controller
|
|
65
|
+
|
|
66
|
+
Para actualizar múltiples partes de la página en una sola respuesta.
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
# app/controllers/posts_controller.rb
|
|
70
|
+
def create
|
|
71
|
+
@post = Post.new(post_params.merge(author: current_user))
|
|
72
|
+
|
|
73
|
+
respond_to do |format|
|
|
74
|
+
if @post.save
|
|
75
|
+
format.turbo_stream
|
|
76
|
+
format.html { redirect_to @post }
|
|
77
|
+
else
|
|
78
|
+
format.turbo_stream do
|
|
79
|
+
render turbo_stream: turbo_stream.replace(
|
|
80
|
+
"new_post_form",
|
|
81
|
+
partial: "posts/form",
|
|
82
|
+
locals: { post: @post }
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
format.html { render :new, status: :unprocessable_entity }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```erb
|
|
92
|
+
<%# app/views/posts/create.turbo_stream.erb %>
|
|
93
|
+
<%= turbo_stream.prepend "lista-posts", partial: "posts/post", locals: { post: @post } %>
|
|
94
|
+
<%= turbo_stream.update "new_post_form", partial: "posts/form", locals: { post: Post.new } %>
|
|
95
|
+
<%= turbo_stream.update "posts-count", @posts_count %>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Acciones disponibles**: `append`, `prepend`, `replace`, `update`, `remove`,
|
|
99
|
+
`before`, `after`.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Turbo Streams desde jobs con Action Cable (broadcast)
|
|
104
|
+
|
|
105
|
+
Para actualizar la UI de múltiples usuarios en tiempo real.
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
# app/models/post.rb
|
|
109
|
+
class Post < ApplicationRecord
|
|
110
|
+
after_create_commit -> { broadcast_prepend_to "posts" }
|
|
111
|
+
after_update_commit -> { broadcast_replace_to "posts" }
|
|
112
|
+
after_destroy_commit -> { broadcast_remove_to "posts" }
|
|
113
|
+
|
|
114
|
+
# Con partial personalizado
|
|
115
|
+
after_create_commit -> {
|
|
116
|
+
broadcast_prepend_to "posts",
|
|
117
|
+
partial: "posts/post_card",
|
|
118
|
+
locals: { post: self }
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```erb
|
|
124
|
+
<%# En la vista que recibe los broadcasts %>
|
|
125
|
+
<%= turbo_stream_from "posts" %>
|
|
126
|
+
|
|
127
|
+
<div id="lista-posts">
|
|
128
|
+
<%= render @posts %>
|
|
129
|
+
</div>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
# Broadcast desde un job (para operaciones async)
|
|
134
|
+
class PublicarPostJob < ApplicationJob
|
|
135
|
+
def perform(post_id)
|
|
136
|
+
post = Post.find(post_id)
|
|
137
|
+
post.update!(status: :publicado)
|
|
138
|
+
Turbo::StreamsChannel.broadcast_replace_to(
|
|
139
|
+
"posts",
|
|
140
|
+
target: dom_id(post),
|
|
141
|
+
partial: "posts/post",
|
|
142
|
+
locals: { post: post }
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Stimulus — controllers de JavaScript
|
|
151
|
+
|
|
152
|
+
Stimulus conecta comportamiento JS a elementos HTML mediante atributos `data-*`.
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
// app/javascript/controllers/contador_controller.js
|
|
156
|
+
import { Controller } from "@hotwired/stimulus"
|
|
157
|
+
|
|
158
|
+
export default class extends Controller {
|
|
159
|
+
static targets = ["valor"]
|
|
160
|
+
static values = { inicio: { type: Number, default: 0 } }
|
|
161
|
+
|
|
162
|
+
connect() {
|
|
163
|
+
this.count = this.inicioValue
|
|
164
|
+
this.actualizar()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
incrementar() {
|
|
168
|
+
this.count++
|
|
169
|
+
this.actualizar()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
actualizar() {
|
|
173
|
+
this.valorTarget.textContent = this.count
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```erb
|
|
179
|
+
<%# En la vista %>
|
|
180
|
+
<div data-controller="contador" data-contador-inicio-value="5">
|
|
181
|
+
<span data-contador-target="valor"></span>
|
|
182
|
+
<button data-action="click->contador#incrementar">+1</button>
|
|
183
|
+
</div>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Reglas de Stimulus:**
|
|
187
|
+
- Un controller por responsabilidad (no acumular lógica no relacionada)
|
|
188
|
+
- `connect()` para setup, `disconnect()` para cleanup (event listeners externos)
|
|
189
|
+
- Usar `values` para pasar datos desde el servidor, no leer del DOM
|
|
190
|
+
- Preferir `targets` sobre `querySelector` para referencias a elementos
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Action Cable — canal completo
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
# app/channels/notificaciones_channel.rb
|
|
198
|
+
class NotificacionesChannel < ApplicationCable::Channel
|
|
199
|
+
def subscribed
|
|
200
|
+
stream_for current_user
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def unsubscribed
|
|
204
|
+
stop_all_streams
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# app/channels/application_cable/connection.rb
|
|
209
|
+
module ApplicationCable
|
|
210
|
+
class Connection < ActionCable::Connection::Base
|
|
211
|
+
identified_by :current_user
|
|
212
|
+
|
|
213
|
+
def connect
|
|
214
|
+
self.current_user = find_verified_user
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
private
|
|
218
|
+
|
|
219
|
+
def find_verified_user
|
|
220
|
+
if (verified = User.find_by(id: cookies.encrypted[:user_id]))
|
|
221
|
+
verified
|
|
222
|
+
else
|
|
223
|
+
reject_unauthorized_connection
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Broadcast desde cualquier parte del sistema
|
|
230
|
+
NotificacionesChannel.broadcast_to(
|
|
231
|
+
usuario,
|
|
232
|
+
{ tipo: "nueva_tarea", mensaje: "Te asignaron una tarea" }
|
|
233
|
+
)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
// app/javascript/controllers/notificaciones_controller.js
|
|
238
|
+
import { Controller } from "@hotwired/stimulus"
|
|
239
|
+
import consumer from "channels/consumer"
|
|
240
|
+
|
|
241
|
+
export default class extends Controller {
|
|
242
|
+
connect() {
|
|
243
|
+
this.subscription = consumer.subscriptions.create("NotificacionesChannel", {
|
|
244
|
+
received: (data) => this.mostrar(data)
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
disconnect() {
|
|
249
|
+
this.subscription.unsubscribe()
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
mostrar(data) {
|
|
253
|
+
// Actualizar UI con la notificación
|
|
254
|
+
console.info("Notificación:", data.mensaje)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Morphing con Turbo 8 (Rails 7.1+)
|
|
262
|
+
|
|
263
|
+
Turbo 8 introduce morphing: en lugar de reemplazar el DOM completo, hace un diff
|
|
264
|
+
inteligente que preserva el estado del cliente (scroll, focus, valores de input).
|
|
265
|
+
|
|
266
|
+
```ruby
|
|
267
|
+
# app/controllers/posts_controller.rb
|
|
268
|
+
def index
|
|
269
|
+
@posts = Post.includes(:author).publicados.recientes
|
|
270
|
+
# Turbo 8 hace morph del <body> en lugar de reemplazarlo completo
|
|
271
|
+
# No requiere configuración extra si las vistas tienen IDs estables en elementos clave
|
|
272
|
+
end
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```erb
|
|
276
|
+
<%# Forzar refresh completo de un frame específico (sin morph) %>
|
|
277
|
+
<%= turbo_frame_tag "estadisticas", refresh: :morph do %>
|
|
278
|
+
<%= render "estadisticas" %>
|
|
279
|
+
<% end %>
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Regla para morphing**: los elementos clave DEBEN tener `id` estable
|
|
283
|
+
(`dom_id(@post)` o equivalente). Sin `id`, Turbo no puede hacer el diff correctamente
|
|
284
|
+
y puede perder estado o duplicar elementos.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Referencias externas
|
|
289
|
+
|
|
290
|
+
- [Turbo Handbook](https://turbo.hotwired.dev/handbook/introduction)
|
|
291
|
+
- [Stimulus Handbook](https://stimulus.hotwired.dev/handbook/introduction)
|
|
292
|
+
- [Action Cable — Rails Guides](https://guides.rubyonrails.org/action_cable_overview.html)
|
|
293
|
+
- [Hotwire — repositorio oficial](https://github.com/hotwired/hotwire-rails)
|