xonecode 0.2.0 → 0.5.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 (406) hide show
  1. package/README.md +49 -7
  2. package/THIRD_PARTY_NOTICES.md +128 -0
  3. package/apps/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  4. package/apps/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  5. package/apps/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  6. package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  7. package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  8. package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  9. package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  10. package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  11. package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  12. package/apps/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  13. package/apps/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  14. package/apps/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  15. package/apps/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  16. package/apps/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  17. package/apps/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  18. package/apps/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  19. package/apps/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  20. package/apps/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  21. package/apps/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  22. package/apps/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  23. package/apps/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  24. package/apps/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  25. package/apps/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  26. package/apps/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  27. package/apps/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  28. package/apps/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  29. package/apps/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  30. package/apps/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  31. package/apps/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  32. package/apps/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  33. package/apps/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  34. package/apps/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  35. package/apps/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  36. package/apps/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  37. package/apps/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  38. package/apps/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  39. package/apps/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  40. package/apps/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  41. package/apps/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  42. package/apps/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  43. package/apps/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  44. package/apps/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  45. package/apps/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  46. package/apps/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  47. package/apps/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  48. package/apps/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  49. package/apps/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  50. package/apps/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  51. package/apps/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  52. package/apps/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  53. package/apps/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  54. package/apps/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  55. package/apps/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  56. package/apps/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  57. package/apps/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  58. package/apps/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  59. package/apps/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  60. package/apps/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  61. package/apps/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  62. package/apps/web/dist/assets/c-BIGW1oBm.js +1 -0
  63. package/apps/web/dist/assets/cpp-DddhVWhK.js +1 -0
  64. package/apps/web/dist/assets/csharp-DSvCPggb.js +1 -0
  65. package/apps/web/dist/assets/css-CLj8gQPS.js +1 -0
  66. package/apps/web/dist/assets/go-C27-OAKa.js +1 -0
  67. package/apps/web/dist/assets/html-CfGypltT.js +1 -0
  68. package/apps/web/dist/assets/index-BB3SamhR.css +1 -0
  69. package/apps/web/dist/assets/index-CFYAoHdw.js +477 -0
  70. package/apps/web/dist/assets/ini-BEwlwnbL.js +1 -0
  71. package/apps/web/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  72. package/apps/web/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  73. package/apps/web/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  74. package/apps/web/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  75. package/apps/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  76. package/apps/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  77. package/apps/web/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  78. package/apps/web/dist/assets/java-CylS5w8V.js +1 -0
  79. package/apps/web/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  80. package/apps/web/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  81. package/apps/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  82. package/apps/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  83. package/apps/web/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  84. package/apps/web/dist/assets/kotlin-BdnUsdx6.js +1 -0
  85. package/apps/web/dist/assets/less-B1dDrJ26.js +1 -0
  86. package/apps/web/dist/assets/lua-BaeVxFsk.js +1 -0
  87. package/apps/web/dist/assets/markdown-Cvjx9yec.js +1 -0
  88. package/apps/web/dist/assets/mdx-Cmh6b_Ma.js +1 -0
  89. package/apps/web/dist/assets/php-D_2--9WK.js +1 -0
  90. package/apps/web/dist/assets/python-B6aJPvgy.js +1 -0
  91. package/apps/web/dist/assets/ruby-DSHSDbk1.js +1 -0
  92. package/apps/web/dist/assets/rust-B1yitclQ.js +1 -0
  93. package/apps/web/dist/assets/scss-D5BDwBP9.js +1 -0
  94. package/apps/web/dist/assets/sql-CRqJ_cUM.js +1 -0
  95. package/apps/web/dist/assets/swift-C2oV4EkX.js +1 -0
  96. package/apps/web/dist/assets/toml-vGWfd6FD.js +1 -0
  97. package/apps/web/dist/assets/xml-sdJ4AIDG.js +1 -0
  98. package/apps/web/dist/assets/yaml-Buea-lGh.js +1 -0
  99. package/apps/web/dist/iconos/xonecode.png +0 -0
  100. package/apps/web/dist/index.html +20 -0
  101. package/dist/agent/agentesEnDisco.js +539 -0
  102. package/dist/agent/agentesEnDisco.js.map +1 -0
  103. package/dist/agent/arbolDeProyecto.js +245 -0
  104. package/dist/agent/arbolDeProyecto.js.map +1 -0
  105. package/dist/agent/artefactosEnDisco.js +139 -0
  106. package/dist/agent/artefactosEnDisco.js.map +1 -0
  107. package/dist/agent/aumentador.js +175 -0
  108. package/dist/agent/aumentador.js.map +1 -0
  109. package/dist/agent/authEnDisco.js +76 -1
  110. package/dist/agent/authEnDisco.js.map +1 -1
  111. package/dist/agent/busquedaRegex.js +92 -0
  112. package/dist/agent/busquedaRegex.js.map +1 -0
  113. package/dist/agent/catalogoModelos.js +345 -0
  114. package/dist/agent/catalogoModelos.js.map +1 -0
  115. package/dist/agent/checkpointer.js +127 -0
  116. package/dist/agent/checkpointer.js.map +1 -0
  117. package/dist/agent/cloudstudioClient.js +194 -0
  118. package/dist/agent/cloudstudioClient.js.map +1 -0
  119. package/dist/agent/cloudstudioMcp.js +722 -0
  120. package/dist/agent/cloudstudioMcp.js.map +1 -0
  121. package/dist/agent/configEnDisco.js +309 -11
  122. package/dist/agent/configEnDisco.js.map +1 -1
  123. package/dist/agent/consumoExterno.js +99 -0
  124. package/dist/agent/consumoExterno.js.map +1 -0
  125. package/dist/agent/descarga.js +149 -0
  126. package/dist/agent/descarga.js.map +1 -0
  127. package/dist/agent/diagnosticoDeTools.js +51 -0
  128. package/dist/agent/diagnosticoDeTools.js.map +1 -0
  129. package/dist/agent/dispositivosEnMaquina.js +596 -0
  130. package/dist/agent/dispositivosEnMaquina.js.map +1 -0
  131. package/dist/agent/escrituraDeCodex.js +134 -0
  132. package/dist/agent/escrituraDeCodex.js.map +1 -0
  133. package/dist/agent/escrituraDeOpencode.js +80 -0
  134. package/dist/agent/escrituraDeOpencode.js.map +1 -0
  135. package/dist/agent/escrituraExterna.js +742 -0
  136. package/dist/agent/escrituraExterna.js.map +1 -0
  137. package/dist/agent/gemini.js +81 -0
  138. package/dist/agent/gemini.js.map +1 -0
  139. package/dist/agent/git.js +83 -0
  140. package/dist/agent/git.js.map +1 -0
  141. package/dist/agent/gitSync.js +441 -0
  142. package/dist/agent/gitSync.js.map +1 -0
  143. package/dist/agent/hotswap.js +448 -0
  144. package/dist/agent/hotswap.js.map +1 -0
  145. package/dist/agent/instalacionEnMaquina.js +252 -0
  146. package/dist/agent/instalacionEnMaquina.js.map +1 -0
  147. package/dist/agent/instantanea.js +7 -10
  148. package/dist/agent/instantanea.js.map +1 -1
  149. package/dist/agent/interrupts.js +11 -2
  150. package/dist/agent/interrupts.js.map +1 -1
  151. package/dist/agent/juezDeTarea.js +345 -0
  152. package/dist/agent/juezDeTarea.js.map +1 -0
  153. package/dist/agent/lanzamientoEnMaquina.js +377 -0
  154. package/dist/agent/lanzamientoEnMaquina.js.map +1 -0
  155. package/dist/agent/manifiesto.js +59 -0
  156. package/dist/agent/manifiesto.js.map +1 -0
  157. package/dist/agent/memoriaDeProyecto.js +60 -0
  158. package/dist/agent/memoriaDeProyecto.js.map +1 -0
  159. package/dist/agent/modelos.js +105 -17
  160. package/dist/agent/modelos.js.map +1 -1
  161. package/dist/agent/modelosDeMotor.js +204 -0
  162. package/dist/agent/modelosDeMotor.js.map +1 -0
  163. package/dist/agent/paqueteDelProyecto.js +181 -0
  164. package/dist/agent/paqueteDelProyecto.js.map +1 -0
  165. package/dist/agent/perfiles.js +92 -31
  166. package/dist/agent/perfiles.js.map +1 -1
  167. package/dist/agent/persona.js +40 -0
  168. package/dist/agent/persona.js.map +1 -0
  169. package/dist/agent/procesosEnMaquina.js +204 -0
  170. package/dist/agent/procesosEnMaquina.js.map +1 -0
  171. package/dist/agent/proyecto.js +311 -13
  172. package/dist/agent/proyecto.js.map +1 -1
  173. package/dist/agent/puente.js +63 -6
  174. package/dist/agent/puente.js.map +1 -1
  175. package/dist/agent/resumenDeContexto.js +30 -0
  176. package/dist/agent/resumenDeContexto.js.map +1 -0
  177. package/dist/agent/resumenDeTool.js +64 -18
  178. package/dist/agent/resumenDeTool.js.map +1 -1
  179. package/dist/agent/sesionGit.js +481 -0
  180. package/dist/agent/sesionGit.js.map +1 -0
  181. package/dist/agent/settingsEnDisco.js +189 -0
  182. package/dist/agent/settingsEnDisco.js.map +1 -0
  183. package/dist/agent/subagenteCodex.js +368 -0
  184. package/dist/agent/subagenteCodex.js.map +1 -0
  185. package/dist/agent/subagenteExterno.js +423 -0
  186. package/dist/agent/subagenteExterno.js.map +1 -0
  187. package/dist/agent/subagenteOpencode.js +389 -0
  188. package/dist/agent/subagenteOpencode.js.map +1 -0
  189. package/dist/agent/subida.js +202 -0
  190. package/dist/agent/subida.js.map +1 -0
  191. package/dist/agent/tareasEnDisco.js +466 -0
  192. package/dist/agent/tareasEnDisco.js.map +1 -0
  193. package/dist/agent/turnoReal.js +663 -50
  194. package/dist/agent/turnoReal.js.map +1 -1
  195. package/dist/agent/versionEnDisco.js +48 -0
  196. package/dist/agent/versionEnDisco.js.map +1 -0
  197. package/dist/agent/xoneAgent.js +290 -49
  198. package/dist/agent/xoneAgent.js.map +1 -1
  199. package/dist/agent/zip.js +52 -0
  200. package/dist/agent/zip.js.map +1 -0
  201. package/dist/cli/acuseDeModelo.js +30 -0
  202. package/dist/cli/acuseDeModelo.js.map +1 -0
  203. package/dist/cli/aprobar.js +55 -2
  204. package/dist/cli/aprobar.js.map +1 -1
  205. package/dist/cli/config.js +9 -13
  206. package/dist/cli/config.js.map +1 -1
  207. package/dist/cli/consola.js +750 -19
  208. package/dist/cli/consola.js.map +1 -1
  209. package/dist/cli/main.js +740 -81
  210. package/dist/cli/main.js.map +1 -1
  211. package/dist/cli/markdown.js +188 -2
  212. package/dist/cli/markdown.js.map +1 -1
  213. package/dist/cli/run.js +32 -4
  214. package/dist/cli/run.js.map +1 -1
  215. package/dist/cli/stdio.js +46 -19
  216. package/dist/cli/stdio.js.map +1 -1
  217. package/dist/cli/tema.js +96 -8
  218. package/dist/cli/tema.js.map +1 -1
  219. package/dist/cli/tokens.js +29 -0
  220. package/dist/cli/tokens.js.map +1 -0
  221. package/dist/cli/tui/app.js +171 -0
  222. package/dist/cli/tui/app.js.map +1 -0
  223. package/dist/cli/tui/aprobarTui.js +80 -0
  224. package/dist/cli/tui/aprobarTui.js.map +1 -0
  225. package/dist/cli/tui/barra.js +37 -0
  226. package/dist/cli/tui/barra.js.map +1 -0
  227. package/dist/cli/tui/correrTui.js +478 -0
  228. package/dist/cli/tui/correrTui.js.map +1 -0
  229. package/dist/cli/tui/entrada.js +166 -0
  230. package/dist/cli/tui/entrada.js.map +1 -0
  231. package/dist/cli/tui/filas.js +24 -0
  232. package/dist/cli/tui/filas.js.map +1 -0
  233. package/dist/cli/tui/logo.js +49 -0
  234. package/dist/cli/tui/logo.js.map +1 -0
  235. package/dist/cli/tui/pielTui.js +14 -0
  236. package/dist/cli/tui/pielTui.js.map +1 -0
  237. package/dist/cli/tui/raton.js +126 -0
  238. package/dist/cli/tui/raton.js.map +1 -0
  239. package/dist/cli/tui/sidebar.js +86 -0
  240. package/dist/cli/tui/sidebar.js.map +1 -0
  241. package/dist/cli/tui/store.js +143 -0
  242. package/dist/cli/tui/store.js.map +1 -0
  243. package/dist/cli/tui/tarjeta.js +19 -0
  244. package/dist/cli/tui/tarjeta.js.map +1 -0
  245. package/dist/cli/tui/temaInk.js +114 -0
  246. package/dist/cli/tui/temaInk.js.map +1 -0
  247. package/dist/cli/tui/transcript.js +254 -0
  248. package/dist/cli/tui/transcript.js.map +1 -0
  249. package/dist/cli/wizardInicial.js +240 -0
  250. package/dist/cli/wizardInicial.js.map +1 -0
  251. package/dist/core/actos.js +113 -0
  252. package/dist/core/actos.js.map +1 -0
  253. package/dist/core/adjuntos.js +97 -0
  254. package/dist/core/adjuntos.js.map +1 -0
  255. package/dist/core/agentes.js +227 -0
  256. package/dist/core/agentes.js.map +1 -0
  257. package/dist/core/artefactos.js +149 -0
  258. package/dist/core/artefactos.js.map +1 -0
  259. package/dist/core/cloudstudio.js +7 -0
  260. package/dist/core/cloudstudio.js.map +1 -0
  261. package/dist/core/config.js +212 -5
  262. package/dist/core/config.js.map +1 -1
  263. package/dist/core/contextos.js +53 -1
  264. package/dist/core/contextos.js.map +1 -1
  265. package/dist/core/descargas.js +106 -0
  266. package/dist/core/descargas.js.map +1 -0
  267. package/dist/core/descriptoresDeApp.js +279 -0
  268. package/dist/core/descriptoresDeApp.js.map +1 -0
  269. package/dist/core/dispositivos.js +466 -0
  270. package/dist/core/dispositivos.js.map +1 -0
  271. package/dist/core/entrega.js +141 -0
  272. package/dist/core/entrega.js.map +1 -0
  273. package/dist/core/entrelazar.js +90 -0
  274. package/dist/core/entrelazar.js.map +1 -0
  275. package/dist/core/esqueleto.js +10 -0
  276. package/dist/core/esqueleto.js.map +1 -1
  277. package/dist/core/modelos.js +235 -3
  278. package/dist/core/modelos.js.map +1 -1
  279. package/dist/core/notify.js +27 -9
  280. package/dist/core/notify.js.map +1 -1
  281. package/dist/core/planDeSubida.js +127 -0
  282. package/dist/core/planDeSubida.js.map +1 -0
  283. package/dist/core/ports.js +189 -1
  284. package/dist/core/ports.js.map +1 -1
  285. package/dist/core/puedeLanzarse.js +239 -0
  286. package/dist/core/puedeLanzarse.js.map +1 -0
  287. package/dist/core/rutaVirtual.js +42 -0
  288. package/dist/core/rutaVirtual.js.map +1 -0
  289. package/dist/core/settings.js +246 -0
  290. package/dist/core/settings.js.map +1 -0
  291. package/dist/core/tareas.js +230 -0
  292. package/dist/core/tareas.js.map +1 -0
  293. package/dist/core/textos.js +36 -0
  294. package/dist/core/textos.js.map +1 -0
  295. package/dist/core/turno.js +70 -10
  296. package/dist/core/turno.js.map +1 -1
  297. package/dist/core/version.js +31 -0
  298. package/dist/core/version.js.map +1 -0
  299. package/dist/vendor/tokenTracking.js +22 -1
  300. package/dist/vendor/tokenTracking.js.map +1 -1
  301. package/dist/web/servidor/arranque.js +3964 -0
  302. package/dist/web/servidor/arranque.js.map +1 -0
  303. package/dist/web/servidor/consolaDeTarea.js +161 -0
  304. package/dist/web/servidor/consolaDeTarea.js.map +1 -0
  305. package/dist/web/servidor/consolaWeb.js +389 -0
  306. package/dist/web/servidor/consolaWeb.js.map +1 -0
  307. package/dist/web/servidor/corredorDeTareas.js +1119 -0
  308. package/dist/web/servidor/corredorDeTareas.js.map +1 -0
  309. package/dist/web/servidor/pielWeb.js +269 -0
  310. package/dist/web/servidor/pielWeb.js.map +1 -0
  311. package/dist/web/servidor/servidor.js +257 -0
  312. package/dist/web/servidor/servidor.js.map +1 -0
  313. package/dist/web/servidor/sesiones.js +440 -0
  314. package/dist/web/servidor/sesiones.js.map +1 -0
  315. package/dist/web/servidor/transporte.js +169 -0
  316. package/dist/web/servidor/transporte.js.map +1 -0
  317. package/dist/web/servidor/vestibulo.js +1276 -0
  318. package/dist/web/servidor/vestibulo.js.map +1 -0
  319. package/package.json +30 -8
  320. package/skills/archify/LICENSE +22 -0
  321. package/skills/archify/SKILL.md +109 -0
  322. package/skills/archify/THIRD_PARTY_NOTICES.md +56 -0
  323. package/skills/archify/assets/template.html +14787 -0
  324. package/skills/archify/bin/archify.mjs +1990 -0
  325. package/skills/archify/bin/open-artifact.mjs +86 -0
  326. package/skills/archify/bin/preview.mjs +648 -0
  327. package/skills/archify/bin/visual-check.mjs +829 -0
  328. package/skills/archify/brand-marks/README.md +31 -0
  329. package/skills/archify/brand-marks/catalog.json +131 -0
  330. package/skills/archify/delta/architecture-delta.mjs +1214 -0
  331. package/skills/archify/examples/agent-run.lifecycle.json +71 -0
  332. package/skills/archify/examples/agent-tool-call.workflow.json +94 -0
  333. package/skills/archify/examples/async-job-roundtrip.sequence.json +61 -0
  334. package/skills/archify/examples/brand-aware-delivery.architecture.json +47 -0
  335. package/skills/archify/examples/cache-miss-request.sequence.json +81 -0
  336. package/skills/archify/examples/checkout-platform.base.architecture.json +31 -0
  337. package/skills/archify/examples/checkout-platform.head.architecture.json +31 -0
  338. package/skills/archify/examples/dataflow-product-analytics.html +14898 -0
  339. package/skills/archify/examples/deployment-release.lifecycle.json +49 -0
  340. package/skills/archify/examples/event-stream.dataflow.json +57 -0
  341. package/skills/archify/examples/incident-response.workflow.json +64 -0
  342. package/skills/archify/examples/lifecycle-agent-run.html +14847 -0
  343. package/skills/archify/examples/product-analytics.dataflow.json +76 -0
  344. package/skills/archify/examples/production-deployment.architecture.json +71 -0
  345. package/skills/archify/examples/release-delivery.workflow.json +62 -0
  346. package/skills/archify/examples/sequence-cache-miss-request.html +14913 -0
  347. package/skills/archify/examples/web-app-rendered.html +14862 -0
  348. package/skills/archify/examples/web-app.architecture.json +46 -0
  349. package/skills/archify/examples/workflow-agent-tool-call-rendered.html +14904 -0
  350. package/skills/archify/migrations/workflow-v2.mjs +279 -0
  351. package/skills/archify/package.json +17 -0
  352. package/skills/archify/recipes/scenarios.mjs +391 -0
  353. package/skills/archify/references/authoring-contract.md +198 -0
  354. package/skills/archify/references/brand-marks.md +69 -0
  355. package/skills/archify/references/delivery-contract.md +116 -0
  356. package/skills/archify/references/viewer-runtime.md +45 -0
  357. package/skills/archify/renderers/architecture/grid.mjs +62 -0
  358. package/skills/archify/renderers/architecture/render-architecture.mjs +1078 -0
  359. package/skills/archify/renderers/dataflow/README.md +104 -0
  360. package/skills/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  361. package/skills/archify/renderers/lifecycle/README.md +115 -0
  362. package/skills/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  363. package/skills/archify/renderers/sequence/README.md +114 -0
  364. package/skills/archify/renderers/sequence/render-sequence.mjs +453 -0
  365. package/skills/archify/renderers/shared/brand-marks.mjs +563 -0
  366. package/skills/archify/renderers/shared/cli.mjs +218 -0
  367. package/skills/archify/renderers/shared/desktop-readability.mjs +26 -0
  368. package/skills/archify/renderers/shared/diagnostics.mjs +127 -0
  369. package/skills/archify/renderers/shared/engineering-profiles.mjs +157 -0
  370. package/skills/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  371. package/skills/archify/renderers/shared/generated-validators.mjs +13 -0
  372. package/skills/archify/renderers/shared/geometry.mjs +1423 -0
  373. package/skills/archify/renderers/shared/i18n.mjs +594 -0
  374. package/skills/archify/renderers/shared/layout-report.mjs +40 -0
  375. package/skills/archify/renderers/shared/legend.mjs +217 -0
  376. package/skills/archify/renderers/shared/output-path.mjs +321 -0
  377. package/skills/archify/renderers/shared/repository-evidence.mjs +235 -0
  378. package/skills/archify/renderers/shared/text-fit.mjs +49 -0
  379. package/skills/archify/renderers/shared/utils.mjs +232 -0
  380. package/skills/archify/renderers/shared/validator.mjs +86 -0
  381. package/skills/archify/renderers/workflow/README.md +223 -0
  382. package/skills/archify/renderers/workflow/render-workflow.mjs +35 -0
  383. package/skills/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  384. package/skills/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  385. package/skills/archify/schemas/README.md +211 -0
  386. package/skills/archify/schemas/architecture.schema.json +176 -0
  387. package/skills/archify/schemas/common.schema.json +115 -0
  388. package/skills/archify/schemas/dataflow.schema.json +243 -0
  389. package/skills/archify/schemas/lifecycle.schema.json +266 -0
  390. package/skills/archify/schemas/sequence.schema.json +223 -0
  391. package/skills/archify/schemas/workflow.schema.json +428 -0
  392. package/skills/archify/scripts/check-render-output.mjs +835 -0
  393. package/skills/archify/scripts/check-update.mjs +1667 -0
  394. package/skills/archify/scripts/render-examples.mjs +26 -0
  395. package/skills/archify/scripts/update-contract.mjs +182 -0
  396. package/skills/archify/skill-release.json +10 -0
  397. package/skills/artifacts-builder/SKILL.md +120 -0
  398. package/skills/artifacts-builder/reference/diagramas.md +123 -0
  399. package/skills/artifacts-builder/reference/estilo.md +123 -0
  400. package/skills/artifacts-builder/reference/exportar-pdf.md +56 -0
  401. package/skills/artifacts-builder/reference/graficas.md +22 -0
  402. package/skills/artifacts-builder/scripts/bundle_artifact.py +109 -0
  403. package/skills/artifacts-builder/scripts/validate_artifact.py +345 -0
  404. package/skills/xone-hotswap/SKILL.md +185 -0
  405. package/skills/xone-hotswap/references/comandos.md +706 -0
  406. package/skills/xone-hotswap/references/conexion-y-despliegue.md +226 -0
