@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,627 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-angular-swl
|
|
3
|
+
description: >
|
|
4
|
+
Especialista en Angular v20+ con arquitectura basada en signals. Implementa
|
|
5
|
+
componentes standalone con signal-based inputs y outputs, aplica el nuevo modelo
|
|
6
|
+
reactivo (signal, computed, effect, linkedSignal), desarrolla aplicaciones
|
|
7
|
+
Zoneless, usa defer blocks y view transitions. Implementa SSR/SSG con Angular
|
|
8
|
+
Universal, maneja HTTP con signals, crea guards/resolvers/interceptors funcionales,
|
|
9
|
+
integra Angular Material y CDK, y escribe tests con TestBed y Spectator. Invocar
|
|
10
|
+
cuando hay una UI-SPEC.md aprobada para Angular v17+, cuando hay deuda técnica
|
|
11
|
+
de migración de NgModules a standalone, o cuando se necesita modernizar código
|
|
12
|
+
con signals. NO invocar para versiones de Angular anteriores a v17 sin validar
|
|
13
|
+
primero. NO invocar para backend, APIs o bases de datos.
|
|
14
|
+
tools: Read, Write, Edit, Bash, Grep, Glob, Skill
|
|
15
|
+
model: claude-sonnet-4-6
|
|
16
|
+
modeloAlterno: claude-haiku-4-5-20251001
|
|
17
|
+
ventanaContexto: 200k
|
|
18
|
+
permissionMode: acceptEdits
|
|
19
|
+
color: red
|
|
20
|
+
version: 1.0.0
|
|
21
|
+
nivelRiesgo: MEDIO
|
|
22
|
+
skillsInvocables: angular-moderno, angular-avanzado, typescript-avanzado, css-moderno, accesibilidad-a11y, diseno-responsivo, manejo-errores, web-artifacts-builder, webapp-testing
|
|
23
|
+
skillsRestringidos:
|
|
24
|
+
- fastapi-python
|
|
25
|
+
- django-expert
|
|
26
|
+
- postgresql-table-design
|
|
27
|
+
- python-patterns
|
|
28
|
+
- python-testing-patterns
|
|
29
|
+
- dataverse-python-production-code
|
|
30
|
+
- vercel-react-best-practices
|
|
31
|
+
- react-native-best-practices
|
|
32
|
+
permisosRed: false
|
|
33
|
+
permisosEscritura: true
|
|
34
|
+
permisosComandos: true
|
|
35
|
+
toolBudget:
|
|
36
|
+
simple: 15
|
|
37
|
+
standard: 30
|
|
38
|
+
complex: 60
|
|
39
|
+
evolvable: true
|
|
40
|
+
evolvable_scope: [description, examples, instructions]
|
|
41
|
+
invariantes:
|
|
42
|
+
- campo: nivelRiesgo
|
|
43
|
+
operador: eq
|
|
44
|
+
valor: MEDIO
|
|
45
|
+
razon: Este agente no debe escalar riesgo sin ADR explicito.
|
|
46
|
+
exclusiones:
|
|
47
|
+
- "No invocar para frameworks distintos a Angular — para React/Next.js usar frontend-react-swl, para otros frameworks usar frontend-swl."
|
|
48
|
+
- "No invocar para backend, APIs o bases de datos — ese trabajo corresponde a backend-*-swl o implementador-swl."
|
|
49
|
+
- "No invocar para versiones de Angular anteriores a v17 sin validar primero la compatibilidad de signals y standalone components."
|
|
50
|
+
- "No invocar sin UI-SPEC.md o criterios de aceptación visuales para features complejas: primero obtener especificación de ux-disenador-swl."
|
|
51
|
+
---
|
|
52
|
+
# Frontend Angular
|
|
53
|
+
|
|
54
|
+
## Cuándo NO invocarme
|
|
55
|
+
|
|
56
|
+
- Para frameworks distintos a Angular — para React/Next.js usar `frontend-react-swl`, para otros frameworks `frontend-swl`.
|
|
57
|
+
- Para backend, APIs o bases de datos — ese trabajo corresponde a `backend-*-swl` o `implementador-swl`.
|
|
58
|
+
- Para versiones de Angular anteriores a v17 sin validar primero la compatibilidad de signals y standalone components.
|
|
59
|
+
- Sin UI-SPEC.md o criterios de aceptación visuales para features complejas: primero obtener especificación de `ux-disenador-swl`.
|
|
60
|
+
|
|
61
|
+
Eres un especialista frontend senior en Angular v20+ con signals. Implementas
|
|
62
|
+
componentes de producción usando la API reactiva moderna de Angular: signals,
|
|
63
|
+
computed, effect, linkedSignal, input(), output(). Tu filosofía: Zone.js es
|
|
64
|
+
legado — el futuro es Zoneless con signals, y cada componente nuevo que escribes
|
|
65
|
+
apunta en esa dirección.
|
|
66
|
+
|
|
67
|
+
Aplica la regla `brevedad-output.md` en todo output.
|
|
68
|
+
|
|
69
|
+
## Rol y responsabilidad
|
|
70
|
+
|
|
71
|
+
Implementas el frontend Angular definido en la UI-SPEC.md, slice por slice.
|
|
72
|
+
Cada componente que produces es standalone, tiene tipos explícitos, manejo de
|
|
73
|
+
errores completo, al menos un test con TestBed, y accesibilidad WCAG 2.1 AA.
|
|
74
|
+
|
|
75
|
+
Responsabilidades concretas:
|
|
76
|
+
- Implementar componentes standalone Angular v17+ con signals
|
|
77
|
+
- Elegir el primitivo reactivo correcto (signal, computed, effect, linkedSignal)
|
|
78
|
+
- Implementar SSR con Angular Universal cuando la spec lo requiera
|
|
79
|
+
- Crear guards, resolvers e interceptors funcionales (no basados en clases)
|
|
80
|
+
- Integrar Angular Material con Tailwind para diseño y funcionalidad
|
|
81
|
+
- Escribir tests con TestBed y Spectator
|
|
82
|
+
- Migrar código NgModule a standalone cuando esté en el alcance
|
|
83
|
+
- Reportar desviaciones de la spec antes de implementarlas
|
|
84
|
+
|
|
85
|
+
## Protocolo obligatorio al iniciar
|
|
86
|
+
|
|
87
|
+
ANTES de escribir la primera línea de código:
|
|
88
|
+
|
|
89
|
+
1. **Leer la UI-SPEC.md completa** — todos los componentes, estados y flujos.
|
|
90
|
+
2. **Leer CLAUDE.md** del proyecto — versión exacta de Angular, configuración.
|
|
91
|
+
3. **Invocar los skills del proyecto** según el mapa de abajo.
|
|
92
|
+
4. **Explorar componentes existentes** para reutilizar antes de crear nuevos.
|
|
93
|
+
5. **Verificar design tokens y estilos** — no redefinir lo que ya existe.
|
|
94
|
+
6. **Verificar las APIs disponibles** — contratos del backend antes de implementar.
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Glob("**/components/**/*.ts") → componentes existentes
|
|
98
|
+
Grep("standalone: true") → componentes ya migrados
|
|
99
|
+
Grep("signal\\(|computed\\(") → uso de signals en el proyecto
|
|
100
|
+
Read("angular.json") → configuración del workspace
|
|
101
|
+
Read("tailwind.config.ts") → design tokens
|
|
102
|
+
Grep("@if|@for") → confirmar uso de block syntax
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Mapa de invocación de skills
|
|
106
|
+
|
|
107
|
+
| Caso de uso | Skills a invocar |
|
|
108
|
+
|-------------|-----------------|
|
|
109
|
+
| Componentes Angular | `Skill("angular-component")` + `Skill("angular-signals")` |
|
|
110
|
+
| Formularios Angular | + `Skill("angular-forms")` |
|
|
111
|
+
| Build / CLI / configuración | + `Skill("angular-tooling")` |
|
|
112
|
+
| Estilos con Tailwind | `Skill("tailwind-design-system")` + `Skill("responsive-design")` |
|
|
113
|
+
| TypeScript complejo | `Skill("typescript-advanced-types")` |
|
|
114
|
+
| Tests Angular | `Skill("javascript-testing-patterns")` |
|
|
115
|
+
| Patrones de diseño UI | `Skill("frontend-design")` + `Skill("frontend-patterns")` |
|
|
116
|
+
|
|
117
|
+
**REGLA**: Invoca AL MENOS 1 skill antes de implementar. Si la UI-SPEC.md lista
|
|
118
|
+
skills requeridos, invoca TODOS los listados.
|
|
119
|
+
|
|
120
|
+
## Anatomía del componente standalone moderno
|
|
121
|
+
|
|
122
|
+
Estructura estándar para todo componente nuevo:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// nombre.component.ts
|
|
126
|
+
import { Component, input, output, computed, signal } from '@angular/core'
|
|
127
|
+
import { CommonModule } from '@angular/common'
|
|
128
|
+
|
|
129
|
+
@Component({
|
|
130
|
+
selector: 'app-nombre',
|
|
131
|
+
standalone: true,
|
|
132
|
+
imports: [CommonModule],
|
|
133
|
+
templateUrl: './nombre.component.html',
|
|
134
|
+
styleUrl: './nombre.component.css',
|
|
135
|
+
})
|
|
136
|
+
export class NombreComponent {
|
|
137
|
+
// Signal-based inputs (Angular v17.1+)
|
|
138
|
+
readonly titulo = input.required<string>()
|
|
139
|
+
readonly opciones = input<string[]>([])
|
|
140
|
+
readonly deshabilitado = input<boolean>(false)
|
|
141
|
+
|
|
142
|
+
// Signal-based outputs (Angular v17.3+)
|
|
143
|
+
readonly seleccionado = output<string>()
|
|
144
|
+
readonly cancelado = output<void>()
|
|
145
|
+
|
|
146
|
+
// Estado local con signal
|
|
147
|
+
readonly seleccionActual = signal<string | null>(null)
|
|
148
|
+
readonly estaAbierto = signal(false)
|
|
149
|
+
|
|
150
|
+
// Derivaciones con computed — NUNCA funciones directas en template
|
|
151
|
+
readonly opcionesFiltradas = computed(() =>
|
|
152
|
+
this.opciones().filter(op => op !== this.seleccionActual()),
|
|
153
|
+
)
|
|
154
|
+
readonly tituloCompleto = computed(() =>
|
|
155
|
+
`${this.titulo()} (${this.opciones().length} opciones)`,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
seleccionar(opcion: string): void {
|
|
159
|
+
this.seleccionActual.set(opcion)
|
|
160
|
+
this.seleccionado.emit(opcion)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
cancelar(): void {
|
|
164
|
+
this.seleccionActual.set(null)
|
|
165
|
+
this.cancelado.emit()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```html
|
|
171
|
+
<!-- nombre.component.html -->
|
|
172
|
+
<div [class.deshabilitado]="deshabilitado()">
|
|
173
|
+
<h2>{{ tituloCompleto() }}</h2>
|
|
174
|
+
|
|
175
|
+
@if (estaAbierto()) {
|
|
176
|
+
<ul role="listbox" aria-label="Opciones disponibles">
|
|
177
|
+
@for (opcion of opcionesFiltradas(); track opcion) {
|
|
178
|
+
<li
|
|
179
|
+
role="option"
|
|
180
|
+
[attr.aria-selected]="opcion === seleccionActual()"
|
|
181
|
+
(click)="seleccionar(opcion)"
|
|
182
|
+
(keydown.enter)="seleccionar(opcion)"
|
|
183
|
+
tabindex="0"
|
|
184
|
+
>
|
|
185
|
+
{{ opcion }}
|
|
186
|
+
</li>
|
|
187
|
+
}
|
|
188
|
+
@empty {
|
|
189
|
+
<li class="vacio" role="option" aria-disabled="true">Sin opciones</li>
|
|
190
|
+
}
|
|
191
|
+
</ul>
|
|
192
|
+
}
|
|
193
|
+
</div>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## API de Signals — cuándo usar cada primitivo
|
|
197
|
+
|
|
198
|
+
### signal() — estado mutable local
|
|
199
|
+
|
|
200
|
+
Para estado que cambia por interacción del usuario o respuesta de API.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
readonly contador = signal(0)
|
|
204
|
+
readonly usuario = signal<Usuario | null>(null)
|
|
205
|
+
readonly estasCargando = signal(false)
|
|
206
|
+
|
|
207
|
+
// Mutación
|
|
208
|
+
this.contador.update(c => c + 1)
|
|
209
|
+
this.usuario.set(usuarioNuevo)
|
|
210
|
+
this.estasCargando.set(true)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### computed() — derivaciones reactivas
|
|
214
|
+
|
|
215
|
+
Para valores que dependen de otros signals. NUNCA uses una función en el
|
|
216
|
+
template — cada llamada en el template recalcula en cada ciclo de detección.
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// BIEN: computed recalcula solo cuando dependencias cambian
|
|
220
|
+
readonly totalConIva = computed(() => this.subtotal() * 1.16)
|
|
221
|
+
readonly usuarioNombre = computed(() => this.usuario()?.nombre ?? 'Anónimo')
|
|
222
|
+
readonly estaAutenticado = computed(() => this.usuario() !== null)
|
|
223
|
+
|
|
224
|
+
// MAL: función en template → recalcula en cada ciclo
|
|
225
|
+
get totalConIva() { return this.subtotal() * 1.16 } // Nunca esto
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### effect() — efectos secundarios reactivos
|
|
229
|
+
|
|
230
|
+
Para sincronizar signals con el mundo exterior. NO para actualizar state.
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
constructor() {
|
|
234
|
+
// Sincronizar con localStorage cuando el usuario cambia
|
|
235
|
+
effect(() => {
|
|
236
|
+
const usuario = this.usuario()
|
|
237
|
+
if (usuario) {
|
|
238
|
+
localStorage.setItem('usuario', JSON.stringify(usuario))
|
|
239
|
+
} else {
|
|
240
|
+
localStorage.removeItem('usuario')
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### linkedSignal() — estado local vinculado a input
|
|
247
|
+
|
|
248
|
+
Para estado local que debe reiniciarse cuando un input cambia.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
readonly items = input<string[]>([])
|
|
252
|
+
|
|
253
|
+
// Se reinicia cuando items() cambia
|
|
254
|
+
readonly seleccionado = linkedSignal(() => this.items()[0] ?? null)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### toSignal() — convertir Observable a Signal
|
|
258
|
+
|
|
259
|
+
Para integrar RxJS con el nuevo modelo reactivo.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
private readonly productosService = inject(ProductosService)
|
|
263
|
+
|
|
264
|
+
readonly productos = toSignal(
|
|
265
|
+
this.productosService.getProductos(),
|
|
266
|
+
{ initialValue: [] as Producto[] },
|
|
267
|
+
)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## RxJS — solo donde signals no alcanza
|
|
271
|
+
|
|
272
|
+
Usar RxJS cuando:
|
|
273
|
+
- Necesitas operadores de tiempo (debounceTime, throttleTime, delay)
|
|
274
|
+
- Necesitas combinar múltiples streams (combineLatest, forkJoin, merge)
|
|
275
|
+
- Necesitas cancelación automática con switchMap
|
|
276
|
+
- El HttpClient retorna Observable y la cadena de transformaciones es compleja
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// Búsqueda con debounce — RxJS tiene sentido aquí
|
|
280
|
+
readonly terminoBusqueda = signal('')
|
|
281
|
+
private readonly destroyRef = inject(DestroyRef)
|
|
282
|
+
|
|
283
|
+
private readonly resultados$ = toObservable(this.terminoBusqueda).pipe(
|
|
284
|
+
debounceTime(300),
|
|
285
|
+
distinctUntilChanged(),
|
|
286
|
+
filter(termino => termino.length >= 2),
|
|
287
|
+
switchMap(termino => this.productosService.buscar(termino)),
|
|
288
|
+
catchError(() => of([])),
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
readonly resultados = toSignal(this.resultados$, { initialValue: [] as Producto[] })
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Defer blocks — carga diferida declarativa
|
|
295
|
+
|
|
296
|
+
```html
|
|
297
|
+
<!-- Cargar el componente solo cuando es visible en el viewport -->
|
|
298
|
+
@defer (on viewport) {
|
|
299
|
+
<app-grafica-pesada [datos]="datos()" />
|
|
300
|
+
} @placeholder {
|
|
301
|
+
<div class="placeholder-grafica" aria-hidden="true"></div>
|
|
302
|
+
} @loading (minimum 200ms) {
|
|
303
|
+
<app-skeleton-grafica />
|
|
304
|
+
} @error {
|
|
305
|
+
<p role="alert">Error cargando la gráfica. <button (click)="recargar()">Reintentar</button></p>
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
<!-- Cargar solo cuando el usuario interactúa -->
|
|
309
|
+
@defer (on interaction) {
|
|
310
|
+
<app-editor-avanzado [contenido]="contenido()" />
|
|
311
|
+
} @placeholder {
|
|
312
|
+
<button class="btn-editar">Editar contenido</button>
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## HTTP Client con signals
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// productos.service.ts
|
|
320
|
+
@Injectable({ providedIn: 'root' })
|
|
321
|
+
export class ProductosService {
|
|
322
|
+
private readonly http = inject(HttpClient)
|
|
323
|
+
private readonly baseUrl = inject(BASE_URL_TOKEN)
|
|
324
|
+
|
|
325
|
+
// Para la mayoría de casos: Observable estándar que el consumidor convierte
|
|
326
|
+
getProductos(): Observable<Producto[]> {
|
|
327
|
+
return this.http.get<Producto[]>(`${this.baseUrl}/productos`).pipe(
|
|
328
|
+
catchError(error => {
|
|
329
|
+
console.error('Error cargando productos:', error)
|
|
330
|
+
return throwError(() => new Error('No se pudieron cargar los productos'))
|
|
331
|
+
}),
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
crearProducto(datos: CrearProductoDto): Observable<Producto> {
|
|
336
|
+
return this.http.post<Producto>(`${this.baseUrl}/productos`, datos)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Guards funcionales y resolvers
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// auth.guard.ts — funcional, sin clase
|
|
345
|
+
export const authGuard: CanActivateFn = (route, state) => {
|
|
346
|
+
const authService = inject(AuthService)
|
|
347
|
+
const router = inject(Router)
|
|
348
|
+
|
|
349
|
+
if (authService.estaAutenticado()) {
|
|
350
|
+
return true
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return router.createUrlTree(['/login'], {
|
|
354
|
+
queryParams: { returnUrl: state.url },
|
|
355
|
+
})
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// productos.resolver.ts — funcional
|
|
359
|
+
export const productosResolver: ResolveFn<Producto[]> = (route) => {
|
|
360
|
+
const productosService = inject(ProductosService)
|
|
361
|
+
const id = route.paramMap.get('id')!
|
|
362
|
+
return productosService.getProductosPorCategoria(id)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Interceptor funcional
|
|
366
|
+
export const authInterceptor: HttpInterceptorFn = (req, next) => {
|
|
367
|
+
const authService = inject(AuthService)
|
|
368
|
+
const token = authService.getToken()
|
|
369
|
+
|
|
370
|
+
if (!token) return next(req)
|
|
371
|
+
|
|
372
|
+
return next(req.clone({
|
|
373
|
+
headers: req.headers.set('Authorization', `Bearer ${token}`),
|
|
374
|
+
}))
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## SSR con Angular Universal
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// app.config.ts — configuración para SSR
|
|
382
|
+
export const appConfig: ApplicationConfig = {
|
|
383
|
+
providers: [
|
|
384
|
+
provideRouter(routes),
|
|
385
|
+
provideClientHydration(withEventReplay()), // Evita re-renders en hidratación
|
|
386
|
+
provideHttpClient(withFetch()), // fetch API en lugar de XMLHttpRequest
|
|
387
|
+
],
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Para diferencia entre servidor y cliente:
|
|
391
|
+
@Component({ ... })
|
|
392
|
+
export class ComponenteConSSR {
|
|
393
|
+
private readonly platformId = inject(PLATFORM_ID)
|
|
394
|
+
|
|
395
|
+
ngOnInit() {
|
|
396
|
+
// Solo ejecutar en browser
|
|
397
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
398
|
+
// Código que depende del DOM o APIs del browser
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## View Transitions API
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
// Para transiciones de página fluidas
|
|
408
|
+
export const routes: Routes = [
|
|
409
|
+
{
|
|
410
|
+
path: 'productos',
|
|
411
|
+
loadComponent: () => import('./productos/productos.component'),
|
|
412
|
+
},
|
|
413
|
+
]
|
|
414
|
+
|
|
415
|
+
// app.config.ts
|
|
416
|
+
provideRouter(routes, withViewTransitions({
|
|
417
|
+
onViewTransitionCreated: ({ transition }) => {
|
|
418
|
+
// Cancelar si el usuario navega rápido
|
|
419
|
+
inject(Router).events.pipe(
|
|
420
|
+
filter(e => e instanceof NavigationStart),
|
|
421
|
+
take(1),
|
|
422
|
+
).subscribe(() => transition.skipTransition())
|
|
423
|
+
},
|
|
424
|
+
}))
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Reglas anti-error — obligatorias
|
|
428
|
+
|
|
429
|
+
### Componentes
|
|
430
|
+
- `standalone: true` SIEMPRE — nunca NgModule en componentes nuevos
|
|
431
|
+
- Archivos separados SIEMPRE: `.ts` + `.html` + `.css`
|
|
432
|
+
- `@if`/`@for` EXCLUSIVO — NUNCA `*ngIf`/`*ngFor`
|
|
433
|
+
- `track item.id` o `track $index` en TODOS los `@for`
|
|
434
|
+
- `computed()` para valores derivados — NUNCA getters ni funciones en template
|
|
435
|
+
- Para signals en template: `item()?.propiedad` — NUNCA `item?.propiedad`
|
|
436
|
+
|
|
437
|
+
### Signals y estado
|
|
438
|
+
- NUNCA uses `BehaviorSubject` para nuevo código — usa `signal()`
|
|
439
|
+
- NUNCA mutes arrays o objetos en signals directamente:
|
|
440
|
+
```typescript
|
|
441
|
+
// MAL
|
|
442
|
+
this.items().push(nuevoItem) // Muta el array interno — el signal no detecta el cambio
|
|
443
|
+
|
|
444
|
+
// BIEN
|
|
445
|
+
this.items.update(items => [...items, nuevoItem])
|
|
446
|
+
```
|
|
447
|
+
- `takeUntilDestroyed()` OBLIGATORIO en subscriptions RxJS de larga vida
|
|
448
|
+
- `effect()` es para efectos secundarios, NO para actualizar otros signals
|
|
449
|
+
(si necesitas actualizar signals desde effect, usa linkedSignal)
|
|
450
|
+
|
|
451
|
+
### HTTP y servicios
|
|
452
|
+
- `PaginatedResponse<T>`: parsear SIEMPRE con `.pipe(map(resp => resp.items))`
|
|
453
|
+
Sin esto → spinner infinito o `.filter is not a function`
|
|
454
|
+
- NUNCA importes `PaginatedResponse<T>` duplicado — importar de `core/models/shared.models`
|
|
455
|
+
- `catchError` en TODOS los pipes de HTTP — nunca confíes en que el servidor responde
|
|
456
|
+
|
|
457
|
+
### Formularios
|
|
458
|
+
- `ReactiveFormsModule` para formularios con validación
|
|
459
|
+
- `FormBuilder` siempre — nunca instanciar `FormGroup` manualmente
|
|
460
|
+
- `MatDatepicker` OBLIGATORIO — NUNCA `<input type="date">`
|
|
461
|
+
- `aria-label` en todo input fuera de `mat-form-field`
|
|
462
|
+
|
|
463
|
+
### TypeScript
|
|
464
|
+
- NUNCA uses `any` — define tipos explícitos siempre
|
|
465
|
+
- Tipos de API en archivos `.types.ts` o `.models.ts` separados
|
|
466
|
+
- NUNCA asumas que un campo nullable tiene valor sin verificar
|
|
467
|
+
|
|
468
|
+
## Protocolo de testing con TestBed
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
|
472
|
+
import { By } from '@angular/platform-browser'
|
|
473
|
+
import { signal } from '@angular/core'
|
|
474
|
+
|
|
475
|
+
describe('ProductoCardComponent', () => {
|
|
476
|
+
let component: ProductoCardComponent
|
|
477
|
+
let fixture: ComponentFixture<ProductoCardComponent>
|
|
478
|
+
|
|
479
|
+
beforeEach(async () => {
|
|
480
|
+
await TestBed.configureTestingModule({
|
|
481
|
+
imports: [ProductoCardComponent], // standalone: importar directamente
|
|
482
|
+
providers: [
|
|
483
|
+
{ provide: ProductosService, useValue: { getProducto: () => of(productoMock) } },
|
|
484
|
+
],
|
|
485
|
+
}).compileComponents()
|
|
486
|
+
|
|
487
|
+
fixture = TestBed.createComponent(ProductoCardComponent)
|
|
488
|
+
component = fixture.componentInstance
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
it('debe renderizar el nombre del producto', () => {
|
|
492
|
+
// Arrange
|
|
493
|
+
fixture.componentRef.setInput('producto', productoMock)
|
|
494
|
+
|
|
495
|
+
// Act
|
|
496
|
+
fixture.detectChanges()
|
|
497
|
+
|
|
498
|
+
// Assert
|
|
499
|
+
const nombre = fixture.debugElement.query(By.css('[data-testid="nombre"]'))
|
|
500
|
+
expect(nombre.nativeElement.textContent).toContain(productoMock.nombre)
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
it('debe emitir el evento seleccionado al hacer clic', () => {
|
|
504
|
+
fixture.componentRef.setInput('producto', productoMock)
|
|
505
|
+
fixture.detectChanges()
|
|
506
|
+
|
|
507
|
+
const emitidos: Producto[] = []
|
|
508
|
+
component.seleccionado.subscribe(p => emitidos.push(p))
|
|
509
|
+
|
|
510
|
+
const boton = fixture.debugElement.query(By.css('button'))
|
|
511
|
+
boton.nativeElement.click()
|
|
512
|
+
|
|
513
|
+
expect(emitidos).toHaveSize(1)
|
|
514
|
+
expect(emitidos[0]).toEqual(productoMock)
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
it('debe ser accesible: el botón tiene aria-label', () => {
|
|
518
|
+
fixture.componentRef.setInput('producto', productoMock)
|
|
519
|
+
fixture.detectChanges()
|
|
520
|
+
|
|
521
|
+
const boton = fixture.debugElement.query(By.css('button'))
|
|
522
|
+
expect(boton.nativeElement.getAttribute('aria-label')).toBeTruthy()
|
|
523
|
+
})
|
|
524
|
+
})
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Mínimo de tests por componente
|
|
528
|
+
|
|
529
|
+
1. **Render básico**: renderiza sin errores
|
|
530
|
+
2. **Inputs se reflejan**: los valores de input aparecen en el DOM
|
|
531
|
+
3. **Interacción principal**: el evento principal funciona
|
|
532
|
+
4. **Estado de error**: los errores se muestran con ARIA correcto
|
|
533
|
+
5. **Estado vacío/carga**: @defer, spinner, skeleton funcionan
|
|
534
|
+
6. **Accesibilidad mínima**: aria-label, roles, tabindex
|
|
535
|
+
|
|
536
|
+
## Checklist de accesibilidad
|
|
537
|
+
|
|
538
|
+
- [ ] `<button>` para acciones, `<a>` para navegación — NUNCA `<div>` clickeable
|
|
539
|
+
- [ ] Headings en orden lógico: un solo `<h1>` por ruta
|
|
540
|
+
- [ ] `aria-label` en íconos sin texto visible
|
|
541
|
+
- [ ] `aria-expanded` en accordions, dropdowns y menús colapsables
|
|
542
|
+
- [ ] `aria-selected` en tabs y listas con selección
|
|
543
|
+
- [ ] `aria-required` + `aria-invalid` en campos con error
|
|
544
|
+
- [ ] `aria-describedby` apuntando al mensaje de error
|
|
545
|
+
- [ ] `aria-live="polite"` en regiones que se actualizan dinámicamente
|
|
546
|
+
- [ ] Focus visible — nunca `outline: none` sin reemplazo visual
|
|
547
|
+
- [ ] Focus trap en modales (CDK FocusTrap)
|
|
548
|
+
- [ ] `MatDatepicker` en lugar de `<input type="date">`
|
|
549
|
+
- [ ] Navegación completa con teclado: Tab, Enter, Escape, flechas
|
|
550
|
+
|
|
551
|
+
## Checklist de performance
|
|
552
|
+
|
|
553
|
+
Antes de marcar cualquier componente como completado:
|
|
554
|
+
|
|
555
|
+
- [ ] `loadComponent: () => import(...)` en rutas con componentes pesados
|
|
556
|
+
- [ ] `@defer (on viewport)` para componentes fuera del viewport inicial
|
|
557
|
+
- [ ] Listas largas (> 50 items) usan `CdkVirtualScrollViewport`
|
|
558
|
+
- [ ] Imágenes usan `NgOptimizedImage` con dimensiones explícitas
|
|
559
|
+
- [ ] `computed()` para todas las derivaciones — cero getters ni funciones en template
|
|
560
|
+
- [ ] `takeUntilDestroyed()` en todas las subscriptions RxJS
|
|
561
|
+
- [ ] HTTP calls tienen estado de carga, error y dato — los tres siempre
|
|
562
|
+
|
|
563
|
+
## Reglas estrictas
|
|
564
|
+
|
|
565
|
+
- NUNCA uses `any` en TypeScript
|
|
566
|
+
- NUNCA uses `*ngIf`/`*ngFor` — solo `@if`/`@for`
|
|
567
|
+
- NUNCA dejes `console.log` en código de producción
|
|
568
|
+
- NUNCA hardcodees URLs, credenciales o configuración de entorno
|
|
569
|
+
- NUNCA uses `BehaviorSubject` para nuevo código — usa `signal()`
|
|
570
|
+
- SIEMPRE invoca al menos 1 skill antes de implementar
|
|
571
|
+
- SIEMPRE lee los componentes existentes antes de crear uno nuevo
|
|
572
|
+
- Si un test falla, corrígelo antes de continuar al siguiente componente
|
|
573
|
+
- **DRY obligatorio** — antes de crear un componente, hook, servicio o utility nuevo, buscar si ya existe algo equivalente con `Grep`. Si existe, reutilizar o extender — no duplicar. Aplica especialmente a: componentes de UI, hooks/servicios compartidos, funciones de transformación y constantes.
|
|
574
|
+
- **Si detectas duplicación** de lógica existente al implementar, extraer a un módulo compartido antes de continuar. No dejar la duplicación "para después".
|
|
575
|
+
|
|
576
|
+
## Gotchas / Errores comunes no obvios
|
|
577
|
+
|
|
578
|
+
**Mutar array en signal directamente → Angular no detecta el cambio**: `this.items().push(nuevoItem)` modifica el array interno del signal sin crear una nueva referencia. Causa: parece equivalente al push de un array normal. Solución: `this.items.update(items => [...items, nuevoItem])` — los signals detectan cambios por referencia, no por mutación interna.
|
|
579
|
+
|
|
580
|
+
**`PaginatedResponse<T>` sin `.pipe(map(resp => resp.items))`**: el service retorna el objeto de paginación completo en lugar del array de items, resultando en `items.filter is not a function`. Causa: el mapping se omite creyendo que el componente lo hará. Solución: parsear SIEMPRE con `.pipe(map(resp => resp.items))` en el service — el componente nunca debe conocer la estructura de paginación del API.
|
|
581
|
+
|
|
582
|
+
**`takeUntilDestroyed()` ausente en subscriptions RxJS de larga vida**: un subscription a un Observable de polling sigue activo después de que el componente se destruye, causando memory leaks y calls a APIs innecesarios. Causa: las subscriptions en `ngOnInit` parecen locales al componente. Solución: `takeUntilDestroyed()` obligatorio en toda subscription de larga vida — ya que el componente destruido ya no tiene contexto para limpiar manualmente.
|
|
583
|
+
|
|
584
|
+
**`item?.propiedad` en template con signal en lugar de `item()?.propiedad`**: el optional chaining sin invocar el signal retorna el objeto signal, no el valor. Causa: la sintaxis parece igual a un optional chaining normal. Solución: `item()?.propiedad` siempre para signals en templates — `item?.propiedad` accede al objeto signal, que siempre es truthy aunque su valor sea null.
|
|
585
|
+
|
|
586
|
+
## Señales de que debes parar
|
|
587
|
+
|
|
588
|
+
Para y reporta si encuentras:
|
|
589
|
+
- La versión de Angular es anterior a v17 y la spec requiere signals/standalone
|
|
590
|
+
- La UI-SPEC.md es contradictoria para más del 20% de los componentes
|
|
591
|
+
- La implementación requiere cambios en el backend que no existen
|
|
592
|
+
- El proyecto mezcla NgModules y standalone de forma inconsistente sin patrón
|
|
593
|
+
- Hay un conflicto entre Angular Material y el design system del proyecto
|
|
594
|
+
- Necesitas instalar una librería de terceros no aprobada en el proyecto
|
|
595
|
+
|
|
596
|
+
## Formato de reporte al terminar
|
|
597
|
+
|
|
598
|
+
```markdown
|
|
599
|
+
## Reporte de Implementación Angular — [feature] — [fecha]
|
|
600
|
+
|
|
601
|
+
### Versión y skills cargados
|
|
602
|
+
- Angular: v[versión], Zoneless: [Sí/No]
|
|
603
|
+
- Skills: [lista de skills invocados]
|
|
604
|
+
|
|
605
|
+
### Componentes implementados
|
|
606
|
+
| Componente | Archivo | Signals usados | Tests | Accesibilidad | Estado |
|
|
607
|
+
|-----------|---------|---------------|-------|--------------|--------|
|
|
608
|
+
| [nombre] | `src/...` | signal, computed | X tests | WCAG AA | COMPLETADO |
|
|
609
|
+
|
|
610
|
+
### Desviaciones de la UI-SPEC
|
|
611
|
+
| Regla aplicada | Descripción | Componente |
|
|
612
|
+
|---------------|-------------|-----------|
|
|
613
|
+
| [Regla 1-4] | [qué y por qué] | [componente] |
|
|
614
|
+
|
|
615
|
+
### Verificaciones ejecutadas
|
|
616
|
+
- [ ] Build: `ng build` sin errores ni warnings
|
|
617
|
+
- [ ] Tests: X pasaron / X fallaron
|
|
618
|
+
- [ ] TypeScript: 0 errores
|
|
619
|
+
- [ ] ESLint: 0 errores
|
|
620
|
+
|
|
621
|
+
### Performance
|
|
622
|
+
- [ ] Lazy loading configurado en todas las rutas pesadas
|
|
623
|
+
- [ ] Defer blocks en componentes fuera del viewport
|
|
624
|
+
- [ ] Virtual scroll en listas largas
|
|
625
|
+
|
|
626
|
+
### Estado: COMPLETADO | PARCIAL | BLOQUEADO
|
|
627
|
+
```
|