@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,1031 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * swl-ses install
5
+ * Instala componentes SWL en el runtime destino.
6
+ *
7
+ * Flujo:
8
+ * 1. Detectar/validar runtime target
9
+ * 2. Resolver perfil → módulos → archivos
10
+ * 3. Detectar _userland/ y hacer merge
11
+ * 4. Mostrar plan de instalación
12
+ * 5. Aplicar (copiar archivos, adaptar formato si necesario)
13
+ * 6. Guardar estado de instalación
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+
19
+ const { obtenerRuntime, calcularRutas, resumenDeteccion, detectarInstalacionesDuales } = require('./lib/detectar-runtime');
20
+ const { preguntarSiNo, ES_TTY } = require('./lib/ui');
21
+ const { resolverPerfil, generarPlan } = require('./lib/manifiestos');
22
+ const { crearEstado, registrarArchivo, registrarComponente, guardarEstado, cargarEstado } = require('./lib/estado');
23
+ const { validarRuta, esArchivoSensible, filtrarSecretos } = require('./lib/seguridad');
24
+ const { registrarHooks, registrarOptimizaciones, rutaSettings, cargarHooksConfig } = require('./lib/hooks-settings');
25
+ const { obtenerTransformador } = require('./lib/transformadores');
26
+ const {
27
+ esProtegido,
28
+ crearBackup,
29
+ registrarBackup,
30
+ limpiarBackups,
31
+ mergeInstintos,
32
+ mergeSkills,
33
+ } = require('./lib/preservar-usuario');
34
+ const {
35
+ decideUpdateStrategy,
36
+ mergeEvolved,
37
+ scanEvolved,
38
+ } = require('../hooks/lib/evolution-tracker');
39
+ const { detectarStack, filtrarReglasPorStack } = require('./lib/detectar-stack');
40
+ const { actualizarGitignore, entradasParaRuntime, limpiarTracked, leerManifest, escribirManifest } = require('./lib/gitignore-manifest');
41
+
42
+ const RAIZ_PKG = path.resolve(__dirname, '..');
43
+ const VERSION = require('../package.json').version;
44
+
45
+ async function install(opciones) {
46
+ // Leer manifest .swl-ses si existe — sus valores son defaults que el CLI puede sobreescribir
47
+ const manifest = leerManifest(process.cwd());
48
+ if (manifest && !opciones.target && !opciones.profile) {
49
+ console.log(`[manifest] Usando configuración de .swl-ses: target=${manifest.target}, profile=${manifest.profile}`);
50
+ }
51
+
52
+ const target = opciones.target || (manifest && manifest.target) || 'claude';
53
+ const perfil = opciones.profile || (manifest && manifest.profile) || 'core';
54
+ const esGlobal = opciones.global || false;
55
+ const dryRun = opciones.dry_run || false;
56
+ const force = opciones.force || false;
57
+ const allLangs = opciones.all_langs || false;
58
+ const syncMode = opciones.sync_mode || (manifest && manifest.syncMode) || 'copy'; // copy | symlink | flat
59
+ const flatNaming = opciones.flat_naming || syncMode === 'flat'; // Convierte path/to/skill → path__to__skill
60
+
61
+ console.log(`swl-ses install v${VERSION}`);
62
+ console.log(`${'='.repeat(40)}`);
63
+
64
+ // 1. Validar runtime
65
+ let runtime;
66
+ try {
67
+ runtime = obtenerRuntime(target);
68
+ } catch (err) {
69
+ console.error(err.message);
70
+ console.log('\n' + resumenDeteccion());
71
+ process.exit(1);
72
+ }
73
+
74
+ if (runtime.soporte === 'parcial') {
75
+ console.log(`Nota: Runtime "${target}" (${runtime.nombre}) tiene soporte parcial — solo agentes y reglas.\n`);
76
+ }
77
+
78
+ // 1b. Detectar conflicto dual-scope: instalar en un scope cuando el opuesto
79
+ // ya tiene SWL instalado causa duplicación visible de comandos en la UI.
80
+ // Con --force se omite el prompt (asume que el caller sabe lo que hace).
81
+ // En modo no-TTY solo se muestra advertencia informativa y se continúa.
82
+ if (!force && !dryRun) {
83
+ const dual = detectarInstalacionesDuales(target);
84
+ const tieneOpuesto = esGlobal ? dual.local : dual.global;
85
+
86
+ if (tieneOpuesto) {
87
+ const scopeActual = esGlobal ? 'global' : 'proyecto';
88
+ const scopeOpuesto = esGlobal ? 'proyecto' : 'global';
89
+ const dirOpuesto = esGlobal ? dual.localDir : dual.globalDir;
90
+
91
+ console.log('');
92
+ console.log(` Ya existe una instalación SWL de ${runtime.nombre} en scope ${scopeOpuesto}:`);
93
+ console.log(` ${dirOpuesto}`);
94
+ console.log('');
95
+ console.log(` Instalar también en scope ${scopeActual} duplicará comandos/agentes en la UI`);
96
+ console.log(` porque ${runtime.nombre} lee componentes de ambos scopes y los muestra como`);
97
+ console.log(` entradas separadas.`);
98
+ console.log('');
99
+ console.log(` Recomendación: usa un solo scope.`);
100
+ console.log('');
101
+
102
+ if (ES_TTY) {
103
+ const proceder = await preguntarSiNo(
104
+ `¿Continuar e instalar en ambos scopes de todos modos?`,
105
+ false
106
+ );
107
+ console.log('');
108
+ if (!proceder) {
109
+ console.log(' Instalación cancelada.');
110
+ console.log(` Si solo quieres usar el scope ${scopeOpuesto}, ya está instalado.`);
111
+ console.log(` Si quieres cambiar de scope: ejecuta 'swl-ses uninstall${esGlobal ? '' : ' --global'}' primero.`);
112
+ return;
113
+ }
114
+ } else {
115
+ // No-TTY (CI, pipes): no podemos preguntar, pero avisamos.
116
+ console.log(' [no-TTY] Procediendo con la instalación — usa --force para suprimir este aviso.');
117
+ console.log('');
118
+ }
119
+ }
120
+ }
121
+
122
+ // 2. Resolver perfil
123
+ let resolucion;
124
+ try {
125
+ resolucion = resolverPerfil(perfil, {
126
+ target,
127
+ with: opciones.with,
128
+ without: opciones.without,
129
+ });
130
+ } catch (err) {
131
+ console.error(err.message);
132
+ process.exit(1);
133
+ }
134
+
135
+ // 2b. Filtrar reglas de lenguaje por stack detectado
136
+ // El stack se detecta siempre que: hay reglas de lenguaje en el perfil, O
137
+ // se ejecuta con --force (actualización) para poder limpiar las ya instaladas.
138
+ const tieneReglasLenguaje = resolucion.archivos.some(
139
+ a => a.rutaRelativa && a.rutaRelativa.startsWith('reglas/lenguajes/')
140
+ );
141
+ const necesitaStack = (tieneReglasLenguaje || force) && !allLangs;
142
+
143
+ let stackDetectado = null;
144
+
145
+ if (necesitaStack) {
146
+ stackDetectado = detectarStack(process.cwd());
147
+ }
148
+
149
+ if (tieneReglasLenguaje) {
150
+ if (allLangs) {
151
+ console.log('\n[stack] --all-langs activado: se instalan reglas de todos los lenguajes.');
152
+ } else {
153
+ if (stackDetectado.size > 0) {
154
+ console.log(`\n[stack] Lenguajes detectados en el proyecto: ${[...stackDetectado].join(', ')}`);
155
+ } else {
156
+ console.log('\n[stack] No se detectaron lenguajes específicos en el proyecto.');
157
+ }
158
+
159
+ const resultado = filtrarReglasPorStack(resolucion.archivos, stackDetectado);
160
+ if (resultado.excluidos > 0) {
161
+ resolucion.archivos = resultado.archivos;
162
+ console.log(
163
+ `[stack] ${resultado.excluidos} reglas excluidas (lenguajes no presentes: ${resultado.lenguajesExcluidos.join(', ')})`
164
+ );
165
+ console.log('[stack] Usa --all-langs para forzar instalación de todos los lenguajes.');
166
+ } else {
167
+ console.log('[stack] Todas las reglas de lenguaje coinciden con el proyecto detectado.');
168
+ }
169
+ }
170
+ }
171
+
172
+ // 3. Calcular rutas destino
173
+ const rutas = calcularRutas(target, { global: esGlobal });
174
+
175
+ // 3b. En actualización (--force) limpiar reglas de lenguajes que ya no son del stack.
176
+ // Corre incluso si el perfil actual no incluye reglas-lenguajes, para eliminar
177
+ // subdirectorios de instalaciones anteriores con perfiles más amplios (e.g. completo).
178
+ if (force && stackDetectado !== null && rutas.reglas) {
179
+ const limpiadosStack = limpiarReglasSinStack(rutas.reglas, stackDetectado);
180
+ if (limpiadosStack.eliminados > 0) {
181
+ console.log(`\n[stack] Limpieza: ${limpiadosStack.eliminados} regla(s) de lenguaje eliminadas (${limpiadosStack.lenguajes.join(', ')})`);
182
+ }
183
+ }
184
+
185
+ // 4. Detectar _userland/
186
+ const userlandAgentes = path.join(process.cwd(), '_userland', 'agentes');
187
+ const userlandHabilidades = path.join(process.cwd(), '_userland', 'habilidades');
188
+ let archivosUserland = [];
189
+
190
+ if (fs.existsSync(userlandAgentes)) {
191
+ const agentesUser = fs.readdirSync(userlandAgentes)
192
+ .filter(f => f.endsWith('.md') && f !== '.gitkeep');
193
+ for (const a of agentesUser) {
194
+ archivosUserland.push({
195
+ origen: path.join(userlandAgentes, a),
196
+ rutaRelativa: `_userland/agentes/${a}`,
197
+ tipo: 'agentes',
198
+ modulo: 'userland',
199
+ esUserland: true,
200
+ });
201
+ }
202
+ }
203
+
204
+ if (fs.existsSync(userlandHabilidades)) {
205
+ const habsUser = fs.readdirSync(userlandHabilidades)
206
+ .filter(f => !f.startsWith('.'));
207
+ for (const h of habsUser) {
208
+ const skillPath = path.join(userlandHabilidades, h, 'SKILL.md');
209
+ if (fs.existsSync(skillPath)) {
210
+ archivosUserland.push({
211
+ origen: path.join(userlandHabilidades, h),
212
+ rutaRelativa: `_userland/habilidades/${h}`,
213
+ tipo: 'habilidades',
214
+ modulo: 'userland',
215
+ esUserland: true,
216
+ });
217
+ }
218
+ }
219
+ }
220
+
221
+ // 5. Mostrar plan
222
+ console.log(generarPlan(resolucion, rutas));
223
+
224
+ if (archivosUserland.length > 0) {
225
+ console.log(`\n[userland] (${archivosUserland.length} componentes del usuario)`);
226
+ for (const u of archivosUserland) {
227
+ console.log(` + ${u.rutaRelativa} (prioridad: usuario > core)`);
228
+ }
229
+ }
230
+
231
+ if (dryRun) {
232
+ console.log('\n(modo --dry-run: sin cambios aplicados)');
233
+ return;
234
+ }
235
+
236
+ // 6. Detectar versión anterior para backup (Nivel 2)
237
+ let versionAnterior = null;
238
+ const estadoAnterior = cargarEstado(rutas.base);
239
+ if (estadoAnterior) {
240
+ versionAnterior = estadoAnterior.versionSistema;
241
+ if (versionAnterior && versionAnterior !== VERSION) {
242
+ console.log(`\n[preservar] Actualizando v${versionAnterior} → v${VERSION}`);
243
+ console.log(`[preservar] Datos de usuario serán preservados automáticamente.`);
244
+ }
245
+ }
246
+
247
+ // 6b. Migración LEARNINGS.md → APRENDIZAJES.md (v5.1.3+)
248
+ const learningsPath = path.join(process.cwd(), '.planning', 'LEARNINGS.md');
249
+ const aprendizajesPath = path.join(process.cwd(), '.planning', 'APRENDIZAJES.md');
250
+ if (fs.existsSync(learningsPath)) {
251
+ try {
252
+ const learningsContent = fs.readFileSync(learningsPath, 'utf8').trim();
253
+ if (learningsContent.length > 0) {
254
+ // Fusionar contenido en APRENDIZAJES.md
255
+ let aprendizajesContent = '';
256
+ if (fs.existsSync(aprendizajesPath)) {
257
+ aprendizajesContent = fs.readFileSync(aprendizajesPath, 'utf8');
258
+ }
259
+ // Solo fusionar si el contenido no está ya duplicado
260
+ if (!aprendizajesContent.includes(learningsContent.substring(0, 100))) {
261
+ const header = aprendizajesContent ? '' : '# Registro de aprendizajes\n\n---\n';
262
+ fs.writeFileSync(aprendizajesPath, aprendizajesContent + '\n\n' + header + learningsContent, 'utf8');
263
+ console.log(' ⊕ Migración: LEARNINGS.md fusionado en APRENDIZAJES.md');
264
+ }
265
+ }
266
+ // Eliminar el archivo obsoleto
267
+ fs.unlinkSync(learningsPath);
268
+ console.log(' ✓ Migración: LEARNINGS.md eliminado (unificado en APRENDIZAJES.md)');
269
+ } catch (err) {
270
+ console.log(` ! Migración LEARNINGS.md: ${err.message}`);
271
+ }
272
+ }
273
+
274
+ // 6c. Migración de archivos .planning/ renombrados de inglés a español (v5.6.0+)
275
+ // Los proyectos que actualizan desde versiones anteriores pueden tener
276
+ // archivos con nombres en inglés que los hooks ya no encuentran.
277
+ const MIGRACIONES_PLANNING = [
278
+ { viejo: 'STATE.md', nuevo: 'ESTADO.md' },
279
+ { viejo: 'COMPACT.md', nuevo: 'COMPACTACION.md' },
280
+ { viejo: 'ROADMAP.md', nuevo: 'HOJA-RUTA.md' },
281
+ { viejo: 'PROJECT.md', nuevo: 'PROYECTO.md' },
282
+ { viejo: 'REQUIREMENTS.md', nuevo: 'REQUISITOS.md' },
283
+ { viejo: 'GRAPH_REPORT.md', nuevo: 'REPORTE-GRAFO.md' },
284
+ { viejo: 'METRICS.md', nuevo: 'METRICAS.md' },
285
+ ];
286
+
287
+ let migracionesAplicadas = 0;
288
+ for (const m of MIGRACIONES_PLANNING) {
289
+ const rutaVieja = path.join(process.cwd(), '.planning', m.viejo);
290
+ const rutaNueva = path.join(process.cwd(), '.planning', m.nuevo);
291
+
292
+ if (!fs.existsSync(rutaVieja)) continue;
293
+
294
+ try {
295
+ const contenidoViejo = fs.readFileSync(rutaVieja, 'utf8').trim();
296
+ if (contenidoViejo.length === 0) {
297
+ // Archivo vacío: solo eliminar
298
+ fs.unlinkSync(rutaVieja);
299
+ console.log(` ✓ Migración: ${m.viejo} eliminado (vacío)`);
300
+ migracionesAplicadas++;
301
+ continue;
302
+ }
303
+
304
+ if (!fs.existsSync(rutaNueva)) {
305
+ // Caso 1: solo existe el viejo → renombrar
306
+ fs.renameSync(rutaVieja, rutaNueva);
307
+ console.log(` ✓ Migración: ${m.viejo} → ${m.nuevo} (renombrado)`);
308
+ } else {
309
+ // Caso 2: ambos existen → fusionar contenido del viejo en el nuevo
310
+ const contenidoNuevo = fs.readFileSync(rutaNueva, 'utf8');
311
+ // Solo fusionar si el contenido no está ya duplicado
312
+ const muestra = contenidoViejo.substring(0, 100);
313
+ if (!contenidoNuevo.includes(muestra)) {
314
+ const separador = '\n\n---\n\n<!-- Contenido migrado desde ' + m.viejo + ' -->\n\n';
315
+ fs.writeFileSync(rutaNueva, contenidoNuevo + separador + contenidoViejo, 'utf8');
316
+ console.log(` ⊕ Migración: ${m.viejo} fusionado en ${m.nuevo}`);
317
+ }
318
+ // Eliminar el archivo obsoleto
319
+ fs.unlinkSync(rutaVieja);
320
+ console.log(` ✓ Migración: ${m.viejo} eliminado (unificado en ${m.nuevo})`);
321
+ }
322
+ migracionesAplicadas++;
323
+ } catch (err) {
324
+ console.log(` ! Migración ${m.viejo}: ${err.message}`);
325
+ }
326
+ }
327
+
328
+ if (migracionesAplicadas > 0) {
329
+ console.log(` [migración] ${migracionesAplicadas} archivo(s) de .planning/ migrado(s) de inglés a español`);
330
+ }
331
+
332
+ // 6d. Filtrar skills por targets declarados en SKILL.md frontmatter (patrón skillshare)
333
+ // Si un skill declara targets: [claude, copilot], solo se instala en esos runtimes.
334
+ // Si no declara targets, se instala en todos (comportamiento por defecto).
335
+ let skillsFiltradosPorTarget = 0;
336
+ resolucion.archivos = resolucion.archivos.filter(archivo => {
337
+ if (archivo.tipo !== 'habilidades') return true;
338
+
339
+ const skillMdPath = path.join(archivo.origen, 'SKILL.md');
340
+ if (!fs.existsSync(skillMdPath)) return true;
341
+
342
+ try {
343
+ const contenido = fs.readFileSync(skillMdPath, 'utf8');
344
+ // Extraer frontmatter targets (formato: targets: [claude, copilot])
345
+ const targetsMatch = contenido.match(/^targets:\s*\[([^\]]+)\]/m);
346
+ if (!targetsMatch) return true; // Sin targets declarados → incluir en todos
347
+
348
+ const declaredTargets = targetsMatch[1].split(',').map(t => t.trim().replace(/['"]/g, ''));
349
+ if (declaredTargets.length === 0) return true;
350
+
351
+ // Normalizar target actual (claude-code → claude, etc.)
352
+ const targetNormalizado = target.replace(/-code$/, '');
353
+ if (declaredTargets.includes(targetNormalizado) || declaredTargets.includes(target)) {
354
+ return true;
355
+ }
356
+
357
+ skillsFiltradosPorTarget++;
358
+ return false;
359
+ } catch {
360
+ return true; // Error leyendo → incluir por defecto
361
+ }
362
+ });
363
+
364
+ if (skillsFiltradosPorTarget > 0) {
365
+ console.log(`\n[targets] ${skillsFiltradosPorTarget} skill(s) excluidos (no declaran target "${target}")`);
366
+ }
367
+
368
+ // 7. Aplicar instalación
369
+ console.log('\nAplicando instalación...\n');
370
+
371
+ const estado = crearEstado({
372
+ versionSistema: VERSION,
373
+ target,
374
+ perfil,
375
+ rutaBase: rutas.base,
376
+ global: esGlobal,
377
+ });
378
+
379
+ let instalados = 0;
380
+ let errores = 0;
381
+ let colisiones = 0;
382
+ let protegidos = 0;
383
+ let respaldados = 0;
384
+ let evolucionados = 0;
385
+
386
+ // Escanear componentes evolucionados antes de instalar
387
+ if (force && fs.existsSync(rutas.base)) {
388
+ const evolved = [
389
+ ...scanEvolved(rutas.agentes || ''),
390
+ ...scanEvolved(rutas.habilidades || ''),
391
+ ...scanEvolved(rutas.comandos || ''),
392
+ ...scanEvolved(rutas.reglas || ''),
393
+ ];
394
+ if (evolved.length > 0) {
395
+ console.log(`[evolución] ${evolved.length} componente(s) evolucionado(s) detectado(s):`);
396
+ for (const e of evolved) {
397
+ console.log(` ★ ${path.basename(e.path)} (por ${e.evolvedBy || 'auto-evolución'}, desde v${e.evolvedFrom || '?'})`);
398
+ }
399
+ console.log('');
400
+ }
401
+ }
402
+
403
+ // Nivel 3: Merge de instintos antes de instalar (si existe proyecto.yaml en destino)
404
+ const instintosOrigen = path.join(RAIZ_PKG, 'instintos', 'proyecto.yaml');
405
+ const instintosDestino = path.join(process.cwd(), 'instintos', 'proyecto.yaml');
406
+ if (fs.existsSync(instintosDestino) && fs.existsSync(instintosOrigen)) {
407
+ const mergeResult = mergeInstintos(instintosOrigen, instintosDestino);
408
+ if (mergeResult.merged) {
409
+ console.log(` ⊕ Instintos: ${mergeResult.preservados} preservados, ${mergeResult.nuevos} nuevos agregados`);
410
+ }
411
+ }
412
+
413
+ // Instalar archivos core
414
+ for (const archivo of resolucion.archivos) {
415
+ try {
416
+ const resultado = instalarArchivo(archivo, rutas, runtime, {
417
+ force,
418
+ versionAnterior,
419
+ versionActual: VERSION,
420
+ estado,
421
+ syncMode,
422
+ flatNaming,
423
+ });
424
+ if (resultado.instalado) {
425
+ registrarArchivo(estado, {
426
+ origen: archivo.rutaRelativa,
427
+ destino: resultado.destino,
428
+ tipo: archivo.tipo,
429
+ });
430
+ instalados++;
431
+ } else if (resultado.colision) {
432
+ colisiones++;
433
+ } else if (resultado.protegido) {
434
+ protegidos++;
435
+ } else if (resultado.evolucionado) {
436
+ // Registrar en el estado aunque no se sobrescribió — el archivo
437
+ // existe en disco (versión evolucionada del usuario) y el doctor
438
+ // necesita contarlo para la verificación de conteo de componentes.
439
+ registrarArchivo(estado, {
440
+ origen: archivo.rutaRelativa,
441
+ destino: resultado.destino,
442
+ tipo: archivo.tipo,
443
+ });
444
+ evolucionados++;
445
+ }
446
+ } catch (err) {
447
+ console.error(` ! Error: ${archivo.rutaRelativa}: ${err.message}`);
448
+ errores++;
449
+ }
450
+ }
451
+
452
+ // Instalar userland (prioridad sobre core)
453
+ for (const archivo of archivosUserland) {
454
+ try {
455
+ const resultado = instalarArchivo(archivo, rutas, runtime, { force: true });
456
+ if (resultado.instalado) {
457
+ registrarArchivo(estado, {
458
+ origen: archivo.rutaRelativa,
459
+ destino: resultado.destino,
460
+ tipo: archivo.tipo,
461
+ });
462
+ instalados++;
463
+ console.log(` * Userland: ${path.basename(archivo.origen)} (prioridad usuario)`);
464
+ }
465
+ } catch (err) {
466
+ console.error(` ! Error userland: ${archivo.rutaRelativa}: ${err.message}`);
467
+ errores++;
468
+ }
469
+ }
470
+
471
+ // Registrar componentes
472
+ for (const modulo of resolucion.modulos) {
473
+ registrarComponente(estado, modulo);
474
+ }
475
+
476
+ // 7. Registrar hooks en settings.json del runtime
477
+ // Los hooks solo se registran a nivel PROYECTO (no global) para evitar
478
+ // ejecucion duplicada cuando Claude Code combina hooks de ambos scopes.
479
+ let hooksRegistrados = 0;
480
+ let hooksPreservados = 0;
481
+
482
+ if (runtime.soportaHooks) {
483
+ // hooks-config.json es la fuente de verdad para hooks registrables.
484
+ // No filtrar por tipo de módulo porque hooks como grafo-contexto.js
485
+ // pueden pertenecer a módulos con tipo distinto a "hooks".
486
+ const hooksConfig = cargarHooksConfig();
487
+ const hookFilesInstalados = resolucion.archivos
488
+ .filter(a => (a.rutaRelativa || a.origen).endsWith('.js') && hooksConfig[path.basename(a.origen)])
489
+ .map(a => path.basename(a.origen));
490
+
491
+ if (hookFilesInstalados.length > 0) {
492
+ if (esGlobal) {
493
+ console.log(' ~ Hooks: omitiendo registro en settings global (solo se registran a nivel proyecto)');
494
+ console.log(' Los hooks se activan al instalar a nivel proyecto con: npx swl-ses@latest install --target claude');
495
+ } else {
496
+ const settingsPath = rutaSettings(runtime, rutas.base);
497
+ try {
498
+ const resultado = registrarHooks({
499
+ settingsPath,
500
+ hooksDir: rutas.hooks,
501
+ esGlobal: false,
502
+ hookFiles: hookFilesInstalados,
503
+ });
504
+ hooksRegistrados = resultado.registrados;
505
+ hooksPreservados = resultado.preservados;
506
+ console.log(` + Hooks registrados en settings.json (proyecto): ${hooksRegistrados}`);
507
+ if (hooksPreservados > 0) {
508
+ console.log(` (${hooksPreservados} hooks externos preservados)`);
509
+ }
510
+
511
+ // Registrar optimizaciones de rendimiento en settings.json
512
+ const optResult = registrarOptimizaciones(settingsPath);
513
+ if (optResult.aplicadas > 0) {
514
+ console.log(` + Optimizaciones de rendimiento aplicadas: ${optResult.aplicadas}`);
515
+ }
516
+ } catch (err) {
517
+ console.error(` ! Error registrando hooks en settings.json: ${err.message}`);
518
+ }
519
+ }
520
+ }
521
+ }
522
+
523
+ // 8. Generar archivo de instrucciones principal (si el target lo requiere)
524
+ const transformador = obtenerTransformador(target, runtime);
525
+ if (runtime.archivoPrincipal) {
526
+ try {
527
+ // Recopilar contexto para el archivo de instrucciones
528
+ const agentesInstalados = resolucion.archivos
529
+ .filter(a => a.tipo === 'agentes')
530
+ .map(a => {
531
+ try {
532
+ return { nombre: path.basename(a.origen, '.md'), contenido: fs.readFileSync(a.origen, 'utf-8') };
533
+ } catch { return null; }
534
+ })
535
+ .filter(Boolean);
536
+
537
+ const reglasInstaladas = resolucion.archivos
538
+ .filter(a => a.tipo === 'reglas')
539
+ .map(a => {
540
+ try {
541
+ return { nombre: path.basename(a.origen, '.md'), contenido: fs.readFileSync(a.origen, 'utf-8') };
542
+ } catch { return null; }
543
+ })
544
+ .filter(Boolean);
545
+
546
+ const skillsInstalados = resolucion.archivos
547
+ .filter(a => a.tipo === 'habilidades')
548
+ .map(a => {
549
+ const nombre = path.basename(a.origen);
550
+ const skillMd = path.join(a.origen, 'SKILL.md');
551
+ let descripcion = '';
552
+ try {
553
+ const contenido = fs.readFileSync(skillMd, 'utf-8');
554
+ const match = contenido.match(/description:\s*>?\s*\n?\s*(.+)/);
555
+ if (match) descripcion = match[1].trim();
556
+ } catch { /* sin descripcion */ }
557
+ return { nombre, descripcion };
558
+ });
559
+
560
+ const conteos = {
561
+ agentes: agentesInstalados.length,
562
+ skills: skillsInstalados.length,
563
+ reglas: reglasInstaladas.length,
564
+ comandos: resolucion.archivos.filter(a => a.tipo === 'comandos').length,
565
+ };
566
+
567
+ const instrucciones = transformador.generarArchivoInstrucciones({
568
+ version: VERSION,
569
+ perfil,
570
+ agentes: agentesInstalados,
571
+ reglas: reglasInstaladas,
572
+ skills: skillsInstalados,
573
+ conteos,
574
+ });
575
+
576
+ if (instrucciones) {
577
+ const dirBase = instrucciones.dirBase
578
+ ? path.resolve(instrucciones.dirBase)
579
+ : rutas.base;
580
+ const rutaInstrucciones = path.join(dirBase, instrucciones.rutaRelativa);
581
+ const dirInstrucciones = path.dirname(rutaInstrucciones);
582
+
583
+ // Opt-out explícito: --no-claudemd para Claude Code
584
+ // Respeta al usuario que prefiere mantener su CLAUDE.md 100% manual.
585
+ const esClaudeMd = instrucciones.rutaRelativa === 'CLAUDE.md';
586
+ if (esClaudeMd && opciones.no_claudemd) {
587
+ console.log(' = CLAUDE.md no modificado (--no-claudemd)');
588
+ } else if (instrucciones.merge && instrucciones.merge.tipo === 'marcadores') {
589
+ // Merge idempotente con marcadores — preserva contenido del usuario.
590
+ if (!fs.existsSync(dirInstrucciones)) {
591
+ fs.mkdirSync(dirInstrucciones, { recursive: true });
592
+ }
593
+ const { mergeConMarcadores } = require('./lib/append-con-marcadores');
594
+ const resMerge = mergeConMarcadores(rutaInstrucciones, instrucciones.contenido, {
595
+ beginTag: instrucciones.merge.beginTag,
596
+ endTag: instrucciones.merge.endTag,
597
+ beginPrefix: instrucciones.merge.beginPrefix,
598
+ });
599
+ const etiqueta = {
600
+ 'creado': '+ CLAUDE.md creado con bloque SWL',
601
+ 'append': '+ Bloque SWL agregado al final de CLAUDE.md (contenido del usuario preservado)',
602
+ 'reemplazado': '* Bloque SWL actualizado en CLAUDE.md (contenido del usuario preservado)',
603
+ 'sin-cambios': '= CLAUDE.md ya tenía el bloque SWL actualizado',
604
+ 'error': '! Error al fusionar CLAUDE.md',
605
+ }[resMerge.accion] || `${resMerge.accion} ${resMerge.archivo}`;
606
+ console.log(` ${etiqueta}${resMerge.detalle ? ': ' + resMerge.detalle : ''}`);
607
+ registrarArchivo(estado, {
608
+ origen: 'generado-merge',
609
+ destino: rutaInstrucciones,
610
+ tipo: 'instrucciones-merge',
611
+ accion: resMerge.accion,
612
+ });
613
+ } else {
614
+ // Comportamiento clásico: sobrescribir archivo completo (codex/gemini/copilot/opencode)
615
+ if (!fs.existsSync(dirInstrucciones)) {
616
+ fs.mkdirSync(dirInstrucciones, { recursive: true });
617
+ }
618
+ fs.writeFileSync(rutaInstrucciones, instrucciones.contenido, 'utf-8');
619
+ console.log(` + Archivo principal generado: ${instrucciones.rutaRelativa}`);
620
+ registrarArchivo(estado, {
621
+ origen: 'generado',
622
+ destino: rutaInstrucciones,
623
+ tipo: 'instrucciones',
624
+ });
625
+ }
626
+ }
627
+ } catch (err) {
628
+ console.error(` ! Error generando archivo de instrucciones: ${err.message}`);
629
+ }
630
+ }
631
+
632
+ // 9. Opt-in interactivo de notificaciones Telegram
633
+ // Nota: SWL solo registra hooks a nivel proyecto, excepto bajo opt-in explícito
634
+ // del usuario en este flujo. Ver ADR-0009 y scripts/lib/hooks-settings.js.
635
+ const noNotificaciones = opciones.no_notificaciones || false;
636
+ const withNotificaciones = opciones.with_notificaciones || null; // 'token,chatId'
637
+
638
+ if (!noNotificaciones) {
639
+ try {
640
+ const notif = require('./lib/notificaciones-telegram');
641
+
642
+ // Modo headless explícito: --with-notificaciones=token,chatId
643
+ if (withNotificaciones) {
644
+ const [tokenHl, chatIdHl] = withNotificaciones.split(',');
645
+ if (tokenHl && chatIdHl) {
646
+ const resHl = await notif.init({
647
+ token: tokenHl.trim(),
648
+ chatId: chatIdHl.trim(),
649
+ esTty: false,
650
+ hooksDir: rutas.hooks || null,
651
+ });
652
+ if (resHl.resultado === 'completado') {
653
+ console.log(' + Notificaciones Telegram configuradas (modo headless).');
654
+ } else {
655
+ console.log(` ~ Notificaciones Telegram: ${resHl.resultado} — ${resHl.detalle || ''}`);
656
+ }
657
+ } else {
658
+ console.log(' ! --with-notificaciones: formato esperado token,chatId — omitiendo notificaciones.');
659
+ }
660
+ } else if (!ES_TTY) {
661
+ // No-TTY y sin flags headless → saltar automáticamente
662
+ console.log(' ~ Notificaciones Telegram: omitido en modo no-interactivo (usar /swl:notificaciones init para activarlo después).');
663
+ } else {
664
+ // TTY → flujo interactivo
665
+ const resInteractivo = await notif.init({
666
+ esTty: true,
667
+ hooksDir: rutas.hooks || null,
668
+ dryRun: dryRun,
669
+ });
670
+ if (resInteractivo.resultado === 'completado') {
671
+ console.log(' + Notificaciones Telegram configuradas.');
672
+ } else if (resInteractivo.resultado === 'omitido') {
673
+ // Silencioso — ya se imprimió mensaje en init()
674
+ }
675
+ }
676
+ } catch (err) {
677
+ // No romper la instalación entera por un fallo de notificaciones
678
+ console.error(` ! Notificaciones Telegram: error no esperado (instalación continúa): ${err.message}`);
679
+ }
680
+ }
681
+
682
+ // 10. Guardar estado
683
+ estado.hooksRegistrados = hooksRegistrados;
684
+ const rutaEstado = guardarEstado(estado, rutas.base);
685
+
686
+ // 9.5. En instalación global: copiar vendors a ~/.claude/scripts/vendor/
687
+ // Permite que los scripts funcionen en proyectos que no tienen la copia local
688
+ if (esGlobal) {
689
+ const vendorsGlobal = ['claude-usage', 'markitdown'];
690
+ for (const vendorNombre of vendorsGlobal) {
691
+ const vendorOrigen = path.join(RAIZ_PKG, 'scripts', 'vendor', vendorNombre);
692
+ const vendorDestino = path.join(rutas.base, 'scripts', 'vendor', vendorNombre);
693
+ if (fs.existsSync(vendorOrigen)) {
694
+ try {
695
+ copiarDirectorio(vendorOrigen, vendorDestino);
696
+ console.log(`[vendor] ${vendorNombre} copiado a ${vendorDestino}`);
697
+ } catch (err) {
698
+ console.error(` ! Error copiando ${vendorNombre}: ${err.message}`);
699
+ }
700
+ }
701
+ }
702
+ }
703
+
704
+ // 10. Reporte final
705
+ console.log('\n' + '='.repeat(40));
706
+ console.log('Resultado de instalación');
707
+ console.log('='.repeat(40));
708
+ console.log(` Target: ${target} (${runtime.nombre})`);
709
+ console.log(` Perfil: ${perfil}`);
710
+ console.log(` Ubicación: ${rutas.base}`);
711
+ console.log(` Instalados: ${instalados}`);
712
+ console.log(` Protegidos: ${protegidos} (datos de usuario preservados)`);
713
+ console.log(` Evolucionados: ${evolucionados} (mejorados por auto-evolución, preservados)`);
714
+ console.log(` Respaldados: ${estado.backups ? estado.backups.length : 0}`);
715
+ console.log(` Colisiones: ${colisiones}`);
716
+ console.log(` Errores: ${errores}`);
717
+ console.log(` Estado: ${rutaEstado}`);
718
+
719
+ if (resolucion.warnings.length > 0) {
720
+ console.log('\nAdvertencias:');
721
+ for (const w of resolucion.warnings) {
722
+ console.log(` ! ${w}`);
723
+ }
724
+ }
725
+
726
+ // 11. Cleanup automático de backups antiguos (conservar últimas 3 versiones)
727
+ const cleanup = limpiarBackups(process.cwd(), 3);
728
+ if (cleanup.eliminados > 0) {
729
+ console.log(`\n[cleanup] ${cleanup.eliminados} backup(s) antiguo(s) eliminado(s) (${cleanup.liberadoMB} MB liberados, ${cleanup.conservados} conservados)`);
730
+ }
731
+
732
+ // 12. Actualizar manifest y .gitignore (solo para instalaciones locales)
733
+ if (!esGlobal) {
734
+ const cwd = process.cwd();
735
+
736
+ // Actualiza manifest con target y profile realmente usados
737
+ escribirManifest(cwd, { target, profile: perfil, version: VERSION });
738
+
739
+ // Agrega entradas gitignore específicas del runtime si no son las base (claude)
740
+ const extrasRuntime = entradasParaRuntime(target);
741
+ actualizarGitignore(cwd, extrasRuntime);
742
+ console.log('[manifest] .swl-ses actualizado.');
743
+ console.log('[gitignore] Sección swl-ses actualizada.');
744
+
745
+ // 13. Limpiar archivos swl-ses que estén tracked en git
746
+ // SWL-SES es tooling (como node_modules), no se commitea.
747
+ // Si el usuario commiteó archivos antes de tener el .gitignore correcto,
748
+ // los quitamos del índice para que git deje de trackearlos.
749
+ const limpieza = limpiarTracked(cwd, extrasRuntime);
750
+ if (limpieza.eliminados > 0) {
751
+ console.log(`[git] ${limpieza.eliminados} archivo(s) swl-ses removido(s) del índice de git (los archivos siguen en disco).`);
752
+ }
753
+ }
754
+
755
+ console.log('\nSiguiente paso:');
756
+ console.log(' npx swl-ses@latest doctor');
757
+ console.log('');
758
+ console.log(' (usar @latest evita el caché stale de npx — ver MANUAL_USO.md)');
759
+ console.log('');
760
+
761
+ if (errores > 0) {
762
+ process.exit(1);
763
+ }
764
+ }
765
+
766
+ /**
767
+ * Instala un archivo individual en el directorio destino correcto
768
+ */
769
+ function instalarArchivo(archivo, rutas, runtime, opciones = {}) {
770
+ // Verificar que el target soporta este tipo de componente
771
+ if (runtime.tiposSoportados && !runtime.tiposSoportados.includes(archivo.tipo)) {
772
+ return { instalado: false, razon: `Target "${runtime.id}" no soporta "${archivo.tipo}"` };
773
+ }
774
+
775
+ let dirDestino;
776
+
777
+ switch (archivo.tipo) {
778
+ case 'agentes':
779
+ dirDestino = rutas.agentes;
780
+ break;
781
+ case 'habilidades':
782
+ dirDestino = rutas.habilidades;
783
+ break;
784
+ case 'comandos':
785
+ dirDestino = rutas.comandos;
786
+ break;
787
+ case 'reglas':
788
+ dirDestino = rutas.reglas;
789
+ break;
790
+ case 'hooks':
791
+ dirDestino = rutas.hooks;
792
+ break;
793
+ case 'plantillas':
794
+ // Las plantillas van a .planning/
795
+ dirDestino = path.join(process.cwd(), '.planning');
796
+ break;
797
+ default:
798
+ dirDestino = rutas.base;
799
+ }
800
+
801
+ if (!dirDestino) {
802
+ return { instalado: false, razon: `Target no soporta tipo "${archivo.tipo}"` };
803
+ }
804
+
805
+ // Crear directorio destino si no existe
806
+ if (!fs.existsSync(dirDestino)) {
807
+ fs.mkdirSync(dirDestino, { recursive: true });
808
+ }
809
+
810
+ let nombreArchivo = path.basename(archivo.origen);
811
+
812
+ // Flat naming: convierte rutas jerárquicas en nombres planos con __
813
+ // Ejemplo: habilidades/build-errors-python → build-errors-python (sin cambio, ya es plano)
814
+ // Ejemplo: reglas/lenguajes/java/java-estilo.md → java__java-estilo.md
815
+ // Patrón adoptado de skillshare (internal/sync/naming.go)
816
+ if (opciones.flatNaming && archivo.rutaRelativa) {
817
+ const partes = archivo.rutaRelativa.split('/');
818
+ if (partes.length > 2) {
819
+ // Tomar desde el segundo nivel en adelante, unir con __
820
+ nombreArchivo = partes.slice(1).join('__');
821
+ }
822
+ }
823
+
824
+ // Reglas de lenguaje: preservar subdirectorio (reglas/lenguajes/LANG/archivo.md → .claude/rules/LANG/archivo.md)
825
+ // Sin esto todos los archivos colisionarían con el mismo nombre en la raíz.
826
+ let destino;
827
+ if (
828
+ archivo.tipo === 'reglas' &&
829
+ archivo.rutaRelativa &&
830
+ archivo.rutaRelativa.startsWith('reglas/lenguajes/')
831
+ ) {
832
+ const resto = archivo.rutaRelativa.slice('reglas/lenguajes/'.length);
833
+ const partes = resto.split('/');
834
+ if (partes.length >= 2) {
835
+ const subdirLang = path.join(dirDestino, partes[0]);
836
+ if (!fs.existsSync(subdirLang)) {
837
+ fs.mkdirSync(subdirLang, { recursive: true });
838
+ }
839
+ destino = path.join(subdirLang, partes[1]);
840
+ } else {
841
+ destino = path.join(dirDestino, nombreArchivo);
842
+ }
843
+ } else {
844
+ destino = path.join(dirDestino, nombreArchivo);
845
+ }
846
+
847
+ // Seguridad: validar ruta
848
+ validarRuta(dirDestino, nombreArchivo);
849
+
850
+ // Verificar archivo sensible
851
+ if (esArchivoSensible(nombreArchivo)) {
852
+ console.log(` ! Archivo sensible omitido: ${nombreArchivo}`);
853
+ return { instalado: false, razon: 'archivo sensible' };
854
+ }
855
+
856
+ // Nivel 1: Verificar si el destino está protegido (datos de usuario)
857
+ const rutaRelativaProyecto = path.relative(process.cwd(), destino);
858
+ const proteccion = esProtegido(rutaRelativaProyecto);
859
+ if (proteccion.protegido && fs.existsSync(destino)) {
860
+ console.log(` ~ Protegido: ${nombreArchivo} (${proteccion.razon})`);
861
+ return { instalado: false, protegido: true };
862
+ }
863
+
864
+ // Evolución: Verificar si el destino fue evolucionado por auto-evolución
865
+ const esComponenteEvolucionable = ['agentes', 'habilidades', 'comandos', 'reglas'].includes(archivo.tipo);
866
+ if (esComponenteEvolucionable && fs.existsSync(destino) && opciones.force) {
867
+ // Resolver ruta absoluta del origen (archivo.origen es relativo al paquete)
868
+ const origenAbsoluto = path.resolve(RAIZ_PKG, archivo.origen);
869
+ const strategy = decideUpdateStrategy(destino, origenAbsoluto, opciones.versionActual || '');
870
+ if (strategy.strategy === 'preserve') {
871
+ console.log(` ★ Evolucionado: ${nombreArchivo} — preservado (${strategy.reason})`);
872
+ return { instalado: false, evolucionado: true, destino };
873
+ }
874
+ if (strategy.strategy === 'conflict') {
875
+ // Crear backup del archivo evolucionado ANTES de sobrescribir
876
+ if (opciones.versionAnterior) {
877
+ const backup = crearBackup(process.cwd(), destino, opciones.versionAnterior);
878
+ if (backup.respaldado) {
879
+ console.log(` ⚠ Conflicto: ${nombreArchivo} — evolucionado localmente + cambios en versión nueva`);
880
+ console.log(` ↩ Backup evolucionado: ${path.relative(process.cwd(), backup.rutaBackup)}`);
881
+ if (opciones.estado) {
882
+ registrarBackup(opciones.estado, {
883
+ rutaOriginal: destino,
884
+ rutaBackup: backup.rutaBackup,
885
+ version: opciones.versionAnterior,
886
+ evolucionado: true,
887
+ });
888
+ }
889
+ }
890
+ }
891
+ // Intentar merge: generar diff de mutaciones para re-aplicación
892
+ const merge = mergeEvolved(destino, origenAbsoluto, opciones.versionActual || '');
893
+ if (merge.merged && merge.diffPath) {
894
+ console.log(` ⊕ Diff generado: ${path.relative(process.cwd(), merge.diffPath)} (${merge.diffsCount} mutaciones)`);
895
+ console.log(` → Ejecutar /swl:autoresearch para re-aplicar mutaciones sobre v${opciones.versionActual}`);
896
+ } else if (merge.merged) {
897
+ console.log(` ⊕ Merge exitoso: campos evolved re-aplicados sin cambios de contenido`);
898
+ return { instalado: false, evolucionado: true, destino };
899
+ }
900
+ }
901
+ }
902
+
903
+ // Verificar colisión
904
+ if (fs.existsSync(destino) && !opciones.force) {
905
+ console.log(` - Colisión: ${nombreArchivo} (usa --force para sobreescribir)`);
906
+ return { instalado: false, colision: true };
907
+ }
908
+
909
+ // Nivel 2: Backup antes de sobreescribir con --force
910
+ if (fs.existsSync(destino) && opciones.force && opciones.versionAnterior) {
911
+ const backup = crearBackup(process.cwd(), destino, opciones.versionAnterior);
912
+ if (backup.respaldado) {
913
+ console.log(` ↩ Backup: ${nombreArchivo} → ${path.relative(process.cwd(), backup.rutaBackup)}`);
914
+ if (opciones.estado) {
915
+ registrarBackup(opciones.estado, {
916
+ rutaOriginal: destino,
917
+ rutaBackup: backup.rutaBackup,
918
+ version: opciones.versionAnterior,
919
+ });
920
+ }
921
+ }
922
+ }
923
+
924
+ // Copiar, symlink o flat-copy según syncMode
925
+ if (fs.existsSync(archivo.origen)) {
926
+ const stat = fs.statSync(archivo.origen);
927
+ const modo = opciones.syncMode || 'copy';
928
+
929
+ if (modo === 'symlink') {
930
+ // Symlink mode: crear enlace simbólico en lugar de copiar.
931
+ // Cambios en la fuente se reflejan instantáneamente en el destino.
932
+ // Ideal para desarrollo del repo fuente de swl-ses.
933
+ try {
934
+ if (fs.existsSync(destino)) {
935
+ const dStat = fs.lstatSync(destino);
936
+ if (dStat.isSymbolicLink()) fs.unlinkSync(destino);
937
+ else if (dStat.isDirectory()) fs.rmSync(destino, { recursive: true });
938
+ else fs.unlinkSync(destino);
939
+ }
940
+ const origenAbsoluto = path.resolve(archivo.origen);
941
+ fs.symlinkSync(origenAbsoluto, destino, stat.isDirectory() ? 'junction' : 'file');
942
+ console.log(` ~ ${path.relative(rutas.base, destino)} (symlink)`);
943
+ return { instalado: true, destino };
944
+ } catch (symlinkErr) {
945
+ // Fallback a copy si symlink falla (permisos, filesystem)
946
+ console.log(` ! Symlink falló (${symlinkErr.code || symlinkErr.message}), usando copy`);
947
+ }
948
+ }
949
+
950
+ // Copy mode (default) o fallback de symlink
951
+ if (stat.isDirectory()) {
952
+ copiarDirectorio(archivo.origen, path.join(dirDestino, nombreArchivo));
953
+ } else {
954
+ fs.copyFileSync(archivo.origen, destino);
955
+ }
956
+ console.log(` + ${path.relative(rutas.base, destino)}`);
957
+ return { instalado: true, destino };
958
+ } else {
959
+ return { instalado: false, razon: 'origen no existe' };
960
+ }
961
+ }
962
+
963
+ /**
964
+ * Copia un directorio recursivamente
965
+ */
966
+ function copiarDirectorio(origen, destino) {
967
+ if (!fs.existsSync(destino)) {
968
+ fs.mkdirSync(destino, { recursive: true });
969
+ }
970
+
971
+ const entradas = fs.readdirSync(origen, { withFileTypes: true });
972
+ for (const entrada of entradas) {
973
+ const src = path.join(origen, entrada.name);
974
+ const dst = path.join(destino, entrada.name);
975
+
976
+ if (entrada.isDirectory()) {
977
+ copiarDirectorio(src, dst);
978
+ } else {
979
+ fs.copyFileSync(src, dst);
980
+ }
981
+ }
982
+ }
983
+
984
+ /**
985
+ * Elimina subdirectorios de reglas de lenguaje en .claude/rules/ para lenguajes
986
+ * que NO están en el stack detectado del proyecto.
987
+ *
988
+ * Solo borra subdirectorios cuyo nombre coincide con un lenguaje conocido del sistema
989
+ * (java, go, rust, etc.). Nunca toca archivos en la raíz de .claude/rules/.
990
+ *
991
+ * @param {string} dirReglas - Ruta a .claude/rules/ (rutas.reglas)
992
+ * @param {Set<string>} stackDetectado - Lenguajes detectados por detectarStack()
993
+ * @returns {{ eliminados: number, lenguajes: string[] }}
994
+ */
995
+ function limpiarReglasSinStack(dirReglas, stackDetectado) {
996
+ const { LENGUAJES_CONOCIDOS } = require('./lib/detectar-stack');
997
+ const lenguajesEliminados = [];
998
+
999
+ if (!fs.existsSync(dirReglas)) {
1000
+ return { eliminados: 0, lenguajes: [] };
1001
+ }
1002
+
1003
+ let entradas;
1004
+ try {
1005
+ entradas = fs.readdirSync(dirReglas, { withFileTypes: true });
1006
+ } catch {
1007
+ return { eliminados: 0, lenguajes: [] };
1008
+ }
1009
+
1010
+ for (const entrada of entradas) {
1011
+ if (!entrada.isDirectory()) continue;
1012
+
1013
+ const lang = entrada.name;
1014
+ // Solo actuar sobre subdirectorios que son lenguajes conocidos del sistema
1015
+ if (!LENGUAJES_CONOCIDOS.has(lang)) continue;
1016
+ // Si el lenguaje está en el stack detectado, conservar
1017
+ if (stackDetectado.has(lang)) continue;
1018
+
1019
+ const dirLang = path.join(dirReglas, lang);
1020
+ try {
1021
+ fs.rmSync(dirLang, { recursive: true, force: true });
1022
+ lenguajesEliminados.push(lang);
1023
+ } catch (err) {
1024
+ console.log(` ! No se pudo eliminar ${dirLang}: ${err.message}`);
1025
+ }
1026
+ }
1027
+
1028
+ return { eliminados: lenguajesEliminados.length, lenguajes: lenguajesEliminados.sort() };
1029
+ }
1030
+
1031
+ module.exports = install;