theus-cli-linux-arm64 1.2.1 → 1.3.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 (772) hide show
  1. package/README.md +15 -0
  2. package/RELEASE.json +6 -6
  3. package/bin/theus +0 -0
  4. package/package.json +1 -1
  5. package/vendor/chrome-extension/README.md +142 -0
  6. package/vendor/chrome-extension/background.js +540 -0
  7. package/vendor/chrome-extension/cdp-core.js +400 -0
  8. package/vendor/chrome-extension/cdp-core.test.ts +321 -0
  9. package/vendor/chrome-extension/cdp.js +672 -0
  10. package/vendor/chrome-extension/icons/icon128.png +0 -0
  11. package/vendor/chrome-extension/icons/icon16.png +0 -0
  12. package/vendor/chrome-extension/icons/icon32.png +0 -0
  13. package/vendor/chrome-extension/icons/icon48.png +0 -0
  14. package/vendor/chrome-extension/manifest.json +36 -0
  15. package/vendor/chrome-extension/popup.html +78 -0
  16. package/vendor/chrome-extension/popup.js +47 -0
  17. package/vendor/chrome-extension/recorder.js +316 -0
  18. package/vendor/higiene-motor/PARCHES.md +244 -0
  19. package/vendor/higiene-motor/audit_dir.py +166 -0
  20. package/vendor/higiene-motor/audit_lib.py +333 -0
  21. package/vendor/higiene-motor/audit_website.py +635 -0
  22. package/vendor/higiene-motor/av_meta.py +498 -0
  23. package/vendor/higiene-motor/check_staged.py +71 -0
  24. package/vendor/higiene-motor/clean_ctrlregen.py +212 -0
  25. package/vendor/higiene-motor/clean_file.py +237 -0
  26. package/vendor/higiene-motor/clean_image.py +218 -0
  27. package/vendor/higiene-motor/clean_staged.py +143 -0
  28. package/vendor/higiene-motor/clean_text.py +108 -0
  29. package/vendor/higiene-motor/common.py +486 -0
  30. package/vendor/higiene-motor/container_meta.py +2522 -0
  31. package/vendor/higiene-motor/detect_gumbel.py +308 -0
  32. package/vendor/higiene-motor/detect_text_watermark.py +613 -0
  33. package/vendor/higiene-motor/format_dispatch.py +157 -0
  34. package/vendor/higiene-motor/hook_written_file.py +253 -0
  35. package/vendor/higiene-motor/image_meta.py +2171 -0
  36. package/vendor/higiene-motor/inspect_file.py +138 -0
  37. package/vendor/higiene-motor/inspect_image.py +72 -0
  38. package/vendor/higiene-motor/inspect_text.py +86 -0
  39. package/vendor/higiene-motor/markdiffusion_harness.py +533 -0
  40. package/vendor/higiene-motor/rewrite_text.py +737 -0
  41. package/vendor/higiene-motor/score_stylometry.py +460 -0
  42. package/vendor/higiene-motor/score_synthid.py +165 -0
  43. package/vendor/higiene-motor/server.py +1059 -0
  44. package/vendor/higiene-motor/synthid_score_server.py +176 -0
  45. package/vendor/higiene-motor/text_detectors.py +433 -0
  46. package/vendor/higiene-motor/text_unicode.py +730 -0
  47. package/vendor/theus-arsenal/.arsenal-nombres-ola2.json +0 -6
  48. package/vendor/theus-arsenal/.arsenal-nombres-ola3.json +0 -72
  49. package/vendor/theus-arsenal/.mailmap +0 -2
  50. package/vendor/theus-arsenal/.theus-plugin/marketplace.json +0 -25
  51. package/vendor/theus-arsenal/.theus-plugin/plugin.json +0 -20
  52. package/vendor/theus-arsenal/AUTHORS.md +0 -8
  53. package/vendor/theus-arsenal/CLEANROOM_REPLACEMENT_PLAN.md +0 -11
  54. package/vendor/theus-arsenal/LICENSE +0 -26
  55. package/vendor/theus-arsenal/PROVENANCE.md +0 -9
  56. package/vendor/theus-arsenal/README.md +0 -41
  57. package/vendor/theus-arsenal/THIRD_PARTY.md +0 -80
  58. package/vendor/theus-arsenal/agents/actualizador-docs.md +0 -123
  59. package/vendor/theus-arsenal/agents/analista-comentarios.md +0 -53
  60. package/vendor/theus-arsenal/agents/analista-conversaciones.md +0 -60
  61. package/vendor/theus-arsenal/agents/analista-tests-pr.md +0 -53
  62. package/vendor/theus-arsenal/agents/analista-tipos.md +0 -49
  63. package/vendor/theus-arsenal/agents/arquitecto-accesibilidad.md +0 -148
  64. package/vendor/theus-arsenal/agents/arquitecto-codigo.md +0 -79
  65. package/vendor/theus-arsenal/agents/arquitecto-homelab.md +0 -90
  66. package/vendor/theus-arsenal/agents/arquitecto-redes.md +0 -116
  67. package/vendor/theus-arsenal/agents/arquitecto-sistemas.md +0 -219
  68. package/vendor/theus-arsenal/agents/bifurcador-opensource.md +0 -206
  69. package/vendor/theus-arsenal/agents/cazador-fallos-silenciosos.md +0 -58
  70. package/vendor/theus-arsenal/agents/consultor-documentacion.md +0 -76
  71. package/vendor/theus-arsenal/agents/diagnosticador-redes.md +0 -135
  72. package/vendor/theus-arsenal/agents/ejecutor-e2e.md +0 -96
  73. package/vendor/theus-arsenal/agents/empaquetador-opensource.md +0 -257
  74. package/vendor/theus-arsenal/agents/escaner-secretos.md +0 -196
  75. package/vendor/theus-arsenal/agents/especialista-seo.md +0 -70
  76. package/vendor/theus-arsenal/agents/estratega-marketing.md +0 -158
  77. package/vendor/theus-arsenal/agents/evaluador-agentes.md +0 -214
  78. package/vendor/theus-arsenal/agents/evaluador-harness.md +0 -217
  79. package/vendor/theus-arsenal/agents/explorador-codigo.md +0 -79
  80. package/vendor/theus-arsenal/agents/extractor-specs.md +0 -214
  81. package/vendor/theus-arsenal/agents/generador-harness.md +0 -139
  82. package/vendor/theus-arsenal/agents/guia-tdd.md +0 -99
  83. package/vendor/theus-arsenal/agents/jefe-de-gabinete.md +0 -162
  84. package/vendor/theus-arsenal/agents/limpiador-refactors.md +0 -93
  85. package/vendor/theus-arsenal/agents/optimizador-rendimiento.md +0 -454
  86. package/vendor/theus-arsenal/agents/planificador-harness.md +0 -107
  87. package/vendor/theus-arsenal/agents/planificador.md +0 -221
  88. package/vendor/theus-arsenal/agents/resolutor-apps-harmonyos.md +0 -181
  89. package/vendor/theus-arsenal/agents/resolutor-builds-cpp.md +0 -98
  90. package/vendor/theus-arsenal/agents/resolutor-builds-dart.md +0 -209
  91. package/vendor/theus-arsenal/agents/resolutor-builds-django.md +0 -253
  92. package/vendor/theus-arsenal/agents/resolutor-builds-go.md +0 -102
  93. package/vendor/theus-arsenal/agents/resolutor-builds-java.md +0 -274
  94. package/vendor/theus-arsenal/agents/resolutor-builds-kotlin.md +0 -128
  95. package/vendor/theus-arsenal/agents/resolutor-builds-pytorch.md +0 -128
  96. package/vendor/theus-arsenal/agents/resolutor-builds-react.md +0 -214
  97. package/vendor/theus-arsenal/agents/resolutor-builds-rust.md +0 -156
  98. package/vendor/theus-arsenal/agents/resolutor-builds-swift.md +0 -169
  99. package/vendor/theus-arsenal/agents/resolutor-builds.md +0 -122
  100. package/vendor/theus-arsenal/agents/revisor-bd.md +0 -97
  101. package/vendor/theus-arsenal/agents/revisor-codigo.md +0 -291
  102. package/vendor/theus-arsenal/agents/revisor-config-red.md +0 -116
  103. package/vendor/theus-arsenal/agents/revisor-cpp.md +0 -80
  104. package/vendor/theus-arsenal/agents/revisor-csharp.md +0 -109
  105. package/vendor/theus-arsenal/agents/revisor-django.md +0 -168
  106. package/vendor/theus-arsenal/agents/revisor-fastapi.md +0 -82
  107. package/vendor/theus-arsenal/agents/revisor-flutter.md +0 -251
  108. package/vendor/theus-arsenal/agents/revisor-go.md +0 -84
  109. package/vendor/theus-arsenal/agents/revisor-java.md +0 -192
  110. package/vendor/theus-arsenal/agents/revisor-kotlin.md +0 -171
  111. package/vendor/theus-arsenal/agents/revisor-ml.md +0 -159
  112. package/vendor/theus-arsenal/agents/revisor-php.md +0 -108
  113. package/vendor/theus-arsenal/agents/revisor-python.md +0 -106
  114. package/vendor/theus-arsenal/agents/revisor-react.md +0 -166
  115. package/vendor/theus-arsenal/agents/revisor-rust.md +0 -102
  116. package/vendor/theus-arsenal/agents/revisor-seguridad.md +0 -116
  117. package/vendor/theus-arsenal/agents/revisor-software-clinico.md +0 -95
  118. package/vendor/theus-arsenal/agents/revisor-swift.md +0 -115
  119. package/vendor/theus-arsenal/agents/revisor-typescript.md +0 -123
  120. package/vendor/theus-arsenal/agents/revisor-vue.md +0 -205
  121. package/vendor/theus-arsenal/agents/simplificador-codigo.md +0 -55
  122. package/vendor/theus-arsenal/commands/actualizar-docs.md +0 -88
  123. package/vendor/theus-arsenal/commands/actualizar-mapas-codigo.md +0 -78
  124. package/vendor/theus-arsenal/commands/aprender-evaluar.md +0 -109
  125. package/vendor/theus-arsenal/commands/aprender.md +0 -74
  126. package/vendor/theus-arsenal/commands/arreglar-build.md +0 -66
  127. package/vendor/theus-arsenal/commands/bucle-multiperspectiva.md +0 -153
  128. package/vendor/theus-arsenal/commands/build-cpp.md +0 -173
  129. package/vendor/theus-arsenal/commands/build-flutter.md +0 -164
  130. package/vendor/theus-arsenal/commands/build-go.md +0 -183
  131. package/vendor/theus-arsenal/commands/build-gradle.md +0 -75
  132. package/vendor/theus-arsenal/commands/build-kotlin.md +0 -176
  133. package/vendor/theus-arsenal/commands/build-react.md +0 -187
  134. package/vendor/theus-arsenal/commands/build-rust.md +0 -187
  135. package/vendor/theus-arsenal/commands/campana-marketing.md +0 -125
  136. package/vendor/theus-arsenal/commands/checkpoint.md +0 -78
  137. package/vendor/theus-arsenal/commands/cobertura-tests.md +0 -73
  138. package/vendor/theus-arsenal/commands/configurar-gestor-paquetes.md +0 -86
  139. package/vendor/theus-arsenal/commands/consulta.md +0 -164
  140. package/vendor/theus-arsenal/commands/control-calidad.md +0 -50
  141. package/vendor/theus-arsenal/commands/crear-skill.md +0 -77
  142. package/vendor/theus-arsenal/commands/enrutar-modelo.md +0 -30
  143. package/vendor/theus-arsenal/commands/epica-desbloquear.md +0 -17
  144. package/vendor/theus-arsenal/commands/epica-descomponer.md +0 -22
  145. package/vendor/theus-arsenal/commands/epica-publicar.md +0 -21
  146. package/vendor/theus-arsenal/commands/epica-reclamar.md +0 -25
  147. package/vendor/theus-arsenal/commands/epica-revisar.md +0 -22
  148. package/vendor/theus-arsenal/commands/epica-sincronizar.md +0 -21
  149. package/vendor/theus-arsenal/commands/epica-validar.md +0 -21
  150. package/vendor/theus-arsenal/commands/evolucionar.md +0 -176
  151. package/vendor/theus-arsenal/commands/funcionalidad.md +0 -49
  152. package/vendor/theus-arsenal/commands/guardar-sesion.md +0 -278
  153. package/vendor/theus-arsenal/commands/harness-build.md +0 -111
  154. package/vendor/theus-arsenal/commands/harness-diseno.md +0 -46
  155. package/vendor/theus-arsenal/commands/informe-costos.md +0 -90
  156. package/vendor/theus-arsenal/commands/iniciar-bucle.md +0 -36
  157. package/vendor/theus-arsenal/commands/instintos-estado.md +0 -53
  158. package/vendor/theus-arsenal/commands/instintos-exportar.md +0 -69
  159. package/vendor/theus-arsenal/commands/instintos-importar.md +0 -120
  160. package/vendor/theus-arsenal/commands/lienzo-planes.md +0 -48
  161. package/vendor/theus-arsenal/commands/limpiar-refactor.md +0 -84
  162. package/vendor/theus-arsenal/commands/modo-seguro.md +0 -96
  163. package/vendor/theus-arsenal/commands/orq-agregar-funcionalidad.md +0 -36
  164. package/vendor/theus-arsenal/commands/orq-cambiar-funcionalidad.md +0 -38
  165. package/vendor/theus-arsenal/commands/orq-construir-mvp.md +0 -36
  166. package/vendor/theus-arsenal/commands/orq-corregir-defecto.md +0 -40
  167. package/vendor/theus-arsenal/commands/orq-refinar-codigo.md +0 -44
  168. package/vendor/theus-arsenal/commands/orq-revisar.md +0 -135
  169. package/vendor/theus-arsenal/commands/plan-prd.md +0 -160
  170. package/vendor/theus-arsenal/commands/plan.md +0 -198
  171. package/vendor/theus-arsenal/commands/podar.md +0 -31
  172. package/vendor/theus-arsenal/commands/pr.md +0 -181
  173. package/vendor/theus-arsenal/commands/promover.md +0 -41
  174. package/vendor/theus-arsenal/commands/proyectos.md +0 -33
  175. package/vendor/theus-arsenal/commands/prp-commit.md +0 -112
  176. package/vendor/theus-arsenal/commands/prp-implementar.md +0 -385
  177. package/vendor/theus-arsenal/commands/prp-planificar.md +0 -501
  178. package/vendor/theus-arsenal/commands/reanudar-sesion.md +0 -160
  179. package/vendor/theus-arsenal/commands/revisar-codigo.md +0 -289
  180. package/vendor/theus-arsenal/commands/revisar-cpp.md +0 -132
  181. package/vendor/theus-arsenal/commands/revisar-fastapi.md +0 -39
  182. package/vendor/theus-arsenal/commands/revisar-flutter.md +0 -115
  183. package/vendor/theus-arsenal/commands/revisar-go.md +0 -148
  184. package/vendor/theus-arsenal/commands/revisar-kotlin.md +0 -140
  185. package/vendor/theus-arsenal/commands/revisar-pr.md +0 -37
  186. package/vendor/theus-arsenal/commands/revisar-python.md +0 -297
  187. package/vendor/theus-arsenal/commands/revisar-react.md +0 -170
  188. package/vendor/theus-arsenal/commands/revisar-rust.md +0 -142
  189. package/vendor/theus-arsenal/commands/revisar-vue.md +0 -174
  190. package/vendor/theus-arsenal/commands/salud-skills.md +0 -52
  191. package/vendor/theus-arsenal/commands/sesiones.md +0 -345
  192. package/vendor/theus-arsenal/commands/test-cpp.md +0 -252
  193. package/vendor/theus-arsenal/commands/test-flutter.md +0 -143
  194. package/vendor/theus-arsenal/commands/test-go.md +0 -268
  195. package/vendor/theus-arsenal/commands/test-kotlin.md +0 -312
  196. package/vendor/theus-arsenal/commands/test-react.md +0 -265
  197. package/vendor/theus-arsenal/commands/test-rust.md +0 -309
  198. package/vendor/theus-arsenal/commands/vigilancia-canary.md +0 -43
  199. package/vendor/theus-arsenal/hooks/hooks.json +0 -274
  200. package/vendor/theus-arsenal/package.json +0 -6
  201. package/vendor/theus-arsenal/rules/angular/coding-style.md +0 -182
  202. package/vendor/theus-arsenal/rules/angular/hooks.md +0 -25
  203. package/vendor/theus-arsenal/rules/angular/patterns.md +0 -249
  204. package/vendor/theus-arsenal/rules/angular/security.md +0 -87
  205. package/vendor/theus-arsenal/rules/angular/testing.md +0 -164
  206. package/vendor/theus-arsenal/rules/arkts/coding-style.md +0 -153
  207. package/vendor/theus-arsenal/rules/arkts/hooks.md +0 -80
  208. package/vendor/theus-arsenal/rules/arkts/patterns.md +0 -236
  209. package/vendor/theus-arsenal/rules/arkts/security.md +0 -141
  210. package/vendor/theus-arsenal/rules/arkts/testing.md +0 -126
  211. package/vendor/theus-arsenal/rules/common/agents.md +0 -49
  212. package/vendor/theus-arsenal/rules/common/code-review.md +0 -123
  213. package/vendor/theus-arsenal/rules/common/coding-style.md +0 -90
  214. package/vendor/theus-arsenal/rules/common/development-workflow.md +0 -44
  215. package/vendor/theus-arsenal/rules/common/git-workflow.md +0 -24
  216. package/vendor/theus-arsenal/rules/common/hooks.md +0 -32
  217. package/vendor/theus-arsenal/rules/common/patterns.md +0 -31
  218. package/vendor/theus-arsenal/rules/common/performance.md +0 -53
  219. package/vendor/theus-arsenal/rules/common/security.md +0 -29
  220. package/vendor/theus-arsenal/rules/common/testing.md +0 -57
  221. package/vendor/theus-arsenal/rules/cpp/coding-style.md +0 -44
  222. package/vendor/theus-arsenal/rules/cpp/hooks.md +0 -39
  223. package/vendor/theus-arsenal/rules/cpp/patterns.md +0 -51
  224. package/vendor/theus-arsenal/rules/cpp/security.md +0 -51
  225. package/vendor/theus-arsenal/rules/cpp/testing.md +0 -44
  226. package/vendor/theus-arsenal/rules/csharp/coding-style.md +0 -72
  227. package/vendor/theus-arsenal/rules/csharp/hooks.md +0 -25
  228. package/vendor/theus-arsenal/rules/csharp/patterns.md +0 -50
  229. package/vendor/theus-arsenal/rules/csharp/security.md +0 -58
  230. package/vendor/theus-arsenal/rules/csharp/testing.md +0 -50
  231. package/vendor/theus-arsenal/rules/dart/coding-style.md +0 -159
  232. package/vendor/theus-arsenal/rules/dart/hooks.md +0 -68
  233. package/vendor/theus-arsenal/rules/dart/patterns.md +0 -261
  234. package/vendor/theus-arsenal/rules/dart/security.md +0 -135
  235. package/vendor/theus-arsenal/rules/dart/testing.md +0 -215
  236. package/vendor/theus-arsenal/rules/fsharp/coding-style.md +0 -112
  237. package/vendor/theus-arsenal/rules/fsharp/hooks.md +0 -26
  238. package/vendor/theus-arsenal/rules/fsharp/patterns.md +0 -111
  239. package/vendor/theus-arsenal/rules/fsharp/security.md +0 -76
  240. package/vendor/theus-arsenal/rules/fsharp/testing.md +0 -62
  241. package/vendor/theus-arsenal/rules/golang/coding-style.md +0 -32
  242. package/vendor/theus-arsenal/rules/golang/hooks.md +0 -17
  243. package/vendor/theus-arsenal/rules/golang/patterns.md +0 -45
  244. package/vendor/theus-arsenal/rules/golang/security.md +0 -34
  245. package/vendor/theus-arsenal/rules/golang/testing.md +0 -31
  246. package/vendor/theus-arsenal/rules/java/coding-style.md +0 -114
  247. package/vendor/theus-arsenal/rules/java/hooks.md +0 -18
  248. package/vendor/theus-arsenal/rules/java/patterns.md +0 -147
  249. package/vendor/theus-arsenal/rules/java/security.md +0 -101
  250. package/vendor/theus-arsenal/rules/java/testing.md +0 -133
  251. package/vendor/theus-arsenal/rules/kotlin/coding-style.md +0 -86
  252. package/vendor/theus-arsenal/rules/kotlin/hooks.md +0 -17
  253. package/vendor/theus-arsenal/rules/kotlin/patterns.md +0 -146
  254. package/vendor/theus-arsenal/rules/kotlin/security.md +0 -82
  255. package/vendor/theus-arsenal/rules/kotlin/testing.md +0 -128
  256. package/vendor/theus-arsenal/rules/nuxt/coding-style.md +0 -47
  257. package/vendor/theus-arsenal/rules/nuxt/hooks.md +0 -39
  258. package/vendor/theus-arsenal/rules/nuxt/patterns.md +0 -54
  259. package/vendor/theus-arsenal/rules/nuxt/security.md +0 -48
  260. package/vendor/theus-arsenal/rules/nuxt/testing.md +0 -49
  261. package/vendor/theus-arsenal/rules/php/coding-style.md +0 -40
  262. package/vendor/theus-arsenal/rules/php/hooks.md +0 -24
  263. package/vendor/theus-arsenal/rules/php/patterns.md +0 -33
  264. package/vendor/theus-arsenal/rules/php/security.md +0 -37
  265. package/vendor/theus-arsenal/rules/php/testing.md +0 -38
  266. package/vendor/theus-arsenal/rules/python/coding-style.md +0 -42
  267. package/vendor/theus-arsenal/rules/python/fastapi.md +0 -58
  268. package/vendor/theus-arsenal/rules/python/hooks.md +0 -19
  269. package/vendor/theus-arsenal/rules/python/patterns.md +0 -39
  270. package/vendor/theus-arsenal/rules/python/security.md +0 -30
  271. package/vendor/theus-arsenal/rules/python/testing.md +0 -38
  272. package/vendor/theus-arsenal/rules/react/coding-style.md +0 -109
  273. package/vendor/theus-arsenal/rules/react/hooks.md +0 -187
  274. package/vendor/theus-arsenal/rules/react/patterns.md +0 -194
  275. package/vendor/theus-arsenal/rules/react/security.md +0 -180
  276. package/vendor/theus-arsenal/rules/react/testing.md +0 -208
  277. package/vendor/theus-arsenal/rules/react-native/accessibility.md +0 -55
  278. package/vendor/theus-arsenal/rules/react-native/coding-style.md +0 -71
  279. package/vendor/theus-arsenal/rules/react-native/hooks.md +0 -28
  280. package/vendor/theus-arsenal/rules/react-native/patterns.md +0 -88
  281. package/vendor/theus-arsenal/rules/react-native/performance.md +0 -45
  282. package/vendor/theus-arsenal/rules/react-native/production-readiness.md +0 -51
  283. package/vendor/theus-arsenal/rules/react-native/security.md +0 -43
  284. package/vendor/theus-arsenal/rules/react-native/testing.md +0 -52
  285. package/vendor/theus-arsenal/rules/ruby/coding-style.md +0 -46
  286. package/vendor/theus-arsenal/rules/ruby/hooks.md +0 -37
  287. package/vendor/theus-arsenal/rules/ruby/patterns.md +0 -44
  288. package/vendor/theus-arsenal/rules/ruby/security.md +0 -51
  289. package/vendor/theus-arsenal/rules/ruby/testing.md +0 -51
  290. package/vendor/theus-arsenal/rules/rust/coding-style.md +0 -151
  291. package/vendor/theus-arsenal/rules/rust/hooks.md +0 -16
  292. package/vendor/theus-arsenal/rules/rust/patterns.md +0 -168
  293. package/vendor/theus-arsenal/rules/rust/security.md +0 -141
  294. package/vendor/theus-arsenal/rules/rust/testing.md +0 -154
  295. package/vendor/theus-arsenal/rules/swift/coding-style.md +0 -47
  296. package/vendor/theus-arsenal/rules/swift/hooks.md +0 -20
  297. package/vendor/theus-arsenal/rules/swift/patterns.md +0 -66
  298. package/vendor/theus-arsenal/rules/swift/security.md +0 -33
  299. package/vendor/theus-arsenal/rules/swift/testing.md +0 -45
  300. package/vendor/theus-arsenal/rules/typescript/coding-style.md +0 -199
  301. package/vendor/theus-arsenal/rules/typescript/hooks.md +0 -22
  302. package/vendor/theus-arsenal/rules/typescript/patterns.md +0 -52
  303. package/vendor/theus-arsenal/rules/typescript/security.md +0 -28
  304. package/vendor/theus-arsenal/rules/typescript/testing.md +0 -18
  305. package/vendor/theus-arsenal/rules/vue/coding-style.md +0 -54
  306. package/vendor/theus-arsenal/rules/vue/hooks.md +0 -45
  307. package/vendor/theus-arsenal/rules/vue/patterns.md +0 -56
  308. package/vendor/theus-arsenal/rules/vue/security.md +0 -46
  309. package/vendor/theus-arsenal/rules/vue/testing.md +0 -53
  310. package/vendor/theus-arsenal/rules/web/coding-style.md +0 -108
  311. package/vendor/theus-arsenal/rules/web/design-quality.md +0 -75
  312. package/vendor/theus-arsenal/rules/web/hooks.md +0 -141
  313. package/vendor/theus-arsenal/rules/web/patterns.md +0 -91
  314. package/vendor/theus-arsenal/rules/web/performance.md +0 -76
  315. package/vendor/theus-arsenal/rules/web/security.md +0 -69
  316. package/vendor/theus-arsenal/rules/web/testing.md +0 -67
  317. package/vendor/theus-arsenal/scripts/hooks/bash-hook-dispatcher.js +0 -192
  318. package/vendor/theus-arsenal/scripts/hooks/block-no-verify.js +0 -556
  319. package/vendor/theus-arsenal/scripts/hooks/check-console-log.js +0 -92
  320. package/vendor/theus-arsenal/scripts/hooks/check-hook-enabled.js +0 -16
  321. package/vendor/theus-arsenal/scripts/hooks/config-protection.js +0 -171
  322. package/vendor/theus-arsenal/scripts/hooks/design-quality-check.js +0 -132
  323. package/vendor/theus-arsenal/scripts/hooks/doc-file-warning.js +0 -110
  324. package/vendor/theus-arsenal/scripts/hooks/modo-seguro.js +0 -158
  325. package/vendor/theus-arsenal/scripts/hooks/notificacion-escritorio.js +0 -208
  326. package/vendor/theus-arsenal/scripts/hooks/plugin-hook-bootstrap.js +0 -280
  327. package/vendor/theus-arsenal/scripts/hooks/post-bash-command-log.js +0 -87
  328. package/vendor/theus-arsenal/scripts/hooks/post-bash-dispatcher.js +0 -24
  329. package/vendor/theus-arsenal/scripts/hooks/post-bash-pr-created.js +0 -60
  330. package/vendor/theus-arsenal/scripts/hooks/post-edit-accumulator.js +0 -94
  331. package/vendor/theus-arsenal/scripts/hooks/post-edit-console-warn.js +0 -54
  332. package/vendor/theus-arsenal/scripts/hooks/post-edit-format.js +0 -110
  333. package/vendor/theus-arsenal/scripts/hooks/post-edit-typecheck.js +0 -98
  334. package/vendor/theus-arsenal/scripts/hooks/pre-bash-commit-quality.js +0 -447
  335. package/vendor/theus-arsenal/scripts/hooks/pre-bash-dev-server-block.js +0 -232
  336. package/vendor/theus-arsenal/scripts/hooks/pre-bash-dispatcher.js +0 -27
  337. package/vendor/theus-arsenal/scripts/hooks/pre-compact.js +0 -101
  338. package/vendor/theus-arsenal/scripts/hooks/pretooluse-visible-output.js +0 -49
  339. package/vendor/theus-arsenal/scripts/hooks/quality-gate.js +0 -168
  340. package/vendor/theus-arsenal/scripts/hooks/run-with-flags.js +0 -271
  341. package/vendor/theus-arsenal/scripts/hooks/salud-mcp.js +0 -749
  342. package/vendor/theus-arsenal/scripts/hooks/seguimiento-costos.js +0 -161
  343. package/vendor/theus-arsenal/scripts/hooks/session-end.js +0 -340
  344. package/vendor/theus-arsenal/scripts/hooks/session-start.js +0 -906
  345. package/vendor/theus-arsenal/scripts/hooks/stop-format-typecheck.js +0 -263
  346. package/vendor/theus-arsenal/scripts/hooks/suggest-compact.js +0 -286
  347. package/vendor/theus-arsenal/scripts/hooks/theus-context-monitor.js +0 -289
  348. package/vendor/theus-arsenal/scripts/hooks/verificacion-factual.js +0 -1278
  349. package/vendor/theus-arsenal/scripts/lib/agent-data-home.js +0 -96
  350. package/vendor/theus-arsenal/scripts/lib/cost-estimate.js +0 -66
  351. package/vendor/theus-arsenal/scripts/lib/hook-flags.js +0 -79
  352. package/vendor/theus-arsenal/scripts/lib/llm-summary.js +0 -185
  353. package/vendor/theus-arsenal/scripts/lib/loopback-guard.js +0 -54
  354. package/vendor/theus-arsenal/scripts/lib/observer-sessions.js +0 -237
  355. package/vendor/theus-arsenal/scripts/lib/package-manager.d.ts +0 -120
  356. package/vendor/theus-arsenal/scripts/lib/package-manager.js +0 -434
  357. package/vendor/theus-arsenal/scripts/lib/path-safety.js +0 -86
  358. package/vendor/theus-arsenal/scripts/lib/plan-canvas/markdown.js +0 -285
  359. package/vendor/theus-arsenal/scripts/lib/plan-canvas/sdk.js +0 -238
  360. package/vendor/theus-arsenal/scripts/lib/plan-canvas/server.js +0 -534
  361. package/vendor/theus-arsenal/scripts/lib/plan-canvas/sessions.js +0 -274
  362. package/vendor/theus-arsenal/scripts/lib/plan-canvas/ui.js +0 -546
  363. package/vendor/theus-arsenal/scripts/lib/project-detect.js +0 -451
  364. package/vendor/theus-arsenal/scripts/lib/resolve-formatter.js +0 -193
  365. package/vendor/theus-arsenal/scripts/lib/resolve-theus-root.js +0 -101
  366. package/vendor/theus-arsenal/scripts/lib/session-aliases.d.ts +0 -138
  367. package/vendor/theus-arsenal/scripts/lib/session-aliases.js +0 -483
  368. package/vendor/theus-arsenal/scripts/lib/session-bridge.js +0 -155
  369. package/vendor/theus-arsenal/scripts/lib/session-manager.d.ts +0 -137
  370. package/vendor/theus-arsenal/scripts/lib/session-manager.js +0 -555
  371. package/vendor/theus-arsenal/scripts/lib/shell-split.js +0 -86
  372. package/vendor/theus-arsenal/scripts/lib/shell-substitution.js +0 -501
  373. package/vendor/theus-arsenal/scripts/lib/skill-evolution/dashboard.js +0 -414
  374. package/vendor/theus-arsenal/scripts/lib/skill-evolution/health.js +0 -285
  375. package/vendor/theus-arsenal/scripts/lib/skill-evolution/index.js +0 -22
  376. package/vendor/theus-arsenal/scripts/lib/skill-evolution/provenance.js +0 -200
  377. package/vendor/theus-arsenal/scripts/lib/skill-evolution/tracker.js +0 -157
  378. package/vendor/theus-arsenal/scripts/lib/skill-evolution/versioning.js +0 -246
  379. package/vendor/theus-arsenal/scripts/lib/transcript-context.js +0 -232
  380. package/vendor/theus-arsenal/scripts/lib/utils.d.ts +0 -205
  381. package/vendor/theus-arsenal/scripts/lib/utils.js +0 -658
  382. package/vendor/theus-arsenal/scripts/plan-canvas.js +0 -341
  383. package/vendor/theus-arsenal/scripts/setup-package-manager.js +0 -46
  384. package/vendor/theus-arsenal/scripts/skills-health.js +0 -143
  385. package/vendor/theus-arsenal/skills/a11y-frontend/SKILL.md +0 -444
  386. package/vendor/theus-arsenal/skills/accesibilidad/SKILL.md +0 -144
  387. package/vendor/theus-arsenal/skills/acelerador-throughput-datos/SKILL.md +0 -72
  388. package/vendor/theus-arsenal/skills/agente-scraper-datos/SKILL.md +0 -771
  389. package/vendor/theus-arsenal/skills/analisis-plataformas-competencia/SKILL.md +0 -137
  390. package/vendor/theus-arsenal/skills/api-x/SKILL.md +0 -233
  391. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/SKILL.md +0 -335
  392. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/observer-loop.sh +0 -374
  393. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/observer.md +0 -188
  394. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/session-guardian.sh +0 -153
  395. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/start-observer.sh +0 -253
  396. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/config.json +0 -8
  397. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/hooks/observe.sh +0 -594
  398. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/detect-project.sh +0 -325
  399. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/instinct-cli.py +0 -1918
  400. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/lib/arsenal-dir.sh +0 -23
  401. package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/test_parse_instinct.py +0 -1420
  402. package/vendor/theus-arsenal/skills/arquitectura-hexagonal/SKILL.md +0 -275
  403. package/vendor/theus-arsenal/skills/arquitectura-limpia-android/SKILL.md +0 -340
  404. package/vendor/theus-arsenal/skills/arquitectura-pipelines-recomendacion/SKILL.md +0 -112
  405. package/vendor/theus-arsenal/skills/atlas-datos-prediccion/SKILL.md +0 -53
  406. package/vendor/theus-arsenal/skills/auditoria-arquitectura-agentes/SKILL.md +0 -257
  407. package/vendor/theus-arsenal/skills/auditoria-produccion/SKILL.md +0 -180
  408. package/vendor/theus-arsenal/skills/auditoria-rutas-clic/SKILL.md +0 -243
  409. package/vendor/theus-arsenal/skills/autoevaluacion-agente/SKILL.md +0 -180
  410. package/vendor/theus-arsenal/skills/autoevaluacion-agente/examples/high-score-example.md +0 -89
  411. package/vendor/theus-arsenal/skills/autoevaluacion-agente/examples/low-score-example.md +0 -87
  412. package/vendor/theus-arsenal/skills/autoevaluacion-agente/references/evaluation-criteria.md +0 -71
  413. package/vendor/theus-arsenal/skills/autoevaluacion-agente/references/hook-integration.md +0 -90
  414. package/vendor/theus-arsenal/skills/autoevaluacion-agente/scripts/evaluate.py +0 -409
  415. package/vendor/theus-arsenal/skills/autoevaluacion-agente/templates/evaluation-report.md +0 -86
  416. package/vendor/theus-arsenal/skills/automatizacion-ssh-netmiko/SKILL.md +0 -176
  417. package/vendor/theus-arsenal/skills/base-datos-pubmed/SKILL.md +0 -174
  418. package/vendor/theus-arsenal/skills/base-datos-uspto/SKILL.md +0 -173
  419. package/vendor/theus-arsenal/skills/benchmark/SKILL.md +0 -92
  420. package/vendor/theus-arsenal/skills/bitacora-crecimiento/SKILL.md +0 -120
  421. package/vendor/theus-arsenal/skills/bucle-verificacion/SKILL.md +0 -125
  422. package/vendor/theus-arsenal/skills/buscar-primero/SKILL.md +0 -184
  423. package/vendor/theus-arsenal/skills/busqueda-exa/SKILL.md +0 -111
  424. package/vendor/theus-arsenal/skills/cache-por-hash/SKILL.md +0 -160
  425. package/vendor/theus-arsenal/skills/campana-marketing/SKILL.md +0 -118
  426. package/vendor/theus-arsenal/skills/capacidad-producto/SKILL.md +0 -138
  427. package/vendor/theus-arsenal/skills/cazador-vulnerabilidades/SKILL.md +0 -104
  428. package/vendor/theus-arsenal/skills/compactacion-estrategica/SKILL.md +0 -115
  429. package/vendor/theus-arsenal/skills/comparador-baskets-prediccion/SKILL.md +0 -69
  430. package/vendor/theus-arsenal/skills/compras-energia/SKILL.md +0 -206
  431. package/vendor/theus-arsenal/skills/concurrencia-swift-6-2/SKILL.md +0 -224
  432. package/vendor/theus-arsenal/skills/consejo/SKILL.md +0 -201
  433. package/vendor/theus-arsenal/skills/construccion-harness-agentes/SKILL.md +0 -78
  434. package/vendor/theus-arsenal/skills/constructor-conectores/SKILL.md +0 -119
  435. package/vendor/theus-arsenal/skills/constructor-equipos/SKILL.md +0 -169
  436. package/vendor/theus-arsenal/skills/consulta-documentacion/SKILL.md +0 -92
  437. package/vendor/theus-arsenal/skills/consultas-genomicas-gget/SKILL.md +0 -170
  438. package/vendor/theus-arsenal/skills/contacto-inversores/SKILL.md +0 -95
  439. package/vendor/theus-arsenal/skills/corrutinas-flows-kotlin/SKILL.md +0 -284
  440. package/vendor/theus-arsenal/skills/creacion-video-remotion/SKILL.md +0 -46
  441. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/3d.md +0 -86
  442. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/animations.md +0 -29
  443. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets/charts-bar-chart.tsx +0 -173
  444. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets/text-animations-typewriter.tsx +0 -100
  445. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets/text-animations-word-highlight.tsx +0 -108
  446. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets.md +0 -78
  447. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/audio.md +0 -172
  448. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/calculate-metadata.md +0 -104
  449. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/can-decode.md +0 -75
  450. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/charts.md +0 -58
  451. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/compositions.md +0 -146
  452. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/display-captions.md +0 -126
  453. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/extract-frames.md +0 -229
  454. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/fonts.md +0 -152
  455. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/get-audio-duration.md +0 -58
  456. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/get-video-dimensions.md +0 -68
  457. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/get-video-duration.md +0 -58
  458. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/gifs.md +0 -138
  459. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/images.md +0 -130
  460. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/import-srt-captions.md +0 -67
  461. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/lottie.md +0 -67
  462. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/measuring-dom-nodes.md +0 -34
  463. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/measuring-text.md +0 -143
  464. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/sequencing.md +0 -106
  465. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/tailwind.md +0 -11
  466. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/text-animations.md +0 -20
  467. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/timing.md +0 -179
  468. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/transcribe-captions.md +0 -19
  469. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/transitions.md +0 -122
  470. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/trimming.md +0 -52
  471. package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/videos.md +0 -171
  472. package/vendor/theus-arsenal/skills/cumplimiento-aduanero/SKILL.md +0 -270
  473. package/vendor/theus-arsenal/skills/cumplimiento-hipaa/SKILL.md +0 -78
  474. package/vendor/theus-arsenal/skills/datos-sensibles-salud/SKILL.md +0 -149
  475. package/vendor/theus-arsenal/skills/decimales-tokens-evm/SKILL.md +0 -128
  476. package/vendor/theus-arsenal/skills/decisiones-arquitectura/SKILL.md +0 -206
  477. package/vendor/theus-arsenal/skills/demos-ui/SKILL.md +0 -469
  478. package/vendor/theus-arsenal/skills/desarrollo-por-intencion/SKILL.md +0 -369
  479. package/vendor/theus-arsenal/skills/descubrimiento-marca/SKILL.md +0 -149
  480. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/10_proposito-porque.md +0 -42
  481. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/20_posicionamiento.md +0 -47
  482. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/30_audiencia-nicho.md +0 -53
  483. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/40_personalidad-arquetipo.md +0 -61
  484. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/50_voz-tono.md +0 -62
  485. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/60_narrativa-historia.md +0 -54
  486. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/70_tension-fundador.md +0 -50
  487. package/vendor/theus-arsenal/skills/descubrimiento-marca/references/90_SINTESIS.md +0 -133
  488. package/vendor/theus-arsenal/skills/descubrimiento-plugins-laravel/SKILL.md +0 -230
  489. package/vendor/theus-arsenal/skills/destilado-reglas/SKILL.md +0 -263
  490. package/vendor/theus-arsenal/skills/destilado-reglas/scripts/scan-rules.sh +0 -58
  491. package/vendor/theus-arsenal/skills/destilado-reglas/scripts/scan-skills.sh +0 -129
  492. package/vendor/theus-arsenal/skills/diagnostico-bgp/SKILL.md +0 -170
  493. package/vendor/theus-arsenal/skills/direccion-estetica/SKILL.md +0 -220
  494. package/vendor/theus-arsenal/skills/direccion-estetica/references/taxonomia-generos.md +0 -89
  495. package/vendor/theus-arsenal/skills/diseno-api/SKILL.md +0 -522
  496. package/vendor/theus-arsenal/skills/diseno-liquid-glass/SKILL.md +0 -282
  497. package/vendor/theus-arsenal/skills/e2e-escritorio-windows/SKILL.md +0 -879
  498. package/vendor/theus-arsenal/skills/edicion-video/SKILL.md +0 -289
  499. package/vendor/theus-arsenal/skills/enfoque-producto/SKILL.md +0 -91
  500. package/vendor/theus-arsenal/skills/entornos-flox/SKILL.md +0 -493
  501. package/vendor/theus-arsenal/skills/estandares-codigo/SKILL.md +0 -548
  502. package/vendor/theus-arsenal/skills/estandares-cpp/SKILL.md +0 -727
  503. package/vendor/theus-arsenal/skills/estandares-java/SKILL.md +0 -389
  504. package/vendor/theus-arsenal/skills/estilo-legado/SKILL.md +0 -149
  505. package/vendor/theus-arsenal/skills/estructura-informes-competencia/SKILL.md +0 -95
  506. package/vendor/theus-arsenal/skills/evaluacion-academica/SKILL.md +0 -165
  507. package/vendor/theus-arsenal/skills/explorador-skills/SKILL.md +0 -129
  508. package/vendor/theus-arsenal/skills/flujo-git/SKILL.md +0 -714
  509. package/vendor/theus-arsenal/skills/flujo-ingenieria-ml/SKILL.md +0 -343
  510. package/vendor/theus-arsenal/skills/flujo-tdd/SKILL.md +0 -584
  511. package/vendor/theus-arsenal/skills/forja-personas/SKILL.md +0 -298
  512. package/vendor/theus-arsenal/skills/forja-personas/gacha.py +0 -224
  513. package/vendor/theus-arsenal/skills/forja-personas/gacha.sh +0 -5
  514. package/vendor/theus-arsenal/skills/forja-personas/references/avatar-style.md +0 -123
  515. package/vendor/theus-arsenal/skills/forja-personas/references/boundary-rules.md +0 -53
  516. package/vendor/theus-arsenal/skills/forja-personas/references/error-handling.md +0 -53
  517. package/vendor/theus-arsenal/skills/forja-personas/references/identity-tension.md +0 -48
  518. package/vendor/theus-arsenal/skills/forja-personas/references/naming-system.md +0 -39
  519. package/vendor/theus-arsenal/skills/forja-personas/references/output-template.md +0 -166
  520. package/vendor/theus-arsenal/skills/fundamentos-animacion/SKILL.md +0 -296
  521. package/vendor/theus-arsenal/skills/generacion-iconos-ios/SKILL.md +0 -156
  522. package/vendor/theus-arsenal/skills/generacion-iconos-ios/scripts/generate_icons.swift +0 -258
  523. package/vendor/theus-arsenal/skills/generacion-iconos-ios/scripts/iconify_gen.sh +0 -235
  524. package/vendor/theus-arsenal/skills/gestion-excepciones-logisticas/SKILL.md +0 -208
  525. package/vendor/theus-arsenal/skills/gestion-transportistas/SKILL.md +0 -204
  526. package/vendor/theus-arsenal/skills/guia-adopcion-ml/SKILL.md +0 -64
  527. package/vendor/theus-arsenal/skills/harness-agente-autonomo/SKILL.md +0 -252
  528. package/vendor/theus-arsenal/skills/harness-eval-clinico/SKILL.md +0 -212
  529. package/vendor/theus-arsenal/skills/harness-evaluacion/SKILL.md +0 -296
  530. package/vendor/theus-arsenal/skills/harness-generador-evaluador/SKILL.md +0 -254
  531. package/vendor/theus-arsenal/skills/homelab-diseno-red/SKILL.md +0 -120
  532. package/vendor/theus-arsenal/skills/homelab-dns-pihole/SKILL.md +0 -264
  533. package/vendor/theus-arsenal/skills/homelab-preparacion-red/SKILL.md +0 -144
  534. package/vendor/theus-arsenal/skills/homelab-segmentacion-vlan/SKILL.md +0 -307
  535. package/vendor/theus-arsenal/skills/homelab-vpn-wireguard/SKILL.md +0 -299
  536. package/vendor/theus-arsenal/skills/ingenieria-agentica/SKILL.md +0 -96
  537. package/vendor/theus-arsenal/skills/inspeccion-animaciones-blender/SKILL.md +0 -164
  538. package/vendor/theus-arsenal/skills/instaladores-python/SKILL.md +0 -820
  539. package/vendor/theus-arsenal/skills/integracion-jira/SKILL.md +0 -307
  540. package/vendor/theus-arsenal/skills/inteligencia-leads/SKILL.md +0 -312
  541. package/vendor/theus-arsenal/skills/inteligencia-leads/agents/agente-enriquecimiento.md +0 -87
  542. package/vendor/theus-arsenal/skills/inteligencia-leads/agents/mapeador-mutuos.md +0 -76
  543. package/vendor/theus-arsenal/skills/inteligencia-leads/agents/puntuador-senales.md +0 -60
  544. package/vendor/theus-arsenal/skills/inteligencia-leads/agents/redactor-outreach.md +0 -102
  545. package/vendor/theus-arsenal/skills/inteligencia-mercados-prediccion/SKILL.md +0 -53
  546. package/vendor/theus-arsenal/skills/introspeccion-agente/SKILL.md +0 -150
  547. package/vendor/theus-arsenal/skills/inventario-skills/SKILL.md +0 -194
  548. package/vendor/theus-arsenal/skills/inventario-skills/scripts/quick-diff.sh +0 -87
  549. package/vendor/theus-arsenal/skills/inventario-skills/scripts/save-results.sh +0 -57
  550. package/vendor/theus-arsenal/skills/inventario-skills/scripts/scan.sh +0 -170
  551. package/vendor/theus-arsenal/skills/investigacion-mercado/SKILL.md +0 -87
  552. package/vendor/theus-arsenal/skills/investigacion-oraculos-prediccion/SKILL.md +0 -59
  553. package/vendor/theus-arsenal/skills/investigacion-profunda/SKILL.md +0 -161
  554. package/vendor/theus-arsenal/skills/keccak256-nodejs/SKILL.md +0 -100
  555. package/vendor/theus-arsenal/skills/libro-decisiones-recursivo/SKILL.md +0 -82
  556. package/vendor/theus-arsenal/skills/lienzo-planes/SKILL.md +0 -111
  557. package/vendor/theus-arsenal/skills/limpieza-configuracion/SKILL.md +0 -116
  558. package/vendor/theus-arsenal/skills/logistica-inversa-devoluciones/SKILL.md +0 -241
  559. package/vendor/theus-arsenal/skills/manejo-errores/SKILL.md +0 -375
  560. package/vendor/theus-arsenal/skills/materiales-inversores/SKILL.md +0 -101
  561. package/vendor/theus-arsenal/skills/memoria-por-proyecto/SKILL.md +0 -170
  562. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/forget.mjs +0 -44
  563. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/info.mjs +0 -24
  564. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/init.mjs +0 -152
  565. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/list.mjs +0 -40
  566. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/migrate.mjs +0 -214
  567. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/resume.mjs +0 -36
  568. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/save.mjs +0 -210
  569. package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/shared.mjs +0 -402
  570. package/vendor/theus-arsenal/skills/memoria-por-proyecto/hooks/session-start.mjs +0 -238
  571. package/vendor/theus-arsenal/skills/metodologia-benchmarks/SKILL.md +0 -131
  572. package/vendor/theus-arsenal/skills/migraciones-bd/SKILL.md +0 -430
  573. package/vendor/theus-arsenal/skills/modelos-fundacionales-en-dispositivo/SKILL.md +0 -244
  574. package/vendor/theus-arsenal/skills/modo-seguro/SKILL.md +0 -86
  575. package/vendor/theus-arsenal/skills/motion-avanzado/SKILL.md +0 -592
  576. package/vendor/theus-arsenal/skills/motor-de-contenido/SKILL.md +0 -136
  577. package/vendor/theus-arsenal/skills/no-conformidades-calidad/SKILL.md +0 -249
  578. package/vendor/theus-arsenal/skills/onboarding-codigo/SKILL.md +0 -244
  579. package/vendor/theus-arsenal/skills/operaciones-agentes-empresariales/SKILL.md +0 -51
  580. package/vendor/theus-arsenal/skills/operaciones-conocimiento/SKILL.md +0 -159
  581. package/vendor/theus-arsenal/skills/operaciones-correo/SKILL.md +0 -123
  582. package/vendor/theus-arsenal/skills/operaciones-facturacion/SKILL.md +0 -142
  583. package/vendor/theus-arsenal/skills/operaciones-flujo-proyectos/SKILL.md +0 -110
  584. package/vendor/theus-arsenal/skills/operaciones-github/SKILL.md +0 -143
  585. package/vendor/theus-arsenal/skills/operaciones-google-workspace/SKILL.md +0 -100
  586. package/vendor/theus-arsenal/skills/operaciones-investigacion/SKILL.md +0 -124
  587. package/vendor/theus-arsenal/skills/operaciones-mensajes/SKILL.md +0 -103
  588. package/vendor/theus-arsenal/skills/operaciones-terminal/SKILL.md +0 -110
  589. package/vendor/theus-arsenal/skills/optimizacion-benchmark/SKILL.md +0 -70
  590. package/vendor/theus-arsenal/skills/optimizacion-costos-llm/SKILL.md +0 -182
  591. package/vendor/theus-arsenal/skills/optimizador-conexiones/SKILL.md +0 -191
  592. package/vendor/theus-arsenal/skills/optimizador-paralelismo/SKILL.md +0 -75
  593. package/vendor/theus-arsenal/skills/optimizador-prompts/SKILL.md +0 -374
  594. package/vendor/theus-arsenal/skills/orq-agregar-funcionalidad/SKILL.md +0 -37
  595. package/vendor/theus-arsenal/skills/orq-cambiar-funcionalidad/SKILL.md +0 -36
  596. package/vendor/theus-arsenal/skills/orq-construir-mvp/SKILL.md +0 -38
  597. package/vendor/theus-arsenal/skills/orq-corregir-defecto/SKILL.md +0 -36
  598. package/vendor/theus-arsenal/skills/orq-pipeline/SKILL.md +0 -134
  599. package/vendor/theus-arsenal/skills/orq-refinar-codigo/SKILL.md +0 -49
  600. package/vendor/theus-arsenal/skills/orquestacion-equipos-agentes/SKILL.md +0 -117
  601. package/vendor/theus-arsenal/skills/pagos-agentes-x402/SKILL.md +0 -237
  602. package/vendor/theus-arsenal/skills/patrones-angular/SKILL.md +0 -153
  603. package/vendor/theus-arsenal/skills/patrones-angular/references/angular-animations.md +0 -160
  604. package/vendor/theus-arsenal/skills/patrones-angular/references/angular-aria.md +0 -410
  605. package/vendor/theus-arsenal/skills/patrones-angular/references/cli.md +0 -86
  606. package/vendor/theus-arsenal/skills/patrones-angular/references/component-harnesses.md +0 -59
  607. package/vendor/theus-arsenal/skills/patrones-angular/references/component-styling.md +0 -91
  608. package/vendor/theus-arsenal/skills/patrones-angular/references/components.md +0 -117
  609. package/vendor/theus-arsenal/skills/patrones-angular/references/creating-services.md +0 -97
  610. package/vendor/theus-arsenal/skills/patrones-angular/references/data-resolvers.md +0 -69
  611. package/vendor/theus-arsenal/skills/patrones-angular/references/define-routes.md +0 -67
  612. package/vendor/theus-arsenal/skills/patrones-angular/references/defining-providers.md +0 -72
  613. package/vendor/theus-arsenal/skills/patrones-angular/references/di-fundamentals.md +0 -120
  614. package/vendor/theus-arsenal/skills/patrones-angular/references/e2e-testing.md +0 -56
  615. package/vendor/theus-arsenal/skills/patrones-angular/references/effects.md +0 -83
  616. package/vendor/theus-arsenal/skills/patrones-angular/references/hierarchical-injectors.md +0 -43
  617. package/vendor/theus-arsenal/skills/patrones-angular/references/host-elements.md +0 -80
  618. package/vendor/theus-arsenal/skills/patrones-angular/references/injection-context.md +0 -63
  619. package/vendor/theus-arsenal/skills/patrones-angular/references/inputs.md +0 -101
  620. package/vendor/theus-arsenal/skills/patrones-angular/references/linked-signal.md +0 -59
  621. package/vendor/theus-arsenal/skills/patrones-angular/references/loading-strategies.md +0 -61
  622. package/vendor/theus-arsenal/skills/patrones-angular/references/mcp.md +0 -67
  623. package/vendor/theus-arsenal/skills/patrones-angular/references/navigate-to-routes.md +0 -69
  624. package/vendor/theus-arsenal/skills/patrones-angular/references/outputs.md +0 -86
  625. package/vendor/theus-arsenal/skills/patrones-angular/references/reactive-forms.md +0 -122
  626. package/vendor/theus-arsenal/skills/patrones-angular/references/rendering-strategies.md +0 -44
  627. package/vendor/theus-arsenal/skills/patrones-angular/references/resource.md +0 -77
  628. package/vendor/theus-arsenal/skills/patrones-angular/references/route-animations.md +0 -56
  629. package/vendor/theus-arsenal/skills/patrones-angular/references/route-guards.md +0 -52
  630. package/vendor/theus-arsenal/skills/patrones-angular/references/router-lifecycle.md +0 -45
  631. package/vendor/theus-arsenal/skills/patrones-angular/references/router-testing.md +0 -87
  632. package/vendor/theus-arsenal/skills/patrones-angular/references/show-routes-with-outlets.md +0 -68
  633. package/vendor/theus-arsenal/skills/patrones-angular/references/signal-forms.md +0 -795
  634. package/vendor/theus-arsenal/skills/patrones-angular/references/signals-overview.md +0 -94
  635. package/vendor/theus-arsenal/skills/patrones-angular/references/tailwind-css.md +0 -69
  636. package/vendor/theus-arsenal/skills/patrones-angular/references/template-driven-forms.md +0 -114
  637. package/vendor/theus-arsenal/skills/patrones-angular/references/testing-fundamentals.md +0 -65
  638. package/vendor/theus-arsenal/skills/patrones-animacion/SKILL.md +0 -432
  639. package/vendor/theus-arsenal/skills/patrones-backend/SKILL.md +0 -560
  640. package/vendor/theus-arsenal/skills/patrones-cdss-clinico/SKILL.md +0 -249
  641. package/vendor/theus-arsenal/skills/patrones-cisco-ios/SKILL.md +0 -148
  642. package/vendor/theus-arsenal/skills/patrones-clickhouse/SKILL.md +0 -443
  643. package/vendor/theus-arsenal/skills/patrones-compose-multiplatform/SKILL.md +0 -298
  644. package/vendor/theus-arsenal/skills/patrones-dart-flutter/SKILL.md +0 -566
  645. package/vendor/theus-arsenal/skills/patrones-despliegue/SKILL.md +0 -426
  646. package/vendor/theus-arsenal/skills/patrones-django/SKILL.md +0 -739
  647. package/vendor/theus-arsenal/skills/patrones-django-celery/SKILL.md +0 -456
  648. package/vendor/theus-arsenal/skills/patrones-docker/SKILL.md +0 -363
  649. package/vendor/theus-arsenal/skills/patrones-dotnet/SKILL.md +0 -321
  650. package/vendor/theus-arsenal/skills/patrones-emr-clinico/SKILL.md +0 -168
  651. package/vendor/theus-arsenal/skills/patrones-fastapi/SKILL.md +0 -513
  652. package/vendor/theus-arsenal/skills/patrones-frontend/SKILL.md +0 -655
  653. package/vendor/theus-arsenal/skills/patrones-go/SKILL.md +0 -674
  654. package/vendor/theus-arsenal/skills/patrones-jpa/SKILL.md +0 -156
  655. package/vendor/theus-arsenal/skills/patrones-kotlin/SKILL.md +0 -717
  656. package/vendor/theus-arsenal/skills/patrones-kotlin-exposed/SKILL.md +0 -724
  657. package/vendor/theus-arsenal/skills/patrones-kotlin-ktor/SKILL.md +0 -694
  658. package/vendor/theus-arsenal/skills/patrones-kubernetes/SKILL.md +0 -754
  659. package/vendor/theus-arsenal/skills/patrones-laravel/SKILL.md +0 -414
  660. package/vendor/theus-arsenal/skills/patrones-mcp/SKILL.md +0 -66
  661. package/vendor/theus-arsenal/skills/patrones-mysql/SKILL.md +0 -420
  662. package/vendor/theus-arsenal/skills/patrones-nestjs/SKILL.md +0 -229
  663. package/vendor/theus-arsenal/skills/patrones-nextjs/SKILL.md +0 -56
  664. package/vendor/theus-arsenal/skills/patrones-nuxt4/SKILL.md +0 -99
  665. package/vendor/theus-arsenal/skills/patrones-perl/SKILL.md +0 -508
  666. package/vendor/theus-arsenal/skills/patrones-postgres/SKILL.md +0 -141
  667. package/vendor/theus-arsenal/skills/patrones-prisma/SKILL.md +0 -399
  668. package/vendor/theus-arsenal/skills/patrones-python/SKILL.md +0 -750
  669. package/vendor/theus-arsenal/skills/patrones-pytorch/SKILL.md +0 -400
  670. package/vendor/theus-arsenal/skills/patrones-quarkus/SKILL.md +0 -729
  671. package/vendor/theus-arsenal/skills/patrones-react/SKILL.md +0 -339
  672. package/vendor/theus-arsenal/skills/patrones-react-native/SKILL.md +0 -325
  673. package/vendor/theus-arsenal/skills/patrones-redis/SKILL.md +0 -401
  674. package/vendor/theus-arsenal/skills/patrones-rust/SKILL.md +0 -504
  675. package/vendor/theus-arsenal/skills/patrones-springboot/SKILL.md +0 -314
  676. package/vendor/theus-arsenal/skills/patrones-swiftui/SKILL.md +0 -261
  677. package/vendor/theus-arsenal/skills/patrones-tinystruct/SKILL.md +0 -281
  678. package/vendor/theus-arsenal/skills/patrones-tinystruct/references/architecture.md +0 -90
  679. package/vendor/theus-arsenal/skills/patrones-tinystruct/references/data-handling.md +0 -60
  680. package/vendor/theus-arsenal/skills/patrones-tinystruct/references/database.md +0 -99
  681. package/vendor/theus-arsenal/skills/patrones-tinystruct/references/routing.md +0 -64
  682. package/vendor/theus-arsenal/skills/patrones-tinystruct/references/system-usage.md +0 -97
  683. package/vendor/theus-arsenal/skills/patrones-tinystruct/references/testing.md +0 -72
  684. package/vendor/theus-arsenal/skills/patrones-vite/SKILL.md +0 -449
  685. package/vendor/theus-arsenal/skills/patrones-vue/SKILL.md +0 -469
  686. package/vendor/theus-arsenal/skills/persistencia-actores-swift/SKILL.md +0 -148
  687. package/vendor/theus-arsenal/skills/pipeline-opensource/SKILL.md +0 -254
  688. package/vendor/theus-arsenal/skills/planificacion-demanda-inventario/SKILL.md +0 -236
  689. package/vendor/theus-arsenal/skills/planificador-trades-prediccion/SKILL.md +0 -60
  690. package/vendor/theus-arsenal/skills/plano-tecnico/SKILL.md +0 -102
  691. package/vendor/theus-arsenal/skills/presentaciones-html/SKILL.md +0 -189
  692. package/vendor/theus-arsenal/skills/presentaciones-html/STYLE_PRESETS.md +0 -330
  693. package/vendor/theus-arsenal/skills/presentaciones-html/animation-patterns.md +0 -122
  694. package/vendor/theus-arsenal/skills/presentaciones-html/html-template.md +0 -419
  695. package/vendor/theus-arsenal/skills/presentaciones-html/scripts/export-pdf.sh +0 -418
  696. package/vendor/theus-arsenal/skills/presentaciones-html/scripts/extract-pptx.py +0 -96
  697. package/vendor/theus-arsenal/skills/presentaciones-html/viewport-base.css +0 -153
  698. package/vendor/theus-arsenal/skills/presupuesto-contexto/SKILL.md +0 -263
  699. package/vendor/theus-arsenal/skills/procesamiento-documentos-nutrient/SKILL.md +0 -168
  700. package/vendor/theus-arsenal/skills/programacion-produccion/SKILL.md +0 -220
  701. package/vendor/theus-arsenal/skills/publicacion-cruzada/SKILL.md +0 -117
  702. package/vendor/theus-arsenal/skills/publicador-social/SKILL.md +0 -121
  703. package/vendor/theus-arsenal/skills/puerta-de-entrega/SKILL.md +0 -164
  704. package/vendor/theus-arsenal/skills/puerta-de-entrega/hooks/puerta-entrega.py +0 -242
  705. package/vendor/theus-arsenal/skills/pulir-interfaces/SKILL.md +0 -126
  706. package/vendor/theus-arsenal/skills/qa-navegador/SKILL.md +0 -103
  707. package/vendor/theus-arsenal/skills/ranking-grafo-social/SKILL.md +0 -153
  708. package/vendor/theus-arsenal/skills/recuperacion-iterativa/SKILL.md +0 -236
  709. package/vendor/theus-arsenal/skills/redaccion-articulos/SKILL.md +0 -81
  710. package/vendor/theus-arsenal/skills/regex-vs-llm/SKILL.md +0 -221
  711. package/vendor/theus-arsenal/skills/regresion-codigo-ia/SKILL.md +0 -388
  712. package/vendor/theus-arsenal/skills/rendimiento-react/SKILL.md +0 -567
  713. package/vendor/theus-arsenal/skills/revision-codigo-flutter-dart/SKILL.md +0 -442
  714. package/vendor/theus-arsenal/skills/revision-literatura-cientifica/SKILL.md +0 -191
  715. package/vendor/theus-arsenal/skills/revision-multiperspectiva/SKILL.md +0 -302
  716. package/vendor/theus-arsenal/skills/revision-riesgo-prediccion/SKILL.md +0 -56
  717. package/vendor/theus-arsenal/skills/revision-seguridad/SKILL.md +0 -505
  718. package/vendor/theus-arsenal/skills/revision-seguridad/cloud-infrastructure-security.md +0 -361
  719. package/vendor/theus-arsenal/skills/runtime-bun/SKILL.md +0 -83
  720. package/vendor/theus-arsenal/skills/salud-codigo-codescene/SKILL.md +0 -163
  721. package/vendor/theus-arsenal/skills/salud-interfaces-red/SKILL.md +0 -143
  722. package/vendor/theus-arsenal/skills/seguimiento-costos/SKILL.md +0 -122
  723. package/vendor/theus-arsenal/skills/seguridad-agentes-trading/SKILL.md +0 -145
  724. package/vendor/theus-arsenal/skills/seguridad-amm-defi/SKILL.md +0 -166
  725. package/vendor/theus-arsenal/skills/seguridad-django/SKILL.md +0 -648
  726. package/vendor/theus-arsenal/skills/seguridad-laravel/SKILL.md +0 -945
  727. package/vendor/theus-arsenal/skills/seguridad-perl/SKILL.md +0 -507
  728. package/vendor/theus-arsenal/skills/seguridad-quarkus/SKILL.md +0 -474
  729. package/vendor/theus-arsenal/skills/seguridad-springboot/SKILL.md +0 -279
  730. package/vendor/theus-arsenal/skills/seo/SKILL.md +0 -166
  731. package/vendor/theus-arsenal/skills/sistema-diseno/SKILL.md +0 -81
  732. package/vendor/theus-arsenal/skills/sistema-operativo-agentico/SKILL.md +0 -375
  733. package/vendor/theus-arsenal/skills/sistemas-latencia-critica/SKILL.md +0 -65
  734. package/vendor/theus-arsenal/skills/tdd-django/SKILL.md +0 -735
  735. package/vendor/theus-arsenal/skills/tdd-laravel/SKILL.md +0 -673
  736. package/vendor/theus-arsenal/skills/tdd-quarkus/SKILL.md +0 -817
  737. package/vendor/theus-arsenal/skills/tdd-springboot/SKILL.md +0 -165
  738. package/vendor/theus-arsenal/skills/testing-cpp/SKILL.md +0 -328
  739. package/vendor/theus-arsenal/skills/testing-csharp/SKILL.md +0 -321
  740. package/vendor/theus-arsenal/skills/testing-e2e/SKILL.md +0 -325
  741. package/vendor/theus-arsenal/skills/testing-go/SKILL.md +0 -719
  742. package/vendor/theus-arsenal/skills/testing-kotlin/SKILL.md +0 -829
  743. package/vendor/theus-arsenal/skills/testing-perl/SKILL.md +0 -479
  744. package/vendor/theus-arsenal/skills/testing-protocolos-di-swift/SKILL.md +0 -196
  745. package/vendor/theus-arsenal/skills/testing-python/SKILL.md +0 -815
  746. package/vendor/theus-arsenal/skills/testing-react/SKILL.md +0 -421
  747. package/vendor/theus-arsenal/skills/testing-rust/SKILL.md +0 -506
  748. package/vendor/theus-arsenal/skills/tours-de-codigo/SKILL.md +0 -252
  749. package/vendor/theus-arsenal/skills/traduccion-documentos-visado/SKILL.md +0 -121
  750. package/vendor/theus-arsenal/skills/ui-a-vue/SKILL.md +0 -141
  751. package/vendor/theus-arsenal/skills/validacion-config-red/SKILL.md +0 -211
  752. package/vendor/theus-arsenal/skills/verificacion-django/SKILL.md +0 -470
  753. package/vendor/theus-arsenal/skills/verificacion-factual/SKILL.md +0 -142
  754. package/vendor/theus-arsenal/skills/verificacion-laravel/SKILL.md +0 -184
  755. package/vendor/theus-arsenal/skills/verificacion-quarkus/SKILL.md +0 -485
  756. package/vendor/theus-arsenal/skills/verificacion-springboot/SKILL.md +0 -237
  757. package/vendor/theus-arsenal/skills/videodb/SKILL.md +0 -374
  758. package/vendor/theus-arsenal/skills/videodb/reference/api-reference.md +0 -550
  759. package/vendor/theus-arsenal/skills/videodb/reference/capture-reference.md +0 -407
  760. package/vendor/theus-arsenal/skills/videodb/reference/capture.md +0 -101
  761. package/vendor/theus-arsenal/skills/videodb/reference/editor.md +0 -443
  762. package/vendor/theus-arsenal/skills/videodb/reference/generative.md +0 -331
  763. package/vendor/theus-arsenal/skills/videodb/reference/rtstream-reference.md +0 -564
  764. package/vendor/theus-arsenal/skills/videodb/reference/rtstream.md +0 -65
  765. package/vendor/theus-arsenal/skills/videodb/reference/search.md +0 -230
  766. package/vendor/theus-arsenal/skills/videodb/reference/streaming.md +0 -406
  767. package/vendor/theus-arsenal/skills/videodb/reference/use-cases.md +0 -118
  768. package/vendor/theus-arsenal/skills/videodb/scripts/ws_listener.py +0 -279
  769. package/vendor/theus-arsenal/skills/videos-manim/SKILL.md +0 -91
  770. package/vendor/theus-arsenal/skills/videos-manim/assets/network_graph_scene.py +0 -52
  771. package/vendor/theus-arsenal/skills/vigilancia-canary/SKILL.md +0 -108
  772. package/vendor/theus-arsenal/skills/voz-de-marca/SKILL.md +0 -106
@@ -1,1420 +0,0 @@
1
- """Tests del instinct-cli.py de aprendizaje-continuo-v2
2
-
3
- Cubre:
4
- - parse_instinct_file() — preservación de contenido, casos límite
5
- - _validate_file_path() — bloqueo de path traversal
6
- - detect_project() — detección de proyecto con git/env simulados
7
- - load_all_instincts() — carga desde dirs de proyecto + globales, dedup
8
- - _load_instincts_from_dir() — recorrido de directorios
9
- - cmd_projects() — listado de proyectos desde el registro
10
- - cmd_status() — presentación del estado
11
- - _promote_specific() — promoción de un instinto individual
12
- - _promote_auto() — autopromoción entre proyectos
13
- """
14
-
15
- import importlib.util
16
- import io
17
- import json
18
- import os
19
- import sys
20
- from pathlib import Path
21
- from types import SimpleNamespace
22
-
23
- import pytest
24
-
25
- # Cargar instinct-cli.py (el nombre con guion requiere importlib)
26
- _spec = importlib.util.spec_from_file_location(
27
- "instinct_cli",
28
- os.path.join(os.path.dirname(__file__), "instinct-cli.py"),
29
- )
30
- _mod = importlib.util.module_from_spec(_spec)
31
- _spec.loader.exec_module(_mod)
32
-
33
- parse_instinct_file = _mod.parse_instinct_file
34
- _validate_file_path = _mod._validate_file_path
35
- detect_project = _mod.detect_project
36
- load_all_instincts = _mod.load_all_instincts
37
- load_project_only_instincts = _mod.load_project_only_instincts
38
- _load_instincts_from_dir = _mod._load_instincts_from_dir
39
- cmd_status = _mod.cmd_status
40
- cmd_projects = _mod.cmd_projects
41
- _promote_specific = _mod._promote_specific
42
- _promote_auto = _mod._promote_auto
43
- _find_cross_project_instincts = _mod._find_cross_project_instincts
44
- load_registry = _mod.load_registry
45
- _validate_instinct_id = _mod._validate_instinct_id
46
- _validate_import_url = _mod._validate_import_url
47
- _update_registry = _mod._update_registry
48
- _write_registry = _mod._write_registry
49
- _remove_project_storage = _mod._remove_project_storage
50
- _confidence_bar = _mod._confidence_bar
51
-
52
-
53
- # ─────────────────────────────────────────────
54
- # Fixtures
55
- # ─────────────────────────────────────────────
56
-
57
- SAMPLE_INSTINCT_YAML = """\
58
- ---
59
- id: test-instinct
60
- trigger: "when writing tests"
61
- confidence: 0.8
62
- domain: testing
63
- scope: project
64
- ---
65
-
66
- ## Action
67
- Always write tests first.
68
-
69
- ## Evidence
70
- TDD leads to better design.
71
- """
72
-
73
- SAMPLE_GLOBAL_INSTINCT_YAML = """\
74
- ---
75
- id: global-instinct
76
- trigger: "always"
77
- confidence: 0.9
78
- domain: security
79
- scope: global
80
- ---
81
-
82
- ## Action
83
- Validate all user input.
84
- """
85
-
86
-
87
- @pytest.fixture
88
- def project_tree(tmp_path):
89
- """Create a realistic project directory tree for testing."""
90
- arsenal = tmp_path / ".theus" / "arsenal"
91
- projects_dir = arsenal / "projects"
92
- global_personal = arsenal / "instincts" / "personal"
93
- global_inherited = arsenal / "instincts" / "inherited"
94
- global_evolved = arsenal / "evolved"
95
-
96
- for d in [
97
- global_personal, global_inherited,
98
- global_evolved / "skills", global_evolved / "commands", global_evolved / "agents",
99
- projects_dir,
100
- ]:
101
- d.mkdir(parents=True, exist_ok=True)
102
-
103
- return {
104
- "root": tmp_path,
105
- "arsenal": arsenal,
106
- "projects_dir": projects_dir,
107
- "global_personal": global_personal,
108
- "global_inherited": global_inherited,
109
- "global_evolved": global_evolved,
110
- "registry_file": arsenal / "projects.json",
111
- }
112
-
113
-
114
- @pytest.fixture
115
- def patch_globals(project_tree, monkeypatch):
116
- """Patch module-level globals to use tmp_path-based directories."""
117
- monkeypatch.setattr(_mod, "ARSENAL_DIR", project_tree["arsenal"])
118
- monkeypatch.setattr(_mod, "PROJECTS_DIR", project_tree["projects_dir"])
119
- monkeypatch.setattr(_mod, "REGISTRY_FILE", project_tree["registry_file"])
120
- monkeypatch.setattr(_mod, "GLOBAL_PERSONAL_DIR", project_tree["global_personal"])
121
- monkeypatch.setattr(_mod, "GLOBAL_INHERITED_DIR", project_tree["global_inherited"])
122
- monkeypatch.setattr(_mod, "GLOBAL_EVOLVED_DIR", project_tree["global_evolved"])
123
- monkeypatch.setattr(_mod, "GLOBAL_OBSERVATIONS_FILE", project_tree["arsenal"] / "observations.jsonl")
124
- return project_tree
125
-
126
-
127
- def _make_project(tree, pid="abc123", pname="test-project"):
128
- """Create project directory structure and return a project dict."""
129
- project_dir = tree["projects_dir"] / pid
130
- personal_dir = project_dir / "instincts" / "personal"
131
- inherited_dir = project_dir / "instincts" / "inherited"
132
- for d in [personal_dir, inherited_dir,
133
- project_dir / "evolved" / "skills",
134
- project_dir / "evolved" / "commands",
135
- project_dir / "evolved" / "agents",
136
- project_dir / "observations.archive"]:
137
- d.mkdir(parents=True, exist_ok=True)
138
-
139
- return {
140
- "id": pid,
141
- "name": pname,
142
- "root": str(tree["root"] / "fake-repo"),
143
- "remote": "https://github.com/test/test-project.git",
144
- "project_dir": project_dir,
145
- "instincts_personal": personal_dir,
146
- "instincts_inherited": inherited_dir,
147
- "evolved_dir": project_dir / "evolved",
148
- "observations_file": project_dir / "observations.jsonl",
149
- }
150
-
151
-
152
- # ─────────────────────────────────────────────
153
- # parse_instinct_file tests
154
- # ─────────────────────────────────────────────
155
-
156
- MULTI_SECTION = """\
157
- ---
158
- id: instinct-a
159
- trigger: "when coding"
160
- confidence: 0.9
161
- domain: general
162
- ---
163
-
164
- ## Action
165
- Do thing A.
166
-
167
- ## Examples
168
- - Example A1
169
-
170
- ---
171
- id: instinct-b
172
- trigger: "when testing"
173
- confidence: 0.7
174
- domain: testing
175
- ---
176
-
177
- ## Action
178
- Do thing B.
179
- """
180
-
181
-
182
- def test_multiple_instincts_preserve_content():
183
- result = parse_instinct_file(MULTI_SECTION)
184
- assert len(result) == 2
185
- assert "Do thing A." in result[0]["content"]
186
- assert "Example A1" in result[0]["content"]
187
- assert "Do thing B." in result[1]["content"]
188
-
189
-
190
- def test_single_instinct_preserves_content():
191
- content = """\
192
- ---
193
- id: solo
194
- trigger: "when reviewing"
195
- confidence: 0.8
196
- domain: review
197
- ---
198
-
199
- ## Action
200
- Check for security issues.
201
-
202
- ## Evidence
203
- Prevents vulnerabilities.
204
- """
205
- result = parse_instinct_file(content)
206
- assert len(result) == 1
207
- assert "Check for security issues." in result[0]["content"]
208
- assert "Prevents vulnerabilities." in result[0]["content"]
209
-
210
-
211
- def test_empty_content_no_error():
212
- content = """\
213
- ---
214
- id: empty
215
- trigger: "placeholder"
216
- confidence: 0.5
217
- domain: general
218
- ---
219
- """
220
- result = parse_instinct_file(content)
221
- assert len(result) == 1
222
- assert result[0]["content"] == ""
223
-
224
-
225
- def test_parse_no_id_skipped():
226
- """Instincts without an 'id' field should be silently dropped."""
227
- content = """\
228
- ---
229
- trigger: "when doing nothing"
230
- confidence: 0.5
231
- ---
232
-
233
- No id here.
234
- """
235
- result = parse_instinct_file(content)
236
- assert len(result) == 0
237
-
238
-
239
- def test_parse_confidence_is_float():
240
- content = """\
241
- ---
242
- id: float-check
243
- trigger: "when parsing"
244
- confidence: 0.42
245
- domain: general
246
- ---
247
-
248
- Body.
249
- """
250
- result = parse_instinct_file(content)
251
- assert isinstance(result[0]["confidence"], float)
252
- assert result[0]["confidence"] == pytest.approx(0.42)
253
-
254
-
255
- def test_parse_trigger_strips_quotes():
256
- content = """\
257
- ---
258
- id: quote-check
259
- trigger: "when quoting"
260
- confidence: 0.5
261
- domain: general
262
- ---
263
-
264
- Body.
265
- """
266
- result = parse_instinct_file(content)
267
- assert result[0]["trigger"] == "when quoting"
268
-
269
-
270
- def test_parse_empty_string():
271
- result = parse_instinct_file("")
272
- assert result == []
273
-
274
-
275
- def test_parse_garbage_input():
276
- result = parse_instinct_file("this is not yaml at all\nno frontmatter here")
277
- assert result == []
278
-
279
-
280
- # ─────────────────────────────────────────────
281
- # _validate_file_path tests
282
- # ─────────────────────────────────────────────
283
-
284
- def test_validate_normal_path(tmp_path):
285
- test_file = tmp_path / "test.yaml"
286
- test_file.write_text("hello")
287
- result = _validate_file_path(str(test_file), must_exist=True)
288
- assert result == test_file.resolve()
289
-
290
-
291
- def test_validate_rejects_etc():
292
- with pytest.raises(ValueError, match="system directory"):
293
- _validate_file_path("/etc/passwd")
294
-
295
-
296
- def test_validate_rejects_var_log():
297
- with pytest.raises(ValueError, match="system directory"):
298
- _validate_file_path("/var/log/syslog")
299
-
300
-
301
- def test_validate_rejects_usr():
302
- with pytest.raises(ValueError, match="system directory"):
303
- _validate_file_path("/usr/local/bin/foo")
304
-
305
-
306
- def test_validate_rejects_proc():
307
- with pytest.raises(ValueError, match="system directory"):
308
- _validate_file_path("/proc/self/status")
309
-
310
-
311
- def test_validate_must_exist_fails(tmp_path):
312
- with pytest.raises(ValueError, match="does not exist"):
313
- _validate_file_path(str(tmp_path / "nonexistent.yaml"), must_exist=True)
314
-
315
-
316
- def test_validate_home_expansion(tmp_path):
317
- """Tilde expansion should work."""
318
- result = _validate_file_path("~/test.yaml")
319
- assert str(result).startswith(str(Path.home()))
320
-
321
-
322
- def test_validate_relative_path(tmp_path, monkeypatch):
323
- """Relative paths should be resolved."""
324
- monkeypatch.chdir(tmp_path)
325
- test_file = tmp_path / "rel.yaml"
326
- test_file.write_text("content")
327
- result = _validate_file_path("rel.yaml", must_exist=True)
328
- assert result == test_file.resolve()
329
-
330
-
331
- def test_validate_import_url_rejects_http():
332
- """Remote imports should not downgrade to plaintext HTTP."""
333
- with pytest.raises(ValueError, match="require https"):
334
- _validate_import_url("http://example.com/instincts.yaml")
335
-
336
-
337
- def test_validate_import_url_rejects_private_hosts(monkeypatch):
338
- """Remote imports should not resolve to private or loopback addresses."""
339
- monkeypatch.setattr(
340
- _mod.socket,
341
- "getaddrinfo",
342
- lambda *args, **kwargs: [(None, None, None, None, ("127.0.0.1", 443))],
343
- )
344
- with pytest.raises(ValueError, match="non-public address"):
345
- _validate_import_url("https://example.com/instincts.yaml")
346
-
347
-
348
- def test_validate_import_url_allows_public_https(monkeypatch):
349
- monkeypatch.setattr(
350
- _mod.socket,
351
- "getaddrinfo",
352
- lambda *args, **kwargs: [(None, None, None, None, ("93.184.216.34", 443))],
353
- )
354
- assert _validate_import_url("https://example.com/instincts.yaml") == "https://example.com/instincts.yaml"
355
-
356
-
357
- # ─────────────────────────────────────────────
358
- # detect_project tests
359
- # ─────────────────────────────────────────────
360
-
361
- def test_detect_project_global_fallback(patch_globals, monkeypatch):
362
- """When no git and no env var, should return global project."""
363
- monkeypatch.delenv("THEUS_PROJECT_DIR", raising=False)
364
-
365
- # Mock subprocess.run to simulate git not available
366
- def mock_run(*args, **kwargs):
367
- raise FileNotFoundError("git not found")
368
-
369
- monkeypatch.setattr("subprocess.run", mock_run)
370
-
371
- project = detect_project()
372
- assert project["id"] == "global"
373
- assert project["name"] == "global"
374
-
375
-
376
- def test_detect_project_from_env(patch_globals, monkeypatch, tmp_path):
377
- """THEUS_PROJECT_DIR env var should be used as project root."""
378
- fake_repo = tmp_path / "my-repo"
379
- fake_repo.mkdir()
380
- monkeypatch.setenv("THEUS_PROJECT_DIR", str(fake_repo))
381
-
382
- # Mock git remote to return a URL
383
- def mock_run(cmd, **kwargs):
384
- if "rev-parse" in cmd:
385
- return SimpleNamespace(returncode=0, stdout=str(fake_repo) + "\n", stderr="")
386
- if "get-url" in cmd:
387
- return SimpleNamespace(returncode=0, stdout="https://github.com/test/my-repo.git\n", stderr="")
388
- return SimpleNamespace(returncode=1, stdout="", stderr="")
389
-
390
- monkeypatch.setattr("subprocess.run", mock_run)
391
-
392
- project = detect_project()
393
- assert project["id"] != "global"
394
- assert project["name"] == "my-repo"
395
-
396
-
397
- def test_detect_project_git_timeout(patch_globals, monkeypatch):
398
- """Git timeout should fall through to global."""
399
- monkeypatch.delenv("THEUS_PROJECT_DIR", raising=False)
400
- import subprocess as sp
401
-
402
- def mock_run(cmd, **kwargs):
403
- raise sp.TimeoutExpired(cmd, 5)
404
-
405
- monkeypatch.setattr("subprocess.run", mock_run)
406
-
407
- project = detect_project()
408
- assert project["id"] == "global"
409
-
410
-
411
- def test_detect_project_creates_directories(patch_globals, monkeypatch, tmp_path):
412
- """detect_project should create the project dir structure."""
413
- fake_repo = tmp_path / "structured-repo"
414
- fake_repo.mkdir()
415
- monkeypatch.setenv("THEUS_PROJECT_DIR", str(fake_repo))
416
-
417
- def mock_run(cmd, **kwargs):
418
- if "rev-parse" in cmd:
419
- return SimpleNamespace(returncode=0, stdout=str(fake_repo) + "\n", stderr="")
420
- if "get-url" in cmd:
421
- return SimpleNamespace(returncode=1, stdout="", stderr="no remote")
422
- return SimpleNamespace(returncode=1, stdout="", stderr="")
423
-
424
- monkeypatch.setattr("subprocess.run", mock_run)
425
-
426
- project = detect_project()
427
- assert project["instincts_personal"].exists()
428
- assert project["instincts_inherited"].exists()
429
- assert (project["evolved_dir"] / "skills").exists()
430
-
431
-
432
- # ─────────────────────────────────────────────
433
- # _load_instincts_from_dir tests
434
- # ─────────────────────────────────────────────
435
-
436
- def test_load_from_empty_dir(tmp_path):
437
- result = _load_instincts_from_dir(tmp_path, "personal", "project")
438
- assert result == []
439
-
440
-
441
- def test_load_from_nonexistent_dir(tmp_path):
442
- result = _load_instincts_from_dir(tmp_path / "does-not-exist", "personal", "project")
443
- assert result == []
444
-
445
-
446
- def test_load_annotates_metadata(tmp_path):
447
- """Loaded instincts should have _source_file, _source_type, _scope_label."""
448
- yaml_file = tmp_path / "test.yaml"
449
- yaml_file.write_text(SAMPLE_INSTINCT_YAML)
450
-
451
- result = _load_instincts_from_dir(tmp_path, "personal", "project")
452
- assert len(result) == 1
453
- assert result[0]["_source_file"] == str(yaml_file)
454
- assert result[0]["_source_type"] == "personal"
455
- assert result[0]["_scope_label"] == "project"
456
-
457
-
458
- def test_load_defaults_scope_from_label(tmp_path):
459
- """If an instinct has no 'scope' in frontmatter, it should default to scope_label."""
460
- no_scope_yaml = """\
461
- ---
462
- id: no-scope
463
- trigger: "test"
464
- confidence: 0.5
465
- domain: general
466
- ---
467
-
468
- Body.
469
- """
470
- (tmp_path / "no-scope.yaml").write_text(no_scope_yaml)
471
- result = _load_instincts_from_dir(tmp_path, "inherited", "global")
472
- assert result[0]["scope"] == "global"
473
-
474
-
475
- def test_load_preserves_explicit_scope(tmp_path):
476
- """If frontmatter has explicit scope, it should be preserved."""
477
- yaml_file = tmp_path / "test.yaml"
478
- yaml_file.write_text(SAMPLE_INSTINCT_YAML)
479
-
480
- result = _load_instincts_from_dir(tmp_path, "personal", "global")
481
- # Frontmatter says scope: project, scope_label is global
482
- # The explicit scope should be preserved (not overwritten)
483
- assert result[0]["scope"] == "project"
484
-
485
-
486
- def test_load_handles_corrupt_file(tmp_path, capsys):
487
- """Corrupt YAML files should be warned about but not crash."""
488
- # A file that will cause parse_instinct_file to return empty
489
- (tmp_path / "good.yaml").write_text(SAMPLE_INSTINCT_YAML)
490
- (tmp_path / "bad.yaml").write_text("not yaml\nno frontmatter")
491
-
492
- result = _load_instincts_from_dir(tmp_path, "personal", "project")
493
- # bad.yaml has no valid instincts (no id), so only good.yaml contributes
494
- assert len(result) == 1
495
- assert result[0]["id"] == "test-instinct"
496
-
497
-
498
- def test_load_supports_yml_extension(tmp_path):
499
- yml_file = tmp_path / "test.yml"
500
- yml_file.write_text(SAMPLE_INSTINCT_YAML)
501
-
502
- result = _load_instincts_from_dir(tmp_path, "personal", "project")
503
- ids = {i["id"] for i in result}
504
- assert "test-instinct" in ids
505
-
506
-
507
- def test_load_supports_md_extension(tmp_path):
508
- md_file = tmp_path / "legacy-instinct.md"
509
- md_file.write_text(SAMPLE_INSTINCT_YAML)
510
-
511
- result = _load_instincts_from_dir(tmp_path, "personal", "project")
512
- ids = {i["id"] for i in result}
513
- assert "test-instinct" in ids
514
-
515
-
516
- def test_load_instincts_from_dir_uses_utf8_encoding(tmp_path, monkeypatch):
517
- yaml_file = tmp_path / "test.yaml"
518
- yaml_file.write_text("placeholder")
519
- calls = []
520
-
521
- def fake_read_text(self, *args, **kwargs):
522
- calls.append(kwargs.get("encoding"))
523
- return SAMPLE_INSTINCT_YAML
524
-
525
- monkeypatch.setattr(Path, "read_text", fake_read_text)
526
- result = _load_instincts_from_dir(tmp_path, "personal", "project")
527
- assert result[0]["id"] == "test-instinct"
528
- assert calls == ["utf-8"]
529
-
530
-
531
- # ─────────────────────────────────────────────
532
- # load_all_instincts tests
533
- # ─────────────────────────────────────────────
534
-
535
- def test_load_all_project_and_global(patch_globals):
536
- """Should load from both project and global directories."""
537
- tree = patch_globals
538
- project = _make_project(tree)
539
-
540
- # Write a project instinct
541
- (project["instincts_personal"] / "proj.yaml").write_text(SAMPLE_INSTINCT_YAML)
542
- # Write a global instinct
543
- (tree["global_personal"] / "glob.yaml").write_text(SAMPLE_GLOBAL_INSTINCT_YAML)
544
-
545
- result = load_all_instincts(project)
546
- ids = {i["id"] for i in result}
547
- assert "test-instinct" in ids
548
- assert "global-instinct" in ids
549
-
550
-
551
- def test_load_all_project_overrides_global(patch_globals):
552
- """When project and global have same ID, project wins."""
553
- tree = patch_globals
554
- project = _make_project(tree)
555
-
556
- # Same ID but different confidence
557
- proj_yaml = SAMPLE_INSTINCT_YAML.replace("id: test-instinct", "id: shared-id")
558
- proj_yaml = proj_yaml.replace("confidence: 0.8", "confidence: 0.9")
559
- glob_yaml = SAMPLE_GLOBAL_INSTINCT_YAML.replace("id: global-instinct", "id: shared-id")
560
- glob_yaml = glob_yaml.replace("confidence: 0.9", "confidence: 0.3")
561
-
562
- (project["instincts_personal"] / "shared.yaml").write_text(proj_yaml)
563
- (tree["global_personal"] / "shared.yaml").write_text(glob_yaml)
564
-
565
- result = load_all_instincts(project)
566
- shared = [i for i in result if i["id"] == "shared-id"]
567
- assert len(shared) == 1
568
- assert shared[0]["_scope_label"] == "project"
569
- assert shared[0]["confidence"] == 0.9
570
-
571
-
572
- def test_load_all_global_only(patch_globals):
573
- """Global project should only load global instincts."""
574
- tree = patch_globals
575
- (tree["global_personal"] / "glob.yaml").write_text(SAMPLE_GLOBAL_INSTINCT_YAML)
576
-
577
- global_project = {
578
- "id": "global",
579
- "name": "global",
580
- "root": "",
581
- "project_dir": tree["arsenal"],
582
- "instincts_personal": tree["global_personal"],
583
- "instincts_inherited": tree["global_inherited"],
584
- "evolved_dir": tree["global_evolved"],
585
- "observations_file": tree["arsenal"] / "observations.jsonl",
586
- }
587
-
588
- result = load_all_instincts(global_project)
589
- assert len(result) == 1
590
- assert result[0]["id"] == "global-instinct"
591
-
592
-
593
- def test_load_project_only_excludes_global(patch_globals):
594
- """load_project_only_instincts should NOT include global instincts."""
595
- tree = patch_globals
596
- project = _make_project(tree)
597
-
598
- (project["instincts_personal"] / "proj.yaml").write_text(SAMPLE_INSTINCT_YAML)
599
- (tree["global_personal"] / "glob.yaml").write_text(SAMPLE_GLOBAL_INSTINCT_YAML)
600
-
601
- result = load_project_only_instincts(project)
602
- ids = {i["id"] for i in result}
603
- assert "test-instinct" in ids
604
- assert "global-instinct" not in ids
605
-
606
-
607
- def test_load_project_only_global_fallback_loads_global(patch_globals):
608
- """Global fallback should return global instincts for project-only queries."""
609
- tree = patch_globals
610
- (tree["global_personal"] / "glob.yaml").write_text(SAMPLE_GLOBAL_INSTINCT_YAML)
611
-
612
- global_project = {
613
- "id": "global",
614
- "name": "global",
615
- "root": "",
616
- "project_dir": tree["arsenal"],
617
- "instincts_personal": tree["global_personal"],
618
- "instincts_inherited": tree["global_inherited"],
619
- "evolved_dir": tree["global_evolved"],
620
- "observations_file": tree["arsenal"] / "observations.jsonl",
621
- }
622
-
623
- result = load_project_only_instincts(global_project)
624
- assert len(result) == 1
625
- assert result[0]["id"] == "global-instinct"
626
-
627
-
628
- def test_load_all_empty(patch_globals):
629
- """No instincts at all should return empty list."""
630
- tree = patch_globals
631
- project = _make_project(tree)
632
-
633
- result = load_all_instincts(project)
634
- assert result == []
635
-
636
-
637
- # ─────────────────────────────────────────────
638
- # cmd_status tests
639
- # ─────────────────────────────────────────────
640
-
641
- def test_cmd_status_no_instincts(patch_globals, monkeypatch, capsys):
642
- """Status with no instincts should print fallback message."""
643
- tree = patch_globals
644
- project = _make_project(tree)
645
- monkeypatch.setattr(_mod, "detect_project", lambda: project)
646
-
647
- args = SimpleNamespace()
648
- ret = cmd_status(args)
649
- assert ret == 0
650
- out = capsys.readouterr().out
651
- assert "No se encontraron instintos." in out
652
-
653
-
654
- def test_cmd_status_with_instincts(patch_globals, monkeypatch, capsys):
655
- """Status should show project and global instinct counts."""
656
- tree = patch_globals
657
- project = _make_project(tree)
658
- monkeypatch.setattr(_mod, "detect_project", lambda: project)
659
-
660
- (project["instincts_personal"] / "proj.yaml").write_text(SAMPLE_INSTINCT_YAML)
661
- (tree["global_personal"] / "glob.yaml").write_text(SAMPLE_GLOBAL_INSTINCT_YAML)
662
-
663
- args = SimpleNamespace()
664
- ret = cmd_status(args)
665
- assert ret == 0
666
- out = capsys.readouterr().out
667
- assert "ESTADO DE INSTINTOS" in out
668
- assert "Instintos del proyecto: 1" in out
669
- assert "Instintos globales: 1" in out
670
- assert "ÁMBITO DE PROYECTO" in out
671
- assert "GLOBALES" in out
672
-
673
-
674
- def test_confidence_bar_uses_unicode_when_supported():
675
- """Confidence bars should retain block glyphs on UTF-8 streams."""
676
- stream = SimpleNamespace(encoding="utf-8")
677
- assert _confidence_bar(0.8, stream=stream) == "\u2588" * 8 + "\u2591" * 2
678
-
679
-
680
- def test_confidence_bar_uses_ascii_when_stream_rejects_block_glyphs():
681
- """Windows cp1252 streams cannot encode block glyphs."""
682
- stream = SimpleNamespace(encoding="cp1252")
683
- assert _confidence_bar(0.8, stream=stream) == "########.."
684
-
685
-
686
- def test_print_instincts_by_domain_is_cp1252_safe(monkeypatch):
687
- """Status rendering should not crash on Windows cp1252 stdout."""
688
- raw = io.BytesIO()
689
- stream = io.TextIOWrapper(raw, encoding="cp1252")
690
- monkeypatch.setattr(_mod.sys, "stdout", stream)
691
-
692
- _mod._print_instincts_by_domain([{
693
- "id": "windows-safe",
694
- "trigger": "when stdout uses cp1252",
695
- "confidence": 0.8,
696
- "domain": "platform",
697
- "scope": "project",
698
- }])
699
-
700
- stream.flush()
701
- out = raw.getvalue().decode("cp1252")
702
- assert "########.." in out
703
- assert "\u2588" not in out
704
- assert "\u2591" not in out
705
-
706
-
707
- def test_cmd_status_returns_int(patch_globals, monkeypatch):
708
- """cmd_status should always return an int."""
709
- tree = patch_globals
710
- project = _make_project(tree)
711
- monkeypatch.setattr(_mod, "detect_project", lambda: project)
712
-
713
- args = SimpleNamespace()
714
- ret = cmd_status(args)
715
- assert isinstance(ret, int)
716
-
717
-
718
- # ─────────────────────────────────────────────
719
- # cmd_projects tests
720
- # ─────────────────────────────────────────────
721
-
722
- def test_cmd_projects_empty_registry(patch_globals, capsys):
723
- """No projects should print helpful message."""
724
- args = SimpleNamespace()
725
- ret = cmd_projects(args)
726
- assert ret == 0
727
- out = capsys.readouterr().out
728
- assert "Aún no hay proyectos registrados." in out
729
-
730
-
731
- def test_cmd_projects_with_registry(patch_globals, capsys):
732
- """Should list projects from registry."""
733
- tree = patch_globals
734
-
735
- # Create a project dir with instincts
736
- pid = "test123abc"
737
- project = _make_project(tree, pid=pid, pname="my-app")
738
- (project["instincts_personal"] / "inst.yaml").write_text(SAMPLE_INSTINCT_YAML)
739
-
740
- # Write registry
741
- registry = {
742
- pid: {
743
- "name": "my-app",
744
- "root": "/home/user/my-app",
745
- "remote": "https://github.com/user/my-app.git",
746
- "last_seen": "2025-01-15T12:00:00Z",
747
- }
748
- }
749
- tree["registry_file"].write_text(json.dumps(registry))
750
-
751
- args = SimpleNamespace()
752
- ret = cmd_projects(args)
753
- assert ret == 0
754
- out = capsys.readouterr().out
755
- assert "my-app" in out
756
- assert pid in out
757
- assert "1 personales" in out
758
-
759
-
760
- # ─────────────────────────────────────────────
761
- # _promote_specific tests
762
- # ─────────────────────────────────────────────
763
-
764
- def test_promote_specific_not_found(patch_globals, capsys):
765
- """Promoting nonexistent instinct should fail."""
766
- tree = patch_globals
767
- project = _make_project(tree)
768
-
769
- ret = _promote_specific(project, "nonexistent", force=True)
770
- assert ret == 1
771
- out = capsys.readouterr().out
772
- assert "No se encontró" in out
773
-
774
-
775
- def test_promote_specific_rejects_invalid_id(patch_globals, capsys):
776
- """Path-like instinct IDs should be rejected before file writes."""
777
- tree = patch_globals
778
- project = _make_project(tree)
779
-
780
- ret = _promote_specific(project, "../escape", force=True)
781
- assert ret == 1
782
- err = capsys.readouterr().err
783
- assert "ID de instinto inválido" in err
784
-
785
-
786
- def test_promote_specific_already_global(patch_globals, capsys):
787
- """Promoting an instinct that already exists globally should fail."""
788
- tree = patch_globals
789
- project = _make_project(tree)
790
-
791
- # Write same-id instinct in both project and global
792
- (project["instincts_personal"] / "shared.yaml").write_text(SAMPLE_INSTINCT_YAML)
793
- global_yaml = SAMPLE_INSTINCT_YAML # same id: test-instinct
794
- (tree["global_personal"] / "shared.yaml").write_text(global_yaml)
795
-
796
- ret = _promote_specific(project, "test-instinct", force=True)
797
- assert ret == 1
798
- out = capsys.readouterr().out
799
- assert "ya existe en el ámbito global" in out
800
-
801
-
802
- def test_promote_specific_success(patch_globals, capsys):
803
- """Promote a project instinct to global with --force."""
804
- tree = patch_globals
805
- project = _make_project(tree)
806
-
807
- (project["instincts_personal"] / "inst.yaml").write_text(SAMPLE_INSTINCT_YAML)
808
-
809
- ret = _promote_specific(project, "test-instinct", force=True)
810
- assert ret == 0
811
- out = capsys.readouterr().out
812
- assert "promovido" in out
813
-
814
- # Verify file was created in global dir
815
- promoted_file = tree["global_personal"] / "test-instinct.yaml"
816
- assert promoted_file.exists()
817
- content = promoted_file.read_text()
818
- assert "scope: global" in content
819
- assert "promoted_from: abc123" in content
820
-
821
-
822
- # ─────────────────────────────────────────────
823
- # _promote_auto tests
824
- # ─────────────────────────────────────────────
825
-
826
- def test_promote_auto_no_candidates(patch_globals, capsys):
827
- """Auto-promote with no cross-project instincts should say so."""
828
- tree = patch_globals
829
- project = _make_project(tree)
830
-
831
- # Empty registry
832
- tree["registry_file"].write_text("{}")
833
-
834
- ret = _promote_auto(project, force=True, dry_run=False)
835
- assert ret == 0
836
- out = capsys.readouterr().out
837
- assert "Ningún instinto califica" in out
838
-
839
-
840
- def test_promote_auto_dry_run(patch_globals, capsys):
841
- """Dry run should list candidates but not write files."""
842
- tree = patch_globals
843
-
844
- # Create two projects with the same high-confidence instinct
845
- p1 = _make_project(tree, pid="proj1", pname="project-one")
846
- p2 = _make_project(tree, pid="proj2", pname="project-two")
847
-
848
- high_conf_yaml = """\
849
- ---
850
- id: cross-project-instinct
851
- trigger: "when reviewing"
852
- confidence: 0.95
853
- domain: security
854
- scope: project
855
- ---
856
-
857
- ## Action
858
- Always review for injection.
859
- """
860
- (p1["instincts_personal"] / "cross.yaml").write_text(high_conf_yaml)
861
- (p2["instincts_personal"] / "cross.yaml").write_text(high_conf_yaml)
862
-
863
- # Write registry
864
- registry = {
865
- "proj1": {"name": "project-one", "root": "/a", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
866
- "proj2": {"name": "project-two", "root": "/b", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
867
- }
868
- tree["registry_file"].write_text(json.dumps(registry))
869
-
870
- project = p1
871
- ret = _promote_auto(project, force=True, dry_run=True)
872
- assert ret == 0
873
- out = capsys.readouterr().out
874
- assert "DRY RUN" in out
875
- assert "cross-project-instinct" in out
876
-
877
- # Verify no file was created
878
- assert not (tree["global_personal"] / "cross-project-instinct.yaml").exists()
879
-
880
-
881
- def test_promote_auto_writes_file(patch_globals, capsys):
882
- """Auto-promote with force should write global instinct file."""
883
- tree = patch_globals
884
-
885
- p1 = _make_project(tree, pid="proj1", pname="project-one")
886
- p2 = _make_project(tree, pid="proj2", pname="project-two")
887
-
888
- high_conf_yaml = """\
889
- ---
890
- id: universal-pattern
891
- trigger: "when coding"
892
- confidence: 0.85
893
- domain: general
894
- scope: project
895
- ---
896
-
897
- ## Action
898
- Use descriptive variable names.
899
- """
900
- (p1["instincts_personal"] / "uni.yaml").write_text(high_conf_yaml)
901
- (p2["instincts_personal"] / "uni.yaml").write_text(high_conf_yaml)
902
-
903
- registry = {
904
- "proj1": {"name": "project-one", "root": "/a", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
905
- "proj2": {"name": "project-two", "root": "/b", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
906
- }
907
- tree["registry_file"].write_text(json.dumps(registry))
908
-
909
- ret = _promote_auto(p1, force=True, dry_run=False)
910
- assert ret == 0
911
-
912
- promoted = tree["global_personal"] / "universal-pattern.yaml"
913
- assert promoted.exists()
914
- content = promoted.read_text()
915
- assert "scope: global" in content
916
- assert "auto-promoted" in content
917
-
918
-
919
- def test_promote_auto_skips_invalid_id(patch_globals, capsys):
920
- tree = patch_globals
921
-
922
- p1 = _make_project(tree, pid="proj1", pname="project-one")
923
- p2 = _make_project(tree, pid="proj2", pname="project-two")
924
-
925
- bad_id_yaml = """\
926
- ---
927
- id: ../escape
928
- trigger: "when coding"
929
- confidence: 0.9
930
- domain: general
931
- scope: project
932
- ---
933
-
934
- ## Action
935
- Invalid id should be skipped.
936
- """
937
- (p1["instincts_personal"] / "bad.yaml").write_text(bad_id_yaml)
938
- (p2["instincts_personal"] / "bad.yaml").write_text(bad_id_yaml)
939
-
940
- registry = {
941
- "proj1": {"name": "project-one", "root": "/a", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
942
- "proj2": {"name": "project-two", "root": "/b", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
943
- }
944
- tree["registry_file"].write_text(json.dumps(registry))
945
-
946
- ret = _promote_auto(p1, force=True, dry_run=False)
947
- assert ret == 0
948
- err = capsys.readouterr().err
949
- assert "Se omite un ID de instinto inválido" in err
950
- assert not (tree["global_personal"] / "../escape.yaml").exists()
951
-
952
-
953
- # ─────────────────────────────────────────────
954
- # _find_cross_project_instincts tests
955
- # ─────────────────────────────────────────────
956
-
957
- def test_find_cross_project_empty_registry(patch_globals):
958
- tree = patch_globals
959
- tree["registry_file"].write_text("{}")
960
- result = _find_cross_project_instincts()
961
- assert result == {}
962
-
963
-
964
- def test_find_cross_project_single_project(patch_globals):
965
- """Single project should return nothing (need 2+)."""
966
- tree = patch_globals
967
- p1 = _make_project(tree, pid="proj1", pname="project-one")
968
- (p1["instincts_personal"] / "inst.yaml").write_text(SAMPLE_INSTINCT_YAML)
969
-
970
- registry = {"proj1": {"name": "project-one", "root": "/a", "remote": "", "last_seen": "2025-01-01T00:00:00Z"}}
971
- tree["registry_file"].write_text(json.dumps(registry))
972
-
973
- result = _find_cross_project_instincts()
974
- assert result == {}
975
-
976
-
977
- def test_find_cross_project_shared_instinct(patch_globals):
978
- """Same instinct ID in 2 projects should be found."""
979
- tree = patch_globals
980
- p1 = _make_project(tree, pid="proj1", pname="project-one")
981
- p2 = _make_project(tree, pid="proj2", pname="project-two")
982
-
983
- (p1["instincts_personal"] / "shared.yaml").write_text(SAMPLE_INSTINCT_YAML)
984
- (p2["instincts_personal"] / "shared.yaml").write_text(SAMPLE_INSTINCT_YAML)
985
-
986
- registry = {
987
- "proj1": {"name": "project-one", "root": "/a", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
988
- "proj2": {"name": "project-two", "root": "/b", "remote": "", "last_seen": "2025-01-01T00:00:00Z"},
989
- }
990
- tree["registry_file"].write_text(json.dumps(registry))
991
-
992
- result = _find_cross_project_instincts()
993
- assert "test-instinct" in result
994
- assert len(result["test-instinct"]) == 2
995
-
996
-
997
- # ─────────────────────────────────────────────
998
- # load_registry tests
999
- # ─────────────────────────────────────────────
1000
-
1001
- def test_load_registry_missing_file(patch_globals):
1002
- result = load_registry()
1003
- assert result == {}
1004
-
1005
-
1006
- def test_load_registry_corrupt_json(patch_globals):
1007
- tree = patch_globals
1008
- tree["registry_file"].write_text("not json at all {{{")
1009
- result = load_registry()
1010
- assert result == {}
1011
-
1012
-
1013
- def test_load_registry_valid(patch_globals):
1014
- tree = patch_globals
1015
- data = {"abc": {"name": "test", "root": "/test"}}
1016
- tree["registry_file"].write_text(json.dumps(data))
1017
- result = load_registry()
1018
- assert result == data
1019
-
1020
-
1021
- def test_load_registry_uses_utf8_encoding(monkeypatch):
1022
- calls = []
1023
-
1024
- def fake_open(path, mode="r", *args, **kwargs):
1025
- calls.append(kwargs.get("encoding"))
1026
- return io.StringIO("{}")
1027
-
1028
- monkeypatch.setattr(_mod, "open", fake_open, raising=False)
1029
- assert load_registry() == {}
1030
- assert calls == ["utf-8"]
1031
-
1032
-
1033
- def test_validate_instinct_id():
1034
- assert _validate_instinct_id("good-id_1.0")
1035
- assert not _validate_instinct_id("../bad")
1036
- assert not _validate_instinct_id("bad/name")
1037
- assert not _validate_instinct_id(".hidden")
1038
-
1039
-
1040
- def test_update_registry_atomic_replaces_file(patch_globals):
1041
- tree = patch_globals
1042
- _update_registry("abc123", "demo", "/repo", "https://example.com/repo.git")
1043
- data = json.loads(tree["registry_file"].read_text())
1044
- assert "abc123" in data
1045
- leftovers = list(tree["registry_file"].parent.glob(".projects.json.tmp.*"))
1046
- assert leftovers == []
1047
-
1048
-
1049
- def test_update_registry_matches_shell_schema(patch_globals):
1050
- # Issue #2299: the Python writer must emit the same field set as the shell
1051
- # counterpart in detect-project.sh (id, name, root, remote, created_at,
1052
- # last_seen) so a projects.json entry has a consistent shape regardless of
1053
- # which path wrote it.
1054
- tree = patch_globals
1055
- _update_registry("abc123", "demo", "/repo", "https://example.com/repo.git")
1056
- entry = json.loads(tree["registry_file"].read_text())["abc123"]
1057
- assert set(entry) == {"id", "name", "root", "remote", "created_at", "last_seen"}
1058
- assert entry["id"] == "abc123"
1059
- assert entry["name"] == "demo"
1060
- assert entry["root"] == "/repo"
1061
- assert entry["remote"] == "https://example.com/repo.git"
1062
- # On the initial write both timestamps come from the same `now`, so the
1063
- # first-write contract is created_at == last_seen.
1064
- assert entry["created_at"]
1065
- assert entry["created_at"] == entry["last_seen"]
1066
-
1067
-
1068
- def test_update_registry_preserves_created_at(patch_globals):
1069
- # created_at is stamped on first write and preserved on subsequent updates,
1070
- # while last_seen advances — matching entry.get("created_at", now) in the
1071
- # shell counterpart.
1072
- tree = patch_globals
1073
- _update_registry("abc123", "demo", "/repo", "https://example.com/repo.git")
1074
- first = json.loads(tree["registry_file"].read_text())["abc123"]
1075
-
1076
- _update_registry("abc123", "demo-renamed", "/repo", "https://example.com/repo.git")
1077
- second = json.loads(tree["registry_file"].read_text())["abc123"]
1078
-
1079
- assert second["created_at"] == first["created_at"]
1080
- assert second["name"] == "demo-renamed"
1081
- assert second["last_seen"] >= first["last_seen"]
1082
-
1083
-
1084
- def test_update_registry_heals_malformed_entry(patch_globals):
1085
- # Issue #2299 follow-up: a non-dict value for the project id (e.g. a
1086
- # corrupt registry) must not crash _update_registry. The entry is healed by
1087
- # the rewrite, preserving the old unconditional-overwrite behavior.
1088
- tree = patch_globals
1089
- tree["registry_file"].write_text(json.dumps({"abc123": None}), encoding="utf-8")
1090
- _update_registry("abc123", "demo", "/repo", "https://example.com/repo.git")
1091
- entry = json.loads(tree["registry_file"].read_text())["abc123"]
1092
- assert isinstance(entry, dict)
1093
- assert entry["id"] == "abc123"
1094
- assert entry["created_at"]
1095
- assert entry["created_at"] == entry["last_seen"]
1096
-
1097
-
1098
- def test_update_registry_heals_non_dict_registry(patch_globals):
1099
- # Issue #2299 follow-up: a top-level registry that is valid JSON but not a
1100
- # mapping (e.g. a list or string from a corrupt projects.json) must not
1101
- # crash _update_registry before the per-entry guard runs. The whole file is
1102
- # healed by the rewrite, preserving the old unconditional-overwrite behavior.
1103
- tree = patch_globals
1104
- tree["registry_file"].write_text(json.dumps(["oops"]), encoding="utf-8")
1105
- _update_registry("abc123", "demo", "/repo", "https://example.com/repo.git")
1106
- registry = json.loads(tree["registry_file"].read_text())
1107
- assert isinstance(registry, dict)
1108
- entry = registry["abc123"]
1109
- assert entry["id"] == "abc123"
1110
- assert entry["created_at"] == entry["last_seen"]
1111
-
1112
-
1113
- def test_write_registry_atomic_no_tmp_leftovers(patch_globals):
1114
- # Issue #2294: _write_registry now holds the registry lock like
1115
- # _update_registry. It must still write atomically with no stray tmp files.
1116
- tree = patch_globals
1117
- _write_registry({"keep": {"name": "demo", "root": "/repo", "remote": ""}})
1118
- data = json.loads(tree["registry_file"].read_text())
1119
- assert data == {"keep": {"name": "demo", "root": "/repo", "remote": ""}}
1120
- leftovers = list(tree["registry_file"].parent.glob(".projects.json.tmp.*"))
1121
- assert leftovers == []
1122
-
1123
-
1124
- def test_remove_project_storage_deletes_contained_dir(patch_globals):
1125
- tree = patch_globals
1126
- target = tree["projects_dir"] / "proj-1"
1127
- (target / "instincts").mkdir(parents=True)
1128
- (target / "instincts" / "x.md").write_text("hi", encoding="utf-8")
1129
- _remove_project_storage("proj-1")
1130
- assert not target.exists()
1131
-
1132
-
1133
- def test_remove_project_storage_missing_dir_is_noop(patch_globals):
1134
- # No raise when the contained dir simply does not exist.
1135
- _remove_project_storage("never-created")
1136
-
1137
-
1138
- def test_remove_project_storage_blocks_traversal(patch_globals):
1139
- # Issue #2297: defense-in-depth — a traversal id must be refused even when a
1140
- # caller skips _validate_project_id, so this can never delete outside
1141
- # PROJECTS_DIR.
1142
- with pytest.raises(ValueError):
1143
- _remove_project_storage("../../etc")
1144
-
1145
-
1146
- def test_remove_project_storage_blocks_root_itself(patch_globals):
1147
- with pytest.raises(ValueError):
1148
- _remove_project_storage(".")
1149
-
1150
-
1151
- # ─────────────────────────────────────────────
1152
- # Issue #2302 coverage:
1153
- # _normalize_remote_url, _promote_specific dry-run,
1154
- # projects delete/gc/merge, cmd_prune
1155
- # ─────────────────────────────────────────────
1156
-
1157
- _normalize_remote_url = _mod._normalize_remote_url
1158
- _cmd_projects_delete = _mod._cmd_projects_delete
1159
- _cmd_projects_gc = _mod._cmd_projects_gc
1160
- _cmd_projects_merge = _mod._cmd_projects_merge
1161
- cmd_prune = _mod.cmd_prune
1162
-
1163
-
1164
- # ── _normalize_remote_url ────────────────────
1165
-
1166
- def test_normalize_remote_url_empty_returns_empty():
1167
- assert _normalize_remote_url("") == ""
1168
- assert _normalize_remote_url(None) == ""
1169
-
1170
-
1171
- def test_normalize_remote_url_scp_form():
1172
- # scp-style host:path -> host/path, credentials/.git stripped, lowercased
1173
- assert _normalize_remote_url("git@github.com:Test/Repo.git") == "github.com/test/repo"
1174
-
1175
-
1176
- def test_normalize_remote_url_https_strips_credentials_and_scheme():
1177
- assert (
1178
- _normalize_remote_url("https://user:token@github.com/test/repo.git")
1179
- == "github.com/test/repo"
1180
- )
1181
-
1182
-
1183
- def test_normalize_remote_url_network_is_lowercased():
1184
- assert _normalize_remote_url("https://GitHub.com/Owner/Project") == "github.com/owner/project"
1185
-
1186
-
1187
- def test_normalize_remote_url_trailing_slash_and_dotgit_stripped():
1188
- assert _normalize_remote_url("https://github.com/a/b.git/") == "github.com/a/b"
1189
-
1190
-
1191
- def test_normalize_remote_url_file_scheme_preserves_case():
1192
- # Local file paths are not network URLs: scheme is stripped but case is preserved.
1193
- assert _normalize_remote_url("file:///srv/Repos/My-Repo/") == "/srv/Repos/My-Repo"
1194
-
1195
-
1196
- def test_normalize_remote_url_idempotent():
1197
- once = _normalize_remote_url("https://user@github.com/Test/Repo.git")
1198
- assert _normalize_remote_url(once) == once
1199
-
1200
-
1201
- # ── _promote_specific dry-run ────────────────
1202
-
1203
- def test_promote_specific_dry_run_writes_nothing(patch_globals, capsys):
1204
- """dry_run returns 0, prints [DRY RUN], and writes no global file."""
1205
- tree = patch_globals
1206
- project = _make_project(tree)
1207
- (project["instincts_personal"] / "inst.yaml").write_text(SAMPLE_INSTINCT_YAML)
1208
-
1209
- ret = _promote_specific(project, "test-instinct", force=True, dry_run=True)
1210
- assert ret == 0
1211
- out = capsys.readouterr().out
1212
- assert "[DRY RUN]" in out
1213
- assert not (tree["global_personal"] / "test-instinct.yaml").exists()
1214
- assert list(tree["global_personal"].iterdir()) == []
1215
-
1216
-
1217
- # ── projects delete ──────────────────────────
1218
-
1219
- def test_projects_delete_rejects_invalid_id(patch_globals, capsys):
1220
- args = SimpleNamespace(project_id="../escape", dry_run=False, force=True)
1221
- assert _cmd_projects_delete(args) == 1
1222
- assert "ID de proyecto inválido" in capsys.readouterr().err
1223
-
1224
-
1225
- def test_projects_delete_not_found(patch_globals, capsys):
1226
- args = SimpleNamespace(project_id="ghost123", dry_run=False, force=True)
1227
- assert _cmd_projects_delete(args) == 1
1228
- assert "No se encontró" in capsys.readouterr().err
1229
-
1230
-
1231
- def test_projects_delete_dry_run_keeps_registry_and_storage(patch_globals, capsys):
1232
- tree = patch_globals
1233
- _make_project(tree, pid="proj1", pname="p1")
1234
- tree["registry_file"].write_text(json.dumps({"proj1": {"name": "p1"}}))
1235
-
1236
- args = SimpleNamespace(project_id="proj1", dry_run=True, force=False)
1237
- assert _cmd_projects_delete(args) == 0
1238
- assert "[DRY RUN]" in capsys.readouterr().out
1239
- assert (tree["projects_dir"] / "proj1").exists()
1240
- assert "proj1" in json.loads(tree["registry_file"].read_text())
1241
-
1242
-
1243
- def test_projects_delete_force_removes_registry_and_storage(patch_globals, capsys):
1244
- tree = patch_globals
1245
- _make_project(tree, pid="proj1", pname="p1")
1246
- tree["registry_file"].write_text(json.dumps({"proj1": {"name": "p1"}}))
1247
-
1248
- args = SimpleNamespace(project_id="proj1", dry_run=False, force=True)
1249
- assert _cmd_projects_delete(args) == 0
1250
- assert "eliminado" in capsys.readouterr().out
1251
- assert not (tree["projects_dir"] / "proj1").exists()
1252
- assert "proj1" not in json.loads(tree["registry_file"].read_text())
1253
-
1254
-
1255
- # ── projects gc ──────────────────────────────
1256
-
1257
- def test_projects_gc_no_candidates(patch_globals, capsys):
1258
- tree = patch_globals
1259
- tree["registry_file"].write_text("{}")
1260
- args = SimpleNamespace(dry_run=False, force=True)
1261
- assert _cmd_projects_gc(args) == 0
1262
- assert "No se encontraron entradas de proyecto vacías" in capsys.readouterr().out
1263
-
1264
-
1265
- def test_projects_gc_dry_run_keeps_entry(patch_globals, capsys):
1266
- tree = patch_globals
1267
- _make_project(tree, pid="empty1", pname="e1") # zero instincts/observations
1268
- tree["registry_file"].write_text(json.dumps({"empty1": {"name": "e1"}}))
1269
-
1270
- args = SimpleNamespace(dry_run=True, force=False)
1271
- assert _cmd_projects_gc(args) == 0
1272
- assert "[DRY RUN]" in capsys.readouterr().out
1273
- assert "empty1" in json.loads(tree["registry_file"].read_text())
1274
- # dry-run must not touch storage on disk
1275
- assert (tree["projects_dir"] / "empty1").exists()
1276
-
1277
-
1278
- def test_projects_gc_force_removes_only_zero_value(patch_globals, capsys):
1279
- tree = patch_globals
1280
- _make_project(tree, pid="empty1", pname="e1")
1281
- full = _make_project(tree, pid="full1", pname="f1")
1282
- (full["instincts_personal"] / "inst.yaml").write_text(SAMPLE_INSTINCT_YAML)
1283
- tree["registry_file"].write_text(
1284
- json.dumps({"empty1": {"name": "e1"}, "full1": {"name": "f1"}})
1285
- )
1286
-
1287
- args = SimpleNamespace(dry_run=False, force=True)
1288
- assert _cmd_projects_gc(args) == 0
1289
- reg = json.loads(tree["registry_file"].read_text())
1290
- assert "empty1" not in reg
1291
- assert "full1" in reg
1292
- assert not (tree["projects_dir"] / "empty1").exists()
1293
- assert (tree["projects_dir"] / "full1").exists()
1294
-
1295
-
1296
- # ── projects merge ───────────────────────────
1297
-
1298
- def test_projects_merge_rejects_same_id(patch_globals, capsys):
1299
- args = SimpleNamespace(from_id="dup", into_id="dup", dry_run=False, force=True)
1300
- assert _cmd_projects_merge(args) == 1
1301
- assert "consigo mismo" in capsys.readouterr().err
1302
-
1303
-
1304
- def test_projects_merge_missing_source(patch_globals, capsys):
1305
- tree = patch_globals
1306
- tree["registry_file"].write_text(json.dumps({"dest": {"name": "d"}}))
1307
- args = SimpleNamespace(from_id="src", into_id="dest", dry_run=False, force=True)
1308
- assert _cmd_projects_merge(args) == 1
1309
- assert "proyecto de origen" in capsys.readouterr().err
1310
-
1311
-
1312
- def test_projects_merge_missing_destination(patch_globals, capsys):
1313
- tree = patch_globals
1314
- # Source present, destination absent — exercises the symmetric error branch.
1315
- tree["registry_file"].write_text(json.dumps({"src": {"name": "s"}}))
1316
- args = SimpleNamespace(from_id="src", into_id="dest", dry_run=False, force=True)
1317
- assert _cmd_projects_merge(args) == 1
1318
- assert "proyecto de destino" in capsys.readouterr().err
1319
-
1320
-
1321
- def test_projects_merge_dry_run_no_changes(patch_globals, capsys):
1322
- tree = patch_globals
1323
- src = _make_project(tree, pid="src", pname="s")
1324
- _make_project(tree, pid="dest", pname="d")
1325
- (src["instincts_personal"] / "i.yaml").write_text(SAMPLE_INSTINCT_YAML)
1326
- tree["registry_file"].write_text(json.dumps({"src": {"name": "s"}, "dest": {"name": "d"}}))
1327
-
1328
- args = SimpleNamespace(from_id="src", into_id="dest", dry_run=True, force=False)
1329
- assert _cmd_projects_merge(args) == 0
1330
- assert "[DRY RUN]" in capsys.readouterr().out
1331
- reg = json.loads(tree["registry_file"].read_text())
1332
- assert "src" in reg and "dest" in reg
1333
- assert (tree["projects_dir"] / "src").exists()
1334
- # dry-run must not copy any instinct into the destination storage
1335
- assert not list((tree["projects_dir"] / "dest" / "instincts" / "personal").glob("*.yaml"))
1336
-
1337
-
1338
- def test_projects_merge_force_moves_and_removes_source(patch_globals, capsys):
1339
- tree = patch_globals
1340
- src = _make_project(tree, pid="src", pname="s")
1341
- _make_project(tree, pid="dest", pname="d")
1342
- (src["instincts_personal"] / "i.yaml").write_text(SAMPLE_INSTINCT_YAML)
1343
- tree["registry_file"].write_text(json.dumps({"src": {"name": "s"}, "dest": {"name": "d"}}))
1344
-
1345
- args = SimpleNamespace(from_id="src", into_id="dest", dry_run=False, force=True)
1346
- assert _cmd_projects_merge(args) == 0
1347
- reg = json.loads(tree["registry_file"].read_text())
1348
- assert "src" not in reg
1349
- assert "dest" in reg
1350
- assert not (tree["projects_dir"] / "src").exists()
1351
- moved = list((tree["projects_dir"] / "dest" / "instincts" / "personal").glob("*.yaml"))
1352
- assert len(moved) >= 1
1353
-
1354
-
1355
- # ── cmd_prune ────────────────────────────────
1356
-
1357
- def _pending_item(path, age_days):
1358
- return {
1359
- "path": path,
1360
- "created": None,
1361
- "age_days": age_days,
1362
- "name": path.stem,
1363
- "parent_dir": str(path.parent),
1364
- }
1365
-
1366
-
1367
- def test_cmd_prune_dry_run_keeps_files(monkeypatch, tmp_path, capsys):
1368
- f_old = tmp_path / "old.yaml"
1369
- f_old.write_text("x", encoding="utf-8")
1370
- f_new = tmp_path / "new.yaml"
1371
- f_new.write_text("y", encoding="utf-8")
1372
- items = [_pending_item(f_old, 40), _pending_item(f_new, 5)]
1373
- monkeypatch.setattr(_mod, "_collect_pending_instincts", lambda: items)
1374
-
1375
- args = SimpleNamespace(max_age=30, dry_run=True, quiet=False)
1376
- assert cmd_prune(args) == 0
1377
- assert "[DRY RUN]" in capsys.readouterr().out
1378
- assert f_old.exists()
1379
- assert f_new.exists()
1380
-
1381
-
1382
- def test_cmd_prune_deletes_only_expired(monkeypatch, tmp_path, capsys):
1383
- f_old = tmp_path / "old.yaml"
1384
- f_old.write_text("x", encoding="utf-8")
1385
- f_new = tmp_path / "new.yaml"
1386
- f_new.write_text("y", encoding="utf-8")
1387
- items = [_pending_item(f_old, 40), _pending_item(f_new, 5)]
1388
- monkeypatch.setattr(_mod, "_collect_pending_instincts", lambda: items)
1389
-
1390
- args = SimpleNamespace(max_age=30, dry_run=False, quiet=False)
1391
- assert cmd_prune(args) == 0
1392
- assert not f_old.exists()
1393
- assert f_new.exists()
1394
- assert "Se podaron 1" in capsys.readouterr().out
1395
-
1396
-
1397
- def test_cmd_prune_quiet_suppresses_output(monkeypatch, tmp_path, capsys):
1398
- f_old = tmp_path / "old.yaml"
1399
- f_old.write_text("x", encoding="utf-8")
1400
- items = [_pending_item(f_old, 99)]
1401
- monkeypatch.setattr(_mod, "_collect_pending_instincts", lambda: items)
1402
-
1403
- args = SimpleNamespace(max_age=30, dry_run=False, quiet=True)
1404
- assert cmd_prune(args) == 0
1405
- assert not f_old.exists()
1406
- captured = capsys.readouterr()
1407
- assert captured.out == ""
1408
- assert captured.err == ""
1409
-
1410
-
1411
- def test_cmd_prune_empty_pending_nothing_to_do(monkeypatch, capsys):
1412
- # Nothing pending at all: the non-dry-run, non-quiet branch must report
1413
- # "nothing to do" (not "[DRY RUN]"), return 0, and not crash.
1414
- monkeypatch.setattr(_mod, "_collect_pending_instincts", lambda: [])
1415
-
1416
- args = SimpleNamespace(max_age=30, dry_run=False, quiet=False)
1417
- assert cmd_prune(args) == 0
1418
- out = capsys.readouterr().out
1419
- assert "No hay instintos pendientes con más de 30 días." in out
1420
- assert "[DRY RUN]" not in out