@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.
Files changed (702) hide show
  1. package/CLAUDE.md +238 -0
  2. package/README.md +560 -0
  3. package/_userland/agentes/.gitkeep +0 -0
  4. package/_userland/habilidades/.gitkeep +0 -0
  5. package/agentes/.evolved.json +9 -0
  6. package/agentes/accesibilidad-wcag-swl.md +692 -0
  7. package/agentes/arquitecto-swl.md +238 -0
  8. package/agentes/auto-evolucion-swl.md +854 -0
  9. package/agentes/backend-api-swl.md +470 -0
  10. package/agentes/backend-csharp-swl.md +418 -0
  11. package/agentes/backend-go-swl.md +388 -0
  12. package/agentes/backend-java-swl.md +279 -0
  13. package/agentes/backend-node-swl.md +477 -0
  14. package/agentes/backend-python-swl.md +608 -0
  15. package/agentes/backend-rust-swl.md +362 -0
  16. package/agentes/backend-workers-swl.md +480 -0
  17. package/agentes/cloud-infra-swl.md +485 -0
  18. package/agentes/consolidador-swl.md +539 -0
  19. package/agentes/datos-swl.md +584 -0
  20. package/agentes/depurador-swl.md +349 -0
  21. package/agentes/devops-ci-swl.md +374 -0
  22. package/agentes/disenador-ui-swl.md +558 -0
  23. package/agentes/documentador-swl.md +343 -0
  24. package/agentes/evals/arquitecto-swl.evals.json +56 -0
  25. package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
  26. package/agentes/evals/implementador-swl.evals.json +56 -0
  27. package/agentes/evals/orquestador-swl.evals.json +60 -0
  28. package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
  29. package/agentes/evals/red-team-swl.evals.json +59 -0
  30. package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
  31. package/agentes/frontend-angular-swl.md +627 -0
  32. package/agentes/frontend-css-swl.md +720 -0
  33. package/agentes/frontend-react-swl.md +696 -0
  34. package/agentes/frontend-swl.md +500 -0
  35. package/agentes/frontend-tailwind-swl.md +830 -0
  36. package/agentes/implementador-swl.md +328 -0
  37. package/agentes/investigador-swl.md +430 -0
  38. package/agentes/investigador-ux-swl.md +500 -0
  39. package/agentes/llm-apps-swl.md +276 -0
  40. package/agentes/migrador-swl.md +417 -0
  41. package/agentes/mobile-android-swl.md +509 -0
  42. package/agentes/mobile-cross-swl.md +539 -0
  43. package/agentes/mobile-ios-swl.md +500 -0
  44. package/agentes/mobile-testing-swl.md +300 -0
  45. package/agentes/notificador-swl.md +916 -0
  46. package/agentes/observabilidad-swl.md +436 -0
  47. package/agentes/orquestador-swl.md +884 -0
  48. package/agentes/pagos-swl.md +283 -0
  49. package/agentes/perfilador-usuario-swl.md +306 -0
  50. package/agentes/planificador-swl.md +402 -0
  51. package/agentes/producto-prd-swl.md +587 -0
  52. package/agentes/red-team-swl.md +216 -0
  53. package/agentes/release-manager-swl.md +568 -0
  54. package/agentes/rendimiento-swl.md +714 -0
  55. package/agentes/resolutor-build-swl.md +243 -0
  56. package/agentes/revisor-angular-swl.md +276 -0
  57. package/agentes/revisor-codigo-swl.md +348 -0
  58. package/agentes/revisor-csharp-swl.md +262 -0
  59. package/agentes/revisor-go-swl.md +257 -0
  60. package/agentes/revisor-java-swl.md +255 -0
  61. package/agentes/revisor-kotlin-swl.md +271 -0
  62. package/agentes/revisor-nextjs-swl.md +279 -0
  63. package/agentes/revisor-php-swl.md +269 -0
  64. package/agentes/revisor-react-swl.md +276 -0
  65. package/agentes/revisor-rust-swl.md +344 -0
  66. package/agentes/revisor-seguridad-swl.md +390 -0
  67. package/agentes/revisor-swift-swl.md +266 -0
  68. package/agentes/revisor-typescript-swl.md +344 -0
  69. package/agentes/sre-swl.md +265 -0
  70. package/agentes/tdd-qa-swl.md +354 -0
  71. package/agentes/ux-disenador-swl.md +501 -0
  72. package/bin/lib/bot-comandos.js +1030 -0
  73. package/bin/lib/bot-discovery.js +182 -0
  74. package/bin/lib/bot-git.js +142 -0
  75. package/bin/swl-ses.js +325 -0
  76. package/bin/swl-telegram-bot.js +442 -0
  77. package/bin/swl-telegram-bot.plist +21 -0
  78. package/bin/swl-telegram-bot.service +14 -0
  79. package/comandos/swl/.evolved.json +23 -0
  80. package/comandos/swl/actualizar.md +174 -0
  81. package/comandos/swl/adoptar-proyecto.md +207 -0
  82. package/comandos/swl/aprender.md +701 -0
  83. package/comandos/swl/auditar-deps.md +134 -0
  84. package/comandos/swl/autoresearch.md +170 -0
  85. package/comandos/swl/ayuda.md +224 -0
  86. package/comandos/swl/brainstorm.md +50 -0
  87. package/comandos/swl/checkpoint.md +330 -0
  88. package/comandos/swl/compactar.md +283 -0
  89. package/comandos/swl/configurar-ci.md +227 -0
  90. package/comandos/swl/contexto.md +112 -0
  91. package/comandos/swl/contribuir.md +233 -0
  92. package/comandos/swl/crear-skill.md +292 -0
  93. package/comandos/swl/cron.md +196 -0
  94. package/comandos/swl/dashboard.md +146 -0
  95. package/comandos/swl/discutir-fase.md +230 -0
  96. package/comandos/swl/ejecutar-fase.md +135 -0
  97. package/comandos/swl/evaluar-skill.md +487 -0
  98. package/comandos/swl/evolucion-estado.md +142 -0
  99. package/comandos/swl/evolucionar.md +259 -0
  100. package/comandos/swl/exportar-vault.md +189 -0
  101. package/comandos/swl/gateway.md +158 -0
  102. package/comandos/swl/inbox.md +116 -0
  103. package/comandos/swl/instalar.md +220 -0
  104. package/comandos/swl/instintos.md +86 -0
  105. package/comandos/swl/mapear-codebase.md +312 -0
  106. package/comandos/swl/mcp-status.md +175 -0
  107. package/comandos/swl/metricas.md +270 -0
  108. package/comandos/swl/modelo.md +102 -0
  109. package/comandos/swl/notificaciones.md +396 -0
  110. package/comandos/swl/nuevo-proyecto.md +154 -0
  111. package/comandos/swl/planear-fase.md +221 -0
  112. package/comandos/swl/plugins.md +256 -0
  113. package/comandos/swl/reflect-skills.md +125 -0
  114. package/comandos/swl/release.md +217 -0
  115. package/comandos/swl/revisar-impacto.md +206 -0
  116. package/comandos/swl/revisar.md +330 -0
  117. package/comandos/swl/salud.md +363 -0
  118. package/comandos/swl/sesiones.md +200 -0
  119. package/comandos/swl/skill-search.md +113 -0
  120. package/comandos/swl/verificar.md +585 -0
  121. package/comandos/swl/wiki.md +620 -0
  122. package/contextos/dev.md +32 -0
  123. package/contextos/research.md +30 -0
  124. package/contextos/review.md +31 -0
  125. package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
  126. package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
  127. package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
  128. package/habilidades/agent-browser/SKILL.md +218 -0
  129. package/habilidades/agentes-como-servicio/SKILL.md +218 -0
  130. package/habilidades/ai-runtime-security/SKILL.md +273 -0
  131. package/habilidades/angular-avanzado/SKILL.md +164 -0
  132. package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
  133. package/habilidades/angular-moderno/SKILL.md +186 -0
  134. package/habilidades/angular-moderno/evals/evals.json +45 -0
  135. package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
  136. package/habilidades/api-rest-diseno/SKILL.md +191 -0
  137. package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
  138. package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
  139. package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
  140. package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
  141. package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
  142. package/habilidades/async-python/SKILL.md +149 -0
  143. package/habilidades/async-python/evals/evals.json +47 -0
  144. package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
  145. package/habilidades/auth-patrones/.evolved.json +9 -0
  146. package/habilidades/auth-patrones/SKILL.md +413 -0
  147. package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
  148. package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
  149. package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
  150. package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
  151. package/habilidades/autoresearch/SKILL.md +268 -0
  152. package/habilidades/autoresearch/evals/evals.json +41 -0
  153. package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
  154. package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
  155. package/habilidades/azure-cloud/SKILL.md +308 -0
  156. package/habilidades/azure-cloud/recursos/aks.md +327 -0
  157. package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
  158. package/habilidades/backend-production-resilience/SKILL.md +288 -0
  159. package/habilidades/brainstorming/SKILL.md +295 -0
  160. package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
  161. package/habilidades/build-errors-cpp/SKILL.md +270 -0
  162. package/habilidades/build-errors-csharp/SKILL.md +265 -0
  163. package/habilidades/build-errors-go/SKILL.md +306 -0
  164. package/habilidades/build-errors-java/SKILL.md +278 -0
  165. package/habilidades/build-errors-kotlin/SKILL.md +303 -0
  166. package/habilidades/build-errors-nextjs/SKILL.md +312 -0
  167. package/habilidades/build-errors-php/SKILL.md +270 -0
  168. package/habilidades/build-errors-python/SKILL.md +292 -0
  169. package/habilidades/build-errors-rust/SKILL.md +284 -0
  170. package/habilidades/build-errors-swift/SKILL.md +272 -0
  171. package/habilidades/build-errors-typescript/SKILL.md +369 -0
  172. package/habilidades/checklist-calidad/SKILL.md +271 -0
  173. package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
  174. package/habilidades/checklist-seguridad/SKILL.md +285 -0
  175. package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
  176. package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
  177. package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
  178. package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
  179. package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
  180. package/habilidades/cloud-aws/SKILL.md +142 -0
  181. package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
  182. package/habilidades/compactacion-contexto/SKILL.md +247 -0
  183. package/habilidades/contenedores-docker/SKILL.md +137 -0
  184. package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
  185. package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
  186. package/habilidades/context-builder/SKILL.md +170 -0
  187. package/habilidades/control-profundidad/SKILL.md +128 -0
  188. package/habilidades/csharp-experto/SKILL.md +322 -0
  189. package/habilidades/csharp-patrones/SKILL.md +316 -0
  190. package/habilidades/csharp-testing/SKILL.md +286 -0
  191. package/habilidades/css-moderno/SKILL.md +166 -0
  192. package/habilidades/css-moderno/evals/evals.json +43 -0
  193. package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
  194. package/habilidades/datos-etl/SKILL.md +129 -0
  195. package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
  196. package/habilidades/dbml-experto/SKILL.md +339 -0
  197. package/habilidades/dbml-experto/evals/evals.json +56 -0
  198. package/habilidades/dependencias-auditoria/SKILL.md +320 -0
  199. package/habilidades/deprecacion-migracion/SKILL.md +169 -0
  200. package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
  201. package/habilidades/design-tokens/SKILL.md +158 -0
  202. package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
  203. package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
  204. package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
  205. package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
  206. package/habilidades/discutir-fase/SKILL.md +188 -0
  207. package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
  208. package/habilidades/diseno-responsivo/SKILL.md +186 -0
  209. package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
  210. package/habilidades/django-experto/SKILL.md +205 -0
  211. package/habilidades/django-experto/recursos/async-django.md +390 -0
  212. package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
  213. package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
  214. package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
  215. package/habilidades/django-experto/recursos/testing-django.md +415 -0
  216. package/habilidades/doc-sync/SKILL.md +280 -0
  217. package/habilidades/drift-detection/SKILL.md +179 -0
  218. package/habilidades/ejecutar-fase/SKILL.md +468 -0
  219. package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
  220. package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
  221. package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
  222. package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
  223. package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
  224. package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
  225. package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
  226. package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
  227. package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
  228. package/habilidades/evaluacion-agentes/SKILL.md +314 -0
  229. package/habilidades/event-driven/SKILL.md +153 -0
  230. package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
  231. package/habilidades/extraccion-documentos/SKILL.md +221 -0
  232. package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
  233. package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
  234. package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
  235. package/habilidades/fastapi-experto/SKILL.md +221 -0
  236. package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
  237. package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
  238. package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
  239. package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
  240. package/habilidades/filament-admin/SKILL.md +290 -0
  241. package/habilidades/frontend-avanzado/SKILL.md +257 -0
  242. package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
  243. package/habilidades/gcp-cloud/SKILL.md +260 -0
  244. package/habilidades/gcp-cloud/recursos/gke.md +234 -0
  245. package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
  246. package/habilidades/generacion-mermaid/SKILL.md +229 -0
  247. package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
  248. package/habilidades/go-experto/SKILL.md +305 -0
  249. package/habilidades/go-patrones/SKILL.md +299 -0
  250. package/habilidades/go-testing/SKILL.md +291 -0
  251. package/habilidades/graphql-experto/SKILL.md +323 -0
  252. package/habilidades/guardrail-semantico/SKILL.md +282 -0
  253. package/habilidades/harness-claude-code/SKILL.md +299 -0
  254. package/habilidades/iam-secretos/SKILL.md +265 -0
  255. package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
  256. package/habilidades/infra-github-actions/SKILL.md +166 -0
  257. package/habilidades/instalar-sistema/.evolved.json +9 -0
  258. package/habilidades/instalar-sistema/SKILL.md +221 -0
  259. package/habilidades/java-experto/SKILL.md +290 -0
  260. package/habilidades/java-patrones/SKILL.md +275 -0
  261. package/habilidades/java-testing/SKILL.md +288 -0
  262. package/habilidades/kotlin-compose/SKILL.md +278 -0
  263. package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
  264. package/habilidades/kotlin-experto/SKILL.md +318 -0
  265. package/habilidades/kotlin-testing/SKILL.md +267 -0
  266. package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
  267. package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
  268. package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
  269. package/habilidades/langchain-langraph/SKILL.md +386 -0
  270. package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
  271. package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
  272. package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
  273. package/habilidades/legacy-code-rescue/SKILL.md +267 -0
  274. package/habilidades/likec4-experto/SKILL.md +412 -0
  275. package/habilidades/likec4-experto/evals/evals.json +69 -0
  276. package/habilidades/manejo-errores/.evolved.json +9 -0
  277. package/habilidades/manejo-errores/SKILL.md +407 -0
  278. package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
  279. package/habilidades/mapear-codebase/SKILL.md +275 -0
  280. package/habilidades/memoria-busqueda/SKILL.md +194 -0
  281. package/habilidades/memoria-busqueda/evals/evals.json +44 -0
  282. package/habilidades/meta-skills-estandar/SKILL.md +298 -0
  283. package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
  284. package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
  285. package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
  286. package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
  287. package/habilidades/microservicios/SKILL.md +155 -0
  288. package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
  289. package/habilidades/mobile-flutter/SKILL.md +199 -0
  290. package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
  291. package/habilidades/mobile-react-native/SKILL.md +176 -0
  292. package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
  293. package/habilidades/mongodb-experto/SKILL.md +302 -0
  294. package/habilidades/monitoring-alertas/SKILL.md +201 -0
  295. package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
  296. package/habilidades/nestjs-experto/SKILL.md +307 -0
  297. package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
  298. package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
  299. package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
  300. package/habilidades/nextjs-experto/SKILL.md +335 -0
  301. package/habilidades/nextjs-patrones/SKILL.md +303 -0
  302. package/habilidades/nextjs-testing/SKILL.md +331 -0
  303. package/habilidades/node-experto/.evolved.json +9 -0
  304. package/habilidades/node-experto/SKILL.md +266 -0
  305. package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
  306. package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
  307. package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
  308. package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
  309. package/habilidades/nuevo-proyecto/SKILL.md +204 -0
  310. package/habilidades/orquestacion-async/SKILL.md +303 -0
  311. package/habilidades/paid-media-tracking/SKILL.md +269 -0
  312. package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
  313. package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
  314. package/habilidades/patrones-python/SKILL.md +228 -0
  315. package/habilidades/patrones-python/evals/evals.json +56 -0
  316. package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
  317. package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
  318. package/habilidades/perfil-usuario/SKILL.md +200 -0
  319. package/habilidades/perfil-usuario/evals/evals.json +55 -0
  320. package/habilidades/performance-baseline/SKILL.md +297 -0
  321. package/habilidades/php-experto/SKILL.md +291 -0
  322. package/habilidades/php-patrones/SKILL.md +306 -0
  323. package/habilidades/php-testing/SKILL.md +280 -0
  324. package/habilidades/planear-fase/SKILL.md +269 -0
  325. package/habilidades/postgresql-experto/SKILL.md +151 -0
  326. package/habilidades/postgresql-experto/evals/evals.json +53 -0
  327. package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
  328. package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
  329. package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
  330. package/habilidades/privacy-memoria/SKILL.md +141 -0
  331. package/habilidades/privacy-memoria/evals/evals.json +43 -0
  332. package/habilidades/prompt-engineering/SKILL.md +518 -0
  333. package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
  334. package/habilidades/rag-arquitectura/SKILL.md +338 -0
  335. package/habilidades/rails-experto/SKILL.md +237 -0
  336. package/habilidades/rails-experto/recursos/active-record.md +260 -0
  337. package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
  338. package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
  339. package/habilidades/react-experto/SKILL.md +209 -0
  340. package/habilidades/react-experto/evals/evals.json +55 -0
  341. package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
  342. package/habilidades/react-optimizacion/SKILL.md +174 -0
  343. package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
  344. package/habilidades/redis-experto/SKILL.md +305 -0
  345. package/habilidades/release-semver/.evolved.json +9 -0
  346. package/habilidades/release-semver/SKILL.md +248 -0
  347. package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
  348. package/habilidades/rust-experto/SKILL.md +400 -0
  349. package/habilidades/rust-patrones/SKILL.md +296 -0
  350. package/habilidades/rust-testing/SKILL.md +311 -0
  351. package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
  352. package/habilidades/sql-optimizacion/SKILL.md +200 -0
  353. package/habilidades/sql-optimizacion/evals/evals.json +54 -0
  354. package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
  355. package/habilidades/sre-patrones/SKILL.md +333 -0
  356. package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
  357. package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
  358. package/habilidades/stripe-pagos/SKILL.md +550 -0
  359. package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
  360. package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
  361. package/habilidades/structured-outputs/SKILL.md +343 -0
  362. package/habilidades/swift-experto/SKILL.md +320 -0
  363. package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
  364. package/habilidades/swift-patrones/SKILL.md +313 -0
  365. package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
  366. package/habilidades/swift-testing/SKILL.md +254 -0
  367. package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
  368. package/habilidades/swl-dashboard/SKILL.md +370 -0
  369. package/habilidades/swl-markitdown/SKILL.md +285 -0
  370. package/habilidades/swl-markitdown/evals/evals.json +52 -0
  371. package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
  372. package/habilidades/tailwind-experto/SKILL.md +240 -0
  373. package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
  374. package/habilidades/tdd-workflow/SKILL.md +293 -0
  375. package/habilidades/terraform-experto/SKILL.md +321 -0
  376. package/habilidades/testing-python/SKILL.md +340 -0
  377. package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
  378. package/habilidades/threat-model-lite/SKILL.md +246 -0
  379. package/habilidades/tracing-processor/SKILL.md +212 -0
  380. package/habilidades/tracking-measurement/SKILL.md +239 -0
  381. package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
  382. package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
  383. package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
  384. package/habilidades/typescript-avanzado/SKILL.md +144 -0
  385. package/habilidades/typescript-avanzado/evals/evals.json +55 -0
  386. package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
  387. package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
  388. package/habilidades/ux-diseno/SKILL.md +116 -0
  389. package/habilidades/ux-diseno/evals/evals.json +43 -0
  390. package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
  391. package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
  392. package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
  393. package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
  394. package/habilidades/verificacion-evidencia/SKILL.md +160 -0
  395. package/habilidades/verificar-trabajo/SKILL.md +303 -0
  396. package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
  397. package/habilidades/wiki-conocimiento/SKILL.md +276 -0
  398. package/habilidades/wireframes-flujos/SKILL.md +212 -0
  399. package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
  400. package/habilidades/workflow-claude-code/SKILL.md +260 -0
  401. package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
  402. package/hooks/_run-hook.sh +57 -0
  403. package/hooks/actualizar-perfil-usuario.js +364 -0
  404. package/hooks/agente-lifecycle.js +71 -0
  405. package/hooks/aiisms-detector.js +173 -0
  406. package/hooks/audit-trail.js +204 -0
  407. package/hooks/auto-background.js +97 -0
  408. package/hooks/auto-consolidacion.js +178 -0
  409. package/hooks/auto-evolucion.js +666 -0
  410. package/hooks/auto-restaurar-settings.js +360 -0
  411. package/hooks/calidad-pre-commit.js +929 -0
  412. package/hooks/calidad-typescript.js +511 -0
  413. package/hooks/captura-feedback-usuario.js +148 -0
  414. package/hooks/check-update.js +211 -0
  415. package/hooks/clasificador-mensajes.js +271 -0
  416. package/hooks/degradacion-instintos.js +272 -0
  417. package/hooks/escaneo-secretos.js +389 -0
  418. package/hooks/extraccion-aprendizajes.js +763 -0
  419. package/hooks/grafo-contexto.js +129 -0
  420. package/hooks/graph-update.js +67 -0
  421. package/hooks/guardrail-modelo.js +247 -0
  422. package/hooks/inbox-aviso.js +75 -0
  423. package/hooks/inyeccion-contexto.js +246 -0
  424. package/hooks/lib/abort-registry.js +214 -0
  425. package/hooks/lib/agent-backend.js +210 -0
  426. package/hooks/lib/agent-comms.js +263 -0
  427. package/hooks/lib/agent-issue-codes.js +284 -0
  428. package/hooks/lib/agent-matcher.js +189 -0
  429. package/hooks/lib/async-hook-registry.js +252 -0
  430. package/hooks/lib/atomic-write.js +130 -0
  431. package/hooks/lib/auto-consolidator.js +335 -0
  432. package/hooks/lib/canary-skills.js +187 -0
  433. package/hooks/lib/consolidation-lock.js +291 -0
  434. package/hooks/lib/context-builder.js +430 -0
  435. package/hooks/lib/context-compressor.js +657 -0
  436. package/hooks/lib/convergence-detector.js +105 -0
  437. package/hooks/lib/delegation-tracker.js +198 -0
  438. package/hooks/lib/detectar-package-manager.js +423 -0
  439. package/hooks/lib/edit-accumulator.js +171 -0
  440. package/hooks/lib/error-classifier.js +308 -0
  441. package/hooks/lib/event-bus.js +112 -0
  442. package/hooks/lib/evolution-tracker.js +442 -0
  443. package/hooks/lib/execution-state.js +316 -0
  444. package/hooks/lib/fingerprint-id.js +135 -0
  445. package/hooks/lib/gateway-notify.js +116 -0
  446. package/hooks/lib/graph-security.js +75 -0
  447. package/hooks/lib/guardrail-metrics.js +202 -0
  448. package/hooks/lib/hook-circuit-breaker.js +206 -0
  449. package/hooks/lib/loop-detector.js +267 -0
  450. package/hooks/lib/mcp-health.js +184 -0
  451. package/hooks/lib/mcp-pool.js +436 -0
  452. package/hooks/lib/memory-search.js +506 -0
  453. package/hooks/lib/merkle-audit.js +96 -0
  454. package/hooks/lib/model-router.js +222 -0
  455. package/hooks/lib/normalize-error.js +324 -0
  456. package/hooks/lib/normalize-input.js +65 -0
  457. package/hooks/lib/nudge-tracker.js +306 -0
  458. package/hooks/lib/otlp-exporter.js +365 -0
  459. package/hooks/lib/performance-marks.js +239 -0
  460. package/hooks/lib/privacy-filter.js +128 -0
  461. package/hooks/lib/prompt-injection-scanner.js +209 -0
  462. package/hooks/lib/provenance-tracker.js +183 -0
  463. package/hooks/lib/rate-limit-tracker.js +253 -0
  464. package/hooks/lib/reflect-classifier.js +164 -0
  465. package/hooks/lib/resource-quota.js +122 -0
  466. package/hooks/lib/retry-jitter.js +165 -0
  467. package/hooks/lib/risk-engine.js +368 -0
  468. package/hooks/lib/run-log.js +408 -0
  469. package/hooks/lib/session-fts.js +379 -0
  470. package/hooks/lib/session-store.js +293 -0
  471. package/hooks/lib/singleton-guard.js +159 -0
  472. package/hooks/lib/skill-auditor.js +588 -0
  473. package/hooks/lib/sync-status.js +228 -0
  474. package/hooks/lib/taint-tracker.js +107 -0
  475. package/hooks/lib/task-service.js +295 -0
  476. package/hooks/lib/tech-skills-map.js +146 -0
  477. package/hooks/lib/telegram-cliente.js +159 -0
  478. package/hooks/lib/telegram-config.js +170 -0
  479. package/hooks/lib/token-budget.js +156 -0
  480. package/hooks/lib/token-estimator.js +420 -0
  481. package/hooks/lib/toon-compressor.js +245 -0
  482. package/hooks/lib/usage-model.js +183 -0
  483. package/hooks/lib/variable-resolver.js +230 -0
  484. package/hooks/linea-estado.js +324 -0
  485. package/hooks/metricas-evolucion.js +209 -0
  486. package/hooks/monitor-contexto.js +325 -0
  487. package/hooks/notificacion-sesion-stop.js +198 -0
  488. package/hooks/notificacion-telegram-notification.js +4 -0
  489. package/hooks/notificacion-telegram-subagent.js +4 -0
  490. package/hooks/notificacion-telegram.js +267 -0
  491. package/hooks/preservar-estado-pre-compact.js +150 -0
  492. package/hooks/proteccion-rutas.js +366 -0
  493. package/hooks/registro-turnos.js +209 -0
  494. package/hooks/resumen-sesion.js +249 -0
  495. package/hooks/risk-scoring.js +323 -0
  496. package/hooks/rotar-audit-auto.js +122 -0
  497. package/hooks/sugerir-regenerar-inventario.js +170 -0
  498. package/hooks/telemetria-agentes.js +167 -0
  499. package/hooks/tracking-costos.js +688 -0
  500. package/instintos/global.yaml +8 -0
  501. package/instintos/perfil-usuario.yaml +53 -0
  502. package/instintos/prompt-appendices.yaml +57 -0
  503. package/instintos/proyecto.yaml +372 -0
  504. package/manifiestos/gateway-config.json +77 -0
  505. package/manifiestos/handoff-context.json +223 -0
  506. package/manifiestos/hook-profiles.json +44 -0
  507. package/manifiestos/hooks-config.json +360 -0
  508. package/manifiestos/modulos.json +1173 -0
  509. package/manifiestos/perfiles.json +404 -0
  510. package/package.json +86 -0
  511. package/plantillas/ESTADO.md +109 -0
  512. package/plantillas/HOJA-RUTA.md +143 -0
  513. package/plantillas/PROYECTO.md +122 -0
  514. package/plantillas/REQUISITOS.md +132 -0
  515. package/plantillas/auditor-veto-template.md +105 -0
  516. package/plantillas/github-workflows/README.md +47 -0
  517. package/plantillas/github-workflows/release-please.yml +44 -0
  518. package/plantillas/github-workflows/swl-ci.yml +107 -0
  519. package/plantillas/github-workflows/swl-security.yml +51 -0
  520. package/plantillas/mcp-mineru.json +13 -0
  521. package/plantillas/research/ARQUITECTURA.md +220 -0
  522. package/plantillas/research/FUNCIONALIDADES.md +175 -0
  523. package/plantillas/research/RESUMEN.md +165 -0
  524. package/plantillas/research/STACK.md +233 -0
  525. package/plantillas/research/TRAMPAS.md +299 -0
  526. package/plantillas/skill-evals-template.json +44 -0
  527. package/plugin.json +343 -0
  528. package/reglas/accesibilidad.md +269 -0
  529. package/reglas/api-diseno.md +400 -0
  530. package/reglas/arquitectura.md +352 -0
  531. package/reglas/brevedad-output.md +124 -0
  532. package/reglas/cloud-infra.md +247 -0
  533. package/reglas/docs.md +245 -0
  534. package/reglas/estilo-codigo.md +201 -0
  535. package/reglas/git-workflow.md +245 -0
  536. package/reglas/gobernanza.md +271 -0
  537. package/reglas/harness-claude-code.md +213 -0
  538. package/reglas/hooks.md +186 -0
  539. package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
  540. package/reglas/lenguajes/csharp/hooks.md +281 -0
  541. package/reglas/lenguajes/csharp/patrones.md +226 -0
  542. package/reglas/lenguajes/csharp/seguridad.md +258 -0
  543. package/reglas/lenguajes/csharp/testing.md +176 -0
  544. package/reglas/lenguajes/go/estilo-codigo.md +195 -0
  545. package/reglas/lenguajes/go/hooks.md +249 -0
  546. package/reglas/lenguajes/go/patrones.md +249 -0
  547. package/reglas/lenguajes/go/seguridad.md +225 -0
  548. package/reglas/lenguajes/go/testing.md +272 -0
  549. package/reglas/lenguajes/java/estilo-codigo.md +217 -0
  550. package/reglas/lenguajes/java/hooks.md +251 -0
  551. package/reglas/lenguajes/java/patrones.md +226 -0
  552. package/reglas/lenguajes/java/seguridad.md +233 -0
  553. package/reglas/lenguajes/java/testing.md +238 -0
  554. package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
  555. package/reglas/lenguajes/kotlin/hooks.md +245 -0
  556. package/reglas/lenguajes/kotlin/patrones.md +201 -0
  557. package/reglas/lenguajes/kotlin/seguridad.md +202 -0
  558. package/reglas/lenguajes/kotlin/testing.md +236 -0
  559. package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
  560. package/reglas/lenguajes/nextjs/hooks.md +186 -0
  561. package/reglas/lenguajes/nextjs/patrones.md +225 -0
  562. package/reglas/lenguajes/nextjs/seguridad.md +216 -0
  563. package/reglas/lenguajes/nextjs/testing.md +193 -0
  564. package/reglas/lenguajes/php/estilo-codigo.md +228 -0
  565. package/reglas/lenguajes/php/hooks.md +165 -0
  566. package/reglas/lenguajes/php/patrones.md +233 -0
  567. package/reglas/lenguajes/php/seguridad.md +186 -0
  568. package/reglas/lenguajes/php/testing.md +205 -0
  569. package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
  570. package/reglas/lenguajes/rust/hooks.md +240 -0
  571. package/reglas/lenguajes/rust/patrones.md +250 -0
  572. package/reglas/lenguajes/rust/seguridad.md +221 -0
  573. package/reglas/lenguajes/rust/testing.md +194 -0
  574. package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
  575. package/reglas/lenguajes/swift/hooks.md +257 -0
  576. package/reglas/lenguajes/swift/patrones.md +235 -0
  577. package/reglas/lenguajes/swift/seguridad.md +248 -0
  578. package/reglas/lenguajes/swift/testing.md +242 -0
  579. package/reglas/markitdown.md +60 -0
  580. package/reglas/memoria-consolidada.md +209 -0
  581. package/reglas/patrones.md +225 -0
  582. package/reglas/performance.md +195 -0
  583. package/reglas/pruebas.md +159 -0
  584. package/reglas/seguridad-agentes.md +351 -0
  585. package/reglas/seguridad.md +151 -0
  586. package/reglas/skills-estandar.md +373 -0
  587. package/reglas/testing.md +193 -0
  588. package/schemas/agent-contract.json +176 -0
  589. package/schemas/agent-frontmatter.schema.json +149 -0
  590. package/schemas/agent-message.schema.json +53 -0
  591. package/schemas/agent-output-implementacion.schema.json +85 -0
  592. package/schemas/agent-output-planificacion.schema.json +113 -0
  593. package/schemas/agent-output-review.schema.json +78 -0
  594. package/schemas/diary-entry.schema.json +80 -0
  595. package/schemas/hook-profiles.schema.json +39 -0
  596. package/schemas/hooks-config.schema.json +74 -0
  597. package/schemas/instinct.schema.json +115 -0
  598. package/schemas/modulos.schema.json +29 -0
  599. package/schemas/perfiles.schema.json +28 -0
  600. package/schemas/plugin.schema.json +64 -0
  601. package/schemas/skill-evals.schema.json +95 -0
  602. package/schemas/skill-frontmatter.schema.json +170 -0
  603. package/scripts/actualizar.js +145 -0
  604. package/scripts/audit-skills.sh +78 -0
  605. package/scripts/auditar-agentes-gaps.js +149 -0
  606. package/scripts/auditar-cobertura-frameworks.js +241 -0
  607. package/scripts/auditar-skills-gaps.js +206 -0
  608. package/scripts/bootstrap-instintos.js +259 -0
  609. package/scripts/check-update.js +109 -0
  610. package/scripts/comandos/agents.js +105 -0
  611. package/scripts/comandos/info.js +108 -0
  612. package/scripts/comandos/install-asistido.js +186 -0
  613. package/scripts/comandos/skills.js +211 -0
  614. package/scripts/configurar-branch-protection.js +418 -0
  615. package/scripts/daemon-swl.py +388 -0
  616. package/scripts/desinstalar.js +130 -0
  617. package/scripts/doctor.js +559 -0
  618. package/scripts/field-report.js +199 -0
  619. package/scripts/generar-inventario.js +317 -0
  620. package/scripts/inbox-tmux-inject.js +161 -0
  621. package/scripts/inferir-herramientas-permitidas.js +586 -0
  622. package/scripts/inicializar.js +133 -0
  623. package/scripts/instalador.js +1031 -0
  624. package/scripts/instalar-git-hook.js +122 -0
  625. package/scripts/lib/agp-frontmatter.js +222 -0
  626. package/scripts/lib/append-con-marcadores.js +199 -0
  627. package/scripts/lib/artefactos-python.js +43 -0
  628. package/scripts/lib/audit-query.js +221 -0
  629. package/scripts/lib/autostart-linux.js +347 -0
  630. package/scripts/lib/autostart-macos.js +360 -0
  631. package/scripts/lib/autostart-windows.js +307 -0
  632. package/scripts/lib/budget-enforcer.js +252 -0
  633. package/scripts/lib/claude-sessions.js +285 -0
  634. package/scripts/lib/configurar-ci.js +380 -0
  635. package/scripts/lib/console-span-exporter.js +92 -0
  636. package/scripts/lib/contadores-inventario.js +217 -0
  637. package/scripts/lib/dashboard-widgets.js +290 -0
  638. package/scripts/lib/detectar-runtime.js +279 -0
  639. package/scripts/lib/detectar-stack.js +187 -0
  640. package/scripts/lib/diary-entry.js +234 -0
  641. package/scripts/lib/drift-detector.js +545 -0
  642. package/scripts/lib/estado.js +124 -0
  643. package/scripts/lib/gestor-componentes.js +243 -0
  644. package/scripts/lib/gitignore-manifest.js +305 -0
  645. package/scripts/lib/graph-analyze.py +556 -0
  646. package/scripts/lib/graph-builder.py +485 -0
  647. package/scripts/lib/graph-cluster.py +259 -0
  648. package/scripts/lib/health-row.js +168 -0
  649. package/scripts/lib/hooks-settings.js +789 -0
  650. package/scripts/lib/manifiestos.js +138 -0
  651. package/scripts/lib/mc-client.js +137 -0
  652. package/scripts/lib/notificaciones-telegram.js +1107 -0
  653. package/scripts/lib/npm-version.js +261 -0
  654. package/scripts/lib/paquetes-conocidos.js +50 -0
  655. package/scripts/lib/preservar-usuario.js +586 -0
  656. package/scripts/lib/prompt-builder.js +264 -0
  657. package/scripts/lib/resolver-externo.js +332 -0
  658. package/scripts/lib/schedule-parser.js +305 -0
  659. package/scripts/lib/scoring-instintos.js +240 -0
  660. package/scripts/lib/seguridad.js +160 -0
  661. package/scripts/lib/selector-interactivo.js +152 -0
  662. package/scripts/lib/semantic-search.js +242 -0
  663. package/scripts/lib/skill-discovery.js +234 -0
  664. package/scripts/lib/skill-metrics.js +246 -0
  665. package/scripts/lib/skill-normalizer.js +112 -0
  666. package/scripts/lib/skills-hub.js +340 -0
  667. package/scripts/lib/span-schema.js +134 -0
  668. package/scripts/lib/tool-cost-analyzer.js +255 -0
  669. package/scripts/lib/tracing-processor-interface.js +286 -0
  670. package/scripts/lib/transformadores/base.js +80 -0
  671. package/scripts/lib/transformadores/claude.js +124 -0
  672. package/scripts/lib/transformadores/codex.js +115 -0
  673. package/scripts/lib/transformadores/copilot.js +106 -0
  674. package/scripts/lib/transformadores/gemini.js +74 -0
  675. package/scripts/lib/transformadores/index.js +35 -0
  676. package/scripts/lib/transformadores/opencode.js +75 -0
  677. package/scripts/lib/ui.js +259 -0
  678. package/scripts/limpiar-artefactos-python.js +131 -0
  679. package/scripts/mcp-orchestrator.py +386 -0
  680. package/scripts/mcp-pool-manager.py +352 -0
  681. package/scripts/mcp-telemetry.py +378 -0
  682. package/scripts/poblar-evolvable.js +226 -0
  683. package/scripts/publicar.js +287 -0
  684. package/scripts/reflect-skills.js +403 -0
  685. package/scripts/rotar-audit-logs.js +185 -0
  686. package/scripts/run-skill-evals.js +242 -0
  687. package/scripts/smoke-test.js +374 -0
  688. package/scripts/token-analysis.py +471 -0
  689. package/scripts/validar-manifest.js +195 -0
  690. package/scripts/validar-memoria.js +321 -0
  691. package/scripts/validar-tests-aislamiento.js +184 -0
  692. package/scripts/validar-tokens-test.js +208 -0
  693. package/scripts/validar.js +147 -0
  694. package/scripts/validate-markdown.py +339 -0
  695. package/scripts/validate-skills.py +385 -0
  696. package/scripts/vendor/claude-usage/README.md +116 -0
  697. package/scripts/vendor/claude-usage/cli.py +334 -0
  698. package/scripts/vendor/claude-usage/dashboard.py +795 -0
  699. package/scripts/vendor/claude-usage/scanner.py +467 -0
  700. package/scripts/vendor/markitdown/cli.py +194 -0
  701. package/scripts/verificar-evolucion.js +289 -0
  702. package/scripts/verificar-release.js +494 -0
@@ -0,0 +1,205 @@
1
+ ---
2
+ name: django-experto
3
+ description: >
4
+ Patrones de producción para Django: ORM avanzado (select_related, prefetch_related,
5
+ F/Q expressions, anotaciones), migraciones con datos, signals, Django REST Framework,
6
+ Channels y testing con pytest-django. Cargar cuando se implemente cualquier
7
+ componente Django: modelos, vistas, serializers, APIs REST, WebSockets o tareas Celery.
8
+ version: "1.0.0"
9
+ herramientasPermitidas: [Read]
10
+ exclusiones:
11
+ - "No cargar para proyectos FastAPI — el ORM sync de Django y el sistema de migrations no aplican a SQLAlchemy async; cargar `fastapi-experto`."
12
+ - "No cargar para scripting Python standalone que no use el stack de Django (manage.py, settings, apps) — si no hay `DJANGO_SETTINGS_MODULE`, los patrones de este skill no aplican; cargar `patrones-python`."
13
+ - "No cargar para optimizar queries SQL en bases de datos no gestionadas por el ORM de Django — para PostgreSQL raw o sin Django ORM, cargar `sql-optimizacion` o `postgresql-experto`."
14
+ - "No cargar para tareas Celery que no tienen relación con modelos Django — si la tarea Celery es procesamiento puro sin acceso al ORM, cargar `async-python` o `orquestacion-async`."
15
+ evolvable: true # default para skill estandar
16
+ ---
17
+ # Django Experto
18
+
19
+ ## Cuándo NO cargar
20
+
21
+ - El proyecto usa FastAPI — los patrones de ORM async y DI son distintos; cargar `fastapi-experto`.
22
+ - No hay `DJANGO_SETTINGS_MODULE` en el contexto — si no es un proyecto Django, los patrones no aplican.
23
+ - La optimización de queries es para PostgreSQL sin ORM de Django — cargar `sql-optimizacion`.
24
+
25
+ ## Estructura de proyecto recomendada
26
+
27
+ ```
28
+ proyecto/
29
+ ├── config/
30
+ │ ├── settings/
31
+ │ │ ├── base.py # Configuración base
32
+ │ │ ├── development.py
33
+ │ │ └── production.py
34
+ │ ├── urls.py
35
+ │ └── wsgi.py / asgi.py
36
+ ├── apps/
37
+ │ ├── usuarios/ # Cada app es un módulo de negocio
38
+ │ │ ├── models.py
39
+ │ │ ├── views.py
40
+ │ │ ├── serializers.py
41
+ │ │ ├── urls.py
42
+ │ │ ├── signals.py
43
+ │ │ ├── admin.py
44
+ │ │ └── tests/
45
+ │ └── facturas/
46
+ ├── common/ # Código compartido entre apps
47
+ │ ├── models.py # Modelos abstractos base
48
+ │ ├── permissions.py
49
+ │ └── pagination.py
50
+ └── manage.py
51
+ ```
52
+
53
+ ---
54
+
55
+ ## ORM Avanzado
56
+
57
+ ### select_related y prefetch_related
58
+
59
+ ```python
60
+ # NUNCA: N+1 queries
61
+ facturas = Factura.objects.all()
62
+ for factura in facturas:
63
+ print(factura.cliente.nombre) # 1 query por factura
64
+
65
+ # BIEN: select_related para FK/OneToOne (JOIN)
66
+ facturas = Factura.objects.select_related("cliente", "empresa").all()
67
+
68
+ # BIEN: prefetch_related para ManyToMany y relaciones inversas
69
+ facturas = Factura.objects.prefetch_related("items", "items__producto").all()
70
+
71
+ # Prefetch con queryset personalizado
72
+ from django.db.models import Prefetch
73
+
74
+ facturas = Factura.objects.prefetch_related(
75
+ Prefetch(
76
+ "items",
77
+ queryset=ItemFactura.objects.filter(activo=True).select_related("producto"),
78
+ to_attr="items_activos",
79
+ )
80
+ ).all()
81
+ ```
82
+
83
+ ### Anotaciones y agregaciones
84
+
85
+ ```python
86
+ from django.db.models import Sum, Count, F, Q
87
+
88
+ # Anotar totales calculados en la base de datos
89
+ facturas = Factura.objects.annotate(
90
+ total_calculado=Sum(F("items__cantidad") * F("items__precio_unitario")),
91
+ num_items=Count("items"),
92
+ ).filter(total_calculado__gt=1000)
93
+
94
+ # Filtros complejos con Q
95
+ facturas_pendientes = Factura.objects.filter(
96
+ Q(estatus="pendiente") | Q(estatus="vencida"),
97
+ empresa=empresa_actual,
98
+ ).exclude(cancelada=True)
99
+ ```
100
+
101
+ ### F expressions para actualizaciones atómicas
102
+
103
+ ```python
104
+ from django.db.models import F
105
+
106
+ # Incrementar sin race condition
107
+ Producto.objects.filter(id=producto_id).update(
108
+ stock=F("stock") - cantidad_vendida
109
+ )
110
+ ```
111
+
112
+ ### Modelo base abstracto
113
+
114
+ ```python
115
+ # common/models.py
116
+ import uuid
117
+ from django.db import models
118
+
119
+ class ModeloBase(models.Model):
120
+ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
121
+ creado_en = models.DateTimeField(auto_now_add=True)
122
+ actualizado_en = models.DateTimeField(auto_now=True)
123
+ creado_por = models.EmailField(max_length=255, blank=True)
124
+ actualizado_por = models.EmailField(max_length=255, blank=True)
125
+
126
+ class Meta:
127
+ abstract = True
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Migraciones
133
+
134
+ ### Migraciones con datos (data migrations)
135
+
136
+ ```python
137
+ # migrations/0023_migrar_estatus_factura.py
138
+ from django.db import migrations
139
+
140
+ def migrar_estatus(apps, schema_editor):
141
+ Factura = apps.get_model("facturas", "Factura")
142
+ Factura.objects.filter(estatus="activa").update(estatus="emitida")
143
+
144
+ def revertir_migrar_estatus(apps, schema_editor):
145
+ Factura = apps.get_model("facturas", "Factura")
146
+ Factura.objects.filter(estatus="emitida").update(estatus="activa")
147
+
148
+ class Migration(migrations.Migration):
149
+ dependencies = [("facturas", "0022_factura_estatus_choices")]
150
+ operations = [
151
+ migrations.RunPython(migrar_estatus, revertir_migrar_estatus),
152
+ ]
153
+ ```
154
+
155
+ ### Optimizaciones en migraciones de producción
156
+
157
+ Para tablas grandes: agregar columna nullable primero, luego data migration,
158
+ luego NOT NULL en siguiente deploy. Esto evita bloqueo de tabla.
159
+
160
+ ---
161
+
162
+ ## Signals
163
+
164
+ ```python
165
+ # apps/facturas/signals.py
166
+ from django.db.models.signals import post_save
167
+ from django.dispatch import receiver
168
+ from .models import Factura
169
+
170
+ @receiver(post_save, sender=Factura)
171
+ def notificar_cambio_estatus(sender, instance, created, **kwargs):
172
+ if not created and instance.tracker.has_changed("estatus"):
173
+ estatus_anterior = instance.tracker.previous("estatus")
174
+ notificacion_service.enviar(
175
+ usuario_id=instance.cliente_id,
176
+ tipo="CAMBIO_ESTATUS_FACTURA",
177
+ datos={"anterior": estatus_anterior, "nuevo": instance.estatus},
178
+ )
179
+
180
+ # Conectar signals en AppConfig (apps/facturas/apps.py)
181
+ class FacturasConfig(AppConfig):
182
+ default_auto_field = "django.db.models.BigAutoField"
183
+ name = "apps.facturas"
184
+
185
+ def ready(self):
186
+ import apps.facturas.signals # noqa: F401
187
+ ```
188
+
189
+ ---
190
+
191
+ ## Gotchas / Errores comunes no obvios
192
+
193
+ - **`select_related('empresa__ciudad')` carga la relación pero la query sigue siendo lenta en producción**: `select_related` hace un JOIN en SQL, pero si la tabla `empresa` tiene millones de registros, el JOIN puede ser más caro que dos queries separadas. Causa: `select_related` no siempre es más eficiente que `prefetch_related` — para relaciones de muchos-a-uno con alta cardinalidad, `prefetch_related` puede ser mejor porque hace una query separada con `IN`. Solución: comparar con `EXPLAIN ANALYZE` ambas aproximaciones antes de decidir — la elección depende de los datos reales, no de una regla absoluta.
194
+ - **Migration que agrega columna `NOT NULL` sin default falla en producción con millones de filas pero pasa en tests con datos vacíos**: `ALTER TABLE ADD COLUMN NOT NULL` en PostgreSQL adquiere un `ACCESS EXCLUSIVE LOCK` sobre la tabla completa durante la reescritura. Causa: en tests la tabla está vacía y la operación es instantánea; en producción con millones de filas, la tabla queda bloqueada segundos o minutos. Solución: para columnas NOT NULL en tablas grandes: (1) agregar columna `NULL` primero, (2) hacer backfill con `update_fields`, (3) agregar constraint NOT NULL con `NOT VALID`, (4) validar en una ventana de mantenimiento.
195
+ - **Signal `post_save` llama a código que lanza excepción, dejando la transacción en estado inconsistente**: la signal se ejecuta dentro de la transacción de `save()`, y si la signal falla, la transacción puede quedar en un estado de error que impide más queries. Causa: Django ejecuta signals síncronamente dentro de la transacción activa — si el código de la signal falla, la transacción original también puede fallar. Solución: usar `transaction.on_commit(lambda: mi_tarea.delay())` para code que debe ejecutarse después del commit exitoso, especialmente para llamadas a Celery o servicios externos.
196
+ - **DRF `SerializerMethodField` que accede a `request.user` devuelve `AnonymousUser` en tests aunque el test está autenticado**: el contexto del serializer no se pasa automáticamente cuando se instancia el serializer directamente en tests. Causa: en la vista, DRF pasa `context={'request': request}` al serializer automáticamente, pero al instanciar `MySerializer(instance)` directamente en tests sin el contexto, `self.context.get('request')` devuelve `None`. Solución: pasar el contexto explícitamente: `MySerializer(instance, context={'request': mock_request})`.
197
+
198
+ ## Referencias especializadas
199
+
200
+ | Tema | Archivo |
201
+ |------|---------|
202
+ | Custom QuerySets, F/Q expressions, window functions, bulk ops | [recursos/orm-avanzado.md](recursos/orm-avanzado.md) |
203
+ | ViewSets, Serializers, filtros, paginación, throttling, versioning | [recursos/drf-patrones.md](recursos/drf-patrones.md) |
204
+ | pytest-django, Factory Boy, fixtures, mocking, performance | [recursos/testing-django.md](recursos/testing-django.md) |
205
+ | Async views, Channels, WebSockets, Celery, ASGI | [recursos/async-django.md](recursos/async-django.md) |
@@ -0,0 +1,390 @@
1
+ # Django Async y Channels — Patrones de Producción
2
+
3
+ ## Async views: cuándo y cómo usarlas
4
+
5
+ Django soporta vistas async desde la versión 3.1. Una vista async permite liberar
6
+ el hilo mientras espera I/O (llamadas HTTP externas, operaciones de archivos),
7
+ pero el ORM de Django es **síncrono**: cada query bloquea. La solución es
8
+ `sync_to_async`.
9
+
10
+ ```python
11
+ # apps/reportes/views.py
12
+ import asyncio
13
+ from django.http import JsonResponse
14
+ from django.views import View
15
+ from asgiref.sync import sync_to_async
16
+
17
+ from apps.clientes.models import Cliente
18
+ from apps.facturas.services import calcular_resumen
19
+
20
+
21
+ class ResumenClienteView(View):
22
+ """
23
+ Vista async que hace consultas ORM y llamadas HTTP externas en paralelo.
24
+ """
25
+
26
+ async def get(self, request, cliente_id: int) -> JsonResponse:
27
+ # sync_to_async envuelve una función síncrona para llamarla desde async
28
+ obtener_cliente = sync_to_async(
29
+ Cliente.objects.select_related("empresa").get
30
+ )
31
+ try:
32
+ cliente = await obtener_cliente(id=cliente_id)
33
+ except Cliente.DoesNotExist:
34
+ return JsonResponse({"error": "Cliente no encontrado."}, status=404)
35
+
36
+ # Ejecutar ORM y llamada HTTP externa en paralelo
37
+ resumen, datos_externos = await asyncio.gather(
38
+ sync_to_async(calcular_resumen)(cliente.id),
39
+ self._obtener_datos_externos(cliente.rfc),
40
+ )
41
+
42
+ return JsonResponse({"resumen": resumen, "externos": datos_externos})
43
+
44
+ async def _obtener_datos_externos(self, rfc: str) -> dict:
45
+ import httpx
46
+ async with httpx.AsyncClient(timeout=5.0) as client:
47
+ respuesta = await client.get(f"https://api.sat.mx/rfc/{rfc}")
48
+ respuesta.raise_for_status()
49
+ return respuesta.json()
50
+ ```
51
+
52
+ ---
53
+
54
+ ## sync_to_async y async_to_sync
55
+
56
+ ```python
57
+ from asgiref.sync import sync_to_async, async_to_sync
58
+
59
+
60
+ # sync_to_async — llamar código síncrono desde un contexto async
61
+ # thread_sensitive=True (default): corre en el mismo hilo principal
62
+ # thread_sensitive=False: corre en un hilo de pool — para operaciones CPU-bound
63
+
64
+ obtener_facturas = sync_to_async(
65
+ lambda: list(Factura.objects.filter(estatus="pendiente").select_related("cliente")),
66
+ thread_sensitive=False, # pool de hilos para operaciones pesadas
67
+ )
68
+ facturas = await obtener_facturas()
69
+
70
+ # Decorador: convierte función síncrona completa en async
71
+ @sync_to_async
72
+ def crear_usuario_sync(email: str, nombre: str) -> Usuario:
73
+ return Usuario.objects.create_user(email=email, nombre=nombre)
74
+
75
+ usuario = await crear_usuario_sync("a@b.com", "Ana")
76
+
77
+
78
+ # async_to_sync — llamar código async desde un contexto síncrono
79
+ # Útil en management commands, scripts de migración o Celery tasks
80
+
81
+ @async_to_sync
82
+ async def tarea_async_en_celery():
83
+ async with httpx.AsyncClient() as client:
84
+ await client.post("https://webhook.ejemplo.com/evento", json={"tipo": "SYNC"})
85
+
86
+ # En una tarea Celery síncrona:
87
+ @shared_task
88
+ def notificar_webhook():
89
+ tarea_async_en_celery() # compatible con Celery síncrono
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Django Channels: configuración y channel layers
95
+
96
+ ```python
97
+ # config/asgi.py
98
+ import os
99
+ from django.core.asgi import get_asgi_application
100
+ from channels.routing import ProtocolTypeRouter, URLRouter
101
+ from channels.auth import AuthMiddlewareStack
102
+ from channels.security.websocket import AllowedHostsOriginValidator
103
+
104
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
105
+
106
+ django_asgi_app = get_asgi_application()
107
+
108
+ from apps.notificaciones.routing import websocket_urlpatterns # noqa: E402
109
+
110
+ application = ProtocolTypeRouter({
111
+ "http": django_asgi_app,
112
+ "websocket": AllowedHostsOriginValidator(
113
+ AuthMiddlewareStack(
114
+ URLRouter(websocket_urlpatterns)
115
+ )
116
+ ),
117
+ })
118
+
119
+
120
+ # config/settings/base.py
121
+ CHANNEL_LAYERS = {
122
+ "default": {
123
+ "BACKEND": "channels_redis.core.RedisChannelLayer",
124
+ "CONFIG": {
125
+ "hosts": [("redis", 6379)],
126
+ "capacity": 1500, # mensajes máximos en cola por canal
127
+ "expiry": 60, # segundos de TTL para mensajes
128
+ },
129
+ },
130
+ }
131
+
132
+ # apps/notificaciones/routing.py
133
+ from django.urls import re_path
134
+ from . import consumers
135
+
136
+ websocket_urlpatterns = [
137
+ re_path(r"ws/notificaciones/(?P<empresa_id>\d+)/$", consumers.NotificacionConsumer.as_asgi()),
138
+ ]
139
+ ```
140
+
141
+ ---
142
+
143
+ ## WebSocket consumer completo
144
+
145
+ ```python
146
+ # apps/notificaciones/consumers.py
147
+ import json
148
+ from channels.generic.websocket import AsyncWebsocketConsumer
149
+ from channels.db import database_sync_to_async
150
+ from django.contrib.auth.models import AnonymousUser
151
+
152
+
153
+ class NotificacionConsumer(AsyncWebsocketConsumer):
154
+ """
155
+ Consumer WebSocket para notificaciones en tiempo real por empresa.
156
+ Grupo: notificaciones_empresa_{empresa_id}
157
+ """
158
+
159
+ async def connect(self) -> None:
160
+ # Rechazar conexiones no autenticadas
161
+ if isinstance(self.scope["user"], AnonymousUser):
162
+ await self.close(code=4001)
163
+ return
164
+
165
+ self.empresa_id = self.scope["url_route"]["kwargs"]["empresa_id"]
166
+ self.nombre_grupo = f"notificaciones_empresa_{self.empresa_id}"
167
+
168
+ # Verificar que el usuario pertenece a la empresa
169
+ tiene_acceso = await self._verificar_acceso()
170
+ if not tiene_acceso:
171
+ await self.close(code=4003)
172
+ return
173
+
174
+ # Unirse al grupo del channel layer (Redis)
175
+ await self.channel_layer.group_add(self.nombre_grupo, self.channel_name)
176
+ await self.accept()
177
+
178
+ # Enviar notificaciones pendientes al conectar
179
+ pendientes = await self._obtener_pendientes()
180
+ if pendientes:
181
+ await self.send(text_data=json.dumps({
182
+ "tipo": "pendientes",
183
+ "datos": pendientes,
184
+ }))
185
+
186
+ async def disconnect(self, close_code: int) -> None:
187
+ if hasattr(self, "nombre_grupo"):
188
+ await self.channel_layer.group_discard(self.nombre_grupo, self.channel_name)
189
+
190
+ async def receive(self, text_data: str) -> None:
191
+ """Manejar mensajes entrantes del cliente WebSocket."""
192
+ try:
193
+ datos = json.loads(text_data)
194
+ except json.JSONDecodeError:
195
+ await self.send(text_data=json.dumps({"error": "JSON inválido"}))
196
+ return
197
+
198
+ tipo = datos.get("tipo")
199
+ if tipo == "marcar_leida":
200
+ notificacion_id = datos.get("id")
201
+ await self._marcar_leida(notificacion_id)
202
+ await self.send(text_data=json.dumps({
203
+ "tipo": "confirmacion",
204
+ "id": notificacion_id,
205
+ }))
206
+
207
+ # Manejador de eventos del channel layer — llamado por group_send
208
+ async def notificacion_nueva(self, evento: dict) -> None:
209
+ """Recibe mensaje del channel layer y lo reenvía al WebSocket."""
210
+ await self.send(text_data=json.dumps({
211
+ "tipo": "nueva",
212
+ "datos": evento["datos"],
213
+ }))
214
+
215
+ @database_sync_to_async
216
+ def _verificar_acceso(self) -> bool:
217
+ usuario = self.scope["user"]
218
+ return str(usuario.empresa_id) == str(self.empresa_id)
219
+
220
+ @database_sync_to_async
221
+ def _obtener_pendientes(self) -> list:
222
+ from apps.notificaciones.models import Notificacion
223
+ return list(
224
+ Notificacion.objects
225
+ .filter(empresa_id=self.empresa_id, leida=False)
226
+ .order_by("-creado_en")[:20]
227
+ .values("id", "mensaje", "tipo", "creado_en")
228
+ )
229
+
230
+ @database_sync_to_async
231
+ def _marcar_leida(self, notificacion_id: int) -> None:
232
+ from apps.notificaciones.models import Notificacion
233
+ Notificacion.objects.filter(id=notificacion_id).update(leida=True)
234
+
235
+
236
+ # Enviar desde cualquier parte del sistema (no solo desde consumers)
237
+ # apps/notificaciones/services.py
238
+ from channels.layers import get_channel_layer
239
+ from asgiref.sync import async_to_sync
240
+
241
+ def enviar_notificacion_ws(empresa_id: int, mensaje: str, tipo: str = "info") -> None:
242
+ """Envía un evento a todos los WebSockets conectados de la empresa."""
243
+ channel_layer = get_channel_layer()
244
+ async_to_sync(channel_layer.group_send)(
245
+ f"notificaciones_empresa_{empresa_id}",
246
+ {
247
+ "type": "notificacion_nueva", # mapea al método del consumer
248
+ "datos": {"mensaje": mensaje, "tipo": tipo},
249
+ },
250
+ )
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Celery con Django: configuración completa
256
+
257
+ ```python
258
+ # config/celery.py
259
+ import os
260
+ from celery import Celery
261
+ from celery.schedules import crontab
262
+
263
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
264
+
265
+ app = Celery("mi_proyecto")
266
+ app.config_from_object("django.conf:settings", namespace="CELERY")
267
+ app.autodiscover_tasks() # descubre tasks.py en todas las INSTALLED_APPS
268
+
269
+
270
+ # config/settings/base.py — configuración de Celery
271
+ CELERY_BROKER_URL = env("CELERY_BROKER_URL", default="redis://localhost:6379/0")
272
+ CELERY_RESULT_BACKEND = env("CELERY_RESULT_BACKEND", default="redis://localhost:6379/1")
273
+ CELERY_ACCEPT_CONTENT = ["json"]
274
+ CELERY_TASK_SERIALIZER = "json"
275
+ CELERY_RESULT_SERIALIZER = "json"
276
+ CELERY_TIMEZONE = "America/Mexico_City"
277
+
278
+ # Routing: separar colas por prioridad
279
+ CELERY_TASK_ROUTES = {
280
+ "apps.facturas.tasks.*": {"queue": "facturas"},
281
+ "apps.reportes.tasks.*": {"queue": "reportes"},
282
+ "apps.notificaciones.tasks.*": {"queue": "emails", "priority": 9},
283
+ }
284
+
285
+ # Beat schedule: tareas periódicas
286
+ CELERY_BEAT_SCHEDULE = {
287
+ "cerrar-facturas-vencidas": {
288
+ "task": "apps.facturas.tasks.cerrar_facturas_vencidas",
289
+ "schedule": crontab(hour=2, minute=0), # cada día a las 2 AM
290
+ },
291
+ "limpiar-sesiones-expiradas": {
292
+ "task": "apps.usuarios.tasks.limpiar_sesiones",
293
+ "schedule": crontab(hour=3, minute=30, day_of_week="sunday"),
294
+ },
295
+ }
296
+
297
+
298
+ # Chord y Chain para flujos de tareas
299
+ # apps/reportes/tasks.py
300
+ from celery import shared_task, chord, chain
301
+ from celery.utils.log import get_task_logger
302
+
303
+ logger = get_task_logger(__name__)
304
+
305
+
306
+ @shared_task(bind=True, max_retries=3)
307
+ def generar_reporte_mensual(self, empresa_id: int, mes: int, anio: int) -> dict:
308
+ """Genera reporte mensual con retry automático."""
309
+ try:
310
+ datos = ReporteService().generar(empresa_id=empresa_id, mes=mes, anio=anio)
311
+ return {"estado": "ok", "registros": len(datos)}
312
+ except Exception as exc:
313
+ logger.error("Error generando reporte", exc_info=exc)
314
+ raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))
315
+
316
+
317
+ @shared_task
318
+ def enviar_reporte_por_email(resultado: dict, destinatario: str) -> None:
319
+ """Callback de chord: recibe resultados de tareas paralelas."""
320
+ logger.info("Enviando reporte", resultado=resultado, destinatario=destinatario)
321
+
322
+
323
+ def orquestar_reportes_mensuales(empresa_ids: list[int], mes: int, anio: int) -> None:
324
+ """Genera reportes en paralelo y envía resumen al terminar."""
325
+ tareas = [generar_reporte_mensual.s(eid, mes, anio) for eid in empresa_ids]
326
+ workflow = chord(tareas)(
327
+ enviar_reporte_por_email.s(destinatario="ops@empresa.com")
328
+ )
329
+ workflow.delay()
330
+ ```
331
+
332
+ ---
333
+
334
+ ## ASGI deployment: Daphne, Uvicorn, Hypercorn
335
+
336
+ ```python
337
+ # Opción 1: Daphne — servidor oficial de Django Channels
338
+ # pip install daphne
339
+ # Procfile / supervisord:
340
+ # web: daphne -b 0.0.0.0 -p 8000 config.asgi:application
341
+ # channels: celery -A config worker -Q facturas,emails --concurrency=4
342
+ # beat: celery -A config beat --scheduler django_celery_beat.schedulers:DatabaseScheduler
343
+
344
+
345
+ # Opción 2: Uvicorn con Gunicorn como gestor de procesos
346
+ # pip install uvicorn[standard] gunicorn
347
+ # gunicorn config.asgi:application \
348
+ # --worker-class uvicorn.workers.UvicornWorker \
349
+ # --workers 4 \
350
+ # --bind 0.0.0.0:8000 \
351
+ # --timeout 60
352
+
353
+
354
+ # Opción 3: Hypercorn — soporte HTTP/2 y HTTP/3
355
+ # pip install hypercorn
356
+ # hypercorn config.asgi:application --bind 0.0.0.0:8000 --workers 4
357
+
358
+
359
+ # docker-compose.yml (fragmento para producción con Channels)
360
+ # services:
361
+ # web:
362
+ # command: daphne -b 0.0.0.0 -p 8000 config.asgi:application
363
+ # environment:
364
+ # - DJANGO_SETTINGS_MODULE=config.settings.production
365
+ # worker:
366
+ # command: celery -A config worker -Q default,facturas,emails -c 4
367
+ # beat:
368
+ # command: celery -A config beat -l info
369
+ # redis:
370
+ # image: redis:7-alpine
371
+ # command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Reglas clave para async en Django
377
+
378
+ ```
379
+ BIEN: async def vista(request) con await sync_to_async(qs.get)()
380
+ MAL: async def vista(request) con Cliente.objects.get() directo — bloquea el event loop
381
+
382
+ BIEN: @database_sync_to_async en métodos de Consumer
383
+ MAL: queries ORM directas en métodos async de Consumer sin envoltura
384
+
385
+ BIEN: CELERY_TASK_ALWAYS_EAGER=True en settings de test
386
+ MAL: tests que dependen de Redis real para verificar tareas Celery
387
+
388
+ BIEN: channel_layer.group_send() para fan-out a múltiples WebSockets
389
+ MAL: iterar sobre conexiones activas manualmente sin channel layers
390
+ ```