xonecode 0.5.1 → 0.8.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 (315) hide show
  1. package/apps/web/dist/assets/{index-BB3SamhR.css → index-Boak51UP.css} +1 -1
  2. package/apps/web/dist/assets/index-Cg28x6nG.js +477 -0
  3. package/apps/web/dist/assets/{php-D_2--9WK.js → php-Cu6F_QCJ.js} +1 -1
  4. package/apps/web/dist/assets/{ruby-DSHSDbk1.js → ruby-BiqQPoC6.js} +1 -1
  5. package/apps/web/dist/index.html +2 -2
  6. package/dist/agent/{cloudstudioClient.js → cloudstudio/cloudstudioClient.js} +10 -0
  7. package/dist/agent/cloudstudio/cloudstudioClient.js.map +1 -0
  8. package/dist/agent/{cloudstudioMcp.js → cloudstudio/cloudstudioMcp.js} +5 -5
  9. package/dist/agent/cloudstudio/cloudstudioMcp.js.map +1 -0
  10. package/dist/agent/{descarga.js → cloudstudio/descarga.js} +17 -7
  11. package/dist/agent/cloudstudio/descarga.js.map +1 -0
  12. package/dist/agent/cloudstudio/manifiesto.js.map +1 -0
  13. package/dist/agent/cloudstudio/ramaActiva.js +11 -0
  14. package/dist/agent/cloudstudio/ramaActiva.js.map +1 -0
  15. package/dist/agent/{subida.js → cloudstudio/subida.js} +16 -7
  16. package/dist/agent/cloudstudio/subida.js.map +1 -0
  17. package/dist/agent/{zip.js → cloudstudio/zip.js} +1 -1
  18. package/dist/agent/cloudstudio/zip.js.map +1 -0
  19. package/dist/agent/{authEnDisco.js → config/authEnDisco.js} +3 -3
  20. package/dist/agent/config/authEnDisco.js.map +1 -0
  21. package/dist/agent/{catalogoModelos.js → config/catalogoModelos.js} +47 -1
  22. package/dist/agent/config/catalogoModelos.js.map +1 -0
  23. package/dist/agent/{configEnDisco.js → config/configEnDisco.js} +6 -6
  24. package/dist/agent/config/configEnDisco.js.map +1 -0
  25. package/dist/agent/{crearProyecto.js → config/crearProyecto.js} +2 -2
  26. package/dist/agent/config/crearProyecto.js.map +1 -0
  27. package/dist/agent/config/entorno.js.map +1 -0
  28. package/dist/agent/config/gemini.js.map +1 -0
  29. package/dist/agent/config/modelos.js +235 -0
  30. package/dist/agent/config/modelos.js.map +1 -0
  31. package/dist/agent/{modelosDeMotor.js → config/modelosDeMotor.js} +1 -1
  32. package/dist/agent/config/modelosDeMotor.js.map +1 -0
  33. package/dist/agent/config/mudanzaEnDisco.js +121 -0
  34. package/dist/agent/config/mudanzaEnDisco.js.map +1 -0
  35. package/dist/agent/{persona.js → config/persona.js} +1 -1
  36. package/dist/agent/config/persona.js.map +1 -0
  37. package/dist/agent/config/selectorEnMaquina.js +45 -0
  38. package/dist/agent/config/selectorEnMaquina.js.map +1 -0
  39. package/dist/agent/{settingsEnDisco.js → config/settingsEnDisco.js} +37 -2
  40. package/dist/agent/config/settingsEnDisco.js.map +1 -0
  41. package/dist/agent/{versionEnDisco.js → config/versionEnDisco.js} +8 -4
  42. package/dist/agent/config/versionEnDisco.js.map +1 -0
  43. package/dist/agent/dispositivos/arranqueDeEmulador.js +146 -0
  44. package/dist/agent/dispositivos/arranqueDeEmulador.js.map +1 -0
  45. package/dist/agent/{dispositivosEnMaquina.js → dispositivos/dispositivosEnMaquina.js} +93 -6
  46. package/dist/agent/dispositivos/dispositivosEnMaquina.js.map +1 -0
  47. package/dist/agent/dispositivos/hotswap.js.map +1 -0
  48. package/dist/agent/dispositivos/instalacionEnMaquina.js.map +1 -0
  49. package/dist/agent/dispositivos/juezVisual.js +152 -0
  50. package/dist/agent/dispositivos/juezVisual.js.map +1 -0
  51. package/dist/agent/{lanzamientoEnMaquina.js → dispositivos/lanzamientoEnMaquina.js} +1 -1
  52. package/dist/agent/dispositivos/lanzamientoEnMaquina.js.map +1 -0
  53. package/dist/agent/{paqueteDelProyecto.js → dispositivos/paqueteDelProyecto.js} +5 -5
  54. package/dist/agent/dispositivos/paqueteDelProyecto.js.map +1 -0
  55. package/dist/agent/dispositivos/procesosEnMaquina.js.map +1 -0
  56. package/dist/agent/dispositivos/sensorDeArranque.js +154 -0
  57. package/dist/agent/dispositivos/sensorDeArranque.js.map +1 -0
  58. package/dist/agent/exportarPdf.js +140 -0
  59. package/dist/agent/exportarPdf.js.map +1 -0
  60. package/dist/agent/{arbolDeProyecto.js → grafo/arbolDeProyecto.js} +2 -2
  61. package/dist/agent/grafo/arbolDeProyecto.js.map +1 -0
  62. package/dist/agent/{artefactosEnDisco.js → grafo/artefactosEnDisco.js} +2 -2
  63. package/dist/agent/grafo/artefactosEnDisco.js.map +1 -0
  64. package/dist/agent/{busquedaRegex.js → grafo/busquedaRegex.js} +41 -1
  65. package/dist/agent/grafo/busquedaRegex.js.map +1 -0
  66. package/dist/agent/grafo/criticaVisual.js +115 -0
  67. package/dist/agent/grafo/criticaVisual.js.map +1 -0
  68. package/dist/agent/grafo/excluirTools.js +82 -0
  69. package/dist/agent/grafo/excluirTools.js.map +1 -0
  70. package/dist/agent/{memoriaDeProyecto.js → grafo/memoriaDeProyecto.js} +1 -1
  71. package/dist/agent/grafo/memoriaDeProyecto.js.map +1 -0
  72. package/dist/agent/grafo/navegacionXone.js +231 -0
  73. package/dist/agent/grafo/navegacionXone.js.map +1 -0
  74. package/dist/agent/{perfiles.js → grafo/perfiles.js} +96 -10
  75. package/dist/agent/grafo/perfiles.js.map +1 -0
  76. package/dist/agent/{proyecto.js → grafo/proyecto.js} +274 -24
  77. package/dist/agent/grafo/proyecto.js.map +1 -0
  78. package/dist/agent/grafo/skills.js +425 -0
  79. package/dist/agent/grafo/skills.js.map +1 -0
  80. package/dist/agent/grafo/xoneAgent.js +566 -0
  81. package/dist/agent/grafo/xoneAgent.js.map +1 -0
  82. package/dist/agent/navegacion/estilosEnDisco.js +110 -0
  83. package/dist/agent/navegacion/estilosEnDisco.js.map +1 -0
  84. package/dist/agent/navegacion/hechosEnDisco.js +26 -0
  85. package/dist/agent/navegacion/hechosEnDisco.js.map +1 -0
  86. package/dist/agent/navegacion/indiceEnDisco.js +36 -0
  87. package/dist/agent/navegacion/indiceEnDisco.js.map +1 -0
  88. package/dist/agent/navegacion/modeloDeProyecto.js +228 -0
  89. package/dist/agent/navegacion/modeloDeProyecto.js.map +1 -0
  90. package/dist/agent/raizDelPaquete.js +56 -0
  91. package/dist/agent/raizDelPaquete.js.map +1 -0
  92. package/dist/agent/{checkpointer.js → sesiones/checkpointer.js} +1 -1
  93. package/dist/agent/sesiones/checkpointer.js.map +1 -0
  94. package/dist/agent/sesiones/git.js.map +1 -0
  95. package/dist/agent/{gitSync.js → sesiones/gitSync.js} +3 -3
  96. package/dist/agent/sesiones/gitSync.js.map +1 -0
  97. package/dist/agent/{sesionGit.js → sesiones/sesionGit.js} +2 -2
  98. package/dist/agent/sesiones/sesionGit.js.map +1 -0
  99. package/dist/agent/subagentes/agentesEnDisco.js +818 -0
  100. package/dist/agent/subagentes/agentesEnDisco.js.map +1 -0
  101. package/dist/agent/subagentes/consumoExterno.js.map +1 -0
  102. package/dist/agent/subagentes/escrituraDeCodex.js.map +1 -0
  103. package/dist/agent/{escrituraDeOpencode.js → subagentes/escrituraDeOpencode.js} +1 -1
  104. package/dist/agent/subagentes/escrituraDeOpencode.js.map +1 -0
  105. package/dist/agent/{escrituraExterna.js → subagentes/escrituraExterna.js} +59 -6
  106. package/dist/agent/subagentes/escrituraExterna.js.map +1 -0
  107. package/dist/agent/subagentes/pluginDeSkills.js +99 -0
  108. package/dist/agent/subagentes/pluginDeSkills.js.map +1 -0
  109. package/dist/agent/subagentes/subagenteCodex.js.map +1 -0
  110. package/dist/agent/{subagenteExterno.js → subagentes/subagenteExterno.js} +48 -0
  111. package/dist/agent/subagentes/subagenteExterno.js.map +1 -0
  112. package/dist/agent/{subagenteOpencode.js → subagentes/subagenteOpencode.js} +53 -1
  113. package/dist/agent/subagentes/subagenteOpencode.js.map +1 -0
  114. package/dist/agent/{aumentador.js → tareas/aumentador.js} +2 -2
  115. package/dist/agent/tareas/aumentador.js.map +1 -0
  116. package/dist/agent/{juezDeTarea.js → tareas/juezDeTarea.js} +6 -6
  117. package/dist/agent/tareas/juezDeTarea.js.map +1 -0
  118. package/dist/agent/{tareasEnDisco.js → tareas/tareasEnDisco.js} +53 -4
  119. package/dist/agent/tareas/tareasEnDisco.js.map +1 -0
  120. package/dist/agent/{diagnosticoDeTools.js → turno/diagnosticoDeTools.js} +5 -1
  121. package/dist/agent/turno/diagnosticoDeTools.js.map +1 -0
  122. package/dist/agent/{guionizado.js → turno/guionizado.js} +1 -1
  123. package/dist/agent/turno/guionizado.js.map +1 -0
  124. package/dist/agent/turno/informeDeTraza.js +245 -0
  125. package/dist/agent/turno/informeDeTraza.js.map +1 -0
  126. package/dist/agent/turno/inspectorDePrompt.js +205 -0
  127. package/dist/agent/turno/inspectorDePrompt.js.map +1 -0
  128. package/dist/agent/{instantanea.js → turno/instantanea.js} +7 -2
  129. package/dist/agent/turno/instantanea.js.map +1 -0
  130. package/dist/agent/{interrupts.js → turno/interrupts.js} +2 -2
  131. package/dist/agent/turno/interrupts.js.map +1 -0
  132. package/dist/agent/turno/mensajes.js.map +1 -0
  133. package/dist/agent/turno/normalizar.js.map +1 -0
  134. package/dist/agent/{puente.js → turno/puente.js} +71 -4
  135. package/dist/agent/turno/puente.js.map +1 -0
  136. package/dist/agent/turno/resumenDeContexto.js +260 -0
  137. package/dist/agent/turno/resumenDeContexto.js.map +1 -0
  138. package/dist/agent/{resumenDeTool.js → turno/resumenDeTool.js} +33 -0
  139. package/dist/agent/turno/resumenDeTool.js.map +1 -0
  140. package/dist/agent/turno/rubrica.js +91 -0
  141. package/dist/agent/turno/rubrica.js.map +1 -0
  142. package/dist/agent/turno/textoDeTool.js.map +1 -0
  143. package/dist/agent/{turnoReal.js → turno/turnoReal.js} +210 -25
  144. package/dist/agent/turno/turnoReal.js.map +1 -0
  145. package/dist/agent/turno/verificador.js.map +1 -0
  146. package/dist/cli/config.js +1 -1
  147. package/dist/cli/config.js.map +1 -1
  148. package/dist/cli/consola.js +72 -9
  149. package/dist/cli/consola.js.map +1 -1
  150. package/dist/cli/describe.js +2 -2
  151. package/dist/cli/describe.js.map +1 -1
  152. package/dist/cli/doctor.js +1 -1
  153. package/dist/cli/doctor.js.map +1 -1
  154. package/dist/cli/fuentesDeDisco.js +29 -0
  155. package/dist/cli/fuentesDeDisco.js.map +1 -0
  156. package/dist/cli/main.js +87 -31
  157. package/dist/cli/main.js.map +1 -1
  158. package/dist/cli/run.js +40 -10
  159. package/dist/cli/run.js.map +1 -1
  160. package/dist/cli/traza.js +48 -0
  161. package/dist/cli/traza.js.map +1 -0
  162. package/dist/cli/tui/correrTui.js +4 -4
  163. package/dist/cli/tui/correrTui.js.map +1 -1
  164. package/dist/cli/verify.js +1 -1
  165. package/dist/cli/verify.js.map +1 -1
  166. package/dist/core/actos.js +1 -1
  167. package/dist/core/adjuntos.js +2 -2
  168. package/dist/core/agentes.js +247 -7
  169. package/dist/core/agentes.js.map +1 -1
  170. package/dist/core/artefactos.js +4 -4
  171. package/dist/core/config.js +1 -1
  172. package/dist/core/contextos.js +12 -1
  173. package/dist/core/contextos.js.map +1 -1
  174. package/dist/core/descargas.js +1 -1
  175. package/dist/core/dispositivos.js +53 -3
  176. package/dist/core/dispositivos.js.map +1 -1
  177. package/dist/core/esfuerzo.js +141 -0
  178. package/dist/core/esfuerzo.js.map +1 -0
  179. package/dist/core/esqueleto.js +1 -1
  180. package/dist/core/estilos.js +78 -0
  181. package/dist/core/estilos.js.map +1 -0
  182. package/dist/core/exportacion.js +140 -0
  183. package/dist/core/exportacion.js.map +1 -0
  184. package/dist/core/hechosDelProyecto.js +87 -0
  185. package/dist/core/hechosDelProyecto.js.map +1 -0
  186. package/dist/core/logDeDispositivo.js +143 -0
  187. package/dist/core/logDeDispositivo.js.map +1 -0
  188. package/dist/core/modelos.js +48 -3
  189. package/dist/core/modelos.js.map +1 -1
  190. package/dist/core/mudanzaDeWorkspace.js +93 -0
  191. package/dist/core/mudanzaDeWorkspace.js.map +1 -0
  192. package/dist/core/navegacion.js +134 -0
  193. package/dist/core/navegacion.js.map +1 -0
  194. package/dist/core/notify.js +5 -0
  195. package/dist/core/notify.js.map +1 -1
  196. package/dist/core/planDeSubida.js +1 -1
  197. package/dist/core/planes.js +70 -0
  198. package/dist/core/planes.js.map +1 -0
  199. package/dist/core/ports.js +4 -0
  200. package/dist/core/ports.js.map +1 -1
  201. package/dist/core/rubrica.js +90 -0
  202. package/dist/core/rubrica.js.map +1 -0
  203. package/dist/core/selectorDeCarpeta.js +87 -0
  204. package/dist/core/selectorDeCarpeta.js.map +1 -0
  205. package/dist/core/settings.js +56 -7
  206. package/dist/core/settings.js.map +1 -1
  207. package/dist/core/shellDeAgente.js +144 -0
  208. package/dist/core/shellDeAgente.js.map +1 -0
  209. package/dist/core/skills.js +158 -0
  210. package/dist/core/skills.js.map +1 -0
  211. package/dist/core/topeAgotado.js +69 -0
  212. package/dist/core/topeAgotado.js.map +1 -0
  213. package/dist/core/zipDeSkill.js +107 -0
  214. package/dist/core/zipDeSkill.js.map +1 -0
  215. package/dist/web/servidor/arranque.js +853 -54
  216. package/dist/web/servidor/arranque.js.map +1 -1
  217. package/dist/web/servidor/corredorDeTareas.js +3 -3
  218. package/dist/web/servidor/corredorDeTareas.js.map +1 -1
  219. package/dist/web/servidor/sesiones.js +34 -6
  220. package/dist/web/servidor/sesiones.js.map +1 -1
  221. package/dist/web/servidor/transporte.js +1 -1
  222. package/dist/web/servidor/transporte.js.map +1 -1
  223. package/dist/web/servidor/vestibulo.js +62 -13
  224. package/dist/web/servidor/vestibulo.js.map +1 -1
  225. package/package.json +7 -4
  226. package/skills/archify/SKILL.md +25 -2
  227. package/skills/artifacts-builder/SKILL.md +23 -0
  228. package/skills/xone-hotswap/SKILL.md +96 -0
  229. package/skills/xone-hotswap/scripts/xone-arrancar-android +202 -0
  230. package/skills/xone-hotswap/scripts/xone-arrancar-ios +85 -0
  231. package/skills/xone-hotswap/scripts/xone-captura-android +93 -0
  232. package/skills/xone-hotswap/scripts/xone-desplegar-android +439 -0
  233. package/skills/xone-hotswap/scripts/xone-hotswap +201 -0
  234. package/skills/xone-hotswap/scripts/xone-log-android +102 -0
  235. package/skills/xone-hotswap/scripts/xone-reiniciar-android +132 -0
  236. package/skills/xone-plan-builder/SKILL.md +22 -4
  237. package/skills/xone-spec-builder/SKILL.md +37 -7
  238. package/apps/web/dist/assets/index-CFYAoHdw.js +0 -477
  239. package/dist/agent/agentesEnDisco.js +0 -539
  240. package/dist/agent/agentesEnDisco.js.map +0 -1
  241. package/dist/agent/arbolDeProyecto.js.map +0 -1
  242. package/dist/agent/artefactosEnDisco.js.map +0 -1
  243. package/dist/agent/aumentador.js.map +0 -1
  244. package/dist/agent/authEnDisco.js.map +0 -1
  245. package/dist/agent/busquedaRegex.js.map +0 -1
  246. package/dist/agent/catalogoModelos.js.map +0 -1
  247. package/dist/agent/checkpointer.js.map +0 -1
  248. package/dist/agent/cloudstudioClient.js.map +0 -1
  249. package/dist/agent/cloudstudioMcp.js.map +0 -1
  250. package/dist/agent/configEnDisco.js.map +0 -1
  251. package/dist/agent/consumoExterno.js.map +0 -1
  252. package/dist/agent/crearProyecto.js.map +0 -1
  253. package/dist/agent/descarga.js.map +0 -1
  254. package/dist/agent/diagnosticoDeTools.js.map +0 -1
  255. package/dist/agent/dispositivosEnMaquina.js.map +0 -1
  256. package/dist/agent/entorno.js.map +0 -1
  257. package/dist/agent/escrituraDeCodex.js.map +0 -1
  258. package/dist/agent/escrituraDeOpencode.js.map +0 -1
  259. package/dist/agent/escrituraExterna.js.map +0 -1
  260. package/dist/agent/gemini.js.map +0 -1
  261. package/dist/agent/git.js.map +0 -1
  262. package/dist/agent/gitSync.js.map +0 -1
  263. package/dist/agent/guionizado.js.map +0 -1
  264. package/dist/agent/hotswap.js.map +0 -1
  265. package/dist/agent/instalacionEnMaquina.js.map +0 -1
  266. package/dist/agent/instantanea.js.map +0 -1
  267. package/dist/agent/interrupts.js.map +0 -1
  268. package/dist/agent/juezDeTarea.js.map +0 -1
  269. package/dist/agent/lanzamientoEnMaquina.js.map +0 -1
  270. package/dist/agent/manifiesto.js.map +0 -1
  271. package/dist/agent/memoriaDeProyecto.js.map +0 -1
  272. package/dist/agent/mensajes.js.map +0 -1
  273. package/dist/agent/modelos.js +0 -130
  274. package/dist/agent/modelos.js.map +0 -1
  275. package/dist/agent/modelosDeMotor.js.map +0 -1
  276. package/dist/agent/normalizar.js.map +0 -1
  277. package/dist/agent/paqueteDelProyecto.js.map +0 -1
  278. package/dist/agent/perfiles.js.map +0 -1
  279. package/dist/agent/persona.js.map +0 -1
  280. package/dist/agent/procesosEnMaquina.js.map +0 -1
  281. package/dist/agent/proyecto.js.map +0 -1
  282. package/dist/agent/puente.js.map +0 -1
  283. package/dist/agent/resumenDeContexto.js +0 -30
  284. package/dist/agent/resumenDeContexto.js.map +0 -1
  285. package/dist/agent/resumenDeTool.js.map +0 -1
  286. package/dist/agent/sesionGit.js.map +0 -1
  287. package/dist/agent/settingsEnDisco.js.map +0 -1
  288. package/dist/agent/skills.js +0 -65
  289. package/dist/agent/skills.js.map +0 -1
  290. package/dist/agent/subagenteCodex.js.map +0 -1
  291. package/dist/agent/subagenteExterno.js.map +0 -1
  292. package/dist/agent/subagenteOpencode.js.map +0 -1
  293. package/dist/agent/subida.js.map +0 -1
  294. package/dist/agent/tareasEnDisco.js.map +0 -1
  295. package/dist/agent/textoDeTool.js.map +0 -1
  296. package/dist/agent/turnoReal.js.map +0 -1
  297. package/dist/agent/verificador.js.map +0 -1
  298. package/dist/agent/versionEnDisco.js.map +0 -1
  299. package/dist/agent/xoneAgent.js +0 -347
  300. package/dist/agent/xoneAgent.js.map +0 -1
  301. package/dist/agent/zip.js.map +0 -1
  302. /package/dist/agent/{manifiesto.js → cloudstudio/manifiesto.js} +0 -0
  303. /package/dist/agent/{entorno.js → config/entorno.js} +0 -0
  304. /package/dist/agent/{gemini.js → config/gemini.js} +0 -0
  305. /package/dist/agent/{hotswap.js → dispositivos/hotswap.js} +0 -0
  306. /package/dist/agent/{instalacionEnMaquina.js → dispositivos/instalacionEnMaquina.js} +0 -0
  307. /package/dist/agent/{procesosEnMaquina.js → dispositivos/procesosEnMaquina.js} +0 -0
  308. /package/dist/agent/{git.js → sesiones/git.js} +0 -0
  309. /package/dist/agent/{consumoExterno.js → subagentes/consumoExterno.js} +0 -0
  310. /package/dist/agent/{escrituraDeCodex.js → subagentes/escrituraDeCodex.js} +0 -0
  311. /package/dist/agent/{subagenteCodex.js → subagentes/subagenteCodex.js} +0 -0
  312. /package/dist/agent/{mensajes.js → turno/mensajes.js} +0 -0
  313. /package/dist/agent/{normalizar.js → turno/normalizar.js} +0 -0
  314. /package/dist/agent/{textoDeTool.js → turno/textoDeTool.js} +0 -0
  315. /package/dist/agent/{verificador.js → turno/verificador.js} +0 -0
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Cuánto tiene que PENSAR un modelo antes de contestar, y qué modelos admiten que se les
3
+ * pida.
4
+ *
5
+ * Es la tercera tabla de esta familia, detrás de `contextos.ts#TOPES` y de
6
+ * `modelos.ts#pideThinkingAdaptativo`, y existe por el mismo motivo que ellas: el
7
+ * parámetro no significa lo mismo en todos, lo que no se reconoce hay que OMITIRLO, y
8
+ * pedirlo a ciegas no da una respuesta peor — da un 400.
9
+ *
10
+ * **La unidad es el MODELO, nunca el proveedor**, y eso está medido: dentro de NVIDIA,
11
+ * `nvidia/nemotron-3-super-120b-a12b` acepta siete niveles y `openai/gpt-oss-20b` acepta
12
+ * tres, contra el mismo host y con la misma clave. Una tabla por proveedor habría sido
13
+ * falsa el primer día.
14
+ *
15
+ * **Y los niveles son una LISTA por modelo, no tres fijos.** La razón es DeepSeek: publica
16
+ * —y su API acepta— siete valores, pero los COLAPSA (`minimal`→low, `medium`→high,
17
+ * `xhigh`→high, `ultra`→max), así que ahí solo hay tres niveles de verdad. Ofrecer
18
+ * low/medium/high en un desplegable contra ese modelo sería dar dos opciones que hacen
19
+ * exactamente lo mismo sin decirlo, que es la misma clase de mentira que un contador a
20
+ * cero que nadie ha medido.
21
+ *
22
+ * **Lo desconocido devuelve `undefined`**: ni se ofrece control ni se manda parámetro. Es
23
+ * el mismo lado conservador de `pideThinkingAdaptativo`, y aquí es literal — un nivel
24
+ * mandado a quien no lo admite se contesta con un error duro, comprobado en los tres
25
+ * proveedores que se pudieron medir.
26
+ */
27
+ export const ESFUERZOS = ["low", "medium", "high", "xhigh", "max"];
28
+ export function esEsfuerzo(valor) {
29
+ return ESFUERZOS.includes(valor);
30
+ }
31
+ /** Los tres de siempre, que es lo que admite la mayoría. */
32
+ const TRES = ["low", "medium", "high"];
33
+ /** Los cinco de Anthropic desde Opus 4.7. */
34
+ const CINCO = ["low", "medium", "high", "xhigh", "max"];
35
+ /**
36
+ * Qué acepta cada familia, emparejado por PREFIJO del id, y el primero que casa gana —
37
+ * igual que en `contextos.ts`, así que lo específico va antes que lo general.
38
+ *
39
+ * De dónde sale cada fila, porque en este repo la procedencia es un dato:
40
+ *
41
+ * - **anthropic**: LEÍDO de la documentación de la casa (no hubo clave con la que medir).
42
+ * `output_config.effort` es GA y su omisión ya es `high`. Los cinco niveles existen desde
43
+ * Opus 4.7; Opus 4.6 y Sonnet 4.6 no tienen `xhigh`; Opus 4.5 solo tiene tres; y **Haiku
44
+ * 4.5, Sonnet 4.5 y todo lo anterior dan ERROR**, así que no tienen fila. Esa frontera es
45
+ * la hermana de la de `pideThinkingAdaptativo`: ahí la pregunta era qué acepta `thinking`
46
+ * y aquí qué acepta `effort`, y las dos parten la misma generación.
47
+ * - **gemini**: MEDIDO contra la API real. `thinkingLevel` solo existe de la generación 3 en
48
+ * adelante: `gemini-2.5-flash` contesta «Thinking level is not supported for this model» y
49
+ * `gemma-4-31b-it` lo mismo. Los tres alias `*-latest` van ENUMERADOS porque apuntan a 3.x
50
+ * y el prefijo `gemini-3` no los casaría — se comprobó uno a uno que los tres lo aceptan.
51
+ * Y el catálogo vivo NO sirve para decidir esto: `GET /v1beta/models/<id>` devuelve
52
+ * `"thinking": true` también para `gemini-2.5-flash`, que es justo el que falla; ese campo
53
+ * dice «sabe pensar», no «acepta niveles».
54
+ * - **deepseek**: MEDIDO que el enum se valida (un valor inventado da 422) y LEÍDO de su
55
+ * documentación que lo colapsa. Por eso la fila tiene TRES valores que no son los tres de
56
+ * siempre: `low`, `high` y `max` son los únicos distintos. Lo que NO se pudo medir es que
57
+ * los niveles cambien el resultado — con un problema fácil y dos pasadas la señal quedó
58
+ * por debajo de la varianza —, y eso es «no medido», que no es lo mismo que «no hace nada».
59
+ * - **nvidia**: MEDIDO con el truco del valor inválido, que devuelve el enum en el propio
60
+ * error. Son dos filas y no una porque los dos modelos probados no coinciden.
61
+ *
62
+ * **Lo que NO tiene fila, y por qué**: `openai`, `groq` y `xai` no se pudieron medir —no
63
+ * había credencial— y sus reglas por modelo no se parecen entre sí, así que se quedan
64
+ * fuera hasta que alguien las mida. Un proveedor PERSONALIZADO tampoco puede tenerla: su
65
+ * modelo lo elige quien dio de alta el endpoint. En los tres casos el resultado es el
66
+ * mismo y es el correcto: sin control y sin parámetro.
67
+ */
68
+ const TABLA = {
69
+ anthropic: [
70
+ ["claude-fable", CINCO],
71
+ ["claude-mythos", CINCO],
72
+ ["claude-opus-5", CINCO],
73
+ ["claude-sonnet-5", CINCO],
74
+ ["claude-opus-4-8", CINCO],
75
+ ["claude-opus-4-7", CINCO],
76
+ // 4.6 es la generación donde `effort` ya existe pero `xhigh` todavía no.
77
+ ["claude-opus-4-6", ["low", "medium", "high", "max"]],
78
+ ["claude-sonnet-4-6", ["low", "medium", "high", "max"]],
79
+ ["claude-opus-4-5", TRES],
80
+ // Y nada más: Haiku 4.5, Sonnet 4.5 y lo anterior devuelven error si se les pide.
81
+ ],
82
+ gemini: [
83
+ ["gemini-3", TRES],
84
+ ["gemini-flash-latest", TRES],
85
+ ["gemini-flash-lite-latest", TRES],
86
+ ["gemini-pro-latest", TRES],
87
+ ],
88
+ deepseek: [["deepseek", ["low", "high", "max"]]],
89
+ nvidia: [
90
+ ["openai/gpt-oss", TRES],
91
+ ["nvidia/nemotron-3", CINCO],
92
+ ],
93
+ };
94
+ /**
95
+ * Los niveles de esfuerzo que admite un modelo, o `undefined` si no admite ninguno —que es
96
+ * también lo que se devuelve cuando no se sabe, porque no saberlo y no poder son lo mismo
97
+ * para quien tiene que decidir si manda el parámetro.
98
+ *
99
+ * **Ollama va por las capacidades vivas y no por la tabla**, y esa asimetría es el hallazgo
100
+ * que la justifica: sus modelos los elige el usuario y no hay prefijo que los describa, pero
101
+ * el servidor contesta por cada uno. Sin capacidades —porque aún no se preguntó— no se
102
+ * afirma nada, que es distinto de afirmar que no puede.
103
+ */
104
+ export function nivelesDeEsfuerzo(proveedor, modelo, vivas) {
105
+ if (proveedor === "ollama" || proveedor === "ollama-cloud") {
106
+ return vivas?.piensa === true ? NIVELES_DE_OLLAMA : undefined;
107
+ }
108
+ return TABLA[proveedor]?.find(([prefijo]) => modelo.startsWith(prefijo))?.[1];
109
+ }
110
+ /**
111
+ * Lo que el servidor de Ollama valida, y está medido en su propio mensaje de error: un
112
+ * `think: "banana"` contesta `must be "high", "medium", "low", "max", true, or false`.
113
+ *
114
+ * O sea que Ollama SÍ tiene niveles; que el tipo de `@langchain/ollama` los declare como un
115
+ * `boolean` es una limitación del cliente y no del servidor, y el cliente pasa el valor tal
116
+ * cual al request.
117
+ *
118
+ * **Y aquí hay un límite declarado que no se puede cerrar desde esta tabla**: que el
119
+ * servidor acepte el nivel no significa que el modelo lo honre. Medido: en `granite4.2:3b`
120
+ * solo `low` cambia algo y `medium`/`high`/`max` son idénticos entre sí; en
121
+ * `glm-5.3-flash:cloud` —que es el modelo POR OMISIÓN de este repo— `high` se comporta como
122
+ * apagado y solo `medium` piensa. No es monótono y no lo podemos arreglar: lo pone el
123
+ * template de cada modelo. Quien pinte esto tiene que DECIRLO.
124
+ */
125
+ export const NIVELES_DE_OLLAMA = ["low", "medium", "high", "max"];
126
+ /**
127
+ * El nivel que se va a usar de verdad, dado lo que el usuario eligió y lo que el modelo
128
+ * admite.
129
+ *
130
+ * Existe porque elegir y aplicar están separados en el tiempo: el esfuerzo se fija una vez
131
+ * y el modelo se cambia después, así que un `xhigh` elegido con Opus 5 sigue puesto cuando
132
+ * alguien se pasa a Gemini, que no lo tiene. Ahí NO se manda el parámetro y NO se sustituye
133
+ * por el más parecido: bajar `xhigh` a `high` por nuestra cuenta sería decidir en nombre de
134
+ * alguien, y en este harness eso se paga en tokens que no pidió.
135
+ */
136
+ export function esfuerzoAplicable(elegido, proveedor, modelo, vivas) {
137
+ if (elegido === undefined)
138
+ return undefined;
139
+ return nivelesDeEsfuerzo(proveedor, modelo, vivas)?.includes(elegido) === true ? elegido : undefined;
140
+ }
141
+ //# sourceMappingURL=esfuerzo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esfuerzo.js","sourceRoot":"","sources":["../../src/core/esfuerzo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAaH,MAAM,CAAC,MAAM,SAAS,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAU,CAAC;AAEjG,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAQ,SAA+B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,4DAA4D;AAC5D,MAAM,IAAI,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC5D,6CAA6C;AAC7C,MAAM,KAAK,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,KAAK,GAAuF;IAChG,SAAS,EAAE;QACT,CAAC,cAAc,EAAE,KAAK,CAAC;QACvB,CAAC,eAAe,EAAE,KAAK,CAAC;QACxB,CAAC,eAAe,EAAE,KAAK,CAAC;QACxB,CAAC,iBAAiB,EAAE,KAAK,CAAC;QAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;QAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;QAC1B,yEAAyE;QACzE,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC,iBAAiB,EAAE,IAAI,CAAC;QACzB,kFAAkF;KACnF;IACD,MAAM,EAAE;QACN,CAAC,UAAU,EAAE,IAAI,CAAC;QAClB,CAAC,qBAAqB,EAAE,IAAI,CAAC;QAC7B,CAAC,0BAA0B,EAAE,IAAI,CAAC;QAClC,CAAC,mBAAmB,EAAE,IAAI,CAAC;KAC5B;IACD,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,EAAE;QACN,CAAC,gBAAgB,EAAE,IAAI,CAAC;QACxB,CAAC,mBAAmB,EAAE,KAAK,CAAC;KAC7B;CACF,CAAC;AAoBF;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAoB,EACpB,MAAc,EACd,KAAwB;IAExB,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,cAAc,EAAE,CAAC;QAC3D,OAAO,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAEvF;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAA6B,EAC7B,SAAoB,EACpB,MAAc,EACd,KAAwB;IAExB,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACvG,CAAC"}
@@ -7,7 +7,7 @@
7
7
  * inventada no da error — da un bug mudo, y un esqueleto recién creado que no
