@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,929 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: calidad-pre-commit.js
6
+ * Tipo: PreToolUse (aplica a: Bash — comandos git commit)
7
+ *
8
+ * Verifica calidad mínima del código staged ANTES de que Claude Code
9
+ * ejecute un `git commit`. Si detecta violaciones, bloquea el commit
10
+ * y lista los problemas encontrados con archivo y número de línea.
11
+ *
12
+ * Verificaciones por tipo de archivo:
13
+ *
14
+ * Todos los archivos:
15
+ * - Sin credenciales hardcodeadas (password=, secret=, api_key=, token=)
16
+ * - Sin archivos > 1 MB siendo commiteados
17
+ * - Sin pendientes (TO-DO) sin referencia a ticket/issue
18
+ *
19
+ * Archivos .py / .ts / .js:
20
+ * - Sin console.log() de debug (.ts / .js)
21
+ * - Sin print() de debug (.py) — excluye print dentro de if __name__
22
+ *
23
+ * Archivos .py:
24
+ * - Funciones públicas deben tener type hints en parámetros y retorno
25
+ *
26
+ * Archivos de producción multi-lenguaje (excluyen test/spec):
27
+ * - .java → Sin System.out.println/printf/print
28
+ * - .go → Sin fmt.Println/Printf/Print
29
+ * - .rs → Sin println!/print!/eprintln!/eprint!
30
+ * - .cs → Sin Console.WriteLine/Write/Error.WriteLine
31
+ * - .kt/.kts → Sin println()
32
+ * - .php → Sin var_dump/dd/dump/print_r/die
33
+ * - .swift → Sin print()
34
+ *
35
+ * Resultado:
36
+ * - Violaciones encontradas → razón en stdout + exit code 2 (block)
37
+ * - Sin violaciones → sin output, proceso termina naturalmente
38
+ * - Error interno → sin output (nunca bloquear por fallo del hook)
39
+ *
40
+ * NOTA: Este hook aplica solo cuando el comando Bash contiene "git commit".
41
+ * Para hooks de git nativos (.git/hooks/pre-commit), usar un script shell
42
+ * que llame a este archivo directamente.
43
+ */
44
+
45
+ const fs = require('fs');
46
+ const path = require('path');
47
+ const { execSync } = require('child_process');
48
+
49
+ const { normalizeForDetection } = require('./lib/normalize-input');
50
+
51
+ // ---------------------------------------------------------------------------
52
+ // Constantes de configuración
53
+ // ---------------------------------------------------------------------------
54
+
55
+ /** Tamaño máximo permitido por archivo a commitear (en bytes). */
56
+ const LIMITE_TAMANO_BYTES = 1024 * 1024; // 1 MB
57
+
58
+ /**
59
+ * Patrones de credenciales hardcodeadas.
60
+ * Se evalúan línea por línea en todos los archivos de texto.
61
+ */
62
+ const PATRONES_CREDENCIALES = [
63
+ {
64
+ nombre: 'password hardcodeado',
65
+ // password = "valor", password: "valor" — no captura placeholders vacíos
66
+ patron: /\bpassword\s*[=:]\s*["'][^"'\s]{4,}["']/i,
67
+ },
68
+ {
69
+ nombre: 'secret hardcodeado',
70
+ patron: /\bsecret\s*[=:]\s*["'][^"'\s]{4,}["']/i,
71
+ },
72
+ {
73
+ nombre: 'api_key hardcodeada',
74
+ patron: /\bapi_key\s*[=:]\s*["'][^"'\s]{4,}["']/i,
75
+ },
76
+ {
77
+ nombre: 'token hardcodeado',
78
+ // "token" como variable independiente, no como parte de otra palabra
79
+ patron: /\btoken\s*[=:]\s*["'][^"'\s]{8,}["']/i,
80
+ },
81
+ ];
82
+
83
+ /**
84
+ * Marcadores que indican que un valor es un placeholder y no una credencial real.
85
+ * Si la línea contiene alguno de estos, se omite la alerta de credencial.
86
+ */
87
+ const MARCADORES_PLACEHOLDER_CREDENCIAL = [
88
+ 'YOUR_',
89
+ 'your_',
90
+ '<YOUR',
91
+ 'PLACEHOLDER',
92
+ 'placeholder',
93
+ 'example',
94
+ 'fake_',
95
+ 'dummy_',
96
+ 'xxxxxxxx',
97
+ 'os.environ',
98
+ 'process.env',
99
+ 'getenv(',
100
+ '# nosec',
101
+ '// nosec',
102
+ 'pragma: allowlist secret',
103
+ 'noqa',
104
+ ];
105
+
106
+ /**
107
+ * Extensiones de archivo que se consideran binarias y se omiten en análisis de texto.
108
+ */
109
+ const EXTENSIONES_BINARIAS = new Set([
110
+ '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.webp', '.svg',
111
+ '.pdf', '.zip', '.tar', '.gz', '.rar', '.7z',
112
+ '.exe', '.dll', '.so', '.dylib', '.bin',
113
+ '.woff', '.woff2', '.ttf', '.otf', '.eot',
114
+ '.mp3', '.mp4', '.avi', '.mov', '.mkv',
115
+ '.pyc', '.pyo', '.pyd',
116
+ '.lock',
117
+ ]);
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Utilidades de sistema
121
+ // ---------------------------------------------------------------------------
122
+
123
+ /**
124
+ * Obtiene la lista de archivos staged en el índice de git.
125
+ * Retorna un array de rutas relativas al repositorio.
126
+ *
127
+ * @returns {string[]}
128
+ */
129
+ function obtenerArchivosStagedGit() {
130
+ try {
131
+ const salida = execSync('git diff --cached --name-only --diff-filter=ACM', {
132
+ encoding: 'utf8',
133
+ stdio: ['pipe', 'pipe', 'pipe'],
134
+ });
135
+ return salida
136
+ .split('\n')
137
+ .map(l => l.trim())
138
+ .filter(Boolean);
139
+ } catch (_) {
140
+ // Si git no está disponible o no hay repositorio, retornar lista vacía
141
+ return [];
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Obtiene el contenido staged de un archivo (lo que realmente se commitea,
147
+ * no la versión en disco que puede tener cambios no staged).
148
+ *
149
+ * @param {string} rutaRelativa - Ruta relativa al repositorio.
150
+ * @returns {string|null} Contenido como string UTF-8, o null si falla/es binario.
151
+ */
152
+ function obtenerContenidoStaged(rutaRelativa) {
153
+ try {
154
+ const contenido = execSync(`git show :${rutaRelativa}`, {
155
+ encoding: 'buffer',
156
+ stdio: ['pipe', 'pipe', 'pipe'],
157
+ });
158
+ // Detectar binario heurísticamente: byte nulo en los primeros 8KB
159
+ const muestra = contenido.slice(0, 8192);
160
+ if (muestra.includes(0)) return null;
161
+ return contenido.toString('utf8');
162
+ } catch (_) {
163
+ return null;
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Obtiene el tamaño en bytes del archivo staged.
169
+ *
170
+ * @param {string} rutaRelativa
171
+ * @returns {number} Tamaño en bytes, o 0 si falla.
172
+ */
173
+ function obtenerTamanoStaged(rutaRelativa) {
174
+ try {
175
+ const salida = execSync(`git cat-file -s :${rutaRelativa}`, {
176
+ encoding: 'utf8',
177
+ stdio: ['pipe', 'pipe', 'pipe'],
178
+ });
179
+ return parseInt(salida.trim(), 10) || 0;
180
+ } catch (_) {
181
+ return 0;
182
+ }
183
+ }
184
+
185
+ // ---------------------------------------------------------------------------
186
+ // Verificaciones individuales
187
+ // ---------------------------------------------------------------------------
188
+
189
+ /**
190
+ * Verifica si una línea tiene marcadores de placeholder para credenciales.
191
+ *
192
+ * @param {string} linea
193
+ * @returns {boolean}
194
+ */
195
+ function esPlaceholderCredencial(linea) {
196
+ return MARCADORES_PLACEHOLDER_CREDENCIAL.some(m => linea.includes(m));
197
+ }
198
+
199
+ /**
200
+ * Verifica que el archivo no supere el límite de tamaño.
201
+ *
202
+ * @param {string} rutaRelativa
203
+ * @returns {{ ok: boolean, mensaje: string }}
204
+ */
205
+ function verificarTamano(rutaRelativa) {
206
+ const tamano = obtenerTamanoStaged(rutaRelativa);
207
+ if (tamano > LIMITE_TAMANO_BYTES) {
208
+ const mb = (tamano / (1024 * 1024)).toFixed(2);
209
+ return {
210
+ ok: false,
211
+ mensaje: ` [TAMAÑO] ${rutaRelativa}: ${mb} MB supera el límite de 1 MB`,
212
+ };
213
+ }
214
+ return { ok: true, mensaje: '' };
215
+ }
216
+
217
+ /**
218
+ * Verifica que no haya credenciales hardcodeadas en el contenido.
219
+ *
220
+ * @param {string} rutaRelativa
221
+ * @param {string} contenido
222
+ * @returns {{ ok: boolean, mensajes: string[] }}
223
+ */
224
+ function verificarCredenciales(rutaRelativa, contenido) {
225
+ // Normalizar para prevenir bypass con fullwidth Unicode, ANSI escapes o null bytes
226
+ const contenidoNorm = normalizeForDetection(contenido);
227
+ const lineas = contenidoNorm.split('\n');
228
+ const mensajes = [];
229
+
230
+ for (let i = 0; i < lineas.length; i++) {
231
+ const linea = lineas[i];
232
+
233
+ // Saltar líneas comentadas con marcadores de exclusión
234
+ if (esPlaceholderCredencial(linea)) continue;
235
+
236
+ for (const { nombre, patron } of PATRONES_CREDENCIALES) {
237
+ if (patron.test(linea)) {
238
+ mensajes.push(
239
+ ` [CREDENCIAL] ${rutaRelativa}:${i + 1} — ${nombre} detectado`
240
+ );
241
+ break; // Una alerta por línea es suficiente
242
+ }
243
+ }
244
+ }
245
+
246
+ return { ok: mensajes.length === 0, mensajes };
247
+ }
248
+
249
+ /**
250
+ * Verifica que no haya sentencias console.log() en archivos TypeScript o JavaScript.
251
+ * Excluye líneas comentadas con // o /* y archivos de test.
252
+ *
253
+ * @param {string} rutaRelativa
254
+ * @param {string} contenido
255
+ * @returns {{ ok: boolean, mensajes: string[] }}
256
+ */
257
+ function verificarConsoleLog(rutaRelativa, contenido) {
258
+ // Excluir archivos de test, scripts CLI y configuración donde console.log es legítimo
259
+ const esArchivoExcluido = /\.(test|spec)\.[jt]s$/.test(rutaRelativa) ||
260
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
261
+ /[/\\]__tests__[/\\]/.test(rutaRelativa) ||
262
+ /^scripts[/\\]/.test(rutaRelativa) ||
263
+ /^bin[/\\]/.test(rutaRelativa) ||
264
+ /^hooks[/\\]/.test(rutaRelativa) ||
265
+ /^gateway[/\\]/.test(rutaRelativa) ||
266
+ /^tests[/\\]/.test(rutaRelativa);
267
+
268
+ if (esArchivoExcluido) return { ok: true, mensajes: [] };
269
+
270
+ const lineas = contenido.split('\n');
271
+ const mensajes = [];
272
+ // Patrón: console.log, console.debug, console.info, console.warn que no sean
273
+ // parte de un comentario de línea completa
274
+ const patronLog = /^\s*console\.(log|debug|info|warn)\s*\(/;
275
+ const esComentario = /^\s*(\/\/|\/\*|\*)/;
276
+
277
+ for (let i = 0; i < lineas.length; i++) {
278
+ const linea = lineas[i];
279
+ if (esComentario.test(linea)) continue;
280
+ if (patronLog.test(linea)) {
281
+ mensajes.push(
282
+ ` [DEBUG] ${rutaRelativa}:${i + 1} — console.log/debug en código no-test`
283
+ );
284
+ }
285
+ }
286
+
287
+ return { ok: mensajes.length === 0, mensajes };
288
+ }
289
+
290
+ /**
291
+ * Verifica que no haya sentencias print() de debug en archivos Python.
292
+ * Reglas de exclusión:
293
+ * - Líneas comentadas con #
294
+ * - print() dentro de bloques if __name__ == '__main__'
295
+ * - Archivos de test
296
+ *
297
+ * @param {string} rutaRelativa
298
+ * @param {string} contenido
299
+ * @returns {{ ok: boolean, mensajes: string[] }}
300
+ */
301
+ function verificarPrintPython(rutaRelativa, contenido) {
302
+ const esArchivoTest = /test.*\.py$/.test(rutaRelativa) ||
303
+ /[/\\]tests?[/\\]/.test(rutaRelativa);
304
+ // Excluir código vendorizado de terceros
305
+ const esVendor = /^scripts[/\\]vendor[/\\]/.test(rutaRelativa);
306
+
307
+ if (esArchivoTest || esVendor) return { ok: true, mensajes: [] };
308
+
309
+ const lineas = contenido.split('\n');
310
+ const mensajes = [];
311
+ // Patrón de print() al inicio de la sentencia (no como argumento de otra función)
312
+ const patronPrint = /^\s*print\s*\(/;
313
+ const esComentario = /^\s*#/;
314
+ // Detectar si estamos dentro de if __name__ == '__main__':
315
+ const patronMainBlock = /if\s+__name__\s*==\s*['"]__main__['"]\s*:/;
316
+
317
+ let dentroDeMainBlock = false;
318
+ let indentacionMain = -1;
319
+
320
+ for (let i = 0; i < lineas.length; i++) {
321
+ const linea = lineas[i];
322
+
323
+ // Detectar inicio del bloque __main__
324
+ if (patronMainBlock.test(linea)) {
325
+ dentroDeMainBlock = true;
326
+ // La indentación del bloque es la del if más 4 espacios (convención Python)
327
+ indentacionMain = (linea.match(/^(\s*)/)?.[1].length ?? 0) + 1;
328
+ continue;
329
+ }
330
+
331
+ // Verificar si seguimos dentro del bloque __main__
332
+ if (dentroDeMainBlock) {
333
+ const indentacionLinea = linea.match(/^(\s*)/)?.[1].length ?? 0;
334
+ const esLineaVacia = linea.trim() === '';
335
+ // Salir del bloque si la indentación vuelve al nivel del if o menor
336
+ if (!esLineaVacia && indentacionLinea < indentacionMain) {
337
+ dentroDeMainBlock = false;
338
+ indentacionMain = -1;
339
+ } else {
340
+ continue; // Dentro del bloque main — permitir print()
341
+ }
342
+ }
343
+
344
+ if (esComentario.test(linea)) continue;
345
+ if (patronPrint.test(linea)) {
346
+ mensajes.push(
347
+ ` [DEBUG] ${rutaRelativa}:${i + 1} — print() de debug en código de producción`
348
+ );
349
+ }
350
+ }
351
+
352
+ return { ok: mensajes.length === 0, mensajes };
353
+ }
354
+
355
+ /**
356
+ * Verifica que no haya pendientes (TO-DO) sin referencia a ticket o issue.
357
+ * Se considera válido si el pendiente va seguido de una referencia como:
358
+ * TO-DO(#123), TO-DO: #456, TO-DO(GH-789), TO-DO: JIRA-123, TO-DO: https://...
359
+ *
360
+ * @param {string} rutaRelativa
361
+ * @param {string} contenido
362
+ * @returns {{ ok: boolean, mensajes: string[] }}
363
+ */
364
+ function verificarTodosSinTicket(rutaRelativa, contenido) {
365
+ // Excluir archivos del sistema SWL (hooks, scripts, bin) de esta verificación
366
+ if (/^(hooks|scripts|bin)[/\\]/.test(rutaRelativa)) {
367
+ return { ok: true, mensajes: [] };
368
+ }
369
+
370
+ const lineas = contenido.split('\n');
371
+ const mensajes = [];
372
+
373
+ // Construir palabra clave dinámicamente para evitar auto-detección
374
+ const keyword = 'TO' + 'DO';
375
+ const patronSinTicket = new RegExp(`\\b${keyword}\\b(?!\\s*[:(]\\s*(?:#\\d+|[A-Z]+-\\d+|https?:\\/\\/))`);
376
+ const patronConTicket = new RegExp(`\\b${keyword}\\s*[:(]\\s*(?:#\\d+|[A-Z]+-\\d+|https?:\\/\\/)`);
377
+ const patronNosec = /\/\/\s*nosec/;
378
+
379
+ let dentroDeCodigoMd = false;
380
+ const esMd = /\.md$/i.test(rutaRelativa);
381
+
382
+ for (let i = 0; i < lineas.length; i++) {
383
+ const linea = lineas[i];
384
+ // En Markdown, rastrear bloques de código (```) para excluir su contenido
385
+ if (esMd && /^```/.test(linea.trim())) {
386
+ dentroDeCodigoMd = !dentroDeCodigoMd;
387
+ continue;
388
+ }
389
+ if (dentroDeCodigoMd) continue;
390
+ // Excluir líneas marcadas con // nosec o <!-- nosec -->
391
+ if (patronNosec.test(linea) || /<!--\s*nosec\s*-->/.test(linea)) continue;
392
+ // En Markdown, excluir "TODO" dentro de backticks (código inline) o como palabra española
393
+ if (esMd && /`[^`]*TODO[^`]*`/.test(linea)) continue;
394
+ if (esMd && /\b(capturar|cargar|cubrir|cumplir|verificar|pasar|incluir|tener)\s+TODO\b/i.test(linea)) continue;
395
+ // En Markdown, excluir líneas descriptivas que mencionan TODO como concepto (ej: "detecta TODO sin ticket")
396
+ if (esMd && /TODO\s+sin\s+ticket/i.test(linea)) continue;
397
+ // Si tiene referencia a ticket, es válido
398
+ if (patronConTicket.test(linea)) continue;
399
+ // Si no tiene referencia, es una violación
400
+ if (patronSinTicket.test(linea)) {
401
+ const tag = '[TO' + 'DO]';
402
+ mensajes.push(
403
+ ` ${tag} ${rutaRelativa}:${i + 1} — sin referencia a ticket/issue`
404
+ );
405
+ }
406
+ }
407
+
408
+ return { ok: mensajes.length === 0, mensajes };
409
+ }
410
+
411
+ /**
412
+ * Verifica que las funciones públicas en Python tengan type hints.
413
+ * Una función "pública" es aquella cuyo nombre NO empieza con "_".
414
+ * Se verifica que los parámetros (excepto self/cls) y el retorno tengan anotaciones.
415
+ *
416
+ * Limitaciones intencionales (análisis estático ligero sin AST):
417
+ * - Solo detecta funciones de una sola línea de definición
418
+ * - No analiza funciones con firmas multi-línea (falso negativo aceptado)
419
+ * - Excluye archivos de test y migraciones
420
+ *
421
+ * @param {string} rutaRelativa
422
+ * @param {string} contenido
423
+ * @returns {{ ok: boolean, mensajes: string[] }}
424
+ */
425
+ function verificarTypeHintsPython(rutaRelativa, contenido) {
426
+ const esArchivoExcluido =
427
+ /test.*\.py$/.test(rutaRelativa) ||
428
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
429
+ /migrations?[/\\]/.test(rutaRelativa) ||
430
+ /conftest\.py$/.test(rutaRelativa) ||
431
+ /setup\.py$/.test(rutaRelativa) ||
432
+ /^scripts[/\\]vendor[/\\]/.test(rutaRelativa); // código vendorizado de terceros
433
+
434
+ if (esArchivoExcluido) return { ok: true, mensajes: [] };
435
+
436
+ const lineas = contenido.split('\n');
437
+ const mensajes = [];
438
+
439
+ // Patrón: def nombre_sin_guion_bajo(params): — función pública en una línea
440
+ // Captura: nombre de función y la lista de parámetros hasta el ':' o '->'
441
+ const patronDef = /^\s*def\s+([a-zA-Z][a-zA-Z0-9_]*)\s*\(([^)]*)\)\s*(->.*?)?:/;
442
+
443
+ for (let i = 0; i < lineas.length; i++) {
444
+ const linea = lineas[i];
445
+ const match = patronDef.exec(linea);
446
+ if (!match) continue;
447
+
448
+ const nombreFuncion = match[1];
449
+ const params = match[2];
450
+ const retorno = match[3] || '';
451
+
452
+ // Solo funciones públicas (sin prefijo _)
453
+ if (nombreFuncion.startsWith('_')) continue;
454
+
455
+ // Verificar type hints en parámetros
456
+ // Excluir self, cls, *args, **kwargs de la verificación
457
+ const paramsList = params
458
+ .split(',')
459
+ .map(p => p.trim())
460
+ .filter(p => p && p !== 'self' && p !== 'cls' && !p.startsWith('*'));
461
+
462
+ // Un parámetro tiene type hint si contiene ":"
463
+ const paramsSinHint = paramsList.filter(p => {
464
+ // Excluir parámetros con valor por defecto que ya tienen hint: "x: int = 0"
465
+ const baseParam = p.split('=')[0].trim();
466
+ return baseParam && !baseParam.includes(':');
467
+ });
468
+
469
+ if (paramsSinHint.length > 0) {
470
+ mensajes.push(
471
+ ` [TYPE HINT] ${rutaRelativa}:${i + 1} — def ${nombreFuncion}(): parámetros sin anotación: ${paramsSinHint.join(', ')}`
472
+ );
473
+ continue; // No duplicar alerta si también falta retorno
474
+ }
475
+
476
+ // Verificar type hint de retorno (-> tipo)
477
+ if (retorno.trim() === '') {
478
+ mensajes.push(
479
+ ` [TYPE HINT] ${rutaRelativa}:${i + 1} — def ${nombreFuncion}(): falta anotación de retorno (->)`
480
+ );
481
+ }
482
+ }
483
+
484
+ return { ok: mensajes.length === 0, mensajes };
485
+ }
486
+
487
+ /**
488
+ * Verifica que no haya bloques catch/except vacíos o con solo pass/comentario.
489
+ * Detecta errores silenciosos que ocultan fallos en producción.
490
+ * Excluye archivos de test.
491
+ *
492
+ * Patrones detectados:
493
+ * - JS/TS: catch (e) {} o catch { }
494
+ * - Python: except: pass / except Exception: pass
495
+ * - Go: if err != nil { } (bloque vacío después de error check)
496
+ *
497
+ * @param {string} rutaRelativa
498
+ * @param {string} contenido
499
+ * @param {string} ext
500
+ * @returns {{ ok: boolean, mensajes: string[] }}
501
+ */
502
+ function verificarErroresSilenciosos(rutaRelativa, contenido, ext) {
503
+ const esArchivoExcluido = /\.(test|spec)\.[jt]s$/.test(rutaRelativa) ||
504
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
505
+ /[/\\]__tests__[/\\]/.test(rutaRelativa) ||
506
+ /^scripts[/\\]/.test(rutaRelativa) ||
507
+ /^hooks[/\\]/.test(rutaRelativa) ||
508
+ /^tests[/\\]/.test(rutaRelativa) ||
509
+ /test.*\.py$/.test(rutaRelativa) ||
510
+ /_test\.go$/.test(rutaRelativa);
511
+
512
+ if (esArchivoExcluido) return { ok: true, mensajes: [] };
513
+
514
+ const extensionesAplicables = new Set(['.js', '.ts', '.tsx', '.py', '.go', '.java', '.kt', '.cs', '.rs', '.php', '.swift']);
515
+ if (!extensionesAplicables.has(ext)) return { ok: true, mensajes: [] };
516
+
517
+ const lineas = contenido.split('\n');
518
+ const mensajes = [];
519
+ const esComentario = /^\s*(\/\/|\/\*|\*|#)/;
520
+
521
+ for (let i = 0; i < lineas.length; i++) {
522
+ const linea = lineas[i];
523
+ if (esComentario.test(linea)) continue;
524
+
525
+ // JS/TS/Java/Kotlin/C#: catch vacío — catch(...) { } o catch { }
526
+ if (['.js', '.ts', '.tsx', '.java', '.kt', '.cs'].includes(ext)) {
527
+ if (/catch\s*(\([^)]*\))?\s*\{\s*\}/.test(linea)) {
528
+ mensajes.push(
529
+ ` [SILENT] ${rutaRelativa}:${i + 1} — catch vacío: error ignorado silenciosamente`
530
+ );
531
+ }
532
+ }
533
+
534
+ // Python: except: pass / except Exception: pass
535
+ if (ext === '.py') {
536
+ if (/^\s*except(\s+\w+)?(\s+as\s+\w+)?\s*:\s*$/.test(linea)) {
537
+ const siguienteLinea = (lineas[i + 1] || '').trim();
538
+ if (siguienteLinea === 'pass' || siguienteLinea === '...') {
539
+ mensajes.push(
540
+ ` [SILENT] ${rutaRelativa}:${i + 1} — except con solo pass: error ignorado silenciosamente`
541
+ );
542
+ }
543
+ }
544
+ }
545
+
546
+ // Go: if err != nil { } (bloque vacío)
547
+ if (ext === '.go') {
548
+ if (/if\s+err\s*!=\s*nil\s*\{\s*\}/.test(linea)) {
549
+ mensajes.push(
550
+ ` [SILENT] ${rutaRelativa}:${i + 1} — error check vacío (if err != nil {})`
551
+ );
552
+ }
553
+ }
554
+
555
+ // Rust: if let Err(_) = ... { } o .unwrap_or_default() sin justificación
556
+ // (ligero: solo catch vacío explícito)
557
+ if (ext === '.rs') {
558
+ if (/if\s+let\s+Err\s*\(_\)\s*=.*\{\s*\}/.test(linea)) {
559
+ mensajes.push(
560
+ ` [SILENT] ${rutaRelativa}:${i + 1} — error match vacío: Err ignorado silenciosamente`
561
+ );
562
+ }
563
+ }
564
+
565
+ // PHP: catch vacío
566
+ if (ext === '.php') {
567
+ if (/catch\s*\([^)]*\)\s*\{\s*\}/.test(linea)) {
568
+ mensajes.push(
569
+ ` [SILENT] ${rutaRelativa}:${i + 1} — catch vacío: excepción ignorada silenciosamente`
570
+ );
571
+ }
572
+ }
573
+ }
574
+
575
+ return { ok: mensajes.length === 0, mensajes };
576
+ }
577
+
578
+ // ---------------------------------------------------------------------------
579
+ // Verificador principal por archivo
580
+ // ---------------------------------------------------------------------------
581
+
582
+ /**
583
+ * Ejecuta todas las verificaciones aplicables sobre un archivo staged.
584
+ *
585
+ * @param {string} rutaRelativa - Ruta relativa del archivo en el repositorio.
586
+ * @returns {string[]} Lista de mensajes de violación. Vacía si pasa todo.
587
+ */
588
+ function verificarArchivo(rutaRelativa) {
589
+ const ext = path.extname(rutaRelativa).toLowerCase();
590
+ const violaciones = [];
591
+
592
+ // --- Verificación de tamaño (aplica a todos) ---
593
+ const { ok: tamanoOk, mensaje: mensajeTamano } = verificarTamano(rutaRelativa);
594
+ if (!tamanoOk) {
595
+ violaciones.push(mensajeTamano);
596
+ // Si el archivo es muy grande, no intentar leerlo para análisis de texto
597
+ return violaciones;
598
+ }
599
+
600
+ // Omitir análisis de texto en archivos binarios conocidos
601
+ if (EXTENSIONES_BINARIAS.has(ext)) return violaciones;
602
+
603
+ // Obtener contenido staged para análisis de texto
604
+ const contenido = obtenerContenidoStaged(rutaRelativa);
605
+ if (contenido === null) return violaciones; // Binario detectado dinámicamente
606
+
607
+ // --- Verificación de credenciales (aplica a todos los archivos de texto) ---
608
+ const { mensajes: msgsCredencial } = verificarCredenciales(rutaRelativa, contenido);
609
+ violaciones.push(...msgsCredencial);
610
+
611
+ // --- Verificación de pendientes sin ticket (aplica a todos los archivos de texto) --- // nosec
612
+ const { mensajes: msgsTodo } = verificarTodosSinTicket(rutaRelativa, contenido);
613
+ violaciones.push(...msgsTodo);
614
+
615
+ // --- Verificación de errores silenciosos (aplica a código fuente multi-lenguaje) ---
616
+ const { mensajes: msgsSilent } = verificarErroresSilenciosos(rutaRelativa, contenido, ext);
617
+ violaciones.push(...msgsSilent);
618
+
619
+ // --- Verificaciones por extensión ---
620
+ if (ext === '.ts' || ext === '.js') {
621
+ const { mensajes: msgsConsole } = verificarConsoleLog(rutaRelativa, contenido);
622
+ violaciones.push(...msgsConsole);
623
+ }
624
+
625
+ if (ext === '.py') {
626
+ const { mensajes: msgsPrint } = verificarPrintPython(rutaRelativa, contenido);
627
+ violaciones.push(...msgsPrint);
628
+
629
+ const { mensajes: msgsHints } = verificarTypeHintsPython(rutaRelativa, contenido);
630
+ violaciones.push(...msgsHints);
631
+ }
632
+
633
+ // --- Java: System.out.println ---
634
+ if (ext === '.java') {
635
+ const esArchivoTestJava = /Test\.java$/.test(rutaRelativa) ||
636
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
637
+ /[/\\]spec[/\\]/.test(rutaRelativa);
638
+
639
+ if (!esArchivoTestJava) {
640
+ const patronJavaPrint = /^\s*System\.(out|err)\.(println|print|printf)\s*\(/;
641
+ const esComentarioJava = /^\s*(\/\/|\/\*|\*)/;
642
+ const lineas = contenido.split('\n');
643
+ for (let i = 0; i < lineas.length; i++) {
644
+ if (esComentarioJava.test(lineas[i])) continue;
645
+ if (patronJavaPrint.test(lineas[i])) {
646
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — System.out.println en código de producción`);
647
+ }
648
+ }
649
+ }
650
+ }
651
+
652
+ // --- Go: fmt.Println ---
653
+ if (ext === '.go') {
654
+ const esArchivoTestGo = /_test\.go$/.test(rutaRelativa) ||
655
+ /[/\\]tests?[/\\]/.test(rutaRelativa);
656
+
657
+ if (!esArchivoTestGo) {
658
+ const patronGoPrint = /^\s*fmt\.(Println|Printf|Print)\s*\(/;
659
+ const esComentarioGo = /^\s*\/\//;
660
+ const lineas = contenido.split('\n');
661
+ for (let i = 0; i < lineas.length; i++) {
662
+ if (esComentarioGo.test(lineas[i])) continue;
663
+ if (patronGoPrint.test(lineas[i])) {
664
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — fmt.Println en código de producción (usar slog/log)`);
665
+ }
666
+ }
667
+ }
668
+ }
669
+
670
+ // --- Rust: println! ---
671
+ if (ext === '.rs') {
672
+ const esArchivoTestRust = /[/\\]tests?[/\\]/.test(rutaRelativa) ||
673
+ /test.*\.rs$/.test(rutaRelativa);
674
+
675
+ if (!esArchivoTestRust) {
676
+ const patronRustPrint = /^\s*(println!|print!|eprintln!|eprint!)\s*\(/;
677
+ const esComentarioRust = /^\s*\/\//;
678
+ const lineas = contenido.split('\n');
679
+ for (let i = 0; i < lineas.length; i++) {
680
+ if (esComentarioRust.test(lineas[i])) continue;
681
+ if (patronRustPrint.test(lineas[i])) {
682
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — println! en código de producción (usar tracing)`);
683
+ }
684
+ }
685
+ }
686
+ }
687
+
688
+ // --- C#: Console.WriteLine ---
689
+ if (ext === '.cs') {
690
+ const esArchivoTestCsharp = /[Tt]est.*\.cs$/.test(rutaRelativa) ||
691
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
692
+ /[Ss]pec.*\.cs$/.test(rutaRelativa);
693
+
694
+ if (!esArchivoTestCsharp) {
695
+ const patronCsharpPrint = /^\s*Console\.(WriteLine|Write|Error\.WriteLine)\s*\(/;
696
+ const esComentarioCsharp = /^\s*\/\//;
697
+ const lineas = contenido.split('\n');
698
+ for (let i = 0; i < lineas.length; i++) {
699
+ if (esComentarioCsharp.test(lineas[i])) continue;
700
+ if (patronCsharpPrint.test(lineas[i])) {
701
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — Console.WriteLine en código de producción (usar ILogger)`);
702
+ }
703
+ }
704
+ }
705
+ }
706
+
707
+ // --- Kotlin: println ---
708
+ if (ext === '.kt' || ext === '.kts') {
709
+ const esArchivoTestKotlin = /[Tt]est.*\.kts?$/.test(rutaRelativa) ||
710
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
711
+ /[Ss]pec.*\.kts?$/.test(rutaRelativa);
712
+
713
+ if (!esArchivoTestKotlin) {
714
+ const patronKotlinPrint = /^\s*println\s*\(/;
715
+ const esComentarioKotlin = /^\s*\/\//;
716
+ const lineas = contenido.split('\n');
717
+ for (let i = 0; i < lineas.length; i++) {
718
+ if (esComentarioKotlin.test(lineas[i])) continue;
719
+ if (patronKotlinPrint.test(lineas[i])) {
720
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — println en código de producción (usar Timber/logger)`);
721
+ }
722
+ }
723
+ }
724
+ }
725
+
726
+ // --- PHP: var_dump / dd / dump / print_r / die ---
727
+ if (ext === '.php') {
728
+ const esArchivoTestPhp = /[Tt]est.*\.php$/.test(rutaRelativa) ||
729
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
730
+ /[Ss]pec.*\.php$/.test(rutaRelativa);
731
+
732
+ if (!esArchivoTestPhp) {
733
+ const patronPhpDebug = /^\s*(var_dump|dd|dump|print_r|die)\s*\(/;
734
+ const esComentarioPhp = /^\s*(\/\/|\/\*|#)/;
735
+ const lineas = contenido.split('\n');
736
+ for (let i = 0; i < lineas.length; i++) {
737
+ if (esComentarioPhp.test(lineas[i])) continue;
738
+ if (patronPhpDebug.test(lineas[i])) {
739
+ const nombre = lineas[i].trim().split('(')[0].trim();
740
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — ${nombre} en código de producción`);
741
+ }
742
+ }
743
+ }
744
+ }
745
+
746
+ // --- Swift: print() ---
747
+ if (ext === '.swift') {
748
+ const esArchivoTestSwift = /[Tt]est.*\.swift$/.test(rutaRelativa) ||
749
+ /[/\\]tests?[/\\]/.test(rutaRelativa) ||
750
+ /[Ss]pec.*\.swift$/.test(rutaRelativa);
751
+
752
+ if (!esArchivoTestSwift) {
753
+ const patronSwiftPrint = /^\s*print\s*\(/;
754
+ const esComentarioSwift = /^\s*\/\//;
755
+ const lineas = contenido.split('\n');
756
+ for (let i = 0; i < lineas.length; i++) {
757
+ if (esComentarioSwift.test(lineas[i])) continue;
758
+ if (patronSwiftPrint.test(lineas[i])) {
759
+ violaciones.push(` [DEBUG] ${rutaRelativa}:${i + 1} — print() en código de producción (usar os_log/Logger)`);
760
+ }
761
+ }
762
+ }
763
+ }
764
+
765
+ return violaciones;
766
+ }
767
+
768
+ // ---------------------------------------------------------------------------
769
+ // Risk score semántico (code-review-graph)
770
+ // ---------------------------------------------------------------------------
771
+
772
+ /**
773
+ * Ejecuta code-review-graph detect-changes y retorna mensajes de violación
774
+ * si el risk score supera el umbral configurado (0.7).
775
+ *
776
+ * Solo actúa si `.code-review-graph/graph.db` existe — es un check opcional.
777
+ * Nunca bloquea el commit por fallo interno del análisis.
778
+ *
779
+ * @returns {string[]} Mensajes de violación de riesgo semántico.
780
+ */
781
+ function verificarRiskScore() {
782
+ try {
783
+ const dbPath = path.join(process.cwd(), '.code-review-graph', 'graph.db');
784
+ if (!fs.existsSync(dbPath)) return []; // Grafo no inicializado — saltar silenciosamente
785
+
786
+ const UMBRAL_RIESGO = 0.7;
787
+
788
+ const salidaRaw = execSync(
789
+ 'python -c "import sys; sys.argv=[\'crg\',\'detect-changes\']; from code_review_graph.cli import main; main()"',
790
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 15_000 }
791
+ );
792
+
793
+ const resultado = JSON.parse(salidaRaw.trim());
794
+ const { risk_score = 0, changed_functions = [], test_gaps = [], affected_flows = [] } = resultado;
795
+
796
+ if (risk_score < UMBRAL_RIESGO) return []; // Riesgo bajo — no reportar
797
+
798
+ const mensajes = [
799
+ ` [RIESGO] Risk score semántico: ${risk_score.toFixed(2)} — supera umbral ${UMBRAL_RIESGO}`,
800
+ ];
801
+
802
+ if (test_gaps.length > 0) {
803
+ const gaps = test_gaps.slice(0, 5).map(g => ` · ${g.name || g}`).join('\n');
804
+ mensajes.push(` [RIESGO] Funciones modificadas sin cobertura de tests (${test_gaps.length}):\n${gaps}`);
805
+ }
806
+
807
+ if (affected_flows.length > 0) {
808
+ const flows = affected_flows.slice(0, 3).map(f => ` · ${f.name || f}`).join('\n');
809
+ mensajes.push(` [RIESGO] Flujos de ejecución afectados (${affected_flows.length}):\n${flows}`);
810
+ }
811
+
812
+ if (changed_functions.length > 0) {
813
+ const fns = changed_functions.slice(0, 5)
814
+ .map(f => ` · ${f.name || f} (riesgo: ${(f.risk_score || 0).toFixed(2)})`)
815
+ .join('\n');
816
+ mensajes.push(` [RIESGO] Funciones de alto impacto (${changed_functions.length}):\n${fns}`);
817
+ }
818
+
819
+ mensajes.push(` [RIESGO] Ejecuta /swl:revisar-impacto cambios para análisis detallado.`);
820
+ return mensajes;
821
+
822
+ } catch (_) {
823
+ return []; /* Fallo del análisis semántico nunca bloquea el commit */
824
+ }
825
+ }
826
+
827
+ // ---------------------------------------------------------------------------
828
+ // Entrypoint principal
829
+ // ---------------------------------------------------------------------------
830
+
831
+ let inputRaw = '';
832
+
833
+ process.stdin.on('data', chunk => {
834
+ inputRaw += chunk;
835
+ });
836
+
837
+ process.stdin.on('end', () => {
838
+ try {
839
+ const data = JSON.parse(inputRaw);
840
+
841
+ const toolName = String(data.tool_name || data.tool?.name || '');
842
+ const toolInput = data.tool_input || data.tool?.input || {};
843
+ const comando = String(toolInput.command || '');
844
+ const sessionId = String(data.session_id || 'default');
845
+
846
+ // Este hook solo aplica cuando el comando Bash es un git commit
847
+ if (toolName !== 'Bash') {
848
+ return;
849
+ }
850
+
851
+ // Verificar que el comando incluye "git commit" (excluir --amend sin cambios,
852
+ // git commit --dry-run, etc. siguen pasando por las verificaciones)
853
+ if (!/\bgit\s+commit\b/.test(comando)) {
854
+ return;
855
+ }
856
+
857
+ // Obtener archivos staged
858
+ const archivos = obtenerArchivosStagedGit();
859
+ if (archivos.length === 0) {
860
+ // Sin archivos staged, nada que verificar
861
+ return;
862
+ }
863
+
864
+ // Verificar cada archivo
865
+ const todasLasViolaciones = [];
866
+
867
+ for (const archivo of archivos) {
868
+ const violaciones = verificarArchivo(archivo);
869
+ todasLasViolaciones.push(...violaciones);
870
+ }
871
+
872
+ // --- Verificación de risk score semántico (code-review-graph) ---
873
+ // Ejecuta detect-changes solo si el grafo existe. No bloquea si falla.
874
+ const riskViolaciones = verificarRiskScore();
875
+ todasLasViolaciones.push(...riskViolaciones);
876
+
877
+ if (todasLasViolaciones.length > 0) {
878
+ const totalArchivos = archivos.length;
879
+ const totalViolaciones = todasLasViolaciones.length;
880
+
881
+ const razon = [
882
+ `Commit bloqueado: se encontraron ${totalViolaciones} violación(es) de calidad en ${totalArchivos} archivo(s) staged.`,
883
+ ``,
884
+ `Problemas encontrados:`,
885
+ ...todasLasViolaciones,
886
+ ``,
887
+ `Acciones requeridas:`,
888
+ ` [CREDENCIAL] → Mover el valor a una variable de entorno (.env no commiteado).`,
889
+ ` [DEBUG] → Eliminar o comentar las sentencias de debug:`,
890
+ ` JS/TS: console.log/debug`,
891
+ ` Python: print()`,
892
+ ` Java: System.out.println → usar SLF4J/Logback`,
893
+ ` Go: fmt.Println → usar slog o log/slog`,
894
+ ` Rust: println! → usar tracing o log`,
895
+ ` C#: Console.WriteLine → usar ILogger<T>`,
896
+ ` Kotlin: println → usar Timber o android.util.Log`,
897
+ ` PHP: var_dump/dd/dump → usar Monolog`,
898
+ ` Swift: print() → usar os_log o Logger`,
899
+ ` [${`TO` + `DO`}] → Agregar referencia con ticket: (#123) o JIRA-456.`,
900
+ ` [TAMAÑO] → Usar git-lfs o excluir el archivo en .gitignore.`,
901
+ ` [TYPE HINT] → Agregar anotaciones de tipo a la función Python.`,
902
+ ` [SILENT] → Agregar manejo de error explícito (log + acción), no catch/except vacío.`,
903
+ ` [RIESGO] → Revisar cobertura de tests y ejecutar /swl:revisar-impacto cambios.`,
904
+ ``,
905
+ `Para omitir una verificación específica en una línea, usa:`,
906
+ ` Python: # noqa: SWL001`,
907
+ ` JS/TS: // nosec`,
908
+ ` Credencial: # pragma: allowlist secret`,
909
+ ].join('\n');
910
+
911
+ // stdout: razón completa para el framework de hooks (hookSpecificOutput)
912
+ process.stdout.write(razon);
913
+ // stderr: resumen conciso visible en la interfaz de Claude Code
914
+ const resumen = [
915
+ `Commit bloqueado: ${totalViolaciones} violación(es) de calidad.`,
916
+ ...todasLasViolaciones,
917
+ ].join('\n');
918
+ process.stderr.write(resumen);
919
+ try { require('./lib/guardrail-metrics').recordActivation('calidad-pre-commit.js', sessionId, true); } catch (_) {}
920
+ process.exit(2);
921
+ }
922
+
923
+ // Todas las verificaciones pasaron — permitir el commit
924
+ try { require('./lib/guardrail-metrics').recordActivation('calidad-pre-commit.js', sessionId, false); } catch (_) {}
925
+
926
+ } catch (err) {
927
+ // El hook nunca bloquea por errores internos propios
928
+ }
929
+ });