@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,201 @@
1
+ # Regla: Patrones de Arquitectura Kotlin
2
+
3
+ Esta regla define los patrones obligatorios para estructurar código Kotlin en Android
4
+ y backend (Ktor/Spring). La arquitectura limpia con coroutines y Flow es el estándar.
5
+
6
+ ---
7
+
8
+ ## Coroutines y Flow para async/reactive
9
+
10
+ - Todo código asíncrono usa `suspend` functions o `Flow`. Sin `AsyncTask`, `Thread` ni callbacks.
11
+ - `Flow` para streams de datos que cambian en el tiempo (lista de items, estados de UI).
12
+ - `StateFlow` para estado que siempre tiene un valor actual (reemplaza `LiveData`).
13
+ - `SharedFlow` para eventos de un solo disparo (navegación, mensajes de error).
14
+
15
+ ```kotlin
16
+ // MAL — LiveData expone detalles de Android en el dominio
17
+ class PedidoRepository {
18
+ fun obtenerPedidos(): LiveData<List<Pedido>> = ...
19
+ }
20
+
21
+ // BIEN — Flow es independiente del framework
22
+ class PedidoRepository {
23
+ fun obtenerPedidos(): Flow<List<Pedido>> = flow {
24
+ emit(dao.obtenerTodos())
25
+ }
26
+ }
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Repository pattern con interfaces
32
+
33
+ Toda fuente de datos se abstrae detrás de una interfaz.
34
+ El dominio depende de la interfaz, no de la implementación concreta.
35
+
36
+ ```kotlin
37
+ // Interfaz en la capa de dominio
38
+ interface PedidoRepository {
39
+ suspend fun obtenerPorId(id: UUID): Pedido?
40
+ fun obtenerTodos(): Flow<List<Pedido>>
41
+ suspend fun guardar(pedido: Pedido)
42
+ }
43
+
44
+ // Implementación en la capa de datos
45
+ class PedidoRepositoryImpl(
46
+ private val dao: PedidoDao,
47
+ private val api: PedidoApi,
48
+ ) : PedidoRepository {
49
+ override suspend fun obtenerPorId(id: UUID): Pedido? =
50
+ dao.buscarPorId(id)?.toDomain()
51
+ }
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Use cases / interactors para lógica de negocio
57
+
58
+ Cada acción de negocio tiene su propio use case. Un use case = una responsabilidad.
59
+ El ViewModel llama al use case; no contiene lógica de negocio.
60
+
61
+ ```kotlin
62
+ // BIEN — use case con responsabilidad única
63
+ class CrearPedidoUseCase(
64
+ private val pedidoRepo: PedidoRepository,
65
+ private val inventarioRepo: InventarioRepository,
66
+ ) {
67
+ suspend operator fun invoke(items: List<ItemPedido>): Result<Pedido> {
68
+ if (items.isEmpty()) return Result.failure(IllegalArgumentException("Sin items"))
69
+ val disponible = inventarioRepo.verificarDisponibilidad(items)
70
+ if (!disponible) return Result.failure(StockInsuficienteException())
71
+ val pedido = Pedido.crear(items)
72
+ pedidoRepo.guardar(pedido)
73
+ return Result.success(pedido)
74
+ }
75
+ }
76
+
77
+ // MAL — lógica de negocio en el ViewModel
78
+ class PedidoViewModel(private val repo: PedidoRepository) : ViewModel() {
79
+ fun crearPedido(items: List<ItemPedido>) {
80
+ if (items.isEmpty()) { /* lógica aquí — MAL */ }
81
+ viewModelScope.launch { repo.guardar(...) }
82
+ }
83
+ }
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Sealed classes para estados de UI
89
+
90
+ ```kotlin
91
+ sealed class UiState<out T> {
92
+ object Loading : UiState<Nothing>()
93
+ data class Success<T>(val data: T) : UiState<T>()
94
+ data class Error(val mensaje: String, val causa: Throwable? = null) : UiState<Nothing>()
95
+ }
96
+
97
+ // ViewModel expone StateFlow de UiState
98
+ class PedidoViewModel(private val obtenerPedidos: ObtenerPedidosUseCase) : ViewModel() {
99
+ private val _uiState = MutableStateFlow<UiState<List<Pedido>>>(UiState.Loading)
100
+ val uiState: StateFlow<UiState<List<Pedido>>> = _uiState.asStateFlow()
101
+
102
+ init {
103
+ cargarPedidos()
104
+ }
105
+
106
+ private fun cargarPedidos() {
107
+ viewModelScope.launch {
108
+ obtenerPedidos()
109
+ .onStart { _uiState.value = UiState.Loading }
110
+ .catch { e -> _uiState.value = UiState.Error(e.message ?: "Error") }
111
+ .collect { pedidos -> _uiState.value = UiState.Success(pedidos) }
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Dependency Injection con Hilt (Android) o Koin
120
+
121
+ Preferir **Hilt** en proyectos Android nuevos por su integración con el compilador.
122
+ **Koin** es aceptable en proyectos multiplatforma o Ktor.
123
+
124
+ ```kotlin
125
+ // Hilt — módulo de provisión
126
+ @Module
127
+ @InstallIn(SingletonComponent::class)
128
+ object RepositorioModule {
129
+ @Provides
130
+ @Singleton
131
+ fun providePedidoRepository(dao: PedidoDao): PedidoRepository =
132
+ PedidoRepositoryImpl(dao)
133
+ }
134
+
135
+ // ViewModel con Hilt
136
+ @HiltViewModel
137
+ class PedidoViewModel @Inject constructor(
138
+ private val obtenerPedidos: ObtenerPedidosUseCase,
139
+ ) : ViewModel()
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Jetpack Compose: remember, LaunchedEffect, derivedStateOf
145
+
146
+ ```kotlin
147
+ @Composable
148
+ fun PantallaPedidos(viewModel: PedidoViewModel = hiltViewModel()) {
149
+ val uiState by viewModel.uiState.collectAsStateWithLifecycle()
150
+
151
+ // remember: cálculos costosos que no deben recalcularse en cada recomposición
152
+ val pedidosOrdenados = remember(uiState) {
153
+ if (uiState is UiState.Success) {
154
+ (uiState as UiState.Success).data.sortedByDescending { it.fecha }
155
+ } else emptyList()
156
+ }
157
+
158
+ // derivedStateOf: valor derivado de otro estado, evita recomposiciones en cascada
159
+ val hayPedidos by remember { derivedStateOf { pedidosOrdenados.isNotEmpty() } }
160
+
161
+ // LaunchedEffect: efectos de un solo disparo atados al ciclo de vida del composable
162
+ LaunchedEffect(Unit) {
163
+ viewModel.eventos.collect { evento ->
164
+ when (evento) {
165
+ is Evento.NavegacionDetalle -> navController.navigate(...)
166
+ }
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Clean Architecture: capas y dependencias
175
+
176
+ ```
177
+ presentation/ — Composables, ViewModels, UiState
178
+ |
179
+ v
180
+ domain/ — UseCases, interfaces de Repository, modelos de dominio
181
+ |
182
+ v
183
+ data/ — implementaciones de Repository, DAOs, API clients, mappers
184
+ ```
185
+
186
+ La capa `domain` NO importa nada de `presentation` ni `data`.
187
+ Los modelos de datos de Room o Retrofit NO se exponen a la capa de presentación.
188
+ Usar mappers explícitos entre capas.
189
+
190
+ ---
191
+
192
+ ## Checklist de patrones Kotlin antes de abrir PR
193
+
194
+ - [ ] Sin callbacks: todo async usa suspend o Flow
195
+ - [ ] Repositories tienen interfaz en dominio e implementación en datos
196
+ - [ ] Lógica de negocio en use cases, no en ViewModels ni Repositories
197
+ - [ ] Estados de UI representados con sealed class (Loading/Success/Error)
198
+ - [ ] ViewModels exponen StateFlow, no MutableStateFlow público
199
+ - [ ] DI configurada con Hilt o Koin, sin instanciación manual de dependencias
200
+ - [ ] Composables con remember/derivedStateOf para evitar recomposiciones
201
+ - [ ] Capas de Clean Architecture sin dependencias inversas
@@ -0,0 +1,202 @@
1
+ # Regla: Seguridad en Kotlin / Android
2
+
3
+ Esta regla es OBLIGATORIA para todo código Kotlin en Android o backend.
4
+ Los errores de seguridad en mobile son especialmente costosos: los APKs son
5
+ descargables y analizables por cualquier actor malicioso.
6
+
7
+ ---
8
+
9
+ ## ProGuard/R8: ofuscación obligatoria en release
10
+
11
+ R8 (sucesor de ProGuard) es la herramienta de ofuscación, shrinking y optimización
12
+ integrada en Gradle. Debe estar habilitada en todos los builds de release.
13
+
14
+ ```kotlin
15
+ // build.gradle.kts — Android
16
+ android {
17
+ buildTypes {
18
+ release {
19
+ isMinifyEnabled = true // ofuscar y reducir código
20
+ isShrinkResources = true // eliminar recursos no usados
21
+ proguardFiles(
22
+ getDefaultProguardFile("proguard-android-optimize.txt"),
23
+ "proguard-rules.pro"
24
+ )
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ Verificar que las reglas de ProGuard no excluyen clases sensibles innecesariamente.
31
+ Los modelos de datos serializados con Retrofit/Gson/Moshi necesitan reglas explícitas.
32
+
33
+ ---
34
+
35
+ ## EncryptedSharedPreferences para datos sensibles locales
36
+
37
+ `SharedPreferences` guarda datos en texto plano. NUNCA almacenar tokens, IDs de sesión
38
+ ni datos personales en SharedPreferences sin cifrado.
39
+
40
+ ```kotlin
41
+ // MAL — texto plano, legible con adb o en dispositivos rooteados
42
+ sharedPreferences.edit().putString("access_token", token).apply()
43
+
44
+ // BIEN — cifrado con EncryptedSharedPreferences (Jetpack Security)
45
+ val masterKey = MasterKey.Builder(context)
46
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
47
+ .build()
48
+
49
+ val prefs = EncryptedSharedPreferences.create(
50
+ context,
51
+ "prefs_seguras",
52
+ masterKey,
53
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
54
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
55
+ )
56
+ prefs.edit().putString("access_token", token).apply()
57
+ ```
58
+
59
+ ---
60
+
61
+ ## No almacenar secretos en BuildConfig
62
+
63
+ Los valores en `BuildConfig` quedan en el DEX y son extraíbles con herramientas
64
+ como `jadx` o `apktool`. Un atacante puede recuperar la API key en minutos.
65
+
66
+ ```kotlin
67
+ // MAL — la key queda en el APK descompilado
68
+ buildConfigField("String", "API_KEY", "\"sk-prod-abc123\"")
69
+
70
+ // BIEN — la key se obtiene del servidor en runtime, autenticando al usuario primero
71
+ // El backend actua como proxy: el cliente nunca toca la API key directamente
72
+ ```
73
+
74
+ Para claves que el cliente DEBE conocer (ej: clave pública de SDK de pagos):
75
+ usar Android Keystore + certificate pinning como defensa adicional.
76
+
77
+ ---
78
+
79
+ ## Certificate Pinning en OkHttp
80
+
81
+ Sin certificate pinning, un atacante con un certificado CA fraudulento puede
82
+ interceptar el tráfico HTTPS (man-in-the-middle).
83
+
84
+ ```kotlin
85
+ // BIEN — pinning por clave pública (más flexible que hash del certificado)
86
+ val certificatePinner = CertificatePinner.Builder()
87
+ .add("api.miapp.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
88
+ .add("api.miapp.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // backup pin
89
+ .build()
90
+
91
+ val okHttpClient = OkHttpClient.Builder()
92
+ .certificatePinner(certificatePinner)
93
+ .build()
94
+ ```
95
+
96
+ Incluir SIEMPRE un pin de respaldo (backup pin) para permitir rotación de certificados
97
+ sin dejar la app sin servicio. Documentar el proceso de rotación de pins.
98
+
99
+ ---
100
+
101
+ ## SQL con Room: queries parametrizados
102
+
103
+ Room previene SQL injection por defecto cuando se usan los parámetros correctamente.
104
+ NUNCA construir queries con concatenación de strings.
105
+
106
+ ```kotlin
107
+ // MAL — SQL injection posible
108
+ @Dao
109
+ interface PedidoDao {
110
+ @RawQuery
111
+ fun buscarPorEstatus(query: SupportSQLiteQuery): List<Pedido>
112
+ }
113
+ // Uso peligroso: SimpleSQLiteQuery("SELECT * FROM pedidos WHERE estatus = '$estatus'")
114
+
115
+ // BIEN — parámetro tipado, Room lo escapa automáticamente
116
+ @Dao
117
+ interface PedidoDao {
118
+ @Query("SELECT * FROM pedidos WHERE estatus = :estatus")
119
+ suspend fun buscarPorEstatus(estatus: String): List<Pedido>
120
+ }
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Autenticación biométrica con BiometricPrompt
126
+
127
+ ```kotlin
128
+ // BIEN — BiometricPrompt con manejo correcto de resultados
129
+ fun autenticarConBiometria(actividad: FragmentActivity, onExito: () -> Unit) {
130
+ val executor = ContextCompat.getMainExecutor(actividad)
131
+ val callback = object : BiometricPrompt.AuthenticationCallback() {
132
+ override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
133
+ onExito()
134
+ }
135
+ override fun onAuthenticationError(código: Int, mensaje: CharSequence) {
136
+ // Registrar error, NO exponer detalles al usuario
137
+ logger.warn("Biometric error $codigo")
138
+ }
139
+ override fun onAuthenticationFailed() {
140
+ // Intento fallido — no bloquear todavía, BiometricPrompt maneja reintentos
141
+ }
142
+ }
143
+
144
+ BiometricPrompt(actividad, executor, callback).authenticate(
145
+ BiometricPrompt.PromptInfo.Builder()
146
+ .setTitle("Confirmar identidad")
147
+ .setNegativeButtonText("Cancelar")
148
+ .setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
149
+ .build()
150
+ )
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Network Security Config y validación de deep links
157
+
158
+ ```xml
159
+ <!-- res/xml/network_security_config.xml -->
160
+ <network-security-config>
161
+ <base-config cleartextTrafficPermitted="false">
162
+ <trust-anchors>
163
+ <certificates src="system" />
164
+ </trust-anchors>
165
+ </base-config>
166
+ <!-- Solo en debug — nunca en release -->
167
+ <debug-overrides>
168
+ <trust-anchors>
169
+ <certificates src="user" />
170
+ </trust-anchors>
171
+ </debug-overrides>
172
+ </network-security-config>
173
+ ```
174
+
175
+ ```kotlin
176
+ // Validar deep links — nunca confiar en el scheme/host sin verificar
177
+ override fun onCreate(savedInstanceState: Bundle?) {
178
+ super.onCreate(savedInstanceState)
179
+ val uri = intent?.data ?: return
180
+ if (uri.host != "miapp.com" || uri.scheme != "https") {
181
+ logger.warn("Deep link invalido: $uri")
182
+ finish()
183
+ return
184
+ }
185
+ val pedidoId = uri.getQueryParameter("pedido_id")
186
+ ?.let { UUID.fromString(it) } // lanza si no es UUID válido
187
+ ?: run { finish(); return }
188
+ }
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Checklist de seguridad Kotlin antes de abrir PR
194
+
195
+ - [ ] R8/ProGuard habilitado en builds de release
196
+ - [ ] Sin `SharedPreferences` sin cifrar para datos sensibles
197
+ - [ ] Sin secretos en `BuildConfig` o strings.xml
198
+ - [ ] Certificate pinning configurado con pin de respaldo
199
+ - [ ] Queries de Room con parámetros tipados (sin concatenación de strings)
200
+ - [ ] Deep links validados en host y scheme antes de procesar parámetros
201
+ - [ ] `clearTextTrafficPermitted="false"` en network security config
202
+ - [ ] Biometric auth usa `BiometricPrompt`, no APIs deprecadas
@@ -0,0 +1,236 @@
1
+ # Regla: Testing en Kotlin
2
+
3
+ Esta regla es OBLIGATORIA para todo código Kotlin nuevo o modificado.
4
+ Las coroutines y los flows requieren herramientas específicas para testearse
5
+ correctamente. Un test de coroutine sin `runTest` no es determinista.
6
+
7
+ ---
8
+
9
+ ## Stack de testing obligatorio
10
+
11
+ | Herramienta | Propósito |
12
+ |------------|----------|
13
+ | JUnit 5 | Framework base de tests |
14
+ | MockK | Mocking idiomático para Kotlin (no Mockito) |
15
+ | Turbine | Testing de `Flow` con `test {}` API |
16
+ | kotlinx-coroutines-test | `runTest`, `TestDispatcher`, `advanceUntilIdle` |
17
+ | Kover | Cobertura de código (reemplaza JaCoCo para Kotlin) |
18
+ | Compose UI Test | Testing de Composables con `createComposeRule` |
19
+
20
+ ```kotlin
21
+ // build.gradle.kts — dependencias de test
22
+ dependencies {
23
+ testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
24
+ testImplementation("io.mockk:mockk:1.13.10")
25
+ testImplementation("app.cash.turbine:turbine:1.1.0")
26
+ testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.0")
27
+ androidTestImplementation("androidx.compose.ui:ui-test-junit4")
28
+ }
29
+ ```
30
+
31
+ ---
32
+
33
+ ## runTest y TestDispatcher para coroutines
34
+
35
+ `runTest` es el único punto de entrada correcto para tests de suspend functions.
36
+ Reemplaza `runBlocking` en tests — maneja los virtual timers del test framework.
37
+
38
+ ```kotlin
39
+ // MAL — runBlocking no controla el tiempo virtual ni los dispatchers de coroutines
40
+ @Test
41
+ fun `obtener usuario por id retorna usuario correcto`() = runBlocking {
42
+ val resultado = repositorio.obtenerPorId(uuid)
43
+ assertEquals("Juan", resultado?.nombre)
44
+ }
45
+
46
+ // BIEN — runTest con dispatcher controlado
47
+ @Test
48
+ fun `obtener usuario por id retorna usuario correcto`() = runTest {
49
+ val resultado = repositorio.obtenerPorId(uuid)
50
+ assertEquals("Juan", resultado?.nombre)
51
+ }
52
+
53
+ // BIEN — StandardTestDispatcher para controlar avance del tiempo
54
+ @Test
55
+ fun `cargando pedidos emite loading luego success`() = runTest {
56
+ val dispatcher = StandardTestDispatcher(testScheduler)
57
+ val viewModel = PedidoViewModel(obtenerPedidosUseCase, dispatcher)
58
+
59
+ val estados = mutableListOf<UiState<*>>()
60
+ val job = launch { viewModel.uiState.collect { estados.add(it) } }
61
+
62
+ advanceUntilIdle()
63
+
64
+ assertEquals(UiState.Loading, estados.first())
65
+ assertIs<UiState.Success<*>>(estados.last())
66
+ job.cancel()
67
+ }
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Turbine para testing de Flow
73
+
74
+ ```kotlin
75
+ // MAL — collect en test puede colgarse o perder emisiones
76
+ @Test
77
+ fun `flujo emite pedidos`() = runTest {
78
+ val emisiones = mutableListOf<List<Pedido>>()
79
+ val job = launch { repositorio.obtenerTodos().collect { emisiones.add(it) } }
80
+ job.cancel()
81
+ assertTrue(emisiones.isNotEmpty())
82
+ }
83
+
84
+ // BIEN — Turbine provee API declarativa y determinista
85
+ @Test
86
+ fun `flujo emite lista de pedidos`() = runTest {
87
+ repositorio.obtenerTodos().test {
88
+ val pedidos = awaitItem()
89
+ assertEquals(3, pedidos.size)
90
+ cancelAndIgnoreRemainingEvents()
91
+ }
92
+ }
93
+
94
+ // BIEN — verificar múltiples emisiones en orden
95
+ @Test
96
+ fun `estado transiciona de loading a success`() = runTest {
97
+ viewModel.uiState.test {
98
+ assertIs<UiState.Loading>(awaitItem())
99
+ val success = awaitItem()
100
+ assertIs<UiState.Success<*>>(success)
101
+ cancelAndIgnoreRemainingEvents()
102
+ }
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## MockK para mocks idiomáticos en Kotlin
109
+
110
+ ```kotlin
111
+ // Configuración típica con MockK
112
+ @ExtendWith(MockKExtension::class)
113
+ class CrearPedidoUseCaseTest {
114
+
115
+ @MockK
116
+ private lateinit var pedidoRepo: PedidoRepository
117
+
118
+ @MockK
119
+ private lateinit var inventarioRepo: InventarioRepository
120
+
121
+ private lateinit var crearPedido: CrearPedidoUseCase
122
+
123
+ @BeforeEach
124
+ fun setup() {
125
+ crearPedido = CrearPedidoUseCase(pedidoRepo, inventarioRepo)
126
+ }
127
+
128
+ @Test
129
+ fun `crear pedido con items disponibles retorna pedido creado`() = runTest {
130
+ // Given
131
+ val items = listOf(ItemPedido(productoId = uuid, cantidad = 2))
132
+ coEvery { inventarioRepo.verificarDisponibilidad(items) } returns true
133
+ coJustRun { pedidoRepo.guardar(any()) }
134
+
135
+ // When
136
+ val resultado = crearPedido(items)
137
+
138
+ // Then
139
+ assertTrue(resultado.isSuccess)
140
+ coVerify(exactly = 1) { pedidoRepo.guardar(any()) }
141
+ }
142
+ }
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Patrón Given-When-Then
148
+
149
+ Todos los tests siguen el patrón Given-When-Then con comentarios explícitos.
150
+
151
+ ```kotlin
152
+ @Test
153
+ fun `crear pedido sin items retorna error de validación`() = runTest {
154
+ // Given
155
+ val itemsVacios = emptyList<ItemPedido>()
156
+
157
+ // When
158
+ val resultado = crearPedido(itemsVacios)
159
+
160
+ // Then
161
+ assertTrue(resultado.isFailure)
162
+ assertIs<IllegalArgumentException>(resultado.exceptionOrNull())
163
+ }
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Cobertura con Kover
169
+
170
+ ```kotlin
171
+ // build.gradle.kts
172
+ plugins {
173
+ id("org.jetbrains.kotlinx.kover") version "0.7.6"
174
+ }
175
+
176
+ koverReport {
177
+ filters {
178
+ excludes {
179
+ classes("**/di/**", "**/*Module*", "**/*_Factory*")
180
+ }
181
+ }
182
+ verify {
183
+ rule {
184
+ bound { minValue = 80 }
185
+ }
186
+ }
187
+ }
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Testing de Composables
193
+
194
+ ```kotlin
195
+ class PantallaPedidosTest {
196
+
197
+ @get:Rule
198
+ val composeTestRule = createComposeRule()
199
+
200
+ @Test
201
+ fun `muestra lista de pedidos cuando estado es success`() {
202
+ // Given
203
+ val pedidos = listOf(Pedido(id = uuid, total = 150.0))
204
+ val estado = UiState.Success(pedidos)
205
+
206
+ // When
207
+ composeTestRule.setContent {
208
+ PantallaPedidos(uiState = estado)
209
+ }
210
+
211
+ // Then
212
+ composeTestRule.onNodeWithText("$150.00").assertIsDisplayed()
213
+ }
214
+
215
+ @Test
216
+ fun `muestra indicador de carga cuando estado es loading`() {
217
+ composeTestRule.setContent {
218
+ PantallaPedidos(uiState = UiState.Loading)
219
+ }
220
+ composeTestRule.onNodeWithTag("loading_indicator").assertIsDisplayed()
221
+ }
222
+ }
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Checklist de testing Kotlin antes de abrir PR
228
+
229
+ - [ ] Tests de coroutines usan `runTest`, no `runBlocking`
230
+ - [ ] Tests de Flow usan Turbine (`flow.test { }`)
231
+ - [ ] Mocks creados con MockK, no con Mockito
232
+ - [ ] `coEvery`/`coVerify` para suspend functions mockeadas
233
+ - [ ] Patrón Given-When-Then con comentarios explícitos
234
+ - [ ] Cobertura >= 80% verificada con Kover
235
+ - [ ] Tests de Composables con `createComposeRule`
236
+ - [ ] Sin `Thread.sleep()` ni delays fijos en tests