8
8
  * arranca sería la peor primera impresión posible.
9
9
  *
10
- * La escritura en disco vive en `agent/crearProyecto.ts`: aquí solo se DECIDE
10
+ * La escritura en disco vive en `agent/config/crearProyecto.ts`: aquí solo se DECIDE
11
11
  * qué ficheros hay y qué llevan dentro, que es exactamente lo que se puede
12
12
  * probar sin conexión, sin simulador y sin clave (el invariante de `npm test`).
13
13
  */
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Qué estilo le toca de verdad a un control, y de dónde sale.
3
+ *
4
+ * ## La medida que lo motiva
5
+ *
6
+ * Diez pasadas reales del mismo encargo visual («el título sale cortado»), 19-09-2026. En OCHO
7
+ * de ellas `xone_navegacion` es la PRIMERA tool del turno —el modelo sí empieza por donde se le
8
+ * dice— y luego deja de servirle: la usa una o dos veces y el resto del turno son **20-46
9
+ * lecturas y 30-42 `grep`**, de los cuales ~22 de cada 30 son **la misma clase con variantes**
10
+ * (`xnTituloHeaderC`, `.xnTituloHeader`, `xnHeader`, `xnLightTitle`, `font42`…). Más cinco
11
+ * ficheros CSS, varios `.xne` AJENOS buscando ejemplos, y nueve documentos de skill.
12
+ *
13
+ * El índice actual contesta sobre el MODELO `.xne` —colecciones, campos, referencias— y el
14
+ * trabajo de un arreglo visual vive en la capa de ESTILOS, que no tenía índice. Esto lo cierra.
15
+ *
16
+ * ## Lo que NO se rederiva
17
+ *
18
+ * La cascada de XOne la resuelve `xone-linter`, no este módulo: `Stylesheet.lookup` está
19
+ * anotado como fiel a `FindStylesheetByClassName` (`CXoneApplication.mm:6146-6166`), con la
20
+ * sutileza de que **un fichero posterior que redirige por `extends` gana al atributo DIRECTO de
21
+ * uno anterior** —resolución intercalada por fichero, no dos pasadas globales—, y
22
+ * `selectorsFor` implementa el orden de prioridad (`prop.clase:tipo` → `prop.clase` →
23
+ * `.clase` → `prop:tipo` → `prop`) con sus dos banderas. Reescribir eso aquí sería un segundo
24
+ * sitio donde decidir lo mismo, que es justo el argumento por el que `xone_navegacion` usa la
25
+ * librería en vez de reimplementar `CrossReferenceRule`.
26
+ *
27
+ * Aquí vive lo que se ENSEÑA y con qué topes. Puro: sin disco y sin librería.
28
+ */
29
+ /**
30
+ * Topes de lo que se enseña.
31
+ *
32
+ * Existen porque esto viaja al contexto del modelo entero y una hoja grande tiene decenas de
33
+ * atributos por selector. **Lo que no cabe se CUENTA**, como en todas partes aquí: una lista
34
+ * recortada en silencio se lee como la lista entera, y sobre eso se concluye de más.
35
+ */
36
+ export const LIMITES_ESTILOS = { atributos: 30, selectores: 12, declaraciones: 12 };
37
+ /** La marca de que un valor no viene de la hoja sino del XML del propio control. */
38
+ export const DEL_XML = "el XML del prop (gana a la hoja)";
39
+ function recortar(lista, tope, pinta) {
40
+ const cabe = lista.slice(0, tope).map(pinta);
41
+ const fuera = lista.length - cabe.length;
42
+ return fuera > 0 ? [...cabe, ` … y ${fuera} más`] : cabe;
43
+ }
44
+ /**
45
+ * La respuesta, en el formato que el turno necesitaba.
46
+ *
47
+ * Las cuatro preguntas que los greps estaban haciendo a mano —qué se aplica, de qué selector,
48
+ * qué selectores compiten y en qué fichero están— en una sola llamada. El orden no es
49
+ * cosmético: primero lo que se aplica, que es lo que se preguntó; los selectores y los ficheros
50
+ * van después, porque son el CAMINO y solo hacen falta si hay que cambiar algo.
51
+ */
52
+ export function pintarEstiloDeProp(e) {
53
+ const cabecera = `${e.coll}.${e.prop}` +
54
+ (e.tipo === undefined ? "" : ` type=${e.tipo}`) +
55
+ (e.clase === undefined ? "" : ` class="${e.clase}"`);
56
+ const nada = e.deLaHoja.length === 0 && e.delXml.length === 0;
57
+ return [
58
+ cabecera,
59
+ "",
60
+ "LO QUE ACABA APLICÁNDOSE",
61
+ ...(nada
62
+ ? [" (nada: ni la hoja ni el XML le ponen ningún atributo)"]
63
+ : recortar([...e.delXml, ...e.deLaHoja], LIMITES_ESTILOS.atributos, (a) => ` ${a.atributo.padEnd(18)} ${a.valor.padEnd(14)} ← ${a.de}`)),
64
+ "",
65
+ "SELECTORES QUE APLICAN, de más a menos prioridad",
66
+ ...(e.selectores.length === 0
67
+ ? [" (ninguno: el prop no tiene clase y la hoja no declara reglas de tipo)"]
68
+ : recortar(e.selectores, LIMITES_ESTILOS.selectores, (s) => ` ${s}`)),
69
+ ...(e.declaradoEn.length === 0
70
+ ? []
71
+ : [
72
+ "",
73
+ "DÓNDE SE DECLARAN",
74
+ ...recortar(e.declaradoEn, LIMITES_ESTILOS.declaraciones, (d) => ` ${d.selector.padEnd(28)} ${d.fichero}`),
75
+ ]),
76
+ ].join("\n");
77
+ }
78
+ //# sourceMappingURL=estilos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"estilos.js","sourceRoot":"","sources":["../../src/core/estilos.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AA0BH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAW,CAAC;AAE7F,oFAAoF;AACpF,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAE1D,SAAS,QAAQ,CAAI,KAAmB,EAAE,IAAY,EAAE,KAAuB;IAC7E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,QAAQ,GACZ,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE;QACrB,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IAExD,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC9D,OAAO;QACL,QAAQ;QACR,EAAE;QACF,0BAA0B;QAC1B,GAAG,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,yDAAyD,CAAC;YAC7D,CAAC,CAAC,QAAQ,CACN,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,EAC5B,eAAe,CAAC,SAAS,EACzB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CACpE,CAAC;QACN,EAAE;QACF,kDAAkD;QAClD,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;YAC3B,CAAC,CAAC,CAAC,yEAAyE,CAAC;YAC7E,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAAE,eAAe,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;YAC5B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,EAAE;gBACF,mBAAmB;gBACnB,GAAG,QAAQ,CACT,CAAC,CAAC,WAAW,EACb,eAAe,CAAC,aAAa,EAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CACjD;aACF,CAAC;KACP,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Exportar un documento del proyecto a PDF: las reglas PURAS.
3
+ *
4
+ * **Por qué el harness y no el agente.** Producir un PDF es lo que las skills `pdf`/`docx`
5
+ * de Claude Code hacen ejecutando scripts, y a un motor externo no se le concede shell
6
+ * —`Bash` está denegada, y abrirla dejaría a ese hijo reescribir el proyecto sin diff ni
7
+ * aprobación—. Medido además sobre la máquina real: esas skills asumen el sandbox donde sus
8
+ * dependencias vienen puestas (`reportlab`, `pypdf`, `docx` de npm, `pandoc`), y ahí no
9
+ * estaba ninguna, así que conceder la shell no habría dado el PDF. Lo que sí hay en cualquier
10
+ * máquina que use la consola web es un navegador, y un navegador imprime — así que la
11
+ * conversión la hace el harness con un comando FIJO, y la shell del hijo sigue cerrada.
12
+ *
13
+ * Aquí solo está lo que se puede decidir sin tocar disco. Lanzar el navegador es de
14
+ * `agent/exportarPdf.ts`.
15
+ */
16
+ /**
17
+ * Lo que se sabe convertir. Lista CERRADA: lo que no está no se intenta.
18
+ *
19
+ * `.md` porque es lo que el agente escribe cuando se le pide documentación, y `.html` porque
20
+ * es lo que produce la skill de artefactos. Un `.xne` o un `.js` no entran: imprimir código
21
+ * fuente a PDF no es una necesidad que nadie haya tenido, y ofrecerlo sería un botón que
22
+ * nadie pulsa sobre cada fichero del árbol.
23
+ */
24
+ export const EXTENSIONES_EXPORTABLES = [".md", ".html", ".htm"];
25
+ /** ¿Hace falta convertir Markdown antes, o el fichero ya es HTML? */
26
+ export function esMarkdown(ruta) {
27
+ return ruta.toLowerCase().endsWith(".md");
28
+ }
29
+ /**
30
+ * Por qué no se puede exportar esa ruta, o AUSENTE si vale.
31
+ *
32
+ * No comprueba que exista ni que se pueda leer: de eso ya hay una barrera
33
+ * (`motivoDeRutaInaceptable` y el `realpath` de `leerFicheroDeProyecto`), y duplicarla aquí
34
+ * sería un segundo sitio donde decidir sobre una ruta.
35
+ */
36
+ export function motivoDeExportacionInaceptable(ruta) {
37
+ const bajo = ruta.toLowerCase();
38
+ if (!EXTENSIONES_EXPORTABLES.some((e) => bajo.endsWith(e))) {
39
+ return `solo se exportan ${EXTENSIONES_EXPORTABLES.join(", ")} — «${ruta}» no es ninguno`;
40
+ }
41
+ return undefined;
42
+ }
43
+ /**
44
+ * Dónde queda el PDF: al lado del original y con su mismo nombre.
45
+ *
46
+ * **El destino lo DERIVA el código, nunca se recibe.** Es lo que impide que quien pide la
47
+ * exportación elija dónde escribir: con un destino por parámetro, esta función sería una
48
+ * forma de escribir cualquier fichero del proyecto sin pasar por ninguna aprobación.
49
+ */
50
+ export function rutaDePdf(ruta) {
51
+ const punto = ruta.lastIndexOf(".");
52
+ return `${punto <= 0 ? ruta : ruta.slice(0, punto)}.pdf`;
53
+ }
54
+ /**
55
+ * El documento listo para imprimir: el cuerpo HTML dentro de una hoja de estilos de PÁGINA.
56
+ *
57
+ * Los estilos no son decoración, son lo que hace legible un PDF de doce páginas y se
58
+ * comprobaron imprimiendo uno de verdad: `@page` con márgenes, `break-inside: avoid` en
59
+ * tablas y bloques de código —sin eso una tabla se parte por la mitad entre dos hojas— y
60
+ * `break-after: avoid` en los encabezados, para que un título no se quede solo al pie.
61
+ *
62
+ * El título va ESCAPADO: sale de un nombre de fichero del proyecto, y un `<` ahí dentro
63
+ * rompería la cabecera del documento.
64
+ */
65
+ export function documentoImprimible(cuerpo, titulo) {
66
+ return `<!doctype html>
67
+ <html lang="es">
68
+ <head>
69
+ <meta charset="utf-8">
70
+ ${POLITICA_SIN_SCRIPTS}
71
+ <title>${escaparHtml(titulo)}</title>
72
+ <style>
73
+ @page { size: A4; margin: 18mm 16mm 20mm; }
74
+ body { font: 10.5pt/1.55 -apple-system, "Segoe UI", Helvetica, Arial, sans-serif; color: #1a1a1a; }
75
+ h1 { font-size: 22pt; border-bottom: 2px solid #0b5fff; padding-bottom: .3em; }
76
+ h2 { font-size: 15pt; margin-top: 1.6em; border-bottom: 1px solid #d7dbe0; padding-bottom: .2em; }
77
+ h3 { font-size: 12pt; margin-top: 1.2em; }
78
+ h1, h2, h3, h4 { break-after: avoid; break-inside: avoid; }
79
+ table { border-collapse: collapse; width: 100%; margin: .8em 0; font-size: 9pt; break-inside: avoid; }
80
+ th, td { border: 1px solid #c9ced6; padding: 5px 7px; text-align: left; vertical-align: top; }
81
+ th { background: #eef2f7; }
82
+ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .88em;
83
+ background: #f3f5f8; padding: 1px 4px; border-radius: 3px; }
84
+ pre { background: #f7f8fa; border: 1px solid #e2e6ec; border-radius: 5px; padding: 10px;
85
+ overflow-x: auto; break-inside: avoid; }
86
+ pre code { background: none; padding: 0; }
87
+ blockquote { border-left: 3px solid #0b5fff; margin: 1em 0; padding: .2em 1em; background: #f5f8ff; }
88
+ img { max-width: 100%; }
89
+ hr { border: 0; border-top: 1px solid #d7dbe0; margin: 1.6em 0; }
90
+ a { color: #0b5fff; text-decoration: none; }
91
+ </style>
92
+ </head>
93
+ <body>${cuerpo}</body>
94
+ </html>
95
+ `;
96
+ }
97
+ /**
98
+ * La política que impide que imprimir ejecute nada.
99
+ *
100
+ * **Y es una CSP y no un flag del navegador, porque los flags NO lo hacen.** Medido contra
101
+ * el Chrome instalado con un documento que reescribe su propio texto desde un `<script>`:
102
+ * con `--disable-javascript`, con `--blink-settings=scriptEnabled=false` y sin nada, el
103
+ * script se ejecutó en los tres casos; y encima el segundo hace que `--print-to-pdf` no
104
+ * escriba el fichero, en silencio y con código de salida 0. Con esta CSP el script no corre.
105
+ *
106
+ * `default-src 'none'` corta además las peticiones de RED: un documento del proyecto podría
107
+ * llevar un `<img src="https://…">` que se lleve fuera el hecho de que se está imprimiendo.
108
+ * Lo que se deja es lo que un PDF necesita: imágenes locales o embebidas, estilos en línea
109
+ * —los nuestros— y tipografías locales.
110
+ */
111
+ export const POLITICA_SIN_SCRIPTS = `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; ` +
112
+ `img-src 'self' data: file:; style-src 'unsafe-inline' 'self'; font-src 'self' data:">`;
113
+ /**
114
+ * El mismo blindaje para un documento que YA es HTML y no pasa por nuestra plantilla.
115
+ *
116
+ * Se inserta lo antes posible: dentro de su `<head>` si lo tiene, dentro de su `<html>` si
117
+ * no, y al principio si no hay ninguno de los dos. **Inyectarla siempre TENSA y nunca
118
+ * afloja**: cuando un documento trae su propia CSP, el navegador exige que TODAS las
119
+ * políticas permitan cada carga, así que añadir la nuestra no puede ampliar lo que el
120
+ * documento ya se permitía.
121
+ *
122
+ * **Límite declarado**: esto es una transformación de TEXTO, no un parser. Un documento
123
+ * con un `<head` dentro de un comentario o de una cadena puede recibir la meta en un sitio
124
+ * raro; el peor caso es que no aplique, que es exactamente donde estábamos antes.
125
+ */
126
+ export function conPoliticaSinScripts(html) {
127
+ const tras = (patron) => {
128
+ const m = patron.exec(html);
129
+ return m === null ? undefined : `${html.slice(0, m.index + m[0].length)}${POLITICA_SIN_SCRIPTS}${html.slice(m.index + m[0].length)}`;
130
+ };
131
+ return tras(/<head\b[^>]*>/i) ?? tras(/<html\b[^>]*>/i) ?? `${POLITICA_SIN_SCRIPTS}${html}`;
132
+ }
133
+ function escaparHtml(texto) {
134
+ return texto
135
+ .replace(/&/g, "&amp;")
136
+ .replace(/</g, "&lt;")
137
+ .replace(/>/g, "&gt;")
138
+ .replace(/"/g, "&quot;");
139
+ }
140
+ //# sourceMappingURL=exportacion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exportacion.js","sourceRoot":"","sources":["../../src/core/exportacion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAEzE,qEAAqE;AACrE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAAY;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,oBAAoB,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,iBAAiB,CAAC;IAC5F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,MAAc;IAChE,OAAO;;;;EAIP,oBAAoB;SACb,WAAW,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;QAsBpB,MAAM;;CAEb,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,0EAA0E;IAC1E,uFAAuF,CAAC;AAE1F;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,IAAI,GAAG,CAAC,MAAc,EAAsB,EAAE;QAClD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACvI,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,oBAAoB,GAAG,IAAI,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * La carta de presentación del proyecto, pegada al turno.
3
+ *
4
+ * **Existe por una medida, y la medida es de hoy** (19-09-2026): en seis turnos reales sobre un
5
+ * proyecto de verdad, cada especialista repetía las MISMAS búsquedas —`grep` ×42 en un solo
6
+ * turno, con `xnTituloHeaderC` ×7 y `xnHeader` ×3— y el orquestador se llevaba entre el 38 % y
7
+ * el 50 % del gasto averiguando. No por delegar mal: porque **nadie hace el descubrimiento una
8
+ * sola vez**. El prompt del orquestador ya PIDE lo contrario («No pidas al siguiente
9
+ * especialista redescubrir esos hechos») y no basta — una instrucción no es una garantía.
10
+ *
11
+ * Así que los hechos baratos se ponen delante en vez de pedirse: el inventario cuesta cientos
12
+ * de tokens donde abrir los `.xne` cuesta decenas de miles (`xone_navegacion`).
13
+ *
14
+ * **Es el patrón de `conAdjuntos` y de `inventarioDelProyecto`**: montar no basta, hay que
15
+ * DECIR lo que hay. Aquí ni siquiera hay nada montado — el índice existe detrás de una tool
16
+ * que el agente tiene que acordarse de llamar, y un turno que no la llama trabaja a ciegas.
17
+ *
18
+ * **Y se calcula al MANDAR el turno, no al abrir la sesión.** Eso no es un detalle de
19
+ * cableado: `xone_navegacion` no cachea a propósito porque «un índice viejo que dice que un
20
+ * campo existe cuando el agente acaba de borrarlo es peor que no tener índice». Congelar esta
21
+ * foto en el prompt de sistema reintroduciría justo eso. Rehacerla por turno cuesta decenas de
22
+ * milisegundos y no puede quedarse vieja dentro del turno que la usa.
23
+ *
24
+ * Puro y en `core/`: quién lee el disco es de `agent/`.
25
+ */
26
+ /**
27
+ * Del índice a los hechos. PURA: el índice entra ya construido.
28
+ *
29
+ * Separada de quien lo construye por el motivo de siempre —poder probar la traducción sin
30
+ * disco— y porque el índice es la AUTORIDAD: aquí solo se elige qué poquito de él se adelanta.
31
+ * Lo que se elige son las cuatro cosas que un turno cualquiera pregunta primero, y ninguna
32
+ * lleva rutas: solo NOMBRES, así que esto no puede filtrar una ruta de la máquina por el cable.
33
+ */
34
+ export function hechosDeIndice(indice) {
35
+ const app = indice.app();
36
+ return {
37
+ entrada: app.entrada,
38
+ login: app.login,
39
+ estilos: app.estilos,
40
+ colecciones: indice.inventario().map((d) => d.nombre),
41
+ };
42
+ }
43
+ /**
44
+ * Cuántos nombres de colección caben antes de contar el resto.
45
+ *
46
+ * Un proyecto real medido tiene 98 colecciones y eso son unos cientos de tokens: barato al
47
+ * lado de los 18.000 que cuesta enterarse leyendo. El tope existe para que un proyecto mucho
48
+ * mayor no se coma la ventana, y **lo que no cabe se CUENTA** en vez de recortarse en
49
+ * silencio: una lista truncada sin decirlo se lee como la lista entera, y entonces el agente
50
+ * concluye que una colección no existe.
51
+ */
52
+ export const TOPE_DE_COLECCIONES = 150;
53
+ /** ¿Hay algo que contar? Sin esto no se pinta el bloque: un control sin dato detrás. */
54
+ function hayAlgo(h) {
55
+ return (h.colecciones.length > 0 || h.entrada.length > 0 || h.login.length > 0 || h.estilos.length > 0);
56
+ }
57
+ /** Una lista, o la marca de que no consta. Vacío NO es «no hay»: es que no se pudo leer. */
58
+ function lista(valores) {
59
+ return valores.length === 0 ? "no consta" : valores.join(", ");
60
+ }
61
+ /**
62
+ * La petición del turno con los hechos del proyecto detrás.
63
+ *
64
+ * Sin hechos —no hay índice, o el proyecto no se pudo leer— devuelve la petición TAL CUAL.
65
+ * Nombrar un inventario que no se tiene sería la mentira con forma de dato de siempre.
66
+ */
67
+ export function conHechosDelProyecto(peticion, hechos) {
68
+ if (hechos === undefined || !hayAlgo(hechos))
69
+ return peticion;
70
+ const visibles = hechos.colecciones.slice(0, TOPE_DE_COLECCIONES);
71
+ const ocultas = hechos.colecciones.length - visibles.length;
72
+ return [
73
+ peticion,
74
+ "",
75
+ `ESTE PROYECTO, medido ahora mismo (${hechos.colecciones.length} colecciones). No vuelvas a`,
76
+ "averiguar lo que ya está aquí, y pásalo en el `HANDOFF DE ANÁLISIS` cuando delegues:",
77
+ `- Entrada: ${lista(hechos.entrada)}`,
78
+ `- Login: ${lista(hechos.login)}`,
79
+ `- Estilos: ${lista(hechos.estilos)}`,
80
+ `- Colecciones: ${visibles.join(", ")}`,
81
+ ...(ocultas > 0 ? [` (y ${ocultas} más que no caben aquí: pídelas con \`xone_navegacion\`)`] : []),
82
+ "Esto es una FOTO del arranque del turno y solo dice QUÉ hay, no cómo es cada cosa. Para los",
83
+ "campos de una colección, dónde se declara algo o quién la referencia, usa `xone_navegacion`:",
84
+ "es la autoridad y está al día, esta lista no lo estará si el turno crea o borra algo.",
85
+ ].join("\n");
86
+ }
87
+ //# sourceMappingURL=hechosDelProyecto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hechosDelProyecto.js","sourceRoot":"","sources":["../../src/core/hechosDelProyecto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAuBH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAA0B;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;IACzB,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,wFAAwF;AACxF,SAAS,OAAO,CAAC,CAAoB;IACnC,OAAO,CACL,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAC/F,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,SAAS,KAAK,CAAC,OAA0B;IACvC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,MAAqC;IAErC,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC5D,OAAO;QACL,QAAQ;QACR,EAAE;QACF,sCAAsC,MAAM,CAAC,WAAW,CAAC,MAAM,6BAA6B;QAC5F,sFAAsF;QACtF,cAAc,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACrC,YAAY,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACjC,cAAc,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACrC,kBAAkB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACvC,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,OAAO,0DAA0D,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnG,6FAA6F;QAC7F,8FAA8F;QAC9F,uFAAuF;KACxF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * El `code` con el que estos hallazgos entran en el bucle.
3
+ *
4
+ * Uno solo y no uno por mensaje: el `code` de un hallazgo del simulador es un identificador
5
+ * ESTABLE de familia (`REF_JS_COLL_MISSING`) y el texto va en `mensaje`. Aquí la familia es
6
+ * «lo que el aparato dijo al arrancar la app», y el mensaje es el que distingue.
7
+ */
8
+ export const ETIQUETA_DE_ARRANQUE = "DISPOSITIVO_ARRANQUE";
9
+ /**
10
+ * El prefijo de `adb logcat -v threadtime`: `MM-DD HH:MM:SS.mmm PID TID N `, donde `N` es
11
+ * el NIVEL.
12
+ *
13
+ * La fecha, el pid y el tid se van. El nivel se captura: lo pone quien escribió la línea, así
14
+ * que es la única clasificación de importancia que no es una opinión nuestra.
15
+ */
16
+ const PREFIJO = /^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\s+\d+\s+\d+\s+([VDIWEF])\s+/;
17
+ /**
18
+ * Del nivel de logcat a la severidad del harness.
19
+ *
20
+ * `F` (fatal) y `E` son errores; `W` es aviso; `V`, `D` e `I` son información. **No se
21
+ * DESCARTA nada** —es la condición que gobierna este módulo— pero solo los errores entran en
22
+ * la huella, exactamente como en `turnoReal.ts#conVerificacion`: «un aviso que va y viene no
23
+ * dice nada de si el error se está arreglando».
24
+ *
25
+ * Y eso no es cosmética: MEDIDO contra el aparato, dos arranques seguidos de la misma app dan
26
+ * líneas `I` y `D` distintas —`Choreographer: Skipped 75 frames` contra `Skipped 33`,
27
+ * `Compiler allocated 5250KB`, ciclos del replicador que solo salen a veces—. Con ellas
28
+ * dentro, la huella cambiaba entre dos vueltas idénticas y la guarda de «no progreso» no
29
+ * habría cortado nunca.
30
+ */
31
+ const SEVERIDAD_DE_NIVEL = {
32
+ F: "error",
33
+ E: "error",
34
+ W: "warning",
35
+ I: "info",
36
+ D: "info",
37
+ V: "info",
38
+ };
39
+ /**
40
+ * El cuerpo de una traza de Java, que NO lleva nivel en cada línea.
41
+ *
42
+ * Se arrastra con la severidad de la línea que la encabeza: partir una excepción en un error
43
+ * y cuatro huérfanas dejaría fuera de la huella justo la parte que la identifica.
44
+ */
45
+ const CUERPO_DE_TRAZA = /^\s*(at [\w$.]+\(|Caused by:|\.{3} \d+ more)/;
46
+ /** La cabecera que pone `xone-log-android`, que no es una línea del log. */
47
+ const CABECERA = /^---/;
48
+ /**
49
+ * Lo que es de ANDROID y no de la app.
50
+ *
51
+ * Es una clave de ORDENACIÓN, nunca un descarte (ver la cabecera del módulo). Son las
52
+ * etiquetas que salieron en la medida real sin tener nada que ver con el proyecto: el
53
+ * cargador de clases, Firebase sin configurar, el renderizador, el gesto de «atrás», los
54
+ * avisos de reflexión del propio Android y el Chromium del WebView.
55
+ */
56
+ const DE_LA_PLATAFORMA = /\b(ziparchive|FirebaseApp|DynamiteModule|ProviderInstaller|HWUI|WindowOnBackDispatcher|chromium|ActivityThread|ApkAssets|OpenGLRenderer)\b|Accessing hidden (method|field)|Cleared Reference was only reachable/;
57
+ export function hallazgosDeLog(texto) {
58
+ const cuenta = new Map();
59
+ /** El nivel de la última línea con nivel, para las continuaciones de una traza. */
60
+ let nivelArrastrado = "I";
61
+ for (const linea of texto.split(/\r?\n/)) {
62
+ const l = linea.trimEnd();
63
+ if (l.trim() === "" || CABECERA.test(l))
64
+ continue;
65
+ const con = PREFIJO.exec(l);
66
+ if (con !== null)
67
+ nivelArrastrado = con[1];
68
+ else if (!CUERPO_DE_TRAZA.test(l))
69
+ nivelArrastrado = "I";
70
+ const mensaje = l.replace(PREFIJO, "").trim();
71
+ if (mensaje === "")
72
+ continue;
73
+ const previo = cuenta.get(mensaje);
74
+ if (previo === undefined) {
75
+ const deLaApp = !DE_LA_PLATAFORMA.test(mensaje);
76
+ cuenta.set(mensaje, {
77
+ mensaje,
78
+ veces: 1,
79
+ deLaApp,
80
+ /**
81
+ * **Lo de la plataforma nunca es ERROR, aunque el log diga `E`.** Un
82
+ * `E chromium: Seed missing signature` es un error de verdad — de Android, no de la
83
+ * app— y nadie lo arregla desde un `.xne`. Como error dejaría el bucle sin poder
84
+ * cerrar jamás. Se ve, con su severidad rebajada; no bloquea.
85
+ */
86
+ severidad: deLaApp
87
+ ? SEVERIDAD_DE_NIVEL[nivelArrastrado]
88
+ : SEVERIDAD_DE_NIVEL[nivelArrastrado] === "error"
89
+ ? "warning"
90
+ : SEVERIDAD_DE_NIVEL[nivelArrastrado],
91
+ });
92
+ }
93
+ else {
94
+ previo.veces += 1;
95
+ }
96
+ }
97
+ // Los de la app delante; dentro de cada grupo, los que más se repiten primero. El orden es
98
+ // ESTABLE (`Map` conserva la inserción y `sort` de V8 es estable), así que dos lecturas del
99
+ // mismo log dan la misma lista — que es media huella.
100
+ const peso = { error: 0, warning: 1, info: 2 };
101
+ const hallazgos = [...cuenta.values()].sort((a, b) => {
102
+ if (peso[a.severidad] !== peso[b.severidad])
103
+ return peso[a.severidad] - peso[b.severidad];
104
+ if (a.deLaApp !== b.deLaApp)
105
+ return a.deLaApp ? -1 : 1;
106
+ return b.veces - a.veces;
107
+ });
108
+ const plataforma = hallazgos.filter((h) => !h.deLaApp).length;
109
+ return {
110
+ hallazgos,
111
+ plataforma,
112
+ /**
113
+ * **Solo lo de la app es ERROR.** Un `Accessing hidden method` de Android entraría en la
114
+ * huella como error, y entonces el bucle se declararía rojo por algo que nadie puede
115
+ * arreglar desde un `.xne` — y no cerraría nunca. Va como `warning`: se ve, no bloquea.
116
+ *
117
+ * Sin `fichero` ni `linea`, y eso es honestidad: el log no los dice. Un fichero adivinado
118
+ * mandaría al agente a abrir el que no es.
119
+ */
120
+ aHallazgosDelTurno: () => hallazgos.map((h) => ({
121
+ code: ETIQUETA_DE_ARRANQUE,
122
+ severidad: h.severidad,
123
+ mensaje: h.veces === 1 ? h.mensaje : `${h.mensaje} (×${h.veces})`,
124
+ })),
125
+ };
126
+ }
127
+ /**
128
+ * La huella de una lectura, con el MISMO formato que la de `conVerificacion`
129
+ * (`code|fichero|linea`), para que las dos sean intercambiables en la misma guarda.
130
+ *
131
+ * Solo los de la app: un aviso de la plataforma que va y viene no dice nada de si el error se
132
+ * está arreglando — la misma razón por la que allí la huella son los ERRORES y no todos los
133
+ * hallazgos. El `mensaje` entra en la huella porque aquí el `code` es uno solo: sin él, dos
134
+ * excepciones distintas darían la misma huella y el bucle se creería atascado.
135
+ */
136
+ export function huellaDeHallazgos(hallazgos) {
137
+ return hallazgos
138
+ .filter((h) => h.severidad === "error")
139
+ .map((h) => `${ETIQUETA_DE_ARRANQUE}|${h.mensaje}|`)
140
+ .sort()
141
+ .join("\n");
142
+ }
143
+ //# sourceMappingURL=logDeDispositivo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logDeDispositivo.js","sourceRoot":"","sources":["../../src/core/logDeDispositivo.ts"],"names":[],"mappings":"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"}