@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,331 @@
1
+ ---
2
+ name: nextjs-testing
3
+ description: >
4
+ Testing Next.js con Vitest, React Testing Library, Playwright y MSW.
5
+ Cubre Server Components, Server Actions, page objects E2E y mocking de API.
6
+ Cargar cuando se escriban tests de componentes, integración o E2E en Next.js.
7
+ version: "1.0.0"
8
+ herramientasPermitidas: [Read]
9
+ exclusiones:
10
+ - "No cargar para tests React puros fuera del contexto de Next.js (Vite, CRA, Remix) — los mocks del router de Next.js y los Server Components son específicos del framework."
11
+ - "No cargar para implementar la lógica del componente que se está testando — si aún no está implementado, cargar `nextjs-experto` primero; los tests se escriben sobre código existente."
12
+ - "No cargar para configurar Playwright en un proyecto no-Next.js — Playwright funciona con cualquier web app, pero este skill cubre la configuración específica de Next.js con `next/server` y Server Actions."
13
+ - "No cargar para cobertura de código o análisis de calidad de tests existentes — para métricas de calidad cargar `checklist-calidad`."
14
+ evolvable: true # default para skill estandar
15
+ ---
16
+ # Next.js Testing — Vitest, RTL, Playwright y MSW
17
+
18
+ El App Router introduce complejidad de testing: Server Components son async,
19
+ los Server Actions requieren contexto de servidor, y el router de Next.js necesita
20
+ mocks específicos. Este skill cubre la configuración y los patrones para cada tipo
21
+ de test en proyectos Next.js modernos.
22
+
23
+ ## Cuándo cargar este skill
24
+
25
+ Invoca `Skill("nextjs-testing")` cuando:
26
+
27
+ - Se configuren Vitest o Jest para un proyecto Next.js
28
+ - Se escriban tests de componentes con React Testing Library
29
+ - Se implementen tests E2E con Playwright
30
+ - Se mockeen APIs externas con MSW en tests
31
+ - Se prueben Server Actions o route handlers
32
+
33
+ ## Cuándo NO cargar
34
+
35
+ - El proyecto usa React sin Next.js (Vite, CRA, Remix) — los mocks de `next/navigation` y los patrones de Server Components son específicos de Next.js.
36
+ - El componente que se quiere testear no está implementado aún — primero implementar con `nextjs-experto`, luego escribir tests.
37
+ - La pregunta es sobre configurar Playwright en un proyecto no-Next.js — Playwright funciona con cualquier web app pero este skill cubre integración con `next/server` y Server Actions.
38
+ - La pregunta es sobre cobertura de código o análisis de calidad de tests existentes — para métricas de calidad cargar `checklist-calidad`.
39
+
40
+ ## Conceptos clave
41
+
42
+ ### Qué testear en Next.js
43
+
44
+ Server Components: testear la lógica de transformación de datos y el HTML
45
+ renderizado. Client Components: testear interacciones, estado y callbacks.
46
+ Server Actions: testear validación, mutaciones y revalidación. E2E: testear
47
+ flujos completos de usuario en el browser real.
48
+
49
+ ### Vitest vs Jest
50
+
51
+ Vitest es la opción moderna: compatible con Vite, más rápido, soporte nativo
52
+ de ESM. Jest requiere más configuración para Next.js con App Router. Ambos son
53
+ compatibles con React Testing Library.
54
+
55
+ ### MSW (Mock Service Worker)
56
+
57
+ MSW intercepta requests HTTP a nivel de Service Worker (browser) o a nivel de
58
+ Node.js (tests). Permite definir handlers una vez y usarlos en tests de unidad,
59
+ integracion y en el browser de desarrollo.
60
+
61
+ ### Estrategia de cobertura por capas
62
+
63
+ Testear Next.js requiere una estrategia sistemática por capas. Cada capa cubre
64
+ un tipo de riesgo distinto — no son intercambiables:
65
+
66
+ | Capa | Qué testea | Herramienta | Ejemplo |
67
+ |------|-----------|-------------|---------|
68
+ | **Componente** | UI aislada, interacciones, estados visuales | Vitest + RTL | `render(<Boton />)` + click + assert texto |
69
+ | **Página (RSC)** | Data fetching + transformación + render | Vitest (async) | `await Pagina({params})` + assert contenido |
70
+ | **Hook** | Lógica reutilizable, efectos, estado | `renderHook` | `renderHook(() => useFiltros())` + act |
71
+ | **Integración** | Server Actions, validación + mutación + revalidación | Vitest + mocks BD | `await crearProducto(formData)` + assert BD |
72
+ | **E2E** | Flujos completos de usuario en browser real | Playwright | Navegar → llenar form → submit → verificar |
73
+
74
+ **Regla de proporción**: ~60% componente/página, ~25% integración, ~15% E2E.
75
+ Los tests E2E son lentos y frágiles — cubrir solo los flujos críticos de negocio.
76
+ Los tests de componente son baratos — cubrir todas las variantes de estado.
77
+
78
+ ## Reglas obligatorias
79
+
80
+ ### Configurar next/jest o Vitest correctamente antes de escribir cualquier test
81
+
82
+ ```javascript
83
+ // vitest.config.ts
84
+ import { defineConfig } from 'vitest/config';
85
+ import react from '@vitejs/plugin-react';
86
+ import path from 'path';
87
+
88
+ export default defineConfig({
89
+ plugins: [react()],
90
+ test: {
91
+ environment: 'jsdom',
92
+ setupFiles: ['./tests/setup.ts'],
93
+ globals: true,
94
+ },
95
+ resolve: {
96
+ alias: { '@': path.resolve(__dirname, './') },
97
+ },
98
+ });
99
+ ```
100
+
101
+ ### Mockear next/navigation y next/router SIEMPRE en tests de componentes
102
+
103
+ ```typescript
104
+ // tests/setup.ts
105
+ vi.mock('next/navigation', () => ({
106
+ useRouter: () => ({ push: vi.fn(), replace: vi.fn(), prefetch: vi.fn() }),
107
+ useSearchParams: () => new URLSearchParams(),
108
+ usePathname: () => '/',
109
+ }));
110
+ ```
111
+
112
+ Sin este mock, cualquier componente que importe de `next/navigation` fallará.
113
+
114
+ ### MSW handlers en archivo centralizado, no inline en cada test
115
+
116
+ ```typescript
117
+ // tests/msw/handlers.ts
118
+ import { http, HttpResponse } from 'msw';
119
+
120
+ export const handlers = [
121
+ http.get('/api/productos', () => {
122
+ return HttpResponse.json({ data: [{ id: 1, nombre: 'Laptop' }] });
123
+ }),
124
+ http.post('/api/productos', async ({ request }) => {
125
+ const body = await request.json();
126
+ return HttpResponse.json({ data: { id: 99, ...body } }, { status: 201 });
127
+ }),
128
+ ];
129
+ ```
130
+
131
+ ## Patrones recomendados
132
+
133
+ ### Testing de Client Component con interacciones
134
+
135
+ ```typescript
136
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
137
+ import userEvent from '@testing-library/user-event';
138
+ import FormularioProducto from '@/components/FormularioProducto';
139
+
140
+ describe('FormularioProducto', () => {
141
+ it('envia el formulario con datos validos', async () => {
142
+ const user = userEvent.setup();
143
+ const mockSubmit = vi.fn();
144
+
145
+ render(<FormularioProducto onSubmit={mockSubmit} />);
146
+
147
+ await user.type(screen.getByLabelText('Nombre'), 'Laptop Pro');
148
+ await user.type(screen.getByLabelText('Precio'), '25000');
149
+ await user.click(screen.getByRole('button', { name: /guardar/i }));
150
+
151
+ await waitFor(() => {
152
+ expect(mockSubmit).toHaveBeenCalledWith({
153
+ nombre: 'Laptop Pro',
154
+ precio: 25000,
155
+ });
156
+ });
157
+ });
158
+
159
+ it('muestra error cuando el nombre esta vacio', async () => {
160
+ const user = userEvent.setup();
161
+ render(<FormularioProducto onSubmit={vi.fn()} />);
162
+
163
+ await user.click(screen.getByRole('button', { name: /guardar/i }));
164
+
165
+ expect(screen.getByText('El nombre es requerido')).toBeInTheDocument();
166
+ });
167
+ });
168
+ ```
169
+
170
+ ### Testing de Server Component (async)
171
+
172
+ ```typescript
173
+ import { render, screen } from '@testing-library/react';
174
+ import ListaProductos from '@/app/productos/page';
175
+
176
+ // Mockear la función de fetch de datos
177
+ vi.mock('@/lib/api', () => ({
178
+ obtenerProductos: vi.fn().mockResolvedValue([
179
+ { id: 1, nombre: 'Laptop', precio: 25000 },
180
+ { id: 2, nombre: 'Mouse', precio: 500 },
181
+ ]),
182
+ }));
183
+
184
+ it('renderiza lista de productos', async () => {
185
+ const ui = await ListaProductos({});
186
+ render(ui);
187
+
188
+ expect(screen.getByText('Laptop')).toBeInTheDocument();
189
+ expect(screen.getByText('Mouse')).toBeInTheDocument();
190
+ });
191
+ ```
192
+
193
+ ### Testing de Server Action
194
+
195
+ ```typescript
196
+ import { crearProducto } from '@/app/actions/productos';
197
+ import { db } from '@/lib/db';
198
+
199
+ vi.mock('@/lib/db');
200
+ vi.mock('@/lib/auth', () => ({
201
+ auth: vi.fn().mockResolvedValue({ user: { id: '1', rol: 'admin' } }),
202
+ }));
203
+
204
+ describe('crearProducto', () => {
205
+ it('crea producto con datos validos', async () => {
206
+ const formData = new FormData();
207
+ formData.append('nombre', 'Laptop Pro');
208
+ formData.append('precio', '25000');
209
+
210
+ const resultado = await crearProducto(formData);
211
+
212
+ expect(resultado).not.toHaveProperty('error');
213
+ expect(db.producto.create).toHaveBeenCalled();
214
+ });
215
+
216
+ it('retorna errores de validacion con datos invalidos', async () => {
217
+ const formData = new FormData();
218
+ formData.append('nombre', ''); // invalido
219
+
220
+ const resultado = await crearProducto(formData);
221
+
222
+ expect(resultado?.error?.nombre).toBeDefined();
223
+ });
224
+ });
225
+ ```
226
+
227
+ ### Playwright Page Object para E2E
228
+
229
+ ```typescript
230
+ // tests/e2e/pages/ProductosPage.ts
231
+ import { Page, Locator } from '@playwright/test';
232
+
233
+ export class ProductosPage {
234
+ readonly page: Page;
235
+ readonly botonNuevo: Locator;
236
+ readonly tablaProductos: Locator;
237
+
238
+ constructor(page: Page) {
239
+ this.page = page;
240
+ this.botonNuevo = page.getByRole('button', { name: 'Nuevo producto' });
241
+ this.tablaProductos = page.getByRole('table', { name: 'Productos' });
242
+ }
243
+
244
+ async navegar() {
245
+ await this.page.goto('/dashboard/productos');
246
+ }
247
+
248
+ async crearProducto(nombre: string, precio: number) {
249
+ await this.botonNuevo.click();
250
+ await this.page.getByLabel('Nombre').fill(nombre);
251
+ await this.page.getByLabel('Precio').fill(precio.toString());
252
+ await this.page.getByRole('button', { name: 'Guardar' }).click();
253
+ }
254
+ }
255
+
256
+ // tests/e2e/productos.spec.ts
257
+ import { test, expect } from '@playwright/test';
258
+ import { ProductosPage } from './pages/ProductosPage';
259
+
260
+ test('admin puede crear un producto', async ({ page }) => {
261
+ const productosPage = new ProductosPage(page);
262
+ await productosPage.navegar();
263
+ await productosPage.crearProducto('Laptop Pro', 25000);
264
+
265
+ await expect(page.getByText('Laptop Pro')).toBeVisible();
266
+ });
267
+ ```
268
+
269
+ ### MSW en tests de integración con servidor Node
270
+
271
+ ```typescript
272
+ // tests/setup.ts
273
+ import { setupServer } from 'msw/node';
274
+ import { handlers } from './msw/handlers';
275
+
276
+ const server = setupServer(...handlers);
277
+
278
+ beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
279
+ afterEach(() => server.resetHandlers());
280
+ afterAll(() => server.close());
281
+ ```
282
+
283
+ ## Anti-patrones conocidos
284
+
285
+ ### getByTestId como primera opción
286
+
287
+ ```typescript
288
+ // MAL — acoplado a detalles de implementación
289
+ screen.getByTestId('boton-submit');
290
+
291
+ // BIEN — accesible y más semántico
292
+ screen.getByRole('button', { name: /guardar/i });
293
+ screen.getByLabelText('Email');
294
+ screen.getByText('Confirmar pedido');
295
+ ```
296
+
297
+ Prioridad: getByRole > getByLabelText > getByPlaceholderText > getByText > getByTestId.
298
+
299
+ ### Snapshot tests para componentes que cambian frecuentemente
300
+
301
+ Los snapshots se desactualizan y se actualizan sin revisar el cambio real.
302
+ Preferir assertions específicas sobre el contenido crítico.
303
+
304
+ ## Gotchas / Errores comunes no obvios
305
+
306
+ **`vi.mock('next/navigation')` no afecta si se importa antes del mock**: si el componente bajo test importa `useRouter` en el nivel de módulo antes de que `vi.mock` se evalúe, el mock no se aplica. Causa: Vitest hoistea los `vi.mock()` al inicio del archivo, pero en algunos setups con transformaciones el orden puede fallar. Fix: asegurarse que `vi.mock('next/navigation', ...)` está en el archivo de setup global (`tests/setup.ts`) y se carga antes de cualquier import del componente.
307
+
308
+ **Server Component async no se puede renderizar directamente con `render()`**: `render(<MiServerComponent />)` falla con `Objects are not valid as a React child (found: [object Promise])` porque RTL no sabe manejar un componente async. Causa: React Testing Library en su versión estable no soporta async Server Components directamente. Fix: `await` el componente primero (`const ui = await MiServerComponent({params})`), luego `render(ui)`.
309
+
310
+ **MSW con `onUnhandledRequest: 'error'` falla en tests que hacen fetches a rutas internas de Next.js**: el test lanza error porque `_next/static/...` o rutas internas del framework generan requests que MSW no tiene handlers para. Causa: Next.js en modo test puede generar requests internos. Fix: usar `onUnhandledRequest: 'warn'` o agregar handlers para las rutas internas de Next.js, o filtrar con una función: `onUnhandledRequest: (req) => { if (!req.url.includes('_next')) throw new Error(...) }`.
311
+
312
+ **`userEvent.setup()` debe llamarse fuera del `it()` o re-instanciarse por test**: compartir una instancia de `userEvent` entre tests causa que el estado del puntero/teclado se acumule entre tests, causando comportamiento impredecible. Causa: `userEvent.setup()` crea un estado de dispositivo virtual que persiste. Fix: llamar `const user = userEvent.setup()` dentro de cada `it()` o en `beforeEach`, no al nivel de `describe`.
313
+
314
+ ## Checklist de verificación
315
+
316
+ - [ ] Vitest/Jest configurado con next/jest transform o plugin react
317
+ - [ ] next/navigation mockeado en setup global de tests
318
+ - [ ] MSW handlers en archivo centralizado
319
+ - [ ] Tests de Client Component usan userEvent (no fireEvent para interacciones)
320
+ - [ ] Server Actions testeadas con FormData real
321
+ - [ ] E2E con Page Objects para reutilizar selectores
322
+ - [ ] `onUnhandledRequest: 'error'` en MSW para detectar fetches sin handler
323
+
324
+ ## Referencias
325
+
326
+ - [Testing Next.js](https://nextjs.org/docs/app/building-your-application/testing)
327
+ - [MSW](https://mswjs.io/docs)
328
+ - [Playwright](https://playwright.dev/docs/intro)
329
+
330
+ ---
331
+ *Skill creado con swl:crear-skill el 2026-03-31. Versión 1.0.0.*
@@ -0,0 +1,9 @@
1
+ {
2
+ "SKILL.md": {
3
+ "evolved": true,
4
+ "evolvedFrom": "5.3.3",
5
+ "evolvedAt": "2026-04-09",
6
+ "evolvedBy": "aprender",
7
+ "evolvedNote": "anti-patrón JSDoc glob, JSONL append-only, webhook fire-and-forget, dual-use scripts"
8
+ }
9
+ }
@@ -0,0 +1,266 @@
1
+ ---
2
+ name: node-experto
3
+ description: Node.js y TypeScript backend moderno. Cubre patterns de Express/Fastify/NestJS, error handling middleware, streams y buffers, worker threads y clustering, Prisma/Drizzle ORM, validación con Zod, graceful shutdown y anti-patrones críticos como callback hell y event loop blocking.
4
+ version: "1.0.0"
5
+ herramientasPermitidas: [Read, Write, Glob]
6
+ exclusiones:
7
+ - "No cargar para aplicaciones Next.js con App Router — Next.js tiene patrones de Server Components, SSR y caché que difieren del backend Node puro; cargar `nextjs-experto`."
8
+ - "No cargar para proyectos NestJS con DI compleja — NestJS tiene su propio sistema de módulos y decoradores que merece su skill; cargar `nestjs-experto`."
9
+ - "No cargar para scripting Python o backend no-JS — este skill cubre el stack Node.js específicamente."
10
+ - "No cargar para errores de compilación TypeScript o tsconfig — para esos cargar `build-errors-typescript`; este skill asume que el código compila."
11
+ evolvable: true # default para skill estandar
12
+ ---
13
+ # Node.js Experto — Backend TypeScript Moderno
14
+
15
+ ## Cuándo NO cargar
16
+
17
+ - El proyecto usa Next.js App Router — los patrones de Server Components, SSR y caché son específicos de Next.js; cargar `nextjs-experto`.
18
+ - El proyecto usa NestJS con inyección de dependencias, decoradores y módulos — NestJS tiene su propio sistema opinionado; cargar `nestjs-experto`.
19
+ - El backend es Python, Go, Java u otro lenguaje no-JS — este skill cubre Node.js específicamente.
20
+ - La pregunta es sobre errores de compilación TypeScript o tsconfig — cargar `build-errors-typescript`; este skill asume que el código compila.
21
+
22
+ ## Filosofía
23
+
24
+ Node.js es monohilo y asíncrono. Todo el rendimiento depende de
25
+ **no bloquear el event loop**. Operaciones I/O siempre asíncronas,
26
+ CPU-intensivo en worker threads, errores siempre manejados.
27
+
28
+ ---
29
+
30
+ ## Frameworks: Cuándo Usar Cuál
31
+
32
+ | Framework | Usar cuando |
33
+ |-----------|------------|
34
+ | **Fastify** | API de alto rendimiento, microservicio |
35
+ | **Express** | Proyecto legacy, equipo familiarizado |
36
+ | **NestJS** | Aplicación empresarial grande, DI, estructura opinionada |
37
+
38
+ ---
39
+
40
+ ## Error Handling — Reglas Obligatorias
41
+
42
+ 1. **Jerarquía de errores tipados**: `AppError` > `ValidationError`, `NotFoundError`, etc.
43
+ 2. **Error middleware SIEMPRE al final** de la cadena.
44
+ 3. **`asyncHandler` wrapper** para capturar errores async sin try/catch repetido.
45
+ 4. **Errores operacionales** (400, 404): respuesta descriptiva al cliente.
46
+ 5. **Errores no esperados** (500): log completo, respuesta genérica. NUNCA stack traces al cliente.
47
+
48
+ ```typescript
49
+ export class AppError extends Error {
50
+ constructor(
51
+ public readonly message: string,
52
+ public readonly statusCode: number,
53
+ public readonly code: string,
54
+ public readonly isOperational = true,
55
+ ) {
56
+ super(message);
57
+ }
58
+ }
59
+
60
+ export class NotFoundError extends AppError {
61
+ constructor(resource: string, id: string) {
62
+ super(`${resource} con id ${id} no encontrado`, 404, 'NOT_FOUND');
63
+ }
64
+ }
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Streams — Reglas
70
+
71
+ - SIEMPRE usar `pipeline()` de `stream/promises` (maneja errores y backpressure).
72
+ - Para archivos grandes: NUNCA cargar todo en memoria. Usar streams.
73
+ - Para respuestas HTTP grandes: `Readable.from()` con generador async.
74
+ - Concatenar buffers con `Buffer.concat()`, NUNCA con `+=` de strings.
75
+
76
+ ---
77
+
78
+ ## Worker Threads y Clustering
79
+
80
+ - CPU-intensivo SIEMPRE en worker threads, NUNCA en el hilo principal.
81
+ - Pool de workers con Piscina para reutilización.
82
+ - Clustering: un worker por CPU core con auto-restart en muerte.
83
+
84
+ ---
85
+
86
+ ## ORM — Prisma y Drizzle
87
+
88
+ - **Prisma**: singleton con `globalThis` para evitar múltiples conexiones.
89
+ - **Transacciones**: `prisma.$transaction()` para operaciones atómicas.
90
+ - **Drizzle**: esquema tipado con `pgTable`, queries type-safe.
91
+
92
+ ---
93
+
94
+ ## Validación con Zod
95
+
96
+ - Schemas reutilizables con `z.infer<typeof Schema>` para tipos.
97
+ - Middleware `validar(schema)` que parsea y lanza `ValidationError` automáticamente.
98
+
99
+ ---
100
+
101
+ ## Graceful Shutdown — OBLIGATORIO
102
+
103
+ 1. Dejar de aceptar nuevas conexiones: `server.close()`
104
+ 2. Cerrar conexiones a BD: `prisma.$disconnect()`
105
+ 3. Timeout de seguridad (10s) para forzar cierre.
106
+ 4. Capturar `SIGTERM`, `SIGINT`, `unhandledRejection`, `uncaughtException`.
107
+
108
+ ---
109
+
110
+ ## Anti-patrones Críticos
111
+
112
+ | Anti-patrón | Corrección |
113
+ |-------------|------------|
114
+ | Callback hell | async/await |
115
+ | `crypto.pbkdf2Sync` en handler | Worker thread |
116
+ | `promise.then()` sin `.catch()` | asyncHandler o try/catch |
117
+ | `require()` dinámico en hot path | Importar al inicio |
118
+ | Operaciones síncronas de fs en requests | `fs.promises.*` |
119
+
120
+ ```typescript
121
+ // MAL: bloquea el event loop
122
+ const hash = crypto.pbkdf2Sync(pass, salt, 100000, 64, 'sha512');
123
+
124
+ // BIEN: en worker thread
125
+ const hash = await pool.run({ pass, salt });
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Checklist Node.js
131
+
132
+ - [ ] NUNCA bloquear el event loop con operaciones síncronas
133
+ - [ ] Error middleware al final de la cadena
134
+ - [ ] Graceful shutdown implementado
135
+ - [ ] CPU-intensivo en worker threads
136
+ - [ ] Streams para archivos/respuestas grandes
137
+ - [ ] Validación de input con Zod
138
+ - [ ] Singleton de Prisma client
139
+ - [ ] `unhandledRejection` y `uncaughtException` capturados
140
+
141
+ Para implementaciones completas de Fastify, Express, streams, workers, ORMs, Zod y graceful shutdown, ver [recursos/patrones-completos.md](recursos/patrones-completos.md).
142
+
143
+ ---
144
+
145
+ ## Gotchas de JSDoc y comentarios multilínea
146
+
147
+ ### NUNCA usar glob `*` dentro de bloques `/** */`
148
+
149
+ **Problema**: El patrón `habilidades/*/SKILL.md` dentro de un bloque JSDoc `/** ... */`
150
+ es interpretado por el parser JS como cierre del comentario en `*/`.
151
+ Produce `SyntaxError: Unexpected identifier` al cargar el módulo.
152
+
153
+ ```javascript
154
+ // MAL — el */ en "habilidades/*/SKILL.md" cierra el bloque JSDoc prematuramente
155
+ /**
156
+ * Scannea habilidades/*/SKILL.md y extrae metadata.
157
+ * ^ este */ cierra el comentario aquí
158
+ */
159
+
160
+ // BIEN — usar <nombre> o texto descriptivo sin glob en JSDoc
161
+ /**
162
+ * Scannea habilidades/<nombre>/SKILL.md y extrae metadata.
163
+ */
164
+ ```
165
+
166
+ Este mismo anti-patrón aplica a cualquier ruta con `*/` dentro de `/** */`:
167
+ `src/*/index.js`, `dist/**/*.js`, etc.
168
+
169
+ ---
170
+
171
+ ## Patrones de I/O para observabilidad
172
+
173
+ ### JSONL + `appendFileSync` para streams de eventos de alta frecuencia
174
+
175
+ Para archivos de telemetría, auditoría o logs append-only, `fs.appendFileSync` es
176
+ superior a escritura atómica JSON:
177
+
178
+ ```javascript
179
+ // MAL para eventos frecuentes — lee y reescribe todo el archivo cada vez
180
+ const eventos = JSON.parse(fs.readFileSync(archivo, 'utf8'));
181
+ eventos.push(nuevoEvento);
182
+ fs.writeFileSync(archivo, JSON.stringify(eventos, null, 2));
183
+
184
+ // BIEN — append-only O(1), sin leer el archivo existente
185
+ fs.appendFileSync(archivo, JSON.stringify(nuevoEvento) + '\n', 'utf8');
186
+
187
+ // Para leer de vuelta: parsear línea a línea
188
+ const eventos = fs.readFileSync(archivo, 'utf8')
189
+ .split('\n').filter(Boolean).map(l => JSON.parse(l));
190
+ ```
191
+
192
+ Usar `atomicWriteJSON` para archivos de estado (mutation frecuente).
193
+ Usar `appendFileSync` para archivos de eventos (solo escritura secuencial).
194
+
195
+ ### Webhook fire-and-forget con `http`/`https` nativo (zero-deps)
196
+
197
+ Para exportaciones opcionales (OTLP, audit webhooks, Slack, Datadog):
198
+
199
+ ```javascript
200
+ const http = require('http');
201
+ const https = require('https');
202
+
203
+ function enviarWebhookAsync(url, payload) {
204
+ if (!url) return; // No lanzar si no está configurado
205
+
206
+ try {
207
+ const body = JSON.stringify(payload);
208
+ const parsed = new URL(url);
209
+ const modulo = parsed.protocol === 'https:' ? https : http;
210
+
211
+ const req = modulo.request({
212
+ hostname: parsed.hostname,
213
+ port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80),
214
+ path: parsed.pathname + (parsed.search || ''),
215
+ method: 'POST',
216
+ headers: {
217
+ 'Content-Type': 'application/json',
218
+ 'Content-Length': Buffer.byteLength(body),
219
+ },
220
+ });
221
+ req.on('error', () => {}); // Silencioso — nunca interrumpir el flujo principal
222
+ req.write(body);
223
+ req.end();
224
+ } catch (_) {}
225
+ }
226
+ ```
227
+
228
+ Verificar siempre `process.env.WEBHOOK_URL` antes de llamar — sin config requerida.
229
+
230
+ ---
231
+
232
+ ## Scripts dual-use: librería + CLI
233
+
234
+ ### `require.main === module` para scripts en `scripts/lib/`
235
+
236
+ Permite que el mismo archivo funcione como librería importable Y como CLI
237
+ sin duplicar lógica:
238
+
239
+ ```javascript
240
+ // scripts/lib/mi-script.js
241
+ function miFuncion(cwd) { /* ... */ }
242
+ module.exports = { miFuncion };
243
+
244
+ // Solo se ejecuta cuando se invoca directamente con `node scripts/lib/mi-script.js`
245
+ // NO se ejecuta cuando otro módulo lo importa con require('./mi-script')
246
+ if (require.main === module) {
247
+ const args = process.argv.slice(2);
248
+ const query = args.filter(a => !a.startsWith('--'))[0] || '';
249
+ const resultado = miFuncion(process.cwd(), query);
250
+ process.stdout.write(JSON.stringify(resultado, null, 2) + '\n');
251
+ }
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Gotchas / Errores comunes no obvios
257
+
258
+ **Prisma Client creado en cada request agota el pool de conexiones**: instanciar `new PrismaClient()` dentro de un handler crea una nueva pool por cada request. En producción esto provoca `Too many connections` en la BD. Fix: exportar un singleton con el patrón `globalThis.__prisma || new PrismaClient()` y reutilizarlo en todos los handlers.
259
+
260
+ **`unhandledRejection` no captura errores en callbacks síncronos dentro de Promises**: el handler `process.on('unhandledRejection', ...)` captura promesas rechazadas sin `.catch()`, pero no captura errores lanzados en código síncrono dentro de un `Promise` executor si ese error no se propaga al reject. Causa: `new Promise((resolve, reject) => { throw new Error('X') })` sí se captura, pero `setTimeout(() => { throw new Error('X') }, 0)` dentro de una promesa no. Fix: usar `uncaughtException` también, y never usar setTimeout con código que puede lanzar dentro de promesas.
261
+
262
+ **`stream.pipeline()` no limpia streams en versiones < Node 16 con errores en mitad del pipe**: en Node 14, un error en un transform stream intermedio deja el readable stream sin destruir, causando memory leak. Fix: usar Node 18+ o agregar listeners de `error` en cada stream del pipeline manualmente en proyectos que deben soportar Node 14/16.
263
+
264
+ **Zod `.parse()` vs `.safeParse()` en middleware**: usar `schema.parse(body)` en un middleware Express lanza una excepción no capturada si no hay un try/catch, y el error llega al cliente con stack trace completo. Fix: usar siempre `schema.safeParse(body)` en middleware y verificar `result.success` antes de continuar; pasar `result.error` al error handler con `next(result.error)`.
265
+
266
+ **`response.json()` sobre body vacío lanza `SyntaxError: Unexpected end of JSON input`**: cuando el servidor responde con 204 No Content, 205 Reset Content, o con `Content-Length: 0`, el body está vacío — `fetch(...).then(r => r.json())` falla en el cliente porque JSON.parse sobre string vacío lanza excepción. Causa: el contrato de fetch no verifica el status antes de parsear; el cliente asume que siempre hay JSON. Fix: verificar status y Content-Length antes de parsear: `if (r.status === 204 || r.status === 205 || r.headers.get('content-length') === '0') return null;`. Si el servidor FastAPI retorna 200 con body vacío por bug, considerar helper `await r.text()` antes y `JSON.parse` con try/catch — o mejor, devolver 204 explícito en endpoints que no retornan cuerpo.