@@ -0,0 +1,440 @@
1
+ /**
2
+ * Las sesiones de un proyecto, en su `.xonecode/sesiones/`.
3
+ *
4
+ * Ahí y no en global porque la sesión es del proyecto, ya hay precedente
5
+ * (`conversation_history/` en `agent/memoriaDeProyecto.ts`), la carpeta está denegada
6
+ * entera al agente (`permisosDe`) y **no sube nunca** a CloudStudio — el mismo trato que
7
+ * `.xonecode/` recibe en todas partes de este repo.
8
+ *
9
+ * Se guardan **actos** (`core/actos.ts`), no `DomainEvent`. La distinción no es cosmética:
10
+ * ningún evento lleva el texto que escribió el usuario — `tool.detalle` es la única
11
+ * excepción, y es una lista blanca de campo de ruta, nunca prosa —, así que un fichero de
12
+ * eventos daría una sesión reabierta con respuestas y sin preguntas. Y por construcción no
13
+ * hay filtrado que hacer para cumplir «nada de diffs ni contenido de fichero»: el tipo
14
+ * `Acto` no tiene ningún campo que pueda llevarlos. El único sitio del sistema donde el
15
+ * contenido de un fichero viaja es el mensaje de aprobación
16
+ * (`consolaWeb.ts#aprobacionesTui`), que no es un acto y se suelta en cuanto hay decisión
17
+ * — nunca llega aquí.
18
+ *
19
+ * Reabrir ya NO es releer, y este fichero dejó de ser la única memoria. El hilo del agente
20
+ * vive en el checkpointer de SQLite del proyecto (`agent/checkpointer.ts`), indexado por el
21
+ * mismo id que titula estas entradas, así que una sesión reabierta continúa de verdad. Lo
22
+ * que sigue viviendo aquí es el TRANSCRIPT —lo que se pinta—, y son dos cosas distintas a
23
+ * propósito: un acto no puede llevar contenido de fichero ni argumentos de tool, y un
24
+ * checkpoint los lleva todos. Por eso el `.jsonl` puede viajar y el `.sqlite` no.
25
+ * `historica` deja de ser «se reabrió» y pasa a ser un hecho comprobado: se pregunta al
26
+ * checkpointer, y solo se marca si de ese hilo no queda memoria —una sesión de antes de que
27
+ * esto existiera, o una cuyo primer turno nunca corrió—. Fingir que la conversación continúa
28
+ * cuando el modelo no recuerda nada sería justo la clase de mentira muda que este repo evita
29
+ * (`bitacora.ts` es el mismo principio aplicado a los avisos de honestidad).
30
+ * `historica` no se escribe a disco — no es un campo de `EntradaIndice` ni del `.jsonl` —
31
+ * porque es un hecho del MOMENTO de reabrir, no del estado de la sesión: quien reabre
32
+ * decide en memoria cuándo el primer turno nuevo la desactiva, y persistir la marca
33
+ * obligaría a un segundo sitio a mantenerla sincronizada con ese momento.
34
+ *
35
+ * `indice.json` se reescribe entero (es pequeño, una entrada por sesión) con el mismo
36
+ * cuidado atómico que `agent/settingsEnDisco.ts#escribirAtomico` — temporal + `renameSync`,
37
+ * porque un `writeFileSync` a medias tras un crash dejaría corrompido el índice de TODAS
38
+ * las sesiones, no solo la que se estaba anotando. El `.jsonl` de una sesión, en cambio, se
39
+ * **anexa** (`appendFileSync`): reescribirlo entero en cada acto lo haría cuadrático en el
40
+ * número de actos de la sesión, y arriesgaría perder la sesión completa a un crash a mitad
41
+ * de escritura en vez de, como mucho, la última línea — que `reabrirSesion` ya tolera.
42
+ */
43
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
44
+ import { randomUUID } from "node:crypto";
45
+ import { dirname, join } from "node:path";
46
+ import { acumularTotales, consumoDeLosActos } from "../../core/actos.js";
47
+ import { carpetaDeArtefactosDeSesion } from "../../core/artefactos.js";
48
+ import { segmentoSeguro } from "../../core/settings.js";
49
+ import { tituloDesde } from "../../core/textos.js";
50
+ /** Cuántos caracteres de la primera prosa del usuario se guardan como título. */
51
+ const LARGO_TITULO = 80;
52
+ /**
53
+ * El título automático de una sesión, a partir de su primera petición.
54
+ *
55
+ * Se movió a `core/textos.ts` cuando las TAREAS necesitaron el mismo título: `core/` no
56
+ * puede importar de `web/`, y una segunda copia habría divergido. Se reexporta con su
57
+ * nombre de siempre porque `anotarActo`, en este mismo fichero, y sus tests lo usan desde
58
+ * aquí.
59
+ */
60
+ export { tituloDesde };
61
+ function carpetaSesiones(raiz) {
62
+ return join(raiz, ".xonecode", "sesiones");
63
+ }
64
+ function rutaIndice(raiz) {
65
+ return join(carpetaSesiones(raiz), "indice.json");
66
+ }
67
+ /** `crearSesion` genera el id con `randomUUID()`, pero `anotarActo` y `reabrirSesion` lo
68
+ * reciben tal cual llega del cliente por HTTP: sin esta guarda un id como `"../../.env"`
69
+ * compondría una ruta fuera de `sesiones/`. Misma función que usa `rutaDeWorkspace` en
70
+ * `core/settings.ts`, no una copia — dos copias es cómo diverge la guarda el día que una
71
+ * se corrija y la otra no.
72
+ */
73
+ function rutaJsonl(raiz, id) {
74
+ return join(carpetaSesiones(raiz), `${segmentoSeguro(id, "id de sesión")}.jsonl`);
75
+ }
76
+ /** Una entrada que no es un objeto reconocible no cuenta: sin este filtro, un índice con
77
+ * basura colada (`[null]`, `[42]`) hace que `entradas.find` reviente en cuanto alguien lea
78
+ * `.id` de un elemento que no lo tiene.
79
+ */
80
+ function esEntrada(v) {
81
+ return typeof v === "object" && v !== null && typeof v.id === "string";
82
+ }
83
+ /** Lee el índice para MOSTRARLO (`listarSesiones`); sin fichero o con JSON roto, una lista
84
+ * vacía — un índice no se puede reconstruir solo leyéndolo, así que fallar aquí no puede
85
+ * tumbar la reapertura de ninguna sesión (mismo principio que la línea corrupta del
86
+ * `.jsonl`, aplicado al índice). Nunca la uses como base de una ESCRITURA: ver
87
+ * `leerIndiceOAbortar`.
88
+ */
89
+ function leerIndice(raiz) {
90
+ const ruta = rutaIndice(raiz);
91
+ if (!existsSync(ruta))
92
+ return [];
93
+ try {
94
+ const bruto = JSON.parse(readFileSync(ruta, "utf8"));
95
+ return Array.isArray(bruto) ? bruto.filter(esEntrada) : [];
96
+ }
97
+ catch {
98
+ return [];
99
+ }
100
+ }
101
+ /** Un índice roto (JSON que no parsea, o que no es una lista) no se puede persistir como
102
+ * base: usar aquí la lista vacía que devuelve `leerIndice` para un JSON roto BORRARÍA del
103
+ * disco todas las sesiones que el índice roto todavía nombraba — el `.jsonl` de cada
104
+ * sesión sigue intacto, pero sin su entrada es irrecuperable. Misma disciplina que
105
+ * `settingsEnDisco.ts#leerCrudoOAbortar`: la lectura que alimenta una escritura PARA sin
106
+ * escribir ante JSON roto, en vez de recuperar el fichero por su cuenta.
107
+ */
108
+ export class IndiceDeSesionesRoto extends Error {
109
+ }
110
+ function leerIndiceOAbortar(raiz) {
111
+ const ruta = rutaIndice(raiz);
112
+ if (!existsSync(ruta))
113
+ return [];
114
+ let bruto;
115
+ try {
116
+ bruto = JSON.parse(readFileSync(ruta, "utf8"));
117
+ }
118
+ catch {
119
+ throw new IndiceDeSesionesRoto(`«${ruta}»: el JSON es inválido; no se sobrescribe. Edita el fichero a mano.`);
120
+ }
121
+ if (!Array.isArray(bruto)) {
122
+ throw new IndiceDeSesionesRoto(`«${ruta}»: el JSON raíz debe ser una lista; no se sobrescribe.`);
123
+ }
124
+ return bruto.filter(esEntrada);
125
+ }
126
+ /** Temporal + `renameSync`, igual que `settingsEnDisco.ts#escribirAtomico`: un rename es
127
+ * atómico y un `writeFileSync` directo no lo es, así que un crash a mitad de escritura
128
+ * dejaría el índice de TODAS las sesiones truncado en vez de solo la última entrada.
129
+ */
130
+ function escribirIndice(raiz, entradas) {
131
+ const carpeta = carpetaSesiones(raiz);
132
+ mkdirSync(carpeta, { recursive: true });
133
+ const ruta = rutaIndice(raiz);
134
+ const temporal = join(carpeta, `.indice.json.${randomUUID()}.tmp`);
135
+ let descriptor;
136
+ try {
137
+ descriptor = openSync(temporal, "w");
138
+ writeFileSync(descriptor, JSON.stringify(entradas, null, 2) + "\n", "utf8");
139
+ closeSync(descriptor);
140
+ descriptor = undefined;
141
+ renameSync(temporal, ruta);
142
+ }
143
+ catch (error) {
144
+ if (descriptor !== undefined) {
145
+ try {
146
+ closeSync(descriptor);
147
+ }
148
+ catch {
149
+ // Un fallo al cerrar durante la recuperación no puede impedir borrar el temporal.
150
+ }
151
+ }
152
+ try {
153
+ unlinkSync(temporal);
154
+ }
155
+ catch {
156
+ // Si no llegó a crearse, no hay nada que limpiar.
157
+ }
158
+ throw error;
159
+ }
160
+ }
161
+ /** Crea una sesión nueva y devuelve su id. El id es `randomUUID()`: no compone rutas por
162
+ * construcción, pero pasa igualmente por `rutaJsonl` (vía `segmentoSeguro`) en cuanto se
163
+ * anota o se reabre — la guarda no distingue de dónde vino el id.
164
+ */
165
+ /**
166
+ * Da de alta una sesión en el índice.
167
+ *
168
+ * El id ENTRA por parámetro desde que es también el `thread_id` del grafo
169
+ * (`agent/checkpointer.ts`): quien abre la consola lo decide al abrir, porque el hilo tiene
170
+ * que existir antes del primer turno, y esto solo escribe la entrada. Sin id se genera uno,
171
+ * que es lo que hacía siempre y lo que sigue valiendo para quien no tenga hilo.
172
+ */
173
+ export function crearSesion(raiz, id = randomUUID(), tarea) {
174
+ const ahora = new Date().toISOString();
175
+ const entradas = leerIndiceOAbortar(raiz);
176
+ // La marca se escribe SOLO aquí, que es el único sitio donde se da de alta la entrada por
177
+ // el camino normal (`vestibulo.ts#volcar`, una vez por sesión) y donde se sabe por qué
178
+ // puerta se abrió. Ponerla en `anotarActo` la haría viajar en cada acto para decidir
179
+ // «solo si falta» en todos.
180
+ entradas.push({ id, titulo: "", creada: ahora, ultimoTurno: ahora, ...(tarea === undefined ? {} : { tarea }) });
181
+ escribirIndice(raiz, entradas);
182
+ return id;
183
+ }
184
+ /** Anexa un acto al `.jsonl` de la sesión y refresca su entrada en el índice: fija el
185
+ * título en el PRIMER acto `usuario` (y no se vuelve a tocar) y actualiza `ultimoTurno`
186
+ * en cada llamada, sea cual sea el tipo de acto.
187
+ *
188
+ * El anexado va ANTES de tocar el índice a propósito: si el índice está roto y
189
+ * `leerIndiceOAbortar` lanza, el acto ya quedó escrito. Un turno completo no se pierde
190
+ * solo porque el índice —que es prescindible, se puede reconstruir barriendo los
191
+ * `.jsonl`— esté corrompido.
192
+ */
193
+ export function anotarActo(raiz, id, acto) {
194
+ const ruta = rutaJsonl(raiz, id);
195
+ mkdirSync(carpetaSesiones(raiz), { recursive: true });
196
+ appendFileSync(ruta, JSON.stringify(acto) + "\n", "utf8");
197
+ const ahora = new Date().toISOString();
198
+ const entradas = leerIndiceOAbortar(raiz);
199
+ let entrada = entradas.find((e) => e.id === id);
200
+ if (entrada === undefined) {
201
+ // Anotar sin haber pasado por `crearSesion` (no debería pasar por el flujo normal,
202
+ // pero un índice perdido o corrupto no puede tumbar la escritura del acto, que ya
203
+ // ocurrió arriba): se da de alta la entrada con lo que se sabe en este momento.
204
+ entrada = {
205
+ id,
206
+ titulo: acto.tipo === "usuario" ? tituloDesde(acto.texto) : "",
207
+ creada: ahora,
208
+ ultimoTurno: ahora,
209
+ };
210
+ entradas.push(entrada);
211
+ }
212
+ else {
213
+ if (entrada.titulo === "" && acto.tipo === "usuario")
214
+ entrada.titulo = tituloDesde(acto.texto);
215
+ entrada.ultimoTurno = ahora;
216
+ }
217
+ anotarConsumoDeActo(raiz, id, entrada, acto);
218
+ escribirIndice(raiz, entradas);
219
+ }
220
+ /**
221
+ * Suma al acumulado de una entrada lo que aporta este acto. Monótono: solo suma, nunca resta,
222
+ * y un acto que no trae consumo —o un `fin` de una sesión anterior a que se midiera— deja la
223
+ * entrada como estaba. **Un cero no se estampa**: ausente es «no consta», y escribir ceros ahí
224
+ * convertiría «no sé lo que gastó» en «no gastó nada».
225
+ *
226
+ * La regla que importa es qué hacer cuando la entrada TODAVÍA no trae acumulado, y no es sumar
227
+ * el delta: eso dejaría en el índice el gasto del ÚLTIMO turno con la forma de un total de la
228
+ * sesión —una sesión de 11k que hace un turno de 3k quedaría en 3k, y nadie lo notaría porque
229
+ * el número es plausible—. Ahí se relee el `.jsonl` —que ya lleva este acto dentro, porque el
230
+ * anexado va primero— y se suma la sesión entera. Es como mucho UNA lectura por sesión: en
231
+ * cuanto el acumulado consta, esto pasa a ser una suma de dos objetos.
232
+ *
233
+ * Se apoya en `reabrirSesion` y no en un lector propio: es el ÚNICO que sabe leer un `.jsonl`
234
+ * —saltando la línea trunca en vez de tumbar la lectura—, y un segundo lector sería un segundo
235
+ * sitio donde esa tolerancia puede dejar de estar.
236
+ */
237
+ function anotarConsumoDeActo(raiz, id, entrada, acto) {
238
+ if (acto.tipo !== "fin" || acto.consumo === undefined)
239
+ return;
240
+ const bruto = entrada.consumo === undefined
241
+ ? consumoDeLosActos(reabrirSesion(raiz, id).actos)
242
+ : acumularTotales(entrada.consumo, acto.consumo);
243
+ // `consumoDeLosActos` contesta «no consta» si el `.jsonl` no tiene ningún `fin` con consumo
244
+ // —una sesión entera anterior a esto—, y entonces no hay nada que estampar.
245
+ //
246
+ // Y se NORMALIZA con `acumularTotales`, pase por donde pase, para que la ventana no entre:
247
+ // la que trae `consumoDeLosActos` es la del último turno que midió, y dentro de un acumulado
248
+ // sería un «ahora» congelado que alguien leería como el de hoy. El `.jsonl` la sigue
249
+ // teniendo, que es donde se mide.
250
+ if (bruto !== undefined)
251
+ entrada.consumo = acumularTotales(undefined, bruto);
252
+ }
253
+ /**
254
+ * SIEMBRA la marca de tarea en una sesión que ya estaba en el índice. Devuelve si la tocó.
255
+ *
256
+ * Existe por las sesiones de tarea anteriores a `EntradaIndice.tarea`: sin esto, la primera
257
+ * que hubo en cada proyecto se queda para siempre pintada como una conversación. La corre el
258
+ * corredor al arrancar, recorriendo su propia cola — o sea leyendo la autoridad sobre de
259
+ * quién es cada sesión, la misma que escribió el dato.
260
+ *
261
+ * **Es MONOTÓNICA, y de ahí sale que sea segura**: solo añade. No pisa una marca puesta —la
262
+ * del disco es la que escribió quien abrió la sesión— y no quita ninguna, así que no hay
263
+ * forma de que convierta una sesión de tarea en una conversación, que es el único fallo
264
+ * abierto posible por aquí. Correrla dos veces no hace nada la segunda.
265
+ *
266
+ * Y **no da de alta la entrada que falte**: la cola vive en `~/.xonecode/tareas` y el índice
267
+ * en el proyecto, así que una tarea puede nombrar una sesión que alguien borró; crearla la
268
+ * resucitaría en la barra apuntando a un `.jsonl` que ya no está.
269
+ */
270
+ export function marcarTareaDeSesion(raiz, id, tarea) {
271
+ const entradas = leerIndiceOAbortar(raiz);
272
+ const entrada = entradas.find((e) => e.id === id);
273
+ if (entrada === undefined || entrada.tarea !== undefined)
274
+ return false;
275
+ entrada.tarea = tarea;
276
+ escribirIndice(raiz, entradas);
277
+ return true;
278
+ }
279
+ /** Cuántas sesiones rellena UNA pasada de `sembrarConsumosPendientes`. */
280
+ export const SESIONES_A_SEMBRAR = 12;
281
+ /** Y por encima de este tamaño no se siembra: la siembra es SÍNCRONA y corre en el bucle de
282
+ * eventos, así que un `.jsonl` enorme congelaría el servidor mientras lo lee. */
283
+ export const TOPE_DE_BYTES_DE_SIEMBRA = 4 * 1024 * 1024;
284
+ /**
285
+ * Rellena el acumulado de las sesiones que ya existían antes de que se estampara. Devuelve
286
+ * cuántas tocó, que es lo que decide si merece la pena reanunciar el alta.
287
+ *
288
+ * Existe porque sin ella la función nace VACÍA en todas las sesiones anteriores: el índice solo
289
+ * aprende el gasto de una sesión cuando alguien la usa, y las que nadie vuelve a abrir se
290
+ * quedarían sin cifra para siempre. Esto es una siembra de PRESENTACIÓN, y no sostiene ninguna
291
+ * corrección: si no llega a una sesión —por el tope de número, por el de bytes o porque su
292
+ * `.jsonl` se fue— lo peor que pasa es que no enseñe cifra hasta su próximo turno, y entonces
293
+ * enseñará la BUENA (`anotarConsumoDeActo` relee cuando no hay acumulado del que partir).
294
+ *
295
+ * **Es MONOTÓNICA, como `marcarTareaDeSesion` y por el mismo motivo**: solo mira las entradas
296
+ * que NO traen acumulado, así que no puede pisar el de ninguna, y correrla dos veces no hace
297
+ * nada la segunda. Devuelve 0 la segunda vez.
298
+ *
299
+ * **Y no da de alta la entrada que falte**, tampoco como la otra: un `.jsonl` sin entrada en el
300
+ * índice es una sesión que alguien borró, y resucitarla la devolvería a la barra apuntando a un
301
+ * fichero que ya no está.
302
+ *
303
+ * Va de las MÁS RECIENTES hacia atrás porque el tope de número tiene que elegir, y lo que se
304
+ * mira en la barra es lo último que se hizo. **UNA sola escritura** al final y no una por
305
+ * entrada: el índice se reescribe entero cada vez.
306
+ */
307
+ export function sembrarConsumosPendientes(raiz) {
308
+ const entradas = leerIndiceOAbortar(raiz);
309
+ const pendientes = entradas
310
+ .filter((e) => e.consumo === undefined)
311
+ // `String(...)` porque `esEntrada` solo comprueba el `id`: un índice tocado a mano puede
312
+ // traer aquí lo que sea, y esto no es sitio para reventar por un campo mal escrito.
313
+ .sort((a, b) => String(b.ultimoTurno).localeCompare(String(a.ultimoTurno)))
314
+ .slice(0, SESIONES_A_SEMBRAR);
315
+ let sembradas = 0;
316
+ for (const entrada of pendientes) {
317
+ const ruta = rutaJsonl(raiz, entrada.id);
318
+ try {
319
+ if (!existsSync(ruta) || statSync(ruta).size > TOPE_DE_BYTES_DE_SIEMBRA)
320
+ continue;
321
+ }
322
+ catch {
323
+ continue; // Un `.jsonl` que no se puede ni medir no se siembra; no es un error.
324
+ }
325
+ const total = consumoDeLosActos(reabrirSesion(raiz, entrada.id).actos);
326
+ if (total === undefined)
327
+ continue;
328
+ // Y se NORMALIZA con `acumularTotales` igual que el estampado, por la MISMA razón y con la
329
+ // misma función: `consumoDeLosActos` se queda con la ventana del último `fin` que la traiga
330
+ // —es su contrato, y hace falta en la piel—, así que sin esto la siembra escribía en el
331
+ // índice un «cuánto ocupa el historial ahora» de un turno de anteayer. Nadie lo pinta hoy
332
+ // (la ventana va en su propio mensaje), que es justo por lo que no se notó: una cifra muerta
333
+ // en disco es una cifra que alguien leerá mañana creyendo que es la de hoy.
334
+ entrada.consumo = acumularTotales(undefined, total);
335
+ sembradas++;
336
+ }
337
+ if (sembradas > 0)
338
+ escribirIndice(raiz, entradas);
339
+ return sembradas;
340
+ }
341
+ /**
342
+ * Borra una sesión: su `.jsonl` y su entrada del índice. Devuelve si había algo que borrar.
343
+ *
344
+ * El fichero va PRIMERO y el índice después, al revés que en `anotarActo` y por el mismo
345
+ * razonamiento invertido: aquí lo que no se puede quedar a medias es una entrada de índice
346
+ * apuntando a un fichero que ya no está —la sesión saldría en la barra y reventaría al
347
+ * abrirla—. Al revés, un `.jsonl` huérfano no lo ve nadie: la barra se pinta con el índice.
348
+ *
349
+ * Un id desconocido devuelve `false` en vez de lanzar: borrar dos veces la misma sesión —dos
350
+ * pestañas abiertas, un doble clic— no es un error, y lo único que hay que saber es si
351
+ * quedaba algo.
352
+ */
353
+ export function borrarSesion(raiz, id) {
354
+ const ruta = rutaJsonl(raiz, id);
355
+ const habia = existsSync(ruta);
356
+ if (habia)
357
+ unlinkSync(ruta);
358
+ // Y sus artefactos, que son de esta sesión y de nadie más. Sin esto, borrar una
359
+ // conversación dejaría en disco los diagramas que se dibujaron en ella, invisibles desde
360
+ // la interfaz — el mismo agujero que dejaba su hilo del checkpointer antes de
361
+ // `olvidarHilo`. `force` porque la carpeta solo existe si el agente escribió algo.
362
+ rmSync(dirname(carpetaDeArtefactosDeSesion(raiz, id)), { recursive: true, force: true });
363
+ const entradas = leerIndiceOAbortar(raiz);
364
+ const quedan = entradas.filter((e) => e.id !== id);
365
+ if (quedan.length === entradas.length)
366
+ return habia;
367
+ escribirIndice(raiz, quedan);
368
+ return true;
369
+ }
370
+ /**
371
+ * Le pone nombre a una sesión. Devuelve si existía.
372
+ *
373
+ * Un título vacío se RECHAZA, y no es una validación de formulario: `anotarActo` fija el
374
+ * título en el primer acto de usuario y solo mientras esté vacío (`entrada.titulo === ""`).
375
+ * Dejarlo vacío devolvería la sesión al régimen automático, así que el siguiente turno la
376
+ * rebautizaría con la primera frase y el nombre que puso una persona desaparecería sin más.
377
+ * Se acota a `LARGO_TITULO` como los automáticos: la barra tiene el ancho que tiene.
378
+ */
379
+ export function renombrarSesion(raiz, id, titulo) {
380
+ const limpio = titulo.trim().slice(0, LARGO_TITULO);
381
+ if (limpio === "")
382
+ return false;
383
+ const entradas = leerIndiceOAbortar(raiz);
384
+ const entrada = entradas.find((e) => e.id === id);
385
+ if (entrada === undefined)
386
+ return false;
387
+ entrada.titulo = limpio;
388
+ escribirIndice(raiz, entradas);
389
+ return true;
390
+ }
391
+ /**
392
+ * Fija —o quita, con `undefined`— el dispositivo preferido de una sesión.
393
+ *
394
+ * Devuelve si había una entrada que tocar: una sesión cuyo id todavía no existe en el índice
395
+ * (nace al volcar el primer acto) no se puede anotar aquí, y quien llama tiene que guardarlo
396
+ * en memoria hasta entonces — decirlo con un `false` es mejor que crear una entrada a medias
397
+ * que la barra enseñaría como una sesión vacía.
398
+ */
399
+ export function elegirDispositivo(raiz, id, dispositivo) {
400
+ const entradas = leerIndiceOAbortar(raiz);
401
+ const entrada = entradas.find((e) => e.id === id);
402
+ if (entrada === undefined)
403
+ return false;
404
+ if (dispositivo === undefined)
405
+ delete entrada.dispositivo;
406
+ else
407
+ entrada.dispositivo = dispositivo;
408
+ escribirIndice(raiz, entradas);
409
+ return true;
410
+ }
411
+ /** El índice completo, tal cual lo enseña la lista de sesiones del proyecto. */
412
+ export function listarSesiones(raiz) {
413
+ return leerIndice(raiz);
414
+ }
415
+ /** Relee una sesión entera. Una línea que no parsea (fichero truncado a mitad de un
416
+ * `appendFileSync`, por ejemplo por un crash) se SALTA en vez de tumbar la reapertura: una
417
+ * sesión que no se puede reabrir porque una línea se truncó es peor que una que reabre con
418
+ * una línea de menos.
419
+ */
420
+ export function reabrirSesion(raiz, id) {
421
+ const ruta = rutaJsonl(raiz, id);
422
+ const actos = [];
423
+ if (existsSync(ruta)) {
424
+ for (const linea of readFileSync(ruta, "utf8").split("\n")) {
425
+ if (linea.trim() === "")
426
+ continue;
427
+ try {
428
+ actos.push(JSON.parse(linea));
429
+ }
430
+ catch {
431
+ // Línea corrupta: se salta, no se tumba la reapertura (ver comentario de cabecera).
432
+ }
433
+ }
434
+ }
435
+ // El dispositivo preferido sale del ÍNDICE y no del `.jsonl`: es un dato de la sesión, no
436
+ // uno de sus actos, y reabrir tiene que devolverlo o la elección se perdería al releer.
437
+ const dispositivo = leerIndice(raiz).find((e) => e.id === id)?.dispositivo;
438
+ return { id, actos, historica: true, ...(dispositivo === undefined ? {} : { dispositivo }) };
439
+ }
440
+ //# sourceMappingURL=sesiones.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sesiones.js","sourceRoot":"","sources":["../../../src/web/servidor/sesiones.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Las seis fases de un lanzamiento, EN ORDEN, y los cinco estados en que puede estar.
3
+ *
4
+ * **Se declaran aquí, en el cable, y no se importan de `agent/lanzamientoEnMaquina.ts`**, que es
5
+ * quien las recorre. El motivo es el de siempre en este fichero: el cable tiene su vocabulario
6
+ * CERRADO, y quien lo cierra es esta constante — la lista blanca del store del cliente y la
7
+ * validación del servidor se escriben contra ESTA lista, así que un valor que no esté aquí no
8
+ * llega a la pantalla. Importarlas ataría el contrato del cable al módulo que hoy lo cumple, y
9
+ * el día que ese módulo añada una fase el cable la aceptaría sin que nadie hubiera decidido si
10
+ * el cliente sabe pintarla.
11
+ *
12
+ * **Y por eso mismo hay un test que las ata** (`arranque.test.ts`: «las fases del cable son las
13
+ * que corre la máquina»): la lista de aquí no puede quedarse corta respecto de la de allí, o el
14
+ * recorrido se quedaría sin emitir justo la fase que alguien acaba de añadir.
15
+ *
16
+ * **`corriendo` no está en `EstadoDeLanzamiento` de la máquina, y aquí sí.** Allí el estado es un
17
+ * DESENLACE —cuatro formas de acabar—, porque `lanzarEnDispositivo` devuelve un resultado; aquí
18
+ * hay además un RECORRIDO EN VIVO, que es lo que permite que la pestaña enseñe en qué fase va
19
+ * en vez de un botón apagado sin explicación.
20
+ */
21
+ export const FASES_DEL_LANZAMIENTO = [
22
+ "comprobando",
23
+ "empaquetando",
24
+ "subiendo",
25
+ "reiniciando",
26
+ "lanzando",
27
+ "comprobando-arranque",
28
+ ];
29
+ export const ESTADOS_DEL_LANZAMIENTO = ["corriendo", "ok", "fallo", "cancelada", "colgada"];
30
+ /**
31
+ * Una `Tarea` del índice traducida a lo que viaja. **La raíz del proyecto se queda aquí.**
32
+ *
33
+ * **Vive en este fichero, exportada, y eso es el arreglo de F1.** Era una copia de campos a
34
+ * mano enterrada en el cierre de `montarRutas` (`arranque.ts`), a mil líneas del tipo que
35
+ * traduce y dentro de algo que todos sus tests doblan — o sea el patrón de fallo que
36
+ * `CLAUDE.md` documenta cinco veces en esta misma tanda: «si una regla de producción se
37
+ * compone dentro de algo que los tests simulan, esa regla no está probada: está escrita».
38
+ * `veredicto` se cayó aquí y en el store del cliente sin que nada se pusiera rojo. Ahora
39
+ * `transporte.test.ts` recorre los campos de `Tarea` y exige decisión explícita por cada
40
+ * uno.
41
+ *
42
+ * Campo a campo, y también DENTRO del veredicto: un `...tarea.veredicto` dejaría pasar sin
43
+ * nombrar el campo que alguien le añada mañana a `VeredictoDeTarea`.
44
+ */
45
+ export function filaDeTarea(t) {
46
+ return {
47
+ id: t.id,
48
+ // El ID, que es con lo que la interfaz filtra; el nombre va aparte, para leer. La RAÍZ
49
+ // no viaja: es una ruta de la máquina.
50
+ proyecto: t.proyecto.id,
51
+ proyectoNombre: t.proyecto.nombre,
52
+ titulo: t.titulo,
53
+ peticion: t.peticion,
54
+ encargo: t.encargo,
55
+ adjuntos: t.adjuntos,
56
+ estado: t.estado,
57
+ creada: t.creada,
58
+ ...(t.motivo === undefined ? {} : { motivo: t.motivo }),
59
+ ...(t.sesion === undefined ? {} : { sesion: t.sesion }),
60
+ ...(t.empezada === undefined ? {} : { empezada: t.empezada }),
61
+ ...(t.acabada === undefined ? {} : { acabada: t.acabada }),
62
+ ...(t.autorizadas === undefined ? {} : { autorizadas: t.autorizadas }),
63
+ ...(t.feedback === undefined ? {} : { feedback: t.feedback }),
64
+ ...(t.veredicto === undefined
65
+ ? {}
66
+ : {
67
+ veredicto: {
68
+ veredicto: t.veredicto.veredicto,
69
+ resumen: t.veredicto.resumen,
70
+ ...(t.veredicto.hallazgos === undefined ? {} : { hallazgos: t.veredicto.hallazgos }),
71
+ ...(t.veredicto.salvedad === undefined ? {} : { salvedad: t.veredicto.salvedad }),
72
+ },
73
+ }),
74
+ ...(t.terminadaAMano === undefined ? {} : { terminadaAMano: t.terminadaAMano }),
75
+ };
76
+ }
77
+ /**
78
+ * Las clases de mensaje que SON el transcript, y las únicas que llegan a un mirón.
79
+ *
80
+ * Lista blanca y no negra: con una negra, la clase que alguien añada mañana al cable
81
+ * llegaría permitida a quien mira una tarea de fondo — y por ahí ya pasan hoy el
82
+ * mensaje `turno` que apagaría su compositor y el `aprobacion` que es el único mensaje con
83
+ * contenido de fichero dentro.
84
+ *
85
+ * **`lanzable` y `lanzamiento` NO entran aquí, y es una decisión, no un olvido.** El recorrido
86
+ * de un lanzamiento es un suceso de la MÁQUINA y del proyecto, no un renglón de la
87
+ * conversación: quien mira una tarea de fondo no tiene por qué ver las fases del lanzamiento de
88
+ * otra consola, y meterlo en esta lista sería exactamente lo que la lista blanca existe para
89
+ * impedir — colar por la puerta de atrás un mensaje que nadie decidió que fuera transcript. Se
90
+ * quedan fuera por la misma razón por la que se quedan fuera `instalacion`, `dispositivos` y
91
+ * `tareas`, que tampoco son la conversación.
92
+ */
93
+ const ES_DE_TRANSCRIPT = new Set(["acto", "sustitucion", "reemision"]);
94
+ export function crearTransporte(actos) {
95
+ const traza = [];
96
+ const escuchasDeCorte = [];
97
+ /** Todos los clientes vivos. `Set` y no lista: conectar dos veces el MISMO sumidero
98
+ * —una reconexión que se solapa con su propio cierre— no puede duplicar sus mensajes. */
99
+ const sumideros = new Set();
100
+ /**
101
+ * Quien MIRA sin ser cliente. Ver `Transporte.mirar`: aparte del otro conjunto porque no
102
+ * cuenta como humano y porque no recibe todo lo que se emite.
103
+ */
104
+ const mirones = new Set();
105
+ /**
106
+ * Hubo cliente alguna vez y todavía no se ha ido el último. Se lleva aparte del `Set`
107
+ * porque `conectar()` sin sumidero (los tests que no miran lo emitido) también cuenta
108
+ * como cliente: `eof()` mira esto, y decir que no hay nadie rechazaría sus aprobaciones.
109
+ */
110
+ let hayCliente = false;
111
+ return {
112
+ conectar(enviar) {
113
+ hayCliente = true;
114
+ if (enviar !== undefined)
115
+ sumideros.add(enviar);
116
+ return [...actos()];
117
+ },
118
+ desconectar(enviar) {
119
+ if (enviar !== undefined) {
120
+ sumideros.delete(enviar);
121
+ // Queda alguien mirando: no se despierta a nadie ni se corta nada. Lo que se fue
122
+ // es una pestaña, no la conversación.
123
+ if (sumideros.size > 0)
124
+ return;
125
+ }
126
+ else {
127
+ sumideros.clear();
128
+ // Sin sumidero es «se van todos»: lo hace `cerrar()` y lo hace mudarse de consola.
129
+ // Un mirón de una consola que se abandona escribe en un socket que ya no está.
130
+ mirones.clear();
131
+ }
132
+ hayCliente = false;
133
+ for (const escucha of escuchasDeCorte)
134
+ escucha();
135
+ },
136
+ soltar(enviar) {
137
+ if (enviar === undefined)
138
+ sumideros.clear();
139
+ else
140
+ sumideros.delete(enviar);
141
+ },
142
+ conectado: () => hayCliente,
143
+ mirar(enviar) {
144
+ mirones.add(enviar);
145
+ return [...actos()];
146
+ },
147
+ dejarDeMirar(enviar) {
148
+ mirones.delete(enviar);
149
+ },
150
+ emitir(mensaje) {
151
+ if (mensaje.clase !== "aprobacion")
152
+ traza.push(mensaje);
153
+ // A TODOS los clientes vivos. Con una sola ranura, el último en conectar dejaba mudos
154
+ // a los anteriores sin decírselo.
155
+ for (const sumidero of sumideros)
156
+ sumidero(mensaje);
157
+ // Y a los mirones, solo el TRANSCRIPT. Ver `Transporte.mirar`.
158
+ if (!ES_DE_TRANSCRIPT.has(mensaje.clase))
159
+ return;
160
+ for (const miron of mirones)
161
+ miron(mensaje);
162
+ },
163
+ emitidos: () => traza,
164
+ alDesconectar(escucha) {
165
+ escuchasDeCorte.push(escucha);
166
+ },
167
+ };
168
+ }
169
+ //# sourceMappingURL=transporte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transporte.js","sourceRoot":"","sources":["../../../src/web/servidor/transporte.ts"],"names":[],"mappings":"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"}