@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,415 @@
|
|
|
1
|
+
# Testing con pytest-django y Factory Boy
|
|
2
|
+
|
|
3
|
+
## Configuración: pytest.ini y conftest.py base
|
|
4
|
+
|
|
5
|
+
```ini
|
|
6
|
+
# pytest.ini (o sección [tool.pytest.ini_options] en pyproject.toml)
|
|
7
|
+
[pytest]
|
|
8
|
+
DJANGO_SETTINGS_MODULE = config.settings.test
|
|
9
|
+
python_files = tests.py test_*.py *_test.py
|
|
10
|
+
python_classes = Test*
|
|
11
|
+
python_functions = test_*
|
|
12
|
+
addopts =
|
|
13
|
+
--reuse-db # reutiliza la BD entre sesiones para velocidad
|
|
14
|
+
--strict-markers # falla si se usa marker no declarado
|
|
15
|
+
-p no:warnings # silenciar deprecation warnings en CI
|
|
16
|
+
markers =
|
|
17
|
+
slow: tests lentos que se omiten en desarrollo local
|
|
18
|
+
integration: tests con servicios externos reales
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
# config/settings/test.py
|
|
23
|
+
from .base import * # noqa: F401, F403
|
|
24
|
+
|
|
25
|
+
DATABASES = {
|
|
26
|
+
"default": {
|
|
27
|
+
"ENGINE": "django.db.backends.postgresql",
|
|
28
|
+
"NAME": "test_db",
|
|
29
|
+
"USER": "postgres",
|
|
30
|
+
"PASSWORD": "postgres",
|
|
31
|
+
"HOST": "localhost",
|
|
32
|
+
"PORT": "5432",
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Acelerar hashing en tests — NUNCA en producción
|
|
37
|
+
PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]
|
|
38
|
+
|
|
39
|
+
# Celery en modo síncrono para tests
|
|
40
|
+
CELERY_TASK_ALWAYS_EAGER = True
|
|
41
|
+
CELERY_TASK_EAGER_PROPAGATES = True
|
|
42
|
+
|
|
43
|
+
# Caché en memoria para tests
|
|
44
|
+
CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
# conftest.py (raíz del proyecto)
|
|
49
|
+
import pytest
|
|
50
|
+
from rest_framework.test import APIClient
|
|
51
|
+
from django.contrib.auth import get_user_model
|
|
52
|
+
|
|
53
|
+
from tests.factories import UsuarioFactory, EmpresaFactory
|
|
54
|
+
|
|
55
|
+
Usuario = get_user_model()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@pytest.fixture
|
|
59
|
+
def api_client() -> APIClient:
|
|
60
|
+
"""Cliente DRF sin autenticar."""
|
|
61
|
+
return APIClient()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.fixture
|
|
65
|
+
def empresa(db):
|
|
66
|
+
"""Empresa de prueba creada en BD."""
|
|
67
|
+
return EmpresaFactory()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@pytest.fixture
|
|
71
|
+
def usuario(db, empresa):
|
|
72
|
+
"""Usuario activo con empresa asignada."""
|
|
73
|
+
return UsuarioFactory(empresa=empresa, is_active=True)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@pytest.fixture
|
|
77
|
+
def usuario_admin(db, empresa):
|
|
78
|
+
"""Usuario con rol administrador."""
|
|
79
|
+
return UsuarioFactory(empresa=empresa, rol="admin", is_active=True)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@pytest.fixture
|
|
83
|
+
def cliente_autenticado(api_client: APIClient, usuario) -> APIClient:
|
|
84
|
+
"""Cliente DRF con usuario autenticado via JWT."""
|
|
85
|
+
api_client.force_authenticate(user=usuario)
|
|
86
|
+
return api_client
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@pytest.fixture
|
|
90
|
+
def cliente_admin(api_client: APIClient, usuario_admin) -> APIClient:
|
|
91
|
+
"""Cliente DRF con usuario administrador autenticado."""
|
|
92
|
+
api_client.force_authenticate(user=usuario_admin)
|
|
93
|
+
return api_client
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Factory Boy: definición de factories
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
# tests/factories.py
|
|
102
|
+
import factory
|
|
103
|
+
from factory.django import DjangoModelFactory
|
|
104
|
+
from factory import SubFactory, LazyAttribute, Faker, Sequence
|
|
105
|
+
from django.contrib.auth import get_user_model
|
|
106
|
+
from decimal import Decimal
|
|
107
|
+
|
|
108
|
+
from apps.empresas.models import Empresa
|
|
109
|
+
from apps.facturas.models import Factura, ItemFactura, Cliente
|
|
110
|
+
|
|
111
|
+
Usuario = get_user_model()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class EmpresaFactory(DjangoModelFactory):
|
|
115
|
+
class Meta:
|
|
116
|
+
model = Empresa
|
|
117
|
+
|
|
118
|
+
nombre = Faker("company", locale="es_MX")
|
|
119
|
+
rfc = Sequence(lambda n: f"EMP{n:09d}A1")
|
|
120
|
+
activa = True
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class UsuarioFactory(DjangoModelFactory):
|
|
124
|
+
class Meta:
|
|
125
|
+
model = Usuario
|
|
126
|
+
|
|
127
|
+
email = Sequence(lambda n: f"usuario{n}@prueba.com")
|
|
128
|
+
nombre = Faker("first_name", locale="es_MX")
|
|
129
|
+
apellido = Faker("last_name", locale="es_MX")
|
|
130
|
+
empresa = SubFactory(EmpresaFactory)
|
|
131
|
+
rol = "operador"
|
|
132
|
+
is_active = True
|
|
133
|
+
|
|
134
|
+
# Contraseña manejada con set_password para que hashee correctamente
|
|
135
|
+
@factory.post_generation
|
|
136
|
+
def password(self, create, extracted, **kwargs):
|
|
137
|
+
if not create:
|
|
138
|
+
return
|
|
139
|
+
self.set_password(extracted or "Contraseña!Segura123")
|
|
140
|
+
self.save(update_fields=["password"])
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class ClienteFactory(DjangoModelFactory):
|
|
144
|
+
class Meta:
|
|
145
|
+
model = Cliente
|
|
146
|
+
|
|
147
|
+
nombre = Faker("company", locale="es_MX")
|
|
148
|
+
rfc = Sequence(lambda n: f"CLI{n:09d}A1")
|
|
149
|
+
empresa = SubFactory(EmpresaFactory)
|
|
150
|
+
activo = True
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class FacturaFactory(DjangoModelFactory):
|
|
154
|
+
class Meta:
|
|
155
|
+
model = Factura
|
|
156
|
+
|
|
157
|
+
folio = Sequence(lambda n: f"FAC-{n:06d}")
|
|
158
|
+
cliente = SubFactory(ClienteFactory)
|
|
159
|
+
empresa = LazyAttribute(lambda obj: obj.cliente.empresa)
|
|
160
|
+
estatus = "emitida"
|
|
161
|
+
total = Faker(
|
|
162
|
+
"pydecimal", min_value=100, max_value=100_000,
|
|
163
|
+
right_digits=2, positive=True,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class ItemFacturaFactory(DjangoModelFactory):
|
|
168
|
+
class Meta:
|
|
169
|
+
model = ItemFactura
|
|
170
|
+
|
|
171
|
+
factura = SubFactory(FacturaFactory)
|
|
172
|
+
descripcion = Faker("sentence", locale="es_MX", nb_words=4)
|
|
173
|
+
cantidad = Faker("random_int", min=1, max=20)
|
|
174
|
+
precio_unitario = Faker(
|
|
175
|
+
"pydecimal", min_value=10, max_value=5_000, right_digits=2, positive=True
|
|
176
|
+
)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Tests de modelo: validaciones, métodos y señales
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# apps/facturas/tests/test_models.py
|
|
185
|
+
import pytest
|
|
186
|
+
from django.core.exceptions import ValidationError
|
|
187
|
+
from tests.factories import FacturaFactory, ItemFacturaFactory
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@pytest.mark.django_db
|
|
191
|
+
class TestFacturaModel:
|
|
192
|
+
def test_calcular_total_suma_items(self):
|
|
193
|
+
factura = FacturaFactory()
|
|
194
|
+
ItemFacturaFactory(factura=factura, cantidad=2, precio_unitario=100)
|
|
195
|
+
ItemFacturaFactory(factura=factura, cantidad=1, precio_unitario=50)
|
|
196
|
+
|
|
197
|
+
assert factura.calcular_total() == pytest.approx(250.00)
|
|
198
|
+
|
|
199
|
+
def test_no_se_puede_cancelar_factura_ya_cancelada(self):
|
|
200
|
+
factura = FacturaFactory(estatus="cancelada")
|
|
201
|
+
|
|
202
|
+
with pytest.raises(ValueError, match="ya está cancelada"):
|
|
203
|
+
factura.cancelar(motivo="prueba")
|
|
204
|
+
|
|
205
|
+
def test_estatus_emitida_es_valido(self):
|
|
206
|
+
factura = FacturaFactory.build(estatus="emitida")
|
|
207
|
+
# .full_clean() ejecuta validadores del modelo sin guardar en BD
|
|
208
|
+
factura.full_clean() # no debe lanzar excepción
|
|
209
|
+
|
|
210
|
+
def test_estatus_invalido_falla_validacion(self):
|
|
211
|
+
factura = FacturaFactory.build(estatus="INVALIDO")
|
|
212
|
+
with pytest.raises(ValidationError):
|
|
213
|
+
factura.full_clean()
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@pytest.mark.django_db
|
|
217
|
+
class TestSignalCambioEstatus:
|
|
218
|
+
def test_signal_post_save_envia_notificacion(self, mocker):
|
|
219
|
+
"""La señal post_save debe llamar al servicio de notificación al cambiar estatus."""
|
|
220
|
+
mock_notificar = mocker.patch(
|
|
221
|
+
"apps.facturas.signals.notificacion_service.enviar"
|
|
222
|
+
)
|
|
223
|
+
factura = FacturaFactory(estatus="emitida")
|
|
224
|
+
# Simular tracker manualmente si se usa django-model-utils
|
|
225
|
+
factura.estatus = "pagada"
|
|
226
|
+
factura.save()
|
|
227
|
+
|
|
228
|
+
mock_notificar.assert_called_once()
|
|
229
|
+
call_kwargs = mock_notificar.call_args.kwargs
|
|
230
|
+
assert call_kwargs["tipo"] == "CAMBIO_ESTATUS_FACTURA"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Tests de API: status codes y payloads
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
# apps/facturas/tests/test_api.py
|
|
239
|
+
import pytest
|
|
240
|
+
from django.urls import reverse
|
|
241
|
+
from rest_framework import status
|
|
242
|
+
from tests.factories import FacturaFactory, ClienteFactory
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@pytest.mark.django_db
|
|
246
|
+
class TestFacturaListAPI:
|
|
247
|
+
def test_listar_requiere_autenticacion(self, api_client):
|
|
248
|
+
url = reverse("factura-list")
|
|
249
|
+
respuesta = api_client.get(url)
|
|
250
|
+
assert respuesta.status_code == status.HTTP_401_UNAUTHORIZED
|
|
251
|
+
|
|
252
|
+
def test_listar_solo_facturas_propias(self, cliente_autenticado, usuario):
|
|
253
|
+
"""El usuario solo debe ver facturas de su empresa."""
|
|
254
|
+
# Facturas de la empresa del usuario
|
|
255
|
+
factura_propia = FacturaFactory(empresa=usuario.empresa)
|
|
256
|
+
# Factura de otra empresa — NO debe aparecer
|
|
257
|
+
FacturaFactory()
|
|
258
|
+
|
|
259
|
+
url = reverse("factura-list")
|
|
260
|
+
respuesta = cliente_autenticado.get(url)
|
|
261
|
+
|
|
262
|
+
assert respuesta.status_code == status.HTTP_200_OK
|
|
263
|
+
ids_retornados = [r["id"] for r in respuesta.data["resultados"]]
|
|
264
|
+
assert str(factura_propia.id) in ids_retornados
|
|
265
|
+
assert len(ids_retornados) == 1
|
|
266
|
+
|
|
267
|
+
def test_crear_factura_con_items(self, cliente_autenticado, usuario):
|
|
268
|
+
cliente = ClienteFactory(empresa=usuario.empresa)
|
|
269
|
+
payload = {
|
|
270
|
+
"cliente_id": str(cliente.id),
|
|
271
|
+
"items": [
|
|
272
|
+
{"producto_id": None, "descripcion": "Servicio A", "cantidad": 2, "precio_unitario": "500.00"},
|
|
273
|
+
{"producto_id": None, "descripcion": "Servicio B", "cantidad": 1, "precio_unitario": "300.00"},
|
|
274
|
+
],
|
|
275
|
+
}
|
|
276
|
+
url = reverse("factura-list")
|
|
277
|
+
respuesta = cliente_autenticado.post(url, data=payload, format="json")
|
|
278
|
+
|
|
279
|
+
assert respuesta.status_code == status.HTTP_201_CREATED
|
|
280
|
+
assert len(respuesta.data["items"]) == 2
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@pytest.mark.django_db
|
|
284
|
+
class TestFacturaCancelarAccion:
|
|
285
|
+
def test_cancelar_factura_emitida(self, cliente_admin, usuario_admin):
|
|
286
|
+
factura = FacturaFactory(empresa=usuario_admin.empresa, estatus="emitida")
|
|
287
|
+
url = reverse("factura-cancelar", kwargs={"pk": factura.pk})
|
|
288
|
+
|
|
289
|
+
respuesta = cliente_admin.post(url, data={"motivo": "Error de captura"}, format="json")
|
|
290
|
+
|
|
291
|
+
assert respuesta.status_code == status.HTTP_200_OK
|
|
292
|
+
factura.refresh_from_db()
|
|
293
|
+
assert factura.estatus == "cancelada"
|
|
294
|
+
|
|
295
|
+
def test_cancelar_factura_ya_cancelada_retorna_422(self, cliente_admin, usuario_admin):
|
|
296
|
+
factura = FacturaFactory(empresa=usuario_admin.empresa, estatus="cancelada")
|
|
297
|
+
url = reverse("factura-cancelar", kwargs={"pk": factura.pk})
|
|
298
|
+
|
|
299
|
+
respuesta = cliente_admin.post(url, data={}, format="json")
|
|
300
|
+
|
|
301
|
+
assert respuesta.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Tests de permisos
|
|
307
|
+
|
|
308
|
+
```python
|
|
309
|
+
# apps/facturas/tests/test_permisos.py
|
|
310
|
+
import pytest
|
|
311
|
+
from django.urls import reverse
|
|
312
|
+
from rest_framework import status
|
|
313
|
+
from tests.factories import FacturaFactory
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@pytest.mark.django_db
|
|
317
|
+
class TestPermisosFactura:
|
|
318
|
+
def test_operador_no_puede_cancelar(self, cliente_autenticado, usuario):
|
|
319
|
+
"""El rol 'operador' no tiene permiso para cancelar facturas."""
|
|
320
|
+
assert usuario.rol == "operador"
|
|
321
|
+
factura = FacturaFactory(empresa=usuario.empresa, estatus="emitida")
|
|
322
|
+
url = reverse("factura-cancelar", kwargs={"pk": factura.pk})
|
|
323
|
+
|
|
324
|
+
respuesta = cliente_autenticado.post(url, data={}, format="json")
|
|
325
|
+
|
|
326
|
+
assert respuesta.status_code == status.HTTP_403_FORBIDDEN
|
|
327
|
+
|
|
328
|
+
def test_no_puede_ver_factura_de_otra_empresa(self, cliente_autenticado):
|
|
329
|
+
factura_ajena = FacturaFactory() # empresa diferente
|
|
330
|
+
url = reverse("factura-detail", kwargs={"pk": factura_ajena.pk})
|
|
331
|
+
|
|
332
|
+
respuesta = cliente_autenticado.get(url)
|
|
333
|
+
|
|
334
|
+
# 404 es preferible a 403 para no revelar que el recurso existe
|
|
335
|
+
assert respuesta.status_code == status.HTTP_404_NOT_FOUND
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Mocking: servicios externos y tareas Celery
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
# apps/facturas/tests/test_servicios.py
|
|
344
|
+
import pytest
|
|
345
|
+
from unittest.mock import patch, MagicMock
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@pytest.mark.django_db
|
|
349
|
+
def test_crear_factura_envia_email(mocker):
|
|
350
|
+
"""El servicio de factura debe encolar email sin llamar SMTP real."""
|
|
351
|
+
mock_tarea = mocker.patch("apps.facturas.services.enviar_email.delay")
|
|
352
|
+
|
|
353
|
+
servicio = FacturaService()
|
|
354
|
+
factura = servicio.crear(cliente_id=1, items=[...])
|
|
355
|
+
|
|
356
|
+
mock_tarea.assert_called_once_with(
|
|
357
|
+
destinatario=factura.cliente.email,
|
|
358
|
+
folio=factura.folio,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
@pytest.mark.django_db
|
|
363
|
+
def test_integracion_pasarela_pago(mocker):
|
|
364
|
+
"""Mockear cliente HTTP de la pasarela para no hacer llamadas reales."""
|
|
365
|
+
mock_respuesta = MagicMock()
|
|
366
|
+
mock_respuesta.status_code = 200
|
|
367
|
+
mock_respuesta.json.return_value = {"transaccion_id": "TXN-001", "aprobado": True}
|
|
368
|
+
|
|
369
|
+
mocker.patch(
|
|
370
|
+
"apps.pagos.clients.PasarelaPagoClient.procesar",
|
|
371
|
+
return_value=mock_respuesta.json(),
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
resultado = PasarelaPagoService().pagar(factura_id=1, monto=500.00)
|
|
375
|
+
assert resultado["aprobado"] is True
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
# Celery con CELERY_TASK_ALWAYS_EAGER=True — las tareas se ejecutan síncronamente
|
|
379
|
+
@pytest.mark.django_db
|
|
380
|
+
def test_tarea_celery_ejecuta_logica():
|
|
381
|
+
from apps.reportes.tasks import generar_reporte_mensual
|
|
382
|
+
|
|
383
|
+
# Con ALWAYS_EAGER, .delay() ejecuta la tarea inmediatamente en el mismo proceso
|
|
384
|
+
resultado = generar_reporte_mensual.delay(empresa_id=1, mes=1, anio=2025)
|
|
385
|
+
assert resultado.successful()
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Performance en tests: transaction.on_commit
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
# El callback de on_commit NO se ejecuta en tests con @pytest.mark.django_db
|
|
394
|
+
# porque los tests hacen rollback en lugar de commit real.
|
|
395
|
+
# Solución: usar transaction=True o TestCase.captureOnCommitCallbacks
|
|
396
|
+
|
|
397
|
+
@pytest.mark.django_db(transaction=True)
|
|
398
|
+
def test_on_commit_ejecuta_tarea(mocker):
|
|
399
|
+
"""Necesita transaction=True para que on_commit dispare el callback."""
|
|
400
|
+
mock_tarea = mocker.patch("apps.facturas.tasks.indexar_factura.delay")
|
|
401
|
+
FacturaFactory() # el signal usa on_commit para encolar la tarea
|
|
402
|
+
|
|
403
|
+
mock_tarea.assert_called_once()
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
# Alternativa con Django 4.1+: captureOnCommitCallbacks sin transaction=True
|
|
407
|
+
@pytest.mark.django_db
|
|
408
|
+
def test_on_commit_sin_transaccion_real(mocker):
|
|
409
|
+
mock_tarea = mocker.patch("apps.facturas.tasks.indexar_factura.delay")
|
|
410
|
+
|
|
411
|
+
from django.test import TestCase
|
|
412
|
+
# En pytest-django se puede usar con el fixture `django_capture_on_commit_callbacks`
|
|
413
|
+
# disponible desde pytest-django 4.6+
|
|
414
|
+
pass # ver documentación de pytest-django para el fixture exacto
|
|
415
|
+
```
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-sync
|
|
3
|
+
description: Sincronización de documentación con el estado actual del código. Detecta documentos desactualizados (README, ADRs, docstrings, comentarios de API), genera un changelog estructurado de los cambios relevantes, y mantiene los Architecture Decision Records (ADRs) actualizados con las decisiones tomadas durante el desarrollo.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
herramientasPermitidas: [Read, Bash, Glob, Grep]
|
|
6
|
+
exclusiones:
|
|
7
|
+
- "No cargar para crear documentación nueva desde cero — este skill sincroniza documentación existente con el código actual; para crear documentación de feature nueva usar `documentador-swl` o escribir el README/ADR directamente."
|
|
8
|
+
- "No cargar para mantener al día la documentación interna SWL (INVENTARIO.md, CLAUDE.md, manifiestos) — esa sincronización sigue la tabla de propagación de cambios de CLAUDE.md y no es responsabilidad de este skill."
|
|
9
|
+
- "No cargar cuando no hay releases ni cambios significativos en los últimos 30 días — el costo del inventario y comparación es alto; si el proyecto está en pausa, la documentación no necesita sincronización."
|
|
10
|
+
- "No cargar para validar la integridad del sistema SWL (frontmatter, exit codes de hooks) — eso es `validacion-ci-sistema`; este skill sincroniza documentación de usuario (README, ADRs, docstrings, OpenAPI)."
|
|
11
|
+
evolvable: true # default para skill estandar
|
|
12
|
+
---
|
|
13
|
+
# Habilidad: Sincronización de Documentación con Código
|
|
14
|
+
|
|
15
|
+
## Propósito
|
|
16
|
+
|
|
17
|
+
La documentación que miente es peor que la documentación que no existe.
|
|
18
|
+
Un README con instrucciones de instalación obsoletas, un ADR que describe
|
|
19
|
+
una decisión revertida hace meses, o una API con docstrings que contradicen
|
|
20
|
+
el comportamiento real — todos estos son bugs de documentación que generan
|
|
21
|
+
desconfianza y pérdida de tiempo. Esta habilidad los detecta y los corrige.
|
|
22
|
+
|
|
23
|
+
## Cuándo activar
|
|
24
|
+
|
|
25
|
+
- Al completar una fase de desarrollo antes de marcar como "done"
|
|
26
|
+
- Al incorporar un colaborador nuevo que reporta confusión con la documentación
|
|
27
|
+
- Trimestralmente como revisión de mantenimiento
|
|
28
|
+
- Cuando el usuario reporta que "la documentación dice X pero el código hace Y"
|
|
29
|
+
- Antes de publicar una release o versión
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Paso 1 — Inventario de documentación existente
|
|
34
|
+
|
|
35
|
+
Identificar todos los artefactos de documentación en el proyecto:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Todos los archivos de documentación
|
|
39
|
+
find . -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" | sort
|
|
40
|
+
|
|
41
|
+
# Docstrings en Python (verificar que existen)
|
|
42
|
+
grep -rn '"""' --include="*.py" -l
|
|
43
|
+
|
|
44
|
+
# JSDoc en TypeScript
|
|
45
|
+
grep -rn '/\*\*' --include="*.ts" -l
|
|
46
|
+
|
|
47
|
+
# OpenAPI / Swagger
|
|
48
|
+
find . -name "openapi.json" -o -name "openapi.yaml" -o -name "swagger.json" 2>/dev/null
|
|
49
|
+
|
|
50
|
+
# ADRs
|
|
51
|
+
find . -name "ADR-*.md" -o -path "*/adr/*.md" -o -path "*/decisions/*.md" | sort
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Construir un mapa de documentación:
|
|
55
|
+
|
|
56
|
+
| Documento | Ruta | Última modificación | Última modificación del código relacionado |
|
|
57
|
+
|-----------|------|--------------------|--------------------------------------------|
|
|
58
|
+
| README.md | / | [fecha] | [fecha] |
|
|
59
|
+
| ADR-001.md | docs/adr/ | [fecha] | N/A (decisiones históricas) |
|
|
60
|
+
| API docs | docs/ | [fecha] | [fecha router modificado] |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Paso 2 — Detectar desincronización
|
|
65
|
+
|
|
66
|
+
### README.md — Verificar secciones críticas
|
|
67
|
+
|
|
68
|
+
**Instalación y setup**:
|
|
69
|
+
```bash
|
|
70
|
+
# Probar las instrucciones de instalación desde cero (en directorio limpio)
|
|
71
|
+
# ¿Funcionan los comandos listados?
|
|
72
|
+
# ¿Faltan pasos que se añadieron al proceso?
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Items a verificar:
|
|
76
|
+
- [ ] Versiones de runtime mencionadas (Python 3.X, Node X.Y) coinciden con `.python-version`, `package.json` engines
|
|
77
|
+
- [ ] Comandos de instalación funcionan como están escritos
|
|
78
|
+
- [ ] Variables de entorno en README coinciden con `.env.example`
|
|
79
|
+
- [ ] Comandos de ejecución del servidor son correctos
|
|
80
|
+
- [ ] Comandos de tests coinciden con la configuración actual (`pytest.ini`, `jest.config.*`)
|
|
81
|
+
- [ ] URLs de la API corresponden al router actual
|
|
82
|
+
|
|
83
|
+
**Señales de desincronización**:
|
|
84
|
+
```bash
|
|
85
|
+
# Variables de entorno usadas en el código vs documentadas
|
|
86
|
+
grep -rn "os\.getenv\|process\.env\." --include="*.py" --include="*.ts" \
|
|
87
|
+
| grep -o '"[A-Z_]*"' | sort | uniq > env_en_codigo.txt
|
|
88
|
+
grep "^[A-Z_]*=" .env.example | cut -d= -f1 | sort > env_documentadas.txt
|
|
89
|
+
diff env_en_codigo.txt env_documentadas.txt
|
|
90
|
+
|
|
91
|
+
# Endpoints en el router vs documentados en README
|
|
92
|
+
grep -rn "@router\.\|app\.[get|post|put|delete]" --include="*.py" \
|
|
93
|
+
| grep -o '"[/a-z_{}]*"' | sort > endpoints_reales.txt
|
|
94
|
+
grep -oE '/api/v[0-9]+/[a-z_/{}]*' README.md | sort > endpoints_readme.txt
|
|
95
|
+
diff endpoints_reales.txt endpoints_readme.txt
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Docstrings y comentarios de código
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Funciones públicas sin docstring (Python)
|
|
102
|
+
grep -rn "^def \|^ def " --include="*.py" -A1 | grep -v '"""' | grep "def " | head -30
|
|
103
|
+
|
|
104
|
+
# Docstrings que mencionan parámetros que ya no existen
|
|
105
|
+
# Revisión manual: comparar firma actual con docstring
|
|
106
|
+
|
|
107
|
+
# Comentarios TODO sin ticket
|
|
108
|
+
grep -rn "TODO\|FIXME" --include="*.py" --include="*.ts" | head -20
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### OpenAPI / Swagger desactualizado
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# FastAPI genera el schema automáticamente — verificar que coincide
|
|
115
|
+
# con la versión commiteada en docs/ (si la hay)
|
|
116
|
+
curl http://localhost:8000/openapi.json | python -m json.tool > /tmp/openapi_actual.json
|
|
117
|
+
diff docs/openapi.json /tmp/openapi_actual.json
|
|
118
|
+
|
|
119
|
+
# Si hay diferencias, actualizar el schema commiteado
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Paso 3 — Generar Changelog
|
|
125
|
+
|
|
126
|
+
El changelog documenta QUÉ cambió y POR QUÉ, no solo el listado de commits.
|
|
127
|
+
|
|
128
|
+
### Formato de CHANGELOG.md (Keep a Changelog)
|
|
129
|
+
|
|
130
|
+
```markdown
|
|
131
|
+
# CHANGELOG.md
|
|
132
|
+
|
|
133
|
+
Todos los cambios notables se documentan aquí.
|
|
134
|
+
Formato basado en [Keep a Changelog](https://keepachangelog.com/es/1.0.0/).
|
|
135
|
+
|
|
136
|
+
## [Sin publicar] — En desarrollo
|
|
137
|
+
|
|
138
|
+
## [2.1.0] — 2026-03-25
|
|
139
|
+
|
|
140
|
+
### Añadido
|
|
141
|
+
- Endpoint `GET /api/v1/reportes` con filtrado por fecha y usuario
|
|
142
|
+
- Autenticación con MFA para cuentas con rol ADMIN
|
|
143
|
+
- Soporte para exportación de datos en formato Excel
|
|
144
|
+
|
|
145
|
+
### Cambiado
|
|
146
|
+
- `POST /api/v1/pedidos` ahora requiere campo `bodega_id` (antes opcional)
|
|
147
|
+
- Tiempo de expiración de tokens JWT reducido de 24h a 8h
|
|
148
|
+
|
|
149
|
+
### Deprecado
|
|
150
|
+
- `GET /api/v1/usuarios/lista` — usar `GET /api/v1/usuarios` con paginación
|
|
151
|
+
|
|
152
|
+
### Eliminado
|
|
153
|
+
- Endpoint `POST /api/v1/auth/refresh-all` eliminado por riesgo de seguridad
|
|
154
|
+
|
|
155
|
+
### Corregido
|
|
156
|
+
- Error al calcular descuentos para clientes con múltiples contratos activos
|
|
157
|
+
- Timeout en exportaciones de más de 10,000 registros
|
|
158
|
+
|
|
159
|
+
### Seguridad
|
|
160
|
+
- CVE-2026-XXXXX: actualizado [paquete] de v1.2.3 a v1.2.4
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Cómo generar el changelog desde git
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Ver commits desde el último tag
|
|
167
|
+
git log $(git describe --tags --abbrev=0)..HEAD \
|
|
168
|
+
--pretty=format:"- %s (%h)" --no-merges
|
|
169
|
+
|
|
170
|
+
# Ver qué archivos cambiaron en la última release
|
|
171
|
+
git diff $(git describe --tags --abbrev=0)..HEAD --name-only | sort
|
|
172
|
+
|
|
173
|
+
# Commits por tipo (si usan Conventional Commits)
|
|
174
|
+
git log --pretty=format:"%s" | grep "^feat:" | head -20
|
|
175
|
+
git log --pretty=format:"%s" | grep "^fix:" | head -20
|
|
176
|
+
git log --pretty=format:"%s" | grep "^security:" | head -20
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Paso 4 — Mantener ADRs vigentes
|
|
182
|
+
|
|
183
|
+
Un Architecture Decision Record (ADR) documenta una decisión de arquitectura:
|
|
184
|
+
qué se decidió, por qué, y cuáles eran las alternativas.
|
|
185
|
+
|
|
186
|
+
### Plantilla de ADR
|
|
187
|
+
|
|
188
|
+
```markdown
|
|
189
|
+
# ADR-[NNN]: [Título de la decisión]
|
|
190
|
+
|
|
191
|
+
**Estado**: Propuesto | Aceptado | Obsoleto | Reemplazado por ADR-[NNN]
|
|
192
|
+
**Fecha**: [YYYY-MM-DD]
|
|
193
|
+
**Decidido por**: [nombres o roles]
|
|
194
|
+
|
|
195
|
+
## Contexto
|
|
196
|
+
|
|
197
|
+
[Describir la situación que requirió una decisión. Qué problema existe,
|
|
198
|
+
qué restricciones aplican, qué opciones se consideraron.]
|
|
199
|
+
|
|
200
|
+
## Decisión
|
|
201
|
+
|
|
202
|
+
[La decisión tomada, en tiempo presente: "Usaremos X", "Adoptaremos Y".]
|
|
203
|
+
|
|
204
|
+
## Consecuencias
|
|
205
|
+
|
|
206
|
+
**Positivas**:
|
|
207
|
+
- [beneficio 1]
|
|
208
|
+
- [beneficio 2]
|
|
209
|
+
|
|
210
|
+
**Negativas / trade-offs**:
|
|
211
|
+
- [costo o limitación 1]
|
|
212
|
+
- [costo o limitación 2]
|
|
213
|
+
|
|
214
|
+
## Alternativas consideradas
|
|
215
|
+
|
|
216
|
+
### Alternativa A: [nombre]
|
|
217
|
+
- Ventajas: [lista]
|
|
218
|
+
- Desventajas: [lista]
|
|
219
|
+
- Razón de rechazo: [explicación]
|
|
220
|
+
|
|
221
|
+
### Alternativa B: [nombre]
|
|
222
|
+
- [ídem]
|
|
223
|
+
|
|
224
|
+
## Referencias
|
|
225
|
+
- [Link a issue, PR o documento relevante]
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Cuándo crear un ADR nuevo
|
|
229
|
+
|
|
230
|
+
Crear un ADR cuando se toma una decisión que:
|
|
231
|
+
- Afecta a más de un módulo o equipo
|
|
232
|
+
- Sería difícil o costosa de revertir
|
|
233
|
+
- Un desarrollador futuro podría cuestionar ("¿por qué hicieron esto?")
|
|
234
|
+
- Involucra un trade-off no obvio entre opciones razonables
|
|
235
|
+
|
|
236
|
+
### Cuándo marcar un ADR como "Obsoleto" o "Reemplazado"
|
|
237
|
+
|
|
238
|
+
Cuando el código ya no refleja lo que el ADR dice, actualizar el ADR:
|
|
239
|
+
```markdown
|
|
240
|
+
**Estado**: Reemplazado por ADR-012
|
|
241
|
+
**Nota**: La decisión de usar Redis como cache fue reemplazada por
|
|
242
|
+
Memcached en 2026-01 por restricciones de licencia del cliente.
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
NUNCA eliminar ADRs — son historia del proyecto.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Checklist de sincronización completa
|
|
250
|
+
|
|
251
|
+
- [ ] README.md — instrucciones de instalación verificadas (funcionan paso a paso)
|
|
252
|
+
- [ ] README.md — variables de entorno en `.env.example` coinciden con el código
|
|
253
|
+
- [ ] README.md — comandos de ejecución y tests son correctos
|
|
254
|
+
- [ ] CHANGELOG.md — tiene entrada para todos los cambios de la fase actual
|
|
255
|
+
- [ ] Docstrings — funciones públicas documentadas y descripción coincide con firma
|
|
256
|
+
- [ ] OpenAPI — schema actualizado si se añadieron/modificaron endpoints
|
|
257
|
+
- [ ] ADRs — nuevas decisiones de arquitectura documentadas
|
|
258
|
+
- [ ] ADRs obsoletos — marcados con estado "Obsoleto" o "Reemplazado"
|
|
259
|
+
- [ ] TODOs con ticket — todos los `TODO` en código tienen referencia a issue
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Regla de cierre
|
|
264
|
+
|
|
265
|
+
Ninguna fase se marca como "completada" si la documentación contradice
|
|
266
|
+
el código implementado. La doc desactualizada es deuda técnica de primer nivel.
|
|
267
|
+
|
|
268
|
+
## Cuándo NO cargar
|
|
269
|
+
|
|
270
|
+
- No hay documentación existente que sincronizar — este skill compara docs existentes con el código; si el proyecto no tiene README, ADRs ni docstrings, crear esos artefactos primero con `documentador-swl`.
|
|
271
|
+
- Los únicos artefactos que necesitan actualización son manifiestos SWL internos (INVENTARIO.md, CLAUDE.md, plugin.json) — esa actualización sigue la tabla de propagación de cambios de CLAUDE.md, no el flujo de 4 pasos de este skill.
|
|
272
|
+
- El proyecto lleva más de 30 días sin commits — si no hay cambios en el código, la documentación no puede estar desactualizada respecto al código; el checklist de sincronización no aplica.
|
|
273
|
+
- Se necesita validar integridad estructural del sistema SWL — eso es `validacion-ci-sistema`; este skill valida coherencia entre documentación de usuario y código, no frontmatter de agentes ni exit codes de hooks.
|
|
274
|
+
|
|
275
|
+
## Gotchas / Errores comunes no obvios
|
|
276
|
+
|
|
277
|
+
- **README marcado como desactualizado porque `grep` encontró un nombre de variable cambiado en un comentario**: el Paso 2 busca variables de entorno que aparezcan en el código pero no en `.env.example`, y el agente concluye que el README está obsoleto. Causa: el grep de variables detecta comentarios y strings de ejemplo, no solo declaraciones reales. Solución: al comparar variables de entorno, filtrar por el patrón de uso real (`os.getenv`, `process.env`, `os.environ`) y excluir archivos de ejemplo y tests.
|
|
278
|
+
- **ADR marcado como "Obsoleto" en lugar de "Reemplazado por ADR-NNN"**: el agente marca decisiones revertidas como obsoletas sin crear el ADR de reemplazo primero. Causa: el estado "Obsoleto" se usa cuando no hay decisión sustituta; "Reemplazado" requiere que el ADR sustituto ya exista. Solución: si la decisión fue reemplazada por otra (no solo abandonada), crear el ADR de reemplazo en el mismo commit y referenciar el número — nunca marcar como "Reemplazado por ADR-NNN" si ese ADR no existe aún.
|
|
279
|
+
- **Changelog generado desde `git log` incluye commits de fix de typo y WIP que no son relevantes para usuarios**: el changelog resultante tiene 40 entradas de "fix: typo" y "wip: progress". Causa: `git log --pretty=format:"- %s"` incluye todos los commits sin filtrar. Solución: usar `git log` con filtros por tipo de commit convencional (`feat:`, `fix:`, `security:`, `BREAKING CHANGE:`) y excluir commits de WIP, typo y refactor — el changelog es para consumidores del paquete, no para el historial interno.
|
|
280
|
+
- **OpenAPI diff muestra diferencias por orden de campos en JSON**: `diff docs/openapi.json /tmp/openapi_actual.json` reporta diferencias aunque la API no cambió. Causa: `python -m json.tool` formatea el JSON pero no garantiza orden consistente de campos. Solución: normalizar ambos JSONs con `jq --sort-keys` antes del diff, o comparar solo los paths y schemas con una herramienta de diff semántico de OpenAPI en lugar de diff de texto.
|