@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,343 @@
1
+ ---
2
+ name: structured-outputs
3
+ description: >
4
+ Patrones para obtener respuestas estructuradas y validadas de LLMs usando
5
+ Pydantic v2. Incluye reask iterativo, validación semántica con LLM,
6
+ caching multinivel y hooks de ciclo de interacción. Cargar cuando se
7
+ construya cualquier sistema que requiera outputs JSON/tipados de un LLM,
8
+ o cuando un agente necesite respuestas validadas programáticamente.
9
+ version: "1.0.0"
10
+ herramientasPermitidas: [Read]
11
+ evolvable: true # default para skill estandar
12
+ exclusiones:
13
+ - "No cargar para validación de inputs de usuario en endpoints REST (formularios, API bodies) — para validación de inputs de API cargar `fastapi-experto` con Pydantic schemas de request."
14
+ - "No cargar para construir pipelines RAG o agentes con LangChain — para RAG cargar `rag-arquitectura`, para agentes cargar `langchain-langraph`."
15
+ - "No cargar para streaming de respuestas LLM en tiempo real donde no se necesita validación del output completo — el reask requiere la respuesta completa para validar."
16
+ - "No cargar para evaluar la calidad semántica de un corpus de documentos existentes sin pipeline LLM activo — para evaluación de calidad de documentos usar el skill de dominio correspondiente."
17
+ ---
18
+ # Structured Outputs — Respuestas validadas de LLMs
19
+
20
+ ## Cuándo NO cargar
21
+
22
+ - La tarea es validar inputs de usuario en endpoints REST: usar Pydantic schemas en FastAPI directamente.
23
+ - La tarea es construir un pipeline RAG: cargar `rag-arquitectura`.
24
+ - La tarea es construir agentes con LangGraph: cargar `langchain-langraph`.
25
+ - La tarea es streaming de LLM sin necesidad de validar el output completo: el reask requiere respuesta completa.
26
+
27
+
28
+ ## Problema que resuelve
29
+
30
+ Los LLMs generan texto libre. Cuando tu código necesita un objeto tipado
31
+ (JSON, modelo Pydantic, enum), parsear la respuesta directamente es frágil:
32
+ falla silenciosamente, requiere regex, y no hay garantía de estructura.
33
+
34
+ Structured outputs resuelve esto con un ciclo:
35
+ **generar → validar → reask si falla → retornar objeto tipado**.
36
+
37
+ ---
38
+
39
+ ## Patrón core: response_model + validación Pydantic
40
+
41
+ ```python
42
+ from pydantic import BaseModel, Field
43
+ from typing import Literal
44
+
45
+ class ExtractionResult(BaseModel):
46
+ entidades: list[str] = Field(..., min_length=1)
47
+ sentimiento: Literal["positivo", "negativo", "neutro"]
48
+ confianza: float = Field(..., ge=0.0, le=1.0)
49
+ resumen: str = Field(..., max_length=500)
50
+
51
+ # El modelo debe devolver JSON que valide contra este schema.
52
+ # Si falla validación → reask automático (ver sección siguiente).
53
+ ```
54
+
55
+ La clave es definir el modelo Pydantic con **constraints reales**:
56
+ `min_length`, `ge/le`, `Literal`, `max_length`. Esto convierte errores
57
+ de formato en errores de validación detectables y corregibles.
58
+
59
+ ---
60
+
61
+ ## Patrón reask — retry inteligente con feedback
62
+
63
+ El retry convencional repite la misma llamada. El **reask** envía el error
64
+ de validación de vuelta al LLM para que se auto-corrija:
65
+
66
+ ```
67
+ Intento 1: LLM genera → Pydantic valida → ValidationError("confianza must be <= 1.0")
68
+ Intento 2: LLM recibe error + respuesta previa → genera corregido → Pydantic valida → OK
69
+ ```
70
+
71
+ ### Implementación del ciclo reask
72
+
73
+ ```python
74
+ from pydantic import ValidationError
75
+ import json
76
+
77
+ def obtener_structured(
78
+ llm_client,
79
+ mensajes: list[dict],
80
+ response_model: type[BaseModel],
81
+ max_retries: int = 3,
82
+ ) -> BaseModel:
83
+ """Ciclo reask: genera, valida, corrige hasta max_retries."""
84
+ intentos_fallidos = []
85
+
86
+ for intento in range(1, max_retries + 1):
87
+ # Agregar errores previos como contexto
88
+ mensajes_con_feedback = mensajes.copy()
89
+ if intentos_fallidos:
90
+ feedback = "\n".join(
91
+ f"Intento {i}: {err}" for i, err in enumerate(intentos_fallidos, 1)
92
+ )
93
+ mensajes_con_feedback.append({
94
+ "role": "user",
95
+ "content": (
96
+ f"Tu respuesta anterior no pasó validación:\n{feedback}\n\n"
97
+ f"Corrige y responde de nuevo en JSON válido según el schema."
98
+ ),
99
+ })
100
+
101
+ respuesta = llm_client.messages.create(
102
+ model="claude-sonnet-4-6-20250514",
103
+ max_tokens=2048,
104
+ system=f"Responde SOLO en JSON válido según este schema:\n"
105
+ f"{json.dumps(response_model.model_json_schema(), indent=2)}",
106
+ messages=mensajes_con_feedback,
107
+ )
108
+
109
+ try:
110
+ texto = respuesta.content[0].text
111
+ resultado = response_model.model_validate_json(texto)
112
+ return resultado
113
+ except (ValidationError, json.JSONDecodeError) as e:
114
+ intentos_fallidos.append(str(e)[:200])
115
+
116
+ raise RuntimeError(
117
+ f"Reask agotado después de {max_retries} intentos. "
118
+ f"Errores: {intentos_fallidos}"
119
+ )
120
+ ```
121
+
122
+ ### Diferencia con retry genérico
123
+
124
+ | Aspecto | Retry genérico | Reask |
125
+ |---------|---------------|-------|
126
+ | Feedback al LLM | Ninguno — repite idéntico | Envía error de validación |
127
+ | Probabilidad de éxito | Baja (misma entrada = misma salida) | Alta (LLM corrige con contexto) |
128
+ | Tokens consumidos | Duplicados sin valor | Incrementales con información nueva |
129
+ | Trazabilidad | Solo cuenta de intentos | Errores específicos por intento |
130
+
131
+ ---
132
+
133
+ ## Validación semántica con LLM (llm_validator)
134
+
135
+ Pydantic valida **estructura**. Un LLM puede validar **semántica**:
136
+
137
+ ```python
138
+ from pydantic import field_validator
139
+
140
+ class ResumenDocumento(BaseModel):
141
+ titulo: str
142
+ resumen: str
143
+ temas: list[str]
144
+
145
+ @field_validator("resumen")
146
+ @classmethod
147
+ def validar_resumen_es_coherente(cls, v: str) -> str:
148
+ """Validación estática: longitud mínima y sin placeholders."""
149
+ if len(v) < 50:
150
+ raise ValueError("Resumen demasiado corto (mínimo 50 caracteres)")
151
+ placeholders = ["PENDIENTE", "PLACEHOLDER", "...", "[insertar"]
152
+ for p in placeholders:
153
+ if p.lower() in v.lower():
154
+ raise ValueError(f"Resumen contiene placeholder: '{p}'")
155
+ return v
156
+
157
+
158
+ def validar_semanticamente(
159
+ llm_juez,
160
+ respuesta: BaseModel,
161
+ regla: str,
162
+ ) -> tuple[bool, str]:
163
+ """Usa un LLM como juez para validar restricciones semánticas."""
164
+ prompt = f"""Evalúa si esta respuesta cumple la regla.
165
+
166
+ Regla: {regla}
167
+ Respuesta: {respuesta.model_dump_json(indent=2)}
168
+
169
+ Responde SOLO con JSON: {{"cumple": true/false, "razon": "..."}}"""
170
+
171
+ resultado = llm_juez.messages.create(
172
+ model="claude-haiku-4-5-20251001", # Haiku es suficiente para validación
173
+ max_tokens=256,
174
+ messages=[{"role": "user", "content": prompt}],
175
+ )
176
+ import json
177
+ evaluacion = json.loads(resultado.content[0].text)
178
+ return evaluacion["cumple"], evaluacion["razon"]
179
+ ```
180
+
181
+ **Cuándo usar**: Cuando las restricciones no son expresables como tipos
182
+ (ej: "el resumen no contradice el documento original", "las entidades
183
+ mencionadas existen en el contexto dado").
184
+
185
+ ---
186
+
187
+ ## Caching de respuestas LLM — 3 niveles
188
+
189
+ Cachear respuestas validadas evita llamadas redundantes al LLM.
190
+
191
+ ### Estrategia de clave de caché
192
+
193
+ ```python
194
+ import hashlib
195
+ import json
196
+
197
+ def generar_cache_key(
198
+ modelo: str,
199
+ mensajes: list[dict],
200
+ response_model: type[BaseModel],
201
+ ) -> str:
202
+ """Clave basada en modelo + mensajes + schema del response_model."""
203
+ payload = json.dumps({
204
+ "model": modelo,
205
+ "messages": mensajes,
206
+ "schema_hash": hashlib.sha256(
207
+ json.dumps(response_model.model_json_schema()).encode()
208
+ ).hexdigest()[:16],
209
+ }, sort_keys=True)
210
+ return hashlib.sha256(payload.encode()).hexdigest()
211
+ ```
212
+
213
+ ### Niveles de caché
214
+
215
+ | Nivel | Tecnología | TTL | Cuándo usar |
216
+ |-------|-----------|-----|-------------|
217
+ | L1 | `functools.lru_cache` | Duración del proceso | Misma sesión, mismas queries |
218
+ | L2 | Disco (`shelve`/`diskcache`) | Horas/días | Queries repetitivos entre sesiones |
219
+ | L3 | Redis (`SETEX`) | Configurable | Múltiples instancias/usuarios |
220
+
221
+ ### Invalidación
222
+
223
+ La clave incluye el hash del schema Pydantic. Si cambias el modelo
224
+ (agregas un campo, cambias un tipo), la clave cambia automáticamente
225
+ y el caché se invalida sin intervención manual.
226
+
227
+ ---
228
+
229
+ ## Hooks de ciclo de interacción LLM
230
+
231
+ Puntos de intercepción en el ciclo genera→valida→reask:
232
+
233
+ ```python
234
+ from typing import Callable, Any
235
+ from dataclasses import dataclass, field
236
+ from enum import Enum
237
+
238
+ class HookLLM(Enum):
239
+ ANTES_LLAMADA = "antes_llamada" # Antes de enviar al LLM
240
+ DESPUES_RESPUESTA = "despues_respuesta" # Respuesta recibida (antes de validar)
241
+ ERROR_VALIDACION = "error_validacion" # Validación Pydantic falló
242
+ ULTIMO_INTENTO = "ultimo_intento" # Último reask antes de fallar
243
+ ERROR_API = "error_api" # Error de red/API
244
+
245
+ @dataclass
246
+ class HooksLLM:
247
+ _handlers: dict[HookLLM, list[Callable]] = field(default_factory=dict)
248
+
249
+ def on(self, evento: HookLLM, handler: Callable) -> None:
250
+ self._handlers.setdefault(evento, []).append(handler)
251
+
252
+ def emit(self, evento: HookLLM, **kwargs: Any) -> None:
253
+ for handler in self._handlers.get(evento, []):
254
+ handler(**kwargs)
255
+
256
+ # Uso: tracking de tokens acumulativo por reintentos
257
+ hooks = HooksLLM()
258
+ tokens_acumulados = {"input": 0, "output": 0}
259
+
260
+ def rastrear_tokens(**kwargs):
261
+ usage = kwargs.get("usage", {})
262
+ tokens_acumulados["input"] += usage.get("input_tokens", 0)
263
+ tokens_acumulados["output"] += usage.get("output_tokens", 0)
264
+
265
+ hooks.on(HookLLM.DESPUES_RESPUESTA, rastrear_tokens)
266
+ ```
267
+
268
+ ---
269
+
270
+ ## Tipos de response_model por caso de uso
271
+
272
+ | Caso | Patrón | Ejemplo |
273
+ |------|--------|---------|
274
+ | Extracción simple | `BaseModel` con campos tipados | `class Usuario(BaseModel): nombre: str; edad: int` |
275
+ | Clasificación | `Literal` o `Enum` | `categoria: Literal["bug", "feature", "pregunta"]` |
276
+ | Respuesta opcional | `BaseModel` con campo `encontrado: bool` | Cuando el LLM puede no tener la respuesta |
277
+ | Lista de items | `list[MiModelo]` como campo | `items: list[Producto]` |
278
+ | Uniones discriminadas | `Annotated[Union[...], Field(discriminator="tipo")]` | Diferentes schemas según el tipo |
279
+
280
+ ---
281
+
282
+ ## Interfaz unificada multi-proveedor (referencia)
283
+
284
+ El patrón `from_provider` abstrae el proveedor de LLM:
285
+
286
+ ```python
287
+ # Patrón conceptual — no es una dependencia de swl-ses
288
+ # Referencia: instructor.from_provider()
289
+
290
+ # OpenAI
291
+ client = crear_cliente_structured("openai", model="gpt-4o")
292
+
293
+ # Anthropic
294
+ client = crear_cliente_structured("anthropic", model="claude-sonnet-4-6-20250514")
295
+
296
+ # La interfaz es idéntica: client.create(response_model=MiModelo, messages=[...])
297
+ ```
298
+
299
+ **Nota**: swl-ses es mono-proveedor (Anthropic). Este patrón se documenta
300
+ como referencia para proyectos que necesiten soportar múltiples LLMs.
301
+ El `hooks/lib/model-router.js` existente ya hace routing por complejidad
302
+ dentro de Anthropic — podría evolucionar a routing por proveedor si se requiere.
303
+
304
+ ---
305
+
306
+ ## MUST DO / MUST NOT DO
307
+
308
+ ### Obligatorio
309
+ - Definir constraints reales en Pydantic (`Field(ge=0)`, `Literal[...]`, `max_length`)
310
+ - Usar reask (no retry ciego) cuando la respuesta del LLM falla validación
311
+ - Incluir el JSON Schema del modelo en el system prompt
312
+ - Trackear tokens acumulados incluyendo reintentos, no solo la llamada exitosa
313
+ - Cachear respuestas validadas con clave que incluya hash del schema
314
+
315
+ ### Prohibido
316
+ - NUNCA parsear JSON con regex — usar `model_validate_json()`
317
+ - NUNCA reintentar sin enviar el error de vuelta al LLM (retry ciego)
318
+ - NUNCA confiar en la respuesta sin validación Pydantic
319
+ - NUNCA usar `temperature > 0.3` para structured outputs (reduce determinismo)
320
+ - NUNCA cachear respuestas que fallaron validación
321
+ - NUNCA usar `Any` como tipo en response_model — pierde toda garantía
322
+
323
+ ---
324
+
325
+ ## Tabla de referencias
326
+
327
+ | Tema | Archivo |
328
+ |------|---------|
329
+ | Patrones avanzados: prompt chaining, LLM-as-judge, caching | [prompt-engineering/recursos/patrones-avanzados.md](../prompt-engineering/recursos/patrones-avanzados.md) |
330
+ | RAG con structured outputs | [langchain-langraph/SKILL.md](../langchain-langraph/SKILL.md) |
331
+ | Validación de schemas JSON | [schemas/](../../schemas/) |
332
+
333
+ ---
334
+
335
+ ## Gotchas / Errores comunes no obvios
336
+
337
+ **`model_validate_json()` lanza `ValidationError` con el mensaje "1 validation error for X: JSON input should be string, bytes or bytearray" cuando el output del LLM envuelve el JSON en bloques de código Markdown**: Claude y GPT frecuentemente responden con ` ```json\n{...}\n``` ` aunque el system prompt diga "responde SOLO en JSON". Causa: los modelos fueron entrenados en conversaciones donde el JSON se muestra en bloques de código por legibilidad; el system prompt de "solo JSON" reduce pero no elimina este comportamiento, especialmente en Haiku y GPT-3.5. Fix: antes de llamar a `model_validate_json()`, limpiar el texto con `texto = re.sub(r'^```(?:json)?\s*|\s*```$', '', texto.strip())`. Alternativamente, usar `tool_use` de Anthropic o `response_format` de OpenAI para forzar JSON estructurado a nivel de API.
338
+
339
+ **El ciclo reask con `max_retries=3` puede consumir 6-9x más tokens que una llamada exitosa sin que el código lo detecte porque los tokens de los intentos fallidos se acumulan silenciosamente**: un sistema que procesa 1,000 documentos por hora y tiene 15% de tasa de fallo en el primer intento gasta 1.15x los tokens esperados. Si el 5% necesita el tercer reintento, el gasto real es 1.35x. Sin tracking explícito, el costo de producción supera el estimado del prototipo en 20-40%. Causa: el código de ejemplo del skill acumula `intentos_fallidos` pero no registra el total de tokens usados incluyendo los intentos fallidos. Fix: registrar `usage.input_tokens + usage.output_tokens` por cada intento (exitoso o fallido) y emitir el total acumulado como métrica. Establecer un alerta si el ratio `tokens_reales / tokens_exitosos` supera 1.5x.
340
+
341
+ **La validación semántica con LLM juez (`validar_semanticamente`) genera un loop infinito cuando el campo `cumple: false` + `reask` del ciclo exterior incluye el error del juez en el mensaje de corrección pero el LLM principal no puede satisfacer la regla semántica**: si la regla es "el resumen no debe contradecir el documento original" y el documento original no está en el contexto de corrección, el LLM nunca puede saber qué contradice. Agota los 3 reintentos, eleva `RuntimeError`, y el pipeline se detiene. Causa: la validación semántica con LLM juez verifica constraints que el LLM corrector no puede satisfacer sin el contexto completo de la regla. Fix: al incluir el error del juez en el mensaje de reask, incluir también el contexto relevante: "Tu resumen contradice el siguiente fragmento del documento original: [cita]". Si el contexto es demasiado grande para el mensaje de reask, reducir el scope de la validación semántica.
342
+
343
+ **`functools.lru_cache` como L1 de caché de embeddings en un servidor FastAPI con múltiples workers no comparte el caché entre procesos, causando que cada worker tenga su propio caché independiente y se llame a la API de embeddings N veces para la misma query en N workers**: con 4 workers uvicorn, la misma query frecuente ("¿cuáles son los horarios?") llama a la API de embeddings 4 veces en lugar de 1. El L1 aparece con 100% de hit rate en cada worker individualmente, pero el hit rate real del sistema es mucho menor. Causa: `lru_cache` es por-proceso; en producción con multiprocessing, el caché no es compartido. Fix: para el L1 inter-proceso, usar una variable de módulo compartida con `multiprocessing.Manager().dict()` o, más simple, subir directamente al L2 (diskcache/Redis) que sí es compartido entre workers.
@@ -0,0 +1,320 @@
1
+ ---
2
+ name: swift-experto
3
+ description: >
4
+ Swift moderno con SwiftUI, @Observable (iOS 17+), NavigationStack,
5
+ async/await con TaskGroup, actors para concurrencia segura, SwiftData,
6
+ Keychain y property wrappers. Cargar cuando se implementen vistas SwiftUI,
7
+ concurrencia Swift, modelos de datos SwiftData, o servicios iOS/macOS.
8
+ version: "1.0.0"
9
+ herramientasPermitidas: [Read, Grep]
10
+ exclusiones:
11
+ - "No cargar para diseñar patrones arquitectónicos Swift (TCA, MVVM, DI con protocolos) — para diseño cargar `swift-patrones`."
12
+ - "No cargar para escribir tests Swift (swift-testing, XCTest, mocks con protocolos) — para testing cargar `swift-testing`."
13
+ - "No cargar para errores de compilación Swift o Xcode — para build errors cargar `build-errors-swift`."
14
+ - "No cargar para Jetpack Compose o Android — Swift/SwiftUI es específico de Apple platforms; para Android cargar `kotlin-compose`."
15
+ evolvable: true # default para skill estandar
16
+ ---
17
+ # Swift Experto — SwiftUI, Concurrencia y SwiftData
18
+
19
+ ## Cuándo NO cargar
20
+
21
+ - La pregunta es sobre diseñar patrones arquitectónicos Swift (TCA, MVVM, dependency injection con protocolos) — cargar `swift-patrones`.
22
+ - La tarea es escribir tests Swift con swift-testing o XCTest — cargar `swift-testing`.
23
+ - Los errores son de compilación Swift o Xcode (provisioning, signing) — cargar `build-errors-swift`.
24
+ - El proyecto es Android con Kotlin/Compose — SwiftUI es específico de Apple platforms; cargar `kotlin-compose`.
25
+
26
+ ## SwiftUI — View Lifecycle y Estructura
27
+
28
+ ```swift
29
+ // Estructura recomendada de una Feature
30
+ // Features/Facturas/
31
+ // FacturasView.swift
32
+ // FacturasViewModel.swift
33
+ // FacturasRepository.swift
34
+ // Models/Factura.swift
35
+
36
+ struct FacturasView: View {
37
+ @State private var viewModel = FacturasViewModel() // @Observable — iOS 17+
38
+
39
+ var body: some View {
40
+ NavigationStack {
41
+ content
42
+ .navigationTitle("Facturas")
43
+ .toolbar { toolbarItems }
44
+ }
45
+ .task { await viewModel.cargar() } // task: se cancela con la vista
46
+ }
47
+
48
+ @ViewBuilder
49
+ private var content: some View {
50
+ switch viewModel.estado {
51
+ case .cargando: ProgressView()
52
+ case .vacio: ContentUnavailableView("Sin facturas", systemImage: "doc.text")
53
+ case .error(let msg): ErrorView(mensaje: msg)
54
+ case .exito(let facturas): listaFacturas(facturas)
55
+ }
56
+ }
57
+
58
+ private func listaFacturas(_ facturas: [Factura]) -> some View {
59
+ List(facturas) { factura in
60
+ NavigationLink(value: factura) {
61
+ FacturaRow(factura: factura)
62
+ }
63
+ }
64
+ .navigationDestination(for: Factura.self) { factura in
65
+ DetalleFacturaView(factura: factura)
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ---
72
+
73
+ ## @Observable — iOS 17+ (preferir sobre ObservableObject)
74
+
75
+ ```swift
76
+ // @Observable: el sistema de dependencias es automático y granular
77
+ // Solo recompone las vistas que leen la propiedad que cambió
78
+ @Observable
79
+ final class FacturasViewModel {
80
+ var estado: EstadoFacturas = .cargando
81
+ var query: String = ""
82
+
83
+ // @Observable NO necesita @Published
84
+ // Las propiedades privadas no rastreadas se marcan con @ObservationIgnored
85
+ @ObservationIgnored private var tarea: Task<Void, Never>?
86
+
87
+ var facturasFiltradas: [Factura] {
88
+ guard case .exito(let facturas) = estado else { return [] }
89
+ return query.isEmpty ? facturas : facturas.filter {
90
+ $0.folio.localizedCaseInsensitiveContains(query)
91
+ }
92
+ }
93
+
94
+ func cargar() async {
95
+ estado = .cargando
96
+ do {
97
+ let facturas = try await repositorio.obtener()
98
+ estado = .exito(facturas)
99
+ } catch {
100
+ estado = .error(error.localizedDescription)
101
+ }
102
+ }
103
+ }
104
+
105
+ enum EstadoFacturas {
106
+ case cargando
107
+ case vacio
108
+ case exito([Factura])
109
+ case error(String)
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Async/Await con TaskGroup
116
+
117
+ ```swift
118
+ // Carga paralela de múltiples recursos
119
+ func cargarDashboard() async throws -> Dashboard {
120
+ async let facturas = api.obtenerFacturas()
121
+ async let clientes = api.obtenerClientes()
122
+ async let estadisticas = api.obtenerEstadisticas()
123
+
124
+ // Espera todos en paralelo
125
+ return try await Dashboard(
126
+ facturas: facturas,
127
+ clientes: clientes,
128
+ estadisticas: estadisticas
129
+ )
130
+ }
131
+
132
+ // TaskGroup para cantidad dinámica de tareas
133
+ func procesarFacturas(_ ids: [String]) async throws -> [FacturaDto] {
134
+ try await withThrowingTaskGroup(of: FacturaDto.self) { group in
135
+ for id in ids {
136
+ group.addTask { try await api.obtenerFactura(id: id) }
137
+ }
138
+ var resultados: [FacturaDto] = []
139
+ for try await dto in group {
140
+ resultados.append(dto)
141
+ }
142
+ return resultados
143
+ }
144
+ }
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Actors — Concurrencia Segura
150
+
151
+ ```swift
152
+ // Actor: acceso exclusivo a estado compartido desde múltiples tareas
153
+ actor CachFacturas {
154
+ private var cache: [String: Factura] = [:]
155
+ private var timestamps: [String: Date] = [:]
156
+ private let ttl: TimeInterval = 300 // 5 minutos
157
+
158
+ func obtener(id: String) -> Factura? {
159
+ guard let ts = timestamps[id], Date().timeIntervalSince(ts) < ttl else {
160
+ return nil
161
+ }
162
+ return cache[id]
163
+ }
164
+
165
+ func guardar(_ factura: Factura) {
166
+ cache[factura.id] = factura
167
+ timestamps[factura.id] = Date()
168
+ }
169
+
170
+ func invalidar(id: String) {
171
+ cache.removeValue(forKey: id)
172
+ timestamps.removeValue(forKey: id)
173
+ }
174
+ }
175
+
176
+ // @MainActor — garantiza ejecución en hilo principal
177
+ @MainActor
178
+ final class FacturasViewModel: ObservableObject {
179
+ func actualizarUI() {
180
+ // Siempre en main thread, sin DispatchQueue.main.async
181
+ }
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## URLSession Async
188
+
189
+ ```swift
190
+ struct FacturasApiClient {
191
+ private let session: URLSession
192
+ private let decoder: JSONDecoder = {
193
+ let d = JSONDecoder()
194
+ d.keyDecodingStrategy = .convertFromSnakeCase
195
+ d.dateDecodingStrategy = .iso8601
196
+ return d
197
+ }()
198
+
199
+ func obtenerFacturas(empresaId: String) async throws -> [FacturaDto] {
200
+ let url = URL(string: "\(baseURL)/v1/facturas?empresa_id=\(empresaId)")!
201
+ var request = URLRequest(url: url)
202
+ request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
203
+ request.timeoutInterval = 30
204
+
205
+ let (data, response) = try await session.data(for: request)
206
+
207
+ guard let http = response as? HTTPURLResponse else {
208
+ throw ApiError.respuestaInvalida
209
+ }
210
+ guard (200..<300).contains(http.statusCode) else {
211
+ throw ApiError.statusCode(http.statusCode)
212
+ }
213
+
214
+ return try decoder.decode([FacturaDto].self, from: data)
215
+ }
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## SwiftData
222
+
223
+ ```swift
224
+ // Modelo
225
+ @Model
226
+ final class Factura {
227
+ @Attribute(.unique) var id: String
228
+ var folio: String
229
+ var total: Double
230
+ var fechaEmision: Date
231
+ var estatus: String
232
+
233
+ @Relationship(deleteRule: .cascade) var items: [ItemFactura] = []
234
+
235
+ init(id: String, folio: String, total: Double) {
236
+ self.id = id
237
+ self.folio = folio
238
+ self.total = total
239
+ self.fechaEmision = Date()
240
+ self.estatus = "borrador"
241
+ }
242
+ }
243
+
244
+ // Configuración en App
245
+ @main
246
+ struct MiApp: App {
247
+ var body: some Scene {
248
+ WindowGroup {
249
+ ContentView()
250
+ }
251
+ .modelContainer(for: [Factura.self, ItemFactura.self])
252
+ }
253
+ }
254
+
255
+ // Uso en Vista
256
+ struct FacturasView: View {
257
+ @Query(sort: \Factura.fechaEmision, order: .reverse) var facturas: [Factura]
258
+ @Environment(\.modelContext) private var ctx
259
+
260
+ func eliminar(_ factura: Factura) {
261
+ ctx.delete(factura)
262
+ }
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ Para la implementación completa del Keychain wrapper (guardar, leer, eliminar)
269
+ y property wrappers personalizados (@Clamped, @Trimmed), ver
270
+ [recursos/keychain-y-wrappers.md](recursos/keychain-y-wrappers.md).
271
+
272
+ ---
273
+
274
+ ## Anti-patrones
275
+
276
+ ### Force unwrap — NUNCA en producción
277
+
278
+ ```swift
279
+ // MAL — crash en runtime
280
+ let factura = facturas.first!
281
+ let url = URL(string: urlString)!
282
+
283
+ // BIEN — manejo explícito
284
+ guard let factura = facturas.first else { return }
285
+ guard let url = URL(string: urlString) else {
286
+ logger.error("URL inválida: \(urlString)")
287
+ return
288
+ }
289
+ ```
290
+
291
+ ### Massive View y ObservableObject con muchas @Published
292
+
293
+ ```swift
294
+ // MAL — body con 200+ líneas mezclando lógica y UI
295
+ // BIEN — extraer sub-vistas (@ViewBuilder) y mover lógica al ViewModel
296
+
297
+ // En iOS 17+, migrar de ObservableObject/@Published a @Observable.
298
+ // @Observable solo recompone las vistas que leen la propiedad que cambió.
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Gotchas / Errores comunes no obvios
304
+
305
+ **`@State` inicializado con un valor que depende de una propiedad del padre no se actualiza cuando el padre cambia**: `@State var total = calcular(items)` se inicializa una vez cuando la vista se crea — si `items` cambia en el padre, `total` no se recalcula. Causa: `@State` es estado local de la vista, no derivado. Fix: usar `@Binding` si el padre necesita controlar el valor, o calcular `total` como una propiedad computada en la vista (sin `@State`) si no necesita ser modificada localmente.
306
+
307
+ **`Task { await ... }` lanzado en `.onAppear` no se cancela cuando la vista desaparece**: si la vista desaparece antes de que el Task termine, el Task sigue ejecutando aunque la vista ya no exista, potencialmente modificando estado stale. Fix: usar `.task { await ... }` (el modificador de SwiftUI, no `Task { }`) — `.task` cancela automáticamente la tarea cuando la vista desaparece.
308
+
309
+ **`actor` con métodos que retornan tipos no-`Sendable` causa errores de concurrencia en Swift 6**: si un `actor` tiene un método que retorna `UIImage` y `UIImage` no es `Sendable`, el compilador con Swift 6 concurrency checks habilitado lanza error. Causa: los valores retornados de actores cruzan isolation boundaries. Fix: marcar los tipos de retorno como `Sendable`, o usar `@unchecked Sendable` con justificación, o rediseñar para que el actor retorne solo tipos value (structs, enums).
310
+
311
+ **`SwiftData` con `@Query` en una vista no se actualiza si el `ModelContext` usado para la mutación es diferente al del `@Environment`**: si se crea un `ModelContext` secundario para inserciones en background y se guarda, la vista con `@Query` del contexto principal puede no reflejar los cambios hasta el próximo ciclo de runloop. Fix: usar el `modelContext` del `@Environment(\.modelContext)` para mutaciones en el hilo principal, o llamar `try context.save()` explícitamente después de las mutaciones en background.
312
+
313
+ ## Checklist Swift
314
+
315
+ - [ ] Usar @Observable en lugar de ObservableObject (iOS 17+)
316
+ - [ ] Sin force unwrap (!) en código de producción
317
+ - [ ] Tokens y datos sensibles en Keychain, nunca en UserDefaults
318
+ - [ ] .task { } en lugar de .onAppear + Task { } para cargas async
319
+ - [ ] Sendable conformance para tipos que cruzan límites de actor
320
+ - [ ] CancellationError no atrapado silenciosamente en catches genéricos