@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,235 @@
|
|
|
1
|
+
# Regla: Patrones de Arquitectura Swift / iOS
|
|
2
|
+
|
|
3
|
+
Esta regla define los patrones obligatorios para estructurar código Swift en iOS.
|
|
4
|
+
La orientación a protocolos, MVVM con `@Observable` y la concurrencia estructurada
|
|
5
|
+
son el estándar para proyectos nuevos con Swift 5.9+.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Protocol-oriented programming sobre herencia
|
|
10
|
+
|
|
11
|
+
Swift favorece composición de protocolos sobre jerarquías de herencia profundas.
|
|
12
|
+
Los protocolos definen capacidades; los tipos las adoptan independientemente.
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
// MAL — jerarquía de herencia que crece y se vuelve frágil
|
|
16
|
+
class Animal { func hacerSonido() {} }
|
|
17
|
+
class Perro: Animal { override func hacerSonido() { } }
|
|
18
|
+
class PerroGuardian: Perro { /* dependencia de toda la cadena */ }
|
|
19
|
+
|
|
20
|
+
// BIEN — protocolos que componen capacidades independientes
|
|
21
|
+
protocol Localizable {
|
|
22
|
+
var coordenadas: CLLocationCoordinate2D { get }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
protocol Notificable {
|
|
26
|
+
func enviarAlerta(_ mensaje: String) async
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
struct DispositivoIoT: Localizable, Notificable {
|
|
30
|
+
let coordenadas: CLLocationCoordinate2D
|
|
31
|
+
func enviarAlerta(_ mensaje: String) async { ... }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Dependency injection via protocolos
|
|
38
|
+
|
|
39
|
+
Las dependencias se declaran como protocolos. En producción se inyectan implementaciones
|
|
40
|
+
reales; en tests, mocks. Nunca instanciar dependencias dentro de un tipo.
|
|
41
|
+
|
|
42
|
+
```swift
|
|
43
|
+
// Protocolo en la capa de dominio
|
|
44
|
+
protocol PedidoRepository {
|
|
45
|
+
func obtenerPorId(_ id: UUID) async throws -> Pedido
|
|
46
|
+
func guardar(_ pedido: Pedido) async throws
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ViewModel recibe el protocolo — no sabe si es real o mock
|
|
50
|
+
@Observable
|
|
51
|
+
final class PedidoViewModel {
|
|
52
|
+
private let repositorio: PedidoRepository
|
|
53
|
+
|
|
54
|
+
init(repositorio: PedidoRepository) {
|
|
55
|
+
self.repositorio = repositorio
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// En produccion
|
|
60
|
+
let vm = PedidoViewModel(repositorio: PedidoRepositoryImpl(apiClient: client))
|
|
61
|
+
|
|
62
|
+
// En tests
|
|
63
|
+
let vm = PedidoViewModel(repositorio: MockPedidoRepository())
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## MVVM con @Observable (iOS 17+)
|
|
69
|
+
|
|
70
|
+
`@Observable` (macro de Swift 5.9+) reemplaza `ObservableObject` + `@Published`.
|
|
71
|
+
Elimina boilerplate y mejora el rendimiento de SwiftUI al rastrear solo las
|
|
72
|
+
propiedades realmente accedidas en cada vista.
|
|
73
|
+
|
|
74
|
+
```swift
|
|
75
|
+
// MAL — ObservableObject con @Published (iOS 16 y anterior)
|
|
76
|
+
class PedidoViewModel: ObservableObject {
|
|
77
|
+
@Published var pedidos: [Pedido] = []
|
|
78
|
+
@Published var isLoading = false
|
|
79
|
+
@Published var error: String?
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// BIEN — @Observable: mas limpio, mejor rendimiento de recomposicion
|
|
83
|
+
@Observable
|
|
84
|
+
final class PedidoViewModel {
|
|
85
|
+
var pedidos: [Pedido] = []
|
|
86
|
+
var isLoading = false
|
|
87
|
+
var error: String?
|
|
88
|
+
private let repositorio: PedidoRepository
|
|
89
|
+
|
|
90
|
+
init(repositorio: PedidoRepository) {
|
|
91
|
+
self.repositorio = repositorio
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func cargarPedidos() async {
|
|
95
|
+
isLoading = true
|
|
96
|
+
defer { isLoading = false }
|
|
97
|
+
do {
|
|
98
|
+
pedidos = try await repositorio.obtenerTodos()
|
|
99
|
+
} catch {
|
|
100
|
+
self.error = error.localizedDescription
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Vista — limpia, sin @StateObject/@ObservedObject
|
|
106
|
+
struct PantallaPedidos: View {
|
|
107
|
+
@State private var viewModel = PedidoViewModel(repositorio: ...)
|
|
108
|
+
|
|
109
|
+
var body: some View {
|
|
110
|
+
Group {
|
|
111
|
+
if viewModel.isLoading { ProgressView() }
|
|
112
|
+
else { ListaPedidos(pedidos: viewModel.pedidos) }
|
|
113
|
+
}
|
|
114
|
+
.task { await viewModel.cargarPedidos() }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## NavigationStack con NavigationPath para navegación programática
|
|
122
|
+
|
|
123
|
+
```swift
|
|
124
|
+
// MAL — NavigationView deprecado en iOS 16+
|
|
125
|
+
NavigationView {
|
|
126
|
+
NavigationLink("Ver detalle", destination: DetallePedidoView())
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// BIEN — NavigationStack con rutas tipadas
|
|
130
|
+
enum RutaApp: Hashable {
|
|
131
|
+
case detallePedido(UUID)
|
|
132
|
+
case editarPerfil
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
struct AppRootView: View {
|
|
136
|
+
@State private var ruta = NavigationPath()
|
|
137
|
+
|
|
138
|
+
var body: some View {
|
|
139
|
+
NavigationStack(path: $ruta) {
|
|
140
|
+
ListaPedidosView(onSeleccion: { id in
|
|
141
|
+
ruta.append(RutaApp.detallePedido(id))
|
|
142
|
+
})
|
|
143
|
+
.navigationDestination(for: RutaApp.self) { ruta in
|
|
144
|
+
switch ruta {
|
|
145
|
+
case .detallePedido(let id): DetallePedidoView(pedidoId: id)
|
|
146
|
+
case .editarPerfil: EditarPerfilView()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## SwiftUI: @State, @Binding, @Environment
|
|
157
|
+
|
|
158
|
+
```swift
|
|
159
|
+
// @State — estado local del componente, no se comparte hacia arriba
|
|
160
|
+
struct ContadorView: View {
|
|
161
|
+
@State private var contador = 0
|
|
162
|
+
var body: some View {
|
|
163
|
+
Button("Contar: \(contador)") { contador += 1 }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// @Binding — estado que viene del padre, el hijo puede modificarlo
|
|
168
|
+
struct SelectorFecha: View {
|
|
169
|
+
@Binding var fecha: Date
|
|
170
|
+
var body: some View {
|
|
171
|
+
DatePicker("Fecha", selection: $fecha, displayedComponents: .date)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// @Environment — dependencias globales inyectadas por SwiftUI
|
|
176
|
+
struct Vista: View {
|
|
177
|
+
@Environment(\.colorScheme) private var colorScheme
|
|
178
|
+
@Environment(GestorAutenticacion.self) private var auth
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Ejemplo: Massive ViewController vs MVVM
|
|
185
|
+
|
|
186
|
+
```swift
|
|
187
|
+
// MAL — UIViewController con 500+ líneas que hace todo
|
|
188
|
+
class PedidosViewController: UIViewController {
|
|
189
|
+
private var pedidos: [Pedido] = []
|
|
190
|
+
|
|
191
|
+
override func viewDidLoad() {
|
|
192
|
+
super.viewDidLoad()
|
|
193
|
+
URLSession.shared.dataTask(with: url) { data, _, error in
|
|
194
|
+
guard let data = data else { return }
|
|
195
|
+
self.pedidos = try! JSONDecoder().decode([Pedido].self, from: data)
|
|
196
|
+
DispatchQueue.main.async { self.tableView.reloadData() }
|
|
197
|
+
}.resume()
|
|
198
|
+
}
|
|
199
|
+
// ... 400 líneas más de UITableViewDataSource, lógica de negocio, formato, etc.
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// BIEN — MVVM con responsabilidades separadas
|
|
203
|
+
@Observable
|
|
204
|
+
final class PedidosViewModel {
|
|
205
|
+
private(set) var pedidos: [Pedido] = []
|
|
206
|
+
private(set) var isLoading = false
|
|
207
|
+
private let repositorio: PedidoRepository
|
|
208
|
+
|
|
209
|
+
func cargar() async {
|
|
210
|
+
isLoading = true
|
|
211
|
+
defer { isLoading = false }
|
|
212
|
+
pedidos = (try? await repositorio.obtenerTodos()) ?? []
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
struct PedidosView: View {
|
|
217
|
+
@State private var vm = PedidosViewModel(repositorio: PedidoRepositoryImpl())
|
|
218
|
+
var body: some View {
|
|
219
|
+
List(vm.pedidos) { pedido in FilaPedido(pedido: pedido) }
|
|
220
|
+
.task { await vm.cargar() }
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Checklist de patrones Swift antes de abrir PR
|
|
228
|
+
|
|
229
|
+
- [ ] Dependencias declaradas como protocolos, inyectadas en el inicializador
|
|
230
|
+
- [ ] ViewModels usan `@Observable` (iOS 17+) o `ObservableObject` (iOS 16-)
|
|
231
|
+
- [ ] Sin lógica de negocio en vistas SwiftUI (va en ViewModel o use case)
|
|
232
|
+
- [ ] Navegación con `NavigationStack` y rutas tipadas
|
|
233
|
+
- [ ] Concurrencia con `async/await`; actores para estado compartido
|
|
234
|
+
- [ ] Sin `Massive ViewController`: UIKit con MVVM si se usa UIKit
|
|
235
|
+
- [ ] Protocolos para composicion de capacidades, no herencia profunda
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Regla: Seguridad en Swift / iOS
|
|
2
|
+
|
|
3
|
+
Esta regla es OBLIGATORIA para todo código Swift en iOS.
|
|
4
|
+
iOS tiene mecanismos de seguridad de primera clase — el error más común es no usarlos
|
|
5
|
+
y recurrir a soluciones inseguras por conveniencia (UserDefaults para tokens, HTTP sin ATS).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Keychain Services para secretos: nunca UserDefaults
|
|
10
|
+
|
|
11
|
+
`UserDefaults` es un plist sin cifrado. Cualquier proceso con acceso al sandbox
|
|
12
|
+
puede leerlo. Los secretos (tokens, credenciales, claves privadas) van en Keychain.
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
// MAL — token en texto plano
|
|
16
|
+
UserDefaults.standard.set(accessToken, forKey: "access_token")
|
|
17
|
+
|
|
18
|
+
// BIEN — Keychain con accesibilidad adecuada
|
|
19
|
+
import Security
|
|
20
|
+
|
|
21
|
+
struct KeychainManager {
|
|
22
|
+
static func guardar(_ valor: String, para clave: String) throws {
|
|
23
|
+
let data = Data(valor.utf8)
|
|
24
|
+
let query: [String: Any] = [
|
|
25
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
26
|
+
kSecAttrAccount as String: clave,
|
|
27
|
+
kSecValueData as String: data,
|
|
28
|
+
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
|
|
29
|
+
]
|
|
30
|
+
SecItemDelete(query as CFDictionary)
|
|
31
|
+
let estado = SecItemAdd(query as CFDictionary, nil)
|
|
32
|
+
guard estado == errSecSuccess else {
|
|
33
|
+
throw KeychainError.escrituraFallida(estado)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static func obtener(_ clave: String) throws -> String? {
|
|
38
|
+
let query: [String: Any] = [
|
|
39
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
40
|
+
kSecAttrAccount as String: clave,
|
|
41
|
+
kSecReturnData as String: true,
|
|
42
|
+
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
43
|
+
]
|
|
44
|
+
var resultado: CFTypeRef?
|
|
45
|
+
let estado = SecItemCopyMatching(query as CFDictionary, &resultado)
|
|
46
|
+
guard estado == errSecSuccess, let data = resultado as? Data else { return nil }
|
|
47
|
+
return String(data: data, encoding: .utf8)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Usar `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` para datos que no deben
|
|
53
|
+
sincronizarse con iCloud Keychain ni estar disponibles cuando el dispositivo está bloqueado.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## App Transport Security (ATS) siempre habilitado
|
|
58
|
+
|
|
59
|
+
ATS fuerza conexiones HTTPS. No desactivarlo en producción. Nunca.
|
|
60
|
+
|
|
61
|
+
```xml
|
|
62
|
+
<!-- Info.plist — CORRECTO: ATS habilitado por defecto -->
|
|
63
|
+
<!-- No se necesita ningún key de NSAppTransportSecurity para el caso normal -->
|
|
64
|
+
|
|
65
|
+
<!-- MAL — desactivar ATS completamente -->
|
|
66
|
+
<key>NSAppTransportSecurity</key>
|
|
67
|
+
<dict>
|
|
68
|
+
<key>NSAllowsArbitraryLoads</key>
|
|
69
|
+
<true/>
|
|
70
|
+
</dict>
|
|
71
|
+
|
|
72
|
+
<!-- ACEPTABLE — excepción para un dominio específico con justificación documentada -->
|
|
73
|
+
<key>NSAppTransportSecurity</key>
|
|
74
|
+
<dict>
|
|
75
|
+
<key>NSExceptionDomains</key>
|
|
76
|
+
<dict>
|
|
77
|
+
<key>legacy-api.empresa.com</key>
|
|
78
|
+
<dict>
|
|
79
|
+
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
|
80
|
+
<true/>
|
|
81
|
+
</dict>
|
|
82
|
+
</dict>
|
|
83
|
+
</dict>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Si se necesita una excepción para la App Store, Apple requiere justificación.
|
|
87
|
+
Documentar en el ADR por qué el dominio no puede usar HTTPS.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Certificate Pinning con URLSession
|
|
92
|
+
|
|
93
|
+
```swift
|
|
94
|
+
// BIEN — delegate de URLSession para validar el certificado
|
|
95
|
+
final class PinningURLSessionDelegate: NSObject, URLSessionDelegate {
|
|
96
|
+
private let hashesEsperados: Set<String>
|
|
97
|
+
|
|
98
|
+
init(hashesEsperados: Set<String>) {
|
|
99
|
+
self.hashesEsperados = hashesEsperados
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
func urlSession(
|
|
103
|
+
_ session: URLSession,
|
|
104
|
+
didReceive challenge: URLAuthenticationChallenge,
|
|
105
|
+
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
|
|
106
|
+
) {
|
|
107
|
+
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
|
|
108
|
+
let serverTrust = challenge.protectionSpace.serverTrust,
|
|
109
|
+
let certificado = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
|
|
110
|
+
completionHandler(.cancelAuthenticationChallenge, nil)
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let dataPublicKey = SecCertificateCopyData(certificado) as Data
|
|
115
|
+
let hashActual = SHA256.hash(data: dataPublicKey)
|
|
116
|
+
.map { String(format: "%02x", $0) }.joined()
|
|
117
|
+
|
|
118
|
+
if hashesEsperados.contains(hashActual) {
|
|
119
|
+
completionHandler(.useCredential, URLCredential(trust: serverTrust))
|
|
120
|
+
} else {
|
|
121
|
+
completionHandler(.cancelAuthenticationChallenge, nil)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Uso
|
|
127
|
+
let session = URLSession(
|
|
128
|
+
configuration: .default,
|
|
129
|
+
delegate: PinningURLSessionDelegate(hashesEsperados: ["abc123...", "def456..."]),
|
|
130
|
+
delegateQueue: nil
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Incluir siempre al menos dos hashes (certificado actual + respaldo) para permitir
|
|
135
|
+
rotación sin dejar la app sin servicio.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Data Protection API para archivos sensibles
|
|
140
|
+
|
|
141
|
+
```swift
|
|
142
|
+
// BIEN — archivos con protección máxima: solo accesibles cuando desbloqueado
|
|
143
|
+
func guardarArchivoSeguro(datos: Data, nombre: String) throws {
|
|
144
|
+
let url = FileManager.default
|
|
145
|
+
.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
|
146
|
+
.appendingPathComponent(nombre)
|
|
147
|
+
|
|
148
|
+
try datos.write(to: url, options: [.completeFileProtection])
|
|
149
|
+
// .completeFileProtection = solo accesible con dispositivo desbloqueado
|
|
150
|
+
// .completeFileProtectionUnlessOpen = accesible mientras el archivo está abierto
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Verificar en la entitlements que `Data Protection` está en `NSFileProtectionComplete`.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Autenticación biométrica con LocalAuthentication
|
|
159
|
+
|
|
160
|
+
```swift
|
|
161
|
+
import LocalAuthentication
|
|
162
|
+
|
|
163
|
+
func autenticarConBiometria() async -> Bool {
|
|
164
|
+
let contexto = LAContext()
|
|
165
|
+
var error: NSError?
|
|
166
|
+
|
|
167
|
+
guard contexto.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
|
|
168
|
+
// Biometría no disponible — ofrecer PIN como alternativa
|
|
169
|
+
return await autenticarConPIN()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
do {
|
|
173
|
+
return try await contexto.evaluatePolicy(
|
|
174
|
+
.deviceOwnerAuthenticationWithBiometrics,
|
|
175
|
+
localizedReason: "Confirma tu identidad para continuar"
|
|
176
|
+
)
|
|
177
|
+
} catch {
|
|
178
|
+
// No loguear el tipo de error LAError — puede revelar información de intentos fallidos
|
|
179
|
+
return false
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Usar `.deviceOwnerAuthentication` (biometría O PIN) en lugar de solo biometría
|
|
185
|
+
para garantizar que el usuario siempre puede autenticarse aunque la biometría falle.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## No hardcodear API keys ni secretos
|
|
190
|
+
|
|
191
|
+
```swift
|
|
192
|
+
// MAL — la key queda en el binario y es extraíble con strings o Hopper
|
|
193
|
+
let apiKey = "sk-prod-abc123def456"
|
|
194
|
+
let urlBase = "https://api.servicio.com?key=\(apiKey)"
|
|
195
|
+
|
|
196
|
+
// BIEN — la key se obtiene del servidor tras autenticacion del usuario
|
|
197
|
+
// El cliente recibe un token de sesión, el servidor maneja las API keys de terceros
|
|
198
|
+
struct ConfiguracionRemota {
|
|
199
|
+
var endpointApiGateway: URL
|
|
200
|
+
// Sin API keys de terceros aquí
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Para SDKs que requieren clave en el cliente (ej: Stripe publishable key, Firebase):
|
|
205
|
+
- Usar Xcode Build Settings con `xcconfig` no versionado para distintos entornos
|
|
206
|
+
- Nunca en el código fuente directamente
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Validación de deep links y universal links
|
|
211
|
+
|
|
212
|
+
```swift
|
|
213
|
+
// BIEN — validar scheme, host y parámetros antes de procesar
|
|
214
|
+
func application(
|
|
215
|
+
_ app: UIApplication,
|
|
216
|
+
open url: URL,
|
|
217
|
+
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
|
|
218
|
+
) -> Bool {
|
|
219
|
+
guard url.scheme == "miapp",
|
|
220
|
+
url.host == "pedidos",
|
|
221
|
+
let componentes = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
|
222
|
+
let parametroId = componentes.queryItems?.first(where: { $0.name == "id" })?.value,
|
|
223
|
+
let pedidoId = UUID(uuidString: parametroId) else {
|
|
224
|
+
// Log del intento inválido para auditoría, pero sin detalles del URL
|
|
225
|
+
logger.warning("Deep link inválido recibido")
|
|
226
|
+
return false
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
navegarADetallePedido(id: pedidoId)
|
|
230
|
+
return true
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Registrar intentos de deep links inválidos para detectar intentos de explotación.
|
|
235
|
+
NUNCA usar los parámetros del URL directamente sin validar el tipo y el formato.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Checklist de seguridad Swift antes de abrir PR
|
|
240
|
+
|
|
241
|
+
- [ ] Sin secretos ni tokens en `UserDefaults` — usar Keychain
|
|
242
|
+
- [ ] ATS habilitado: sin `NSAllowsArbitraryLoads` en producción
|
|
243
|
+
- [ ] Certificate pinning configurado con hash de respaldo
|
|
244
|
+
- [ ] Archivos sensibles con `Data Protection (.completeFileProtection)`
|
|
245
|
+
- [ ] Autenticación biométrica usa `LocalAuthentication` framework
|
|
246
|
+
- [ ] Sin API keys hardcodeadas en el código fuente
|
|
247
|
+
- [ ] Deep links y universal links validados en scheme, host y parámetros
|
|
248
|
+
- [ ] Code signing con provisioning profiles correctos para el ambiente
|