@hoilab/ada-cli 0.84.22 → 0.85.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 (1114) hide show
  1. package/CHANGELOG.md +29 -2
  2. package/README.es.md +17 -6
  3. package/README.md +109 -11
  4. package/dist/ada-publico.d.ts +35 -0
  5. package/dist/ada-publico.d.ts.map +1 -0
  6. package/dist/ada-publico.js +40 -0
  7. package/dist/ada-publico.js.map +1 -0
  8. package/dist/cli/audit-command.d.ts +15 -0
  9. package/dist/cli/audit-command.d.ts.map +1 -0
  10. package/dist/cli/audit-command.js +280 -0
  11. package/dist/cli/audit-command.js.map +1 -0
  12. package/dist/cli/banco-command.d.ts +15 -0
  13. package/dist/cli/banco-command.d.ts.map +1 -0
  14. package/dist/cli/banco-command.js +213 -0
  15. package/dist/cli/banco-command.js.map +1 -0
  16. package/dist/cli/cleanse-command.d.ts +11 -0
  17. package/dist/cli/cleanse-command.d.ts.map +1 -0
  18. package/dist/cli/cleanse-command.js +101 -0
  19. package/dist/cli/cleanse-command.js.map +1 -0
  20. package/dist/cli/commit-command.d.ts +31 -0
  21. package/dist/cli/commit-command.d.ts.map +1 -0
  22. package/dist/cli/commit-command.js +158 -0
  23. package/dist/cli/commit-command.js.map +1 -0
  24. package/dist/cli/computer-command.d.ts +12 -0
  25. package/dist/cli/computer-command.d.ts.map +1 -0
  26. package/dist/cli/computer-command.js +141 -0
  27. package/dist/cli/computer-command.js.map +1 -0
  28. package/dist/cli/discover-command.d.ts +18 -0
  29. package/dist/cli/discover-command.d.ts.map +1 -0
  30. package/dist/cli/discover-command.js +108 -0
  31. package/dist/cli/discover-command.js.map +1 -0
  32. package/dist/cli/hashline-command.d.ts +11 -0
  33. package/dist/cli/hashline-command.d.ts.map +1 -0
  34. package/dist/cli/hashline-command.js +106 -0
  35. package/dist/cli/hashline-command.js.map +1 -0
  36. package/dist/cli/import-command.d.ts +35 -0
  37. package/dist/cli/import-command.d.ts.map +1 -0
  38. package/dist/cli/import-command.js +164 -0
  39. package/dist/cli/import-command.js.map +1 -0
  40. package/dist/cli/politica-command.d.ts +20 -0
  41. package/dist/cli/politica-command.d.ts.map +1 -0
  42. package/dist/cli/politica-command.js +93 -0
  43. package/dist/cli/politica-command.js.map +1 -0
  44. package/dist/cli/refine-command.d.ts +18 -0
  45. package/dist/cli/refine-command.d.ts.map +1 -0
  46. package/dist/cli/refine-command.js +101 -0
  47. package/dist/cli/refine-command.js.map +1 -0
  48. package/dist/cli/review-command.d.ts +24 -0
  49. package/dist/cli/review-command.d.ts.map +1 -0
  50. package/dist/cli/review-command.js +168 -0
  51. package/dist/cli/review-command.js.map +1 -0
  52. package/dist/cli/schedule-command.d.ts +17 -0
  53. package/dist/cli/schedule-command.d.ts.map +1 -0
  54. package/dist/cli/schedule-command.js +117 -0
  55. package/dist/cli/schedule-command.js.map +1 -0
  56. package/dist/cli/serve-command.d.ts +72 -0
  57. package/dist/cli/serve-command.d.ts.map +1 -0
  58. package/dist/cli/serve-command.js +568 -0
  59. package/dist/cli/serve-command.js.map +1 -0
  60. package/dist/cli/telegram-command.d.ts +18 -0
  61. package/dist/cli/telegram-command.d.ts.map +1 -0
  62. package/dist/cli/telegram-command.js +137 -0
  63. package/dist/cli/telegram-command.js.map +1 -0
  64. package/dist/cli/telemetria-command.d.ts +22 -0
  65. package/dist/cli/telemetria-command.d.ts.map +1 -0
  66. package/dist/cli/telemetria-command.js +127 -0
  67. package/dist/cli/telemetria-command.js.map +1 -0
  68. package/dist/cli/undo-command.d.ts +9 -0
  69. package/dist/cli/undo-command.d.ts.map +1 -0
  70. package/dist/cli/undo-command.js +56 -0
  71. package/dist/cli/undo-command.js.map +1 -0
  72. package/dist/cli/usage-command.d.ts +10 -0
  73. package/dist/cli/usage-command.d.ts.map +1 -0
  74. package/dist/cli/usage-command.js +209 -0
  75. package/dist/cli/usage-command.js.map +1 -0
  76. package/dist/cli/wiki-command.d.ts +9 -0
  77. package/dist/cli/wiki-command.d.ts.map +1 -0
  78. package/dist/cli/wiki-command.js +76 -0
  79. package/dist/cli/wiki-command.js.map +1 -0
  80. package/dist/cli.d.ts +6 -0
  81. package/dist/cli.d.ts.map +1 -1
  82. package/dist/cli.js +10 -11
  83. package/dist/cli.js.map +1 -1
  84. package/dist/config.d.ts +1 -1
  85. package/dist/config.d.ts.map +1 -1
  86. package/dist/config.js +1 -1
  87. package/dist/config.js.map +1 -1
  88. package/dist/core/ada.d.ts +58 -0
  89. package/dist/core/ada.d.ts.map +1 -0
  90. package/dist/core/ada.js +61 -0
  91. package/dist/core/ada.js.map +1 -0
  92. package/dist/core/advisor/guarda.d.ts +66 -0
  93. package/dist/core/advisor/guarda.d.ts.map +1 -0
  94. package/dist/core/advisor/guarda.js +191 -0
  95. package/dist/core/advisor/guarda.js.map +1 -0
  96. package/dist/core/advisor/runtime.d.ts +66 -0
  97. package/dist/core/advisor/runtime.d.ts.map +1 -0
  98. package/dist/core/advisor/runtime.js +121 -0
  99. package/dist/core/advisor/runtime.js.map +1 -0
  100. package/dist/core/advisor/sesion.d.ts +109 -0
  101. package/dist/core/advisor/sesion.d.ts.map +1 -0
  102. package/dist/core/advisor/sesion.js +139 -0
  103. package/dist/core/advisor/sesion.js.map +1 -0
  104. package/dist/core/agent-session.d.ts +30 -2
  105. package/dist/core/agent-session.d.ts.map +1 -1
  106. package/dist/core/agent-session.js +430 -22
  107. package/dist/core/agent-session.js.map +1 -1
  108. package/dist/core/agents/loader.d.ts +77 -0
  109. package/dist/core/agents/loader.d.ts.map +1 -0
  110. package/dist/core/agents/loader.js +154 -0
  111. package/dist/core/agents/loader.js.map +1 -0
  112. package/dist/core/aprobacion/generados.d.ts +37 -0
  113. package/dist/core/aprobacion/generados.d.ts.map +1 -0
  114. package/dist/core/aprobacion/generados.js +85 -0
  115. package/dist/core/aprobacion/generados.js.map +1 -0
  116. package/dist/core/aprobacion/politica-de-maquina.d.ts +90 -0
  117. package/dist/core/aprobacion/politica-de-maquina.d.ts.map +1 -0
  118. package/dist/core/aprobacion/politica-de-maquina.js +212 -0
  119. package/dist/core/aprobacion/politica-de-maquina.js.map +1 -0
  120. package/dist/core/aprobacion/politica.d.ts +90 -0
  121. package/dist/core/aprobacion/politica.d.ts.map +1 -0
  122. package/dist/core/aprobacion/politica.js +375 -0
  123. package/dist/core/aprobacion/politica.js.map +1 -0
  124. package/dist/core/arranque/atajos.d.ts +46 -0
  125. package/dist/core/arranque/atajos.d.ts.map +1 -0
  126. package/dist/core/arranque/atajos.js +113 -0
  127. package/dist/core/arranque/atajos.js.map +1 -0
  128. package/dist/core/audit/exportacion.d.ts +54 -0
  129. package/dist/core/audit/exportacion.d.ts.map +1 -0
  130. package/dist/core/audit/exportacion.js +265 -0
  131. package/dist/core/audit/exportacion.js.map +1 -0
  132. package/dist/core/audit/libro.d.ts +318 -0
  133. package/dist/core/audit/libro.d.ts.map +1 -0
  134. package/dist/core/audit/libro.js +508 -0
  135. package/dist/core/audit/libro.js.map +1 -0
  136. package/dist/core/audit/registro-sesion.d.ts +78 -0
  137. package/dist/core/audit/registro-sesion.d.ts.map +1 -0
  138. package/dist/core/audit/registro-sesion.js +202 -0
  139. package/dist/core/audit/registro-sesion.js.map +1 -0
  140. package/dist/core/audit/retencion.d.ts +82 -0
  141. package/dist/core/audit/retencion.d.ts.map +1 -0
  142. package/dist/core/audit/retencion.js +152 -0
  143. package/dist/core/audit/retencion.js.map +1 -0
  144. package/dist/core/audit/rutas.d.ts +23 -0
  145. package/dist/core/audit/rutas.d.ts.map +1 -0
  146. package/dist/core/audit/rutas.js +23 -0
  147. package/dist/core/audit/rutas.js.map +1 -0
  148. package/dist/core/auth-storage.d.ts +0 -3
  149. package/dist/core/auth-storage.d.ts.map +1 -1
  150. package/dist/core/auth-storage.js +17 -5
  151. package/dist/core/auth-storage.js.map +1 -1
  152. package/dist/core/banco/almacenamiento.d.ts +18 -0
  153. package/dist/core/banco/almacenamiento.d.ts.map +1 -0
  154. package/dist/core/banco/almacenamiento.js +50 -0
  155. package/dist/core/banco/almacenamiento.js.map +1 -0
  156. package/dist/core/banco/analisis.d.ts +37 -0
  157. package/dist/core/banco/analisis.d.ts.map +1 -0
  158. package/dist/core/banco/analisis.js +164 -0
  159. package/dist/core/banco/analisis.js.map +1 -0
  160. package/dist/core/banco/bloques.d.ts +39 -0
  161. package/dist/core/banco/bloques.d.ts.map +1 -0
  162. package/dist/core/banco/bloques.js +84 -0
  163. package/dist/core/banco/bloques.js.map +1 -0
  164. package/dist/core/banco/cargas.d.ts +84 -0
  165. package/dist/core/banco/cargas.d.ts.map +1 -0
  166. package/dist/core/banco/cargas.js +520 -0
  167. package/dist/core/banco/cargas.js.map +1 -0
  168. package/dist/core/banco/comparar.d.ts +29 -0
  169. package/dist/core/banco/comparar.d.ts.map +1 -0
  170. package/dist/core/banco/comparar.js +28 -0
  171. package/dist/core/banco/comparar.js.map +1 -0
  172. package/dist/core/banco/ejecutar.d.ts +44 -0
  173. package/dist/core/banco/ejecutar.d.ts.map +1 -0
  174. package/dist/core/banco/ejecutar.js +183 -0
  175. package/dist/core/banco/ejecutar.js.map +1 -0
  176. package/dist/core/banco/generar.d.ts +24 -0
  177. package/dist/core/banco/generar.d.ts.map +1 -0
  178. package/dist/core/banco/generar.js +159 -0
  179. package/dist/core/banco/generar.js.map +1 -0
  180. package/dist/core/banco/mutaciones.d.ts +25 -0
  181. package/dist/core/banco/mutaciones.d.ts.map +1 -0
  182. package/dist/core/banco/mutaciones.js +215 -0
  183. package/dist/core/banco/mutaciones.js.map +1 -0
  184. package/dist/core/banco/tipos.d.ts +121 -0
  185. package/dist/core/banco/tipos.d.ts.map +1 -0
  186. package/dist/core/banco/tipos.js +16 -0
  187. package/dist/core/banco/tipos.js.map +1 -0
  188. package/dist/core/blobs/almacen.d.ts +81 -0
  189. package/dist/core/blobs/almacen.d.ts.map +1 -0
  190. package/dist/core/blobs/almacen.js +198 -0
  191. package/dist/core/blobs/almacen.js.map +1 -0
  192. package/dist/core/blobs/broker.d.ts +103 -0
  193. package/dist/core/blobs/broker.d.ts.map +1 -0
  194. package/dist/core/blobs/broker.js +204 -0
  195. package/dist/core/blobs/broker.js.map +1 -0
  196. package/dist/core/blobs/index.d.ts +70 -0
  197. package/dist/core/blobs/index.d.ts.map +1 -0
  198. package/dist/core/blobs/index.js +232 -0
  199. package/dist/core/blobs/index.js.map +1 -0
  200. package/dist/core/blobs/payload.d.ts +55 -0
  201. package/dist/core/blobs/payload.d.ts.map +1 -0
  202. package/dist/core/blobs/payload.js +255 -0
  203. package/dist/core/blobs/payload.js.map +1 -0
  204. package/dist/core/blobs/proveedor.d.ts +85 -0
  205. package/dist/core/blobs/proveedor.d.ts.map +1 -0
  206. package/dist/core/blobs/proveedor.js +196 -0
  207. package/dist/core/blobs/proveedor.js.map +1 -0
  208. package/dist/core/browser/cdp.d.ts +41 -0
  209. package/dist/core/browser/cdp.d.ts.map +1 -0
  210. package/dist/core/browser/cdp.js +119 -0
  211. package/dist/core/browser/cdp.js.map +1 -0
  212. package/dist/core/browser/politica.d.ts +51 -0
  213. package/dist/core/browser/politica.d.ts.map +1 -0
  214. package/dist/core/browser/politica.js +123 -0
  215. package/dist/core/browser/politica.js.map +1 -0
  216. package/dist/core/browser/sesion.d.ts +52 -0
  217. package/dist/core/browser/sesion.d.ts.map +1 -0
  218. package/dist/core/browser/sesion.js +176 -0
  219. package/dist/core/browser/sesion.js.map +1 -0
  220. package/dist/core/browser/tools.d.ts +16 -0
  221. package/dist/core/browser/tools.d.ts.map +1 -0
  222. package/dist/core/browser/tools.js +279 -0
  223. package/dist/core/browser/tools.js.map +1 -0
  224. package/dist/core/commit/diff.d.ts +56 -0
  225. package/dist/core/commit/diff.d.ts.map +1 -0
  226. package/dist/core/commit/diff.js +145 -0
  227. package/dist/core/commit/diff.js.map +1 -0
  228. package/dist/core/commit/mensaje.d.ts +80 -0
  229. package/dist/core/commit/mensaje.d.ts.map +1 -0
  230. package/dist/core/commit/mensaje.js +207 -0
  231. package/dist/core/commit/mensaje.js.map +1 -0
  232. package/dist/core/compactar/index.d.ts +52 -0
  233. package/dist/core/compactar/index.d.ts.map +1 -0
  234. package/dist/core/compactar/index.js +91 -0
  235. package/dist/core/compactar/index.js.map +1 -0
  236. package/dist/core/compactar/registro-denso.d.ts +160 -0
  237. package/dist/core/compactar/registro-denso.d.ts.map +1 -0
  238. package/dist/core/compactar/registro-denso.js +620 -0
  239. package/dist/core/compactar/registro-denso.js.map +1 -0
  240. package/dist/core/computer/captura.d.ts +35 -0
  241. package/dist/core/computer/captura.d.ts.map +1 -0
  242. package/dist/core/computer/captura.js +140 -0
  243. package/dist/core/computer/captura.js.map +1 -0
  244. package/dist/core/computer/driver.d.ts +130 -0
  245. package/dist/core/computer/driver.d.ts.map +1 -0
  246. package/dist/core/computer/driver.js +206 -0
  247. package/dist/core/computer/driver.js.map +1 -0
  248. package/dist/core/computer/motor/actions.d.ts +109 -0
  249. package/dist/core/computer/motor/actions.d.ts.map +1 -0
  250. package/dist/core/computer/motor/actions.js +157 -0
  251. package/dist/core/computer/motor/actions.js.map +1 -0
  252. package/dist/core/computer/motor/bridge.d.ts +232 -0
  253. package/dist/core/computer/motor/bridge.d.ts.map +1 -0
  254. package/dist/core/computer/motor/bridge.js +2335 -0
  255. package/dist/core/computer/motor/bridge.js.map +1 -0
  256. package/dist/core/computer/motor/cdp.d.ts +107 -0
  257. package/dist/core/computer/motor/cdp.d.ts.map +1 -0
  258. package/dist/core/computer/motor/cdp.js +659 -0
  259. package/dist/core/computer/motor/cdp.js.map +1 -0
  260. package/dist/core/computer/motor/config.d.ts +23 -0
  261. package/dist/core/computer/motor/config.d.ts.map +1 -0
  262. package/dist/core/computer/motor/config.js +100 -0
  263. package/dist/core/computer/motor/config.js.map +1 -0
  264. package/dist/core/computer/motor/contract.d.ts +81 -0
  265. package/dist/core/computer/motor/contract.d.ts.map +1 -0
  266. package/dist/core/computer/motor/contract.js +14 -0
  267. package/dist/core/computer/motor/contract.js.map +1 -0
  268. package/dist/core/computer/motor/note.d.ts +37 -0
  269. package/dist/core/computer/motor/note.d.ts.map +1 -0
  270. package/dist/core/computer/motor/note.js +162 -0
  271. package/dist/core/computer/motor/note.js.map +1 -0
  272. package/dist/core/computer/motor/outline.d.ts +155 -0
  273. package/dist/core/computer/motor/outline.d.ts.map +1 -0
  274. package/dist/core/computer/motor/outline.js +590 -0
  275. package/dist/core/computer/motor/outline.js.map +1 -0
  276. package/dist/core/computer/motor/output.d.ts +18 -0
  277. package/dist/core/computer/motor/output.d.ts.map +1 -0
  278. package/dist/core/computer/motor/output.js +148 -0
  279. package/dist/core/computer/motor/output.js.map +1 -0
  280. package/dist/core/computer/motor/permissions.d.ts +41 -0
  281. package/dist/core/computer/motor/permissions.d.ts.map +1 -0
  282. package/dist/core/computer/motor/permissions.js +51 -0
  283. package/dist/core/computer/motor/permissions.js.map +1 -0
  284. package/dist/core/computer/motor/platform/architecture.d.ts +5 -0
  285. package/dist/core/computer/motor/platform/architecture.d.ts.map +1 -0
  286. package/dist/core/computer/motor/platform/architecture.js +21 -0
  287. package/dist/core/computer/motor/platform/architecture.js.map +1 -0
  288. package/dist/core/computer/motor/platform/coerce.d.ts +4 -0
  289. package/dist/core/computer/motor/platform/coerce.d.ts.map +1 -0
  290. package/dist/core/computer/motor/platform/coerce.js +17 -0
  291. package/dist/core/computer/motor/platform/coerce.js.map +1 -0
  292. package/dist/core/computer/motor/platform/index.d.ts +4 -0
  293. package/dist/core/computer/motor/platform/index.d.ts.map +1 -0
  294. package/dist/core/computer/motor/platform/index.js +79 -0
  295. package/dist/core/computer/motor/platform/index.js.map +1 -0
  296. package/dist/core/computer/motor/platform/linux/backend.d.ts +3 -0
  297. package/dist/core/computer/motor/platform/linux/backend.d.ts.map +1 -0
  298. package/dist/core/computer/motor/platform/linux/backend.js +173 -0
  299. package/dist/core/computer/motor/platform/linux/backend.js.map +1 -0
  300. package/dist/core/computer/motor/platform/linux/helper.d.ts +29 -0
  301. package/dist/core/computer/motor/platform/linux/helper.d.ts.map +1 -0
  302. package/dist/core/computer/motor/platform/linux/helper.js +261 -0
  303. package/dist/core/computer/motor/platform/linux/helper.js.map +1 -0
  304. package/dist/core/computer/motor/platform/macos/backend.d.ts +3 -0
  305. package/dist/core/computer/motor/platform/macos/backend.d.ts.map +1 -0
  306. package/dist/core/computer/motor/platform/macos/backend.js +124 -0
  307. package/dist/core/computer/motor/platform/macos/backend.js.map +1 -0
  308. package/dist/core/computer/motor/platform/macos/browser.d.ts +7 -0
  309. package/dist/core/computer/motor/platform/macos/browser.d.ts.map +1 -0
  310. package/dist/core/computer/motor/platform/macos/browser.js +101 -0
  311. package/dist/core/computer/motor/platform/macos/browser.js.map +1 -0
  312. package/dist/core/computer/motor/platform/macos/helper-path.mjs +34 -0
  313. package/dist/core/computer/motor/platform/macos/helper.d.ts +32 -0
  314. package/dist/core/computer/motor/platform/macos/helper.d.ts.map +1 -0
  315. package/dist/core/computer/motor/platform/macos/helper.js +277 -0
  316. package/dist/core/computer/motor/platform/macos/helper.js.map +1 -0
  317. package/dist/core/computer/motor/platform/macos/permissions.d.ts +4 -0
  318. package/dist/core/computer/motor/platform/macos/permissions.d.ts.map +1 -0
  319. package/dist/core/computer/motor/platform/macos/permissions.js +118 -0
  320. package/dist/core/computer/motor/platform/macos/permissions.js.map +1 -0
  321. package/dist/core/computer/motor/platform/types.d.ts +263 -0
  322. package/dist/core/computer/motor/platform/types.d.ts.map +1 -0
  323. package/dist/core/computer/motor/platform/types.js +2 -0
  324. package/dist/core/computer/motor/platform/types.js.map +1 -0
  325. package/dist/core/computer/motor/platform/windows/backend.d.ts +3 -0
  326. package/dist/core/computer/motor/platform/windows/backend.d.ts.map +1 -0
  327. package/dist/core/computer/motor/platform/windows/backend.js +163 -0
  328. package/dist/core/computer/motor/platform/windows/backend.js.map +1 -0
  329. package/dist/core/computer/motor/platform/windows/helper.d.ts +18 -0
  330. package/dist/core/computer/motor/platform/windows/helper.d.ts.map +1 -0
  331. package/dist/core/computer/motor/platform/windows/helper.js +174 -0
  332. package/dist/core/computer/motor/platform/windows/helper.js.map +1 -0
  333. package/dist/core/computer/motor/root-selection.d.ts +6 -0
  334. package/dist/core/computer/motor/root-selection.d.ts.map +1 -0
  335. package/dist/core/computer/motor/root-selection.js +28 -0
  336. package/dist/core/computer/motor/root-selection.js.map +1 -0
  337. package/dist/core/computer/motor/runtime.d.ts +50 -0
  338. package/dist/core/computer/motor/runtime.d.ts.map +1 -0
  339. package/dist/core/computer/motor/runtime.js +119 -0
  340. package/dist/core/computer/motor/runtime.js.map +1 -0
  341. package/dist/core/computer/motor/state.d.ts +68 -0
  342. package/dist/core/computer/motor/state.d.ts.map +1 -0
  343. package/dist/core/computer/motor/state.js +100 -0
  344. package/dist/core/computer/motor/state.js.map +1 -0
  345. package/dist/core/computer/motor/view.d.ts +6 -0
  346. package/dist/core/computer/motor/view.d.ts.map +1 -0
  347. package/dist/core/computer/motor/view.js +185 -0
  348. package/dist/core/computer/motor/view.js.map +1 -0
  349. package/dist/core/computer/motor-ada.d.ts +159 -0
  350. package/dist/core/computer/motor-ada.d.ts.map +1 -0
  351. package/dist/core/computer/motor-ada.js +412 -0
  352. package/dist/core/computer/motor-ada.js.map +1 -0
  353. package/dist/core/computer/politica.d.ts +56 -0
  354. package/dist/core/computer/politica.d.ts.map +1 -0
  355. package/dist/core/computer/politica.js +163 -0
  356. package/dist/core/computer/politica.js.map +1 -0
  357. package/dist/core/computer/tools.d.ts +26 -0
  358. package/dist/core/computer/tools.d.ts.map +1 -0
  359. package/dist/core/computer/tools.js +399 -0
  360. package/dist/core/computer/tools.js.map +1 -0
  361. package/dist/core/context-breakdown.d.ts +80 -0
  362. package/dist/core/context-breakdown.d.ts.map +1 -0
  363. package/dist/core/context-breakdown.js +87 -0
  364. package/dist/core/context-breakdown.js.map +1 -0
  365. package/dist/core/credenciales/cliente.d.ts +60 -0
  366. package/dist/core/credenciales/cliente.d.ts.map +1 -0
  367. package/dist/core/credenciales/cliente.js +81 -0
  368. package/dist/core/credenciales/cliente.js.map +1 -0
  369. package/dist/core/credenciales/pool.d.ts +96 -0
  370. package/dist/core/credenciales/pool.d.ts.map +1 -0
  371. package/dist/core/credenciales/pool.js +128 -0
  372. package/dist/core/credenciales/pool.js.map +1 -0
  373. package/dist/core/credenciales/reposo.d.ts +93 -0
  374. package/dist/core/credenciales/reposo.d.ts.map +1 -0
  375. package/dist/core/credenciales/reposo.js +489 -0
  376. package/dist/core/credenciales/reposo.js.map +1 -0
  377. package/dist/core/credenciales/servidor.d.ts +55 -0
  378. package/dist/core/credenciales/servidor.d.ts.map +1 -0
  379. package/dist/core/credenciales/servidor.js +205 -0
  380. package/dist/core/credenciales/servidor.js.map +1 -0
  381. package/dist/core/descubrimiento/comandos.d.ts +30 -0
  382. package/dist/core/descubrimiento/comandos.d.ts.map +1 -0
  383. package/dist/core/descubrimiento/comandos.js +76 -0
  384. package/dist/core/descubrimiento/comandos.js.map +1 -0
  385. package/dist/core/descubrimiento/mcp.d.ts +42 -0
  386. package/dist/core/descubrimiento/mcp.d.ts.map +1 -0
  387. package/dist/core/descubrimiento/mcp.js +130 -0
  388. package/dist/core/descubrimiento/mcp.js.map +1 -0
  389. package/dist/core/descubrimiento/reglas.d.ts +61 -0
  390. package/dist/core/descubrimiento/reglas.d.ts.map +1 -0
  391. package/dist/core/descubrimiento/reglas.js +134 -0
  392. package/dist/core/descubrimiento/reglas.js.map +1 -0
  393. package/dist/core/descubrimiento/skills.d.ts +57 -0
  394. package/dist/core/descubrimiento/skills.d.ts.map +1 -0
  395. package/dist/core/descubrimiento/skills.js +113 -0
  396. package/dist/core/descubrimiento/skills.js.map +1 -0
  397. package/dist/core/dificultad/clasificador.d.ts +133 -0
  398. package/dist/core/dificultad/clasificador.d.ts.map +1 -0
  399. package/dist/core/dificultad/clasificador.js +288 -0
  400. package/dist/core/dificultad/clasificador.js.map +1 -0
  401. package/dist/core/edicion/diario.d.ts +37 -0
  402. package/dist/core/edicion/diario.d.ts.map +1 -0
  403. package/dist/core/edicion/diario.js +51 -0
  404. package/dist/core/edicion/diario.js.map +1 -0
  405. package/dist/core/edicion/hashline.d.ts +71 -0
  406. package/dist/core/edicion/hashline.d.ts.map +1 -0
  407. package/dist/core/edicion/hashline.js +111 -0
  408. package/dist/core/edicion/hashline.js.map +1 -0
  409. package/dist/core/edicion/hueco.d.ts +64 -0
  410. package/dist/core/edicion/hueco.d.ts.map +1 -0
  411. package/dist/core/edicion/hueco.js +162 -0
  412. package/dist/core/edicion/hueco.js.map +1 -0
  413. package/dist/core/edicion/limpiar-carga.d.ts +39 -0
  414. package/dist/core/edicion/limpiar-carga.d.ts.map +1 -0
  415. package/dist/core/edicion/limpiar-carga.js +121 -0
  416. package/dist/core/edicion/limpiar-carga.js.map +1 -0
  417. package/dist/core/edicion/observador.d.ts +80 -0
  418. package/dist/core/edicion/observador.d.ts.map +1 -0
  419. package/dist/core/edicion/observador.js +183 -0
  420. package/dist/core/edicion/observador.js.map +1 -0
  421. package/dist/core/edicion/parecido.d.ts +53 -0
  422. package/dist/core/edicion/parecido.d.ts.map +1 -0
  423. package/dist/core/edicion/parecido.js +145 -0
  424. package/dist/core/edicion/parecido.js.map +1 -0
  425. package/dist/core/edicion/parseo.d.ts +58 -0
  426. package/dist/core/edicion/parseo.d.ts.map +1 -0
  427. package/dist/core/edicion/parseo.js +124 -0
  428. package/dist/core/edicion/parseo.js.map +1 -0
  429. package/dist/core/edicion/reparacion.d.ts +67 -0
  430. package/dist/core/edicion/reparacion.d.ts.map +1 -0
  431. package/dist/core/edicion/reparacion.js +202 -0
  432. package/dist/core/edicion/reparacion.js.map +1 -0
  433. package/dist/core/edicion/sangria.d.ts +121 -0
  434. package/dist/core/edicion/sangria.d.ts.map +1 -0
  435. package/dist/core/edicion/sangria.js +341 -0
  436. package/dist/core/edicion/sangria.js.map +1 -0
  437. package/dist/core/edicion/tipos.d.ts +58 -0
  438. package/dist/core/edicion/tipos.d.ts.map +1 -0
  439. package/dist/core/edicion/tipos.js +160 -0
  440. package/dist/core/edicion/tipos.js.map +1 -0
  441. package/dist/core/errores/proveedor.d.ts +53 -0
  442. package/dist/core/errores/proveedor.d.ts.map +1 -0
  443. package/dist/core/errores/proveedor.js +191 -0
  444. package/dist/core/errores/proveedor.js.map +1 -0
  445. package/dist/core/estructural/buscar.d.ts +61 -0
  446. package/dist/core/estructural/buscar.d.ts.map +1 -0
  447. package/dist/core/estructural/buscar.js +261 -0
  448. package/dist/core/estructural/buscar.js.map +1 -0
  449. package/dist/core/estructural/editar.d.ts +36 -0
  450. package/dist/core/estructural/editar.d.ts.map +1 -0
  451. package/dist/core/estructural/editar.js +123 -0
  452. package/dist/core/estructural/editar.js.map +1 -0
  453. package/dist/core/estructural/tools.d.ts +11 -0
  454. package/dist/core/estructural/tools.d.ts.map +1 -0
  455. package/dist/core/estructural/tools.js +100 -0
  456. package/dist/core/estructural/tools.js.map +1 -0
  457. package/dist/core/experimental.d.ts.map +1 -1
  458. package/dist/core/experimental.js +10 -1
  459. package/dist/core/experimental.js.map +1 -1
  460. package/dist/core/extensiones/suplantacion.d.ts +49 -0
  461. package/dist/core/extensiones/suplantacion.d.ts.map +1 -0
  462. package/dist/core/extensiones/suplantacion.js +61 -0
  463. package/dist/core/extensiones/suplantacion.js.map +1 -0
  464. package/dist/core/extensiones/vigilancia.d.ts +54 -0
  465. package/dist/core/extensiones/vigilancia.d.ts.map +1 -0
  466. package/dist/core/extensiones/vigilancia.js +217 -0
  467. package/dist/core/extensiones/vigilancia.js.map +1 -0
  468. package/dist/core/extensions/loader.d.ts.map +1 -1
  469. package/dist/core/extensions/loader.js +11 -1
  470. package/dist/core/extensions/loader.js.map +1 -1
  471. package/dist/core/harness/fuentes-de-contexto.d.ts +29 -0
  472. package/dist/core/harness/fuentes-de-contexto.d.ts.map +1 -0
  473. package/dist/core/harness/fuentes-de-contexto.js +44 -0
  474. package/dist/core/harness/fuentes-de-contexto.js.map +1 -0
  475. package/dist/core/harness/refine.d.ts +40 -0
  476. package/dist/core/harness/refine.d.ts.map +1 -0
  477. package/dist/core/harness/refine.js +109 -0
  478. package/dist/core/harness/refine.js.map +1 -0
  479. package/dist/core/harness/store.d.ts +75 -0
  480. package/dist/core/harness/store.d.ts.map +1 -0
  481. package/dist/core/harness/store.js +149 -0
  482. package/dist/core/harness/store.js.map +1 -0
  483. package/dist/core/hooks/contract.d.ts +85 -0
  484. package/dist/core/hooks/contract.d.ts.map +1 -0
  485. package/dist/core/hooks/contract.js +140 -0
  486. package/dist/core/hooks/contract.js.map +1 -0
  487. package/dist/core/hooks/runner.d.ts +42 -0
  488. package/dist/core/hooks/runner.d.ts.map +1 -0
  489. package/dist/core/hooks/runner.js +85 -0
  490. package/dist/core/hooks/runner.js.map +1 -0
  491. package/dist/core/hooks/session-hooks.d.ts +62 -0
  492. package/dist/core/hooks/session-hooks.d.ts.map +1 -0
  493. package/dist/core/hooks/session-hooks.js +84 -0
  494. package/dist/core/hooks/session-hooks.js.map +1 -0
  495. package/dist/core/importar/formatos.d.ts +69 -0
  496. package/dist/core/importar/formatos.d.ts.map +1 -0
  497. package/dist/core/importar/formatos.js +235 -0
  498. package/dist/core/importar/formatos.js.map +1 -0
  499. package/dist/core/interactivo/deteccion.d.ts +44 -0
  500. package/dist/core/interactivo/deteccion.d.ts.map +1 -0
  501. package/dist/core/interactivo/deteccion.js +82 -0
  502. package/dist/core/interactivo/deteccion.js.map +1 -0
  503. package/dist/core/interactivo/sesion.d.ts +50 -0
  504. package/dist/core/interactivo/sesion.d.ts.map +1 -0
  505. package/dist/core/interactivo/sesion.js +156 -0
  506. package/dist/core/interactivo/sesion.js.map +1 -0
  507. package/dist/core/interactivo/tools.d.ts +21 -0
  508. package/dist/core/interactivo/tools.d.ts.map +1 -0
  509. package/dist/core/interactivo/tools.js +122 -0
  510. package/dist/core/interactivo/tools.js.map +1 -0
  511. package/dist/core/lectura/mapa.d.ts +70 -0
  512. package/dist/core/lectura/mapa.d.ts.map +1 -0
  513. package/dist/core/lectura/mapa.js +177 -0
  514. package/dist/core/lectura/mapa.js.map +1 -0
  515. package/dist/core/lectura/pdf.d.ts +49 -0
  516. package/dist/core/lectura/pdf.d.ts.map +1 -0
  517. package/dist/core/lectura/pdf.js +337 -0
  518. package/dist/core/lectura/pdf.js.map +1 -0
  519. package/dist/core/limpieza/comprobadores.d.ts +28 -0
  520. package/dist/core/limpieza/comprobadores.d.ts.map +1 -0
  521. package/dist/core/limpieza/comprobadores.js +311 -0
  522. package/dist/core/limpieza/comprobadores.js.map +1 -0
  523. package/dist/core/limpieza/parseo.d.ts +19 -0
  524. package/dist/core/limpieza/parseo.d.ts.map +1 -0
  525. package/dist/core/limpieza/parseo.js +124 -0
  526. package/dist/core/limpieza/parseo.js.map +1 -0
  527. package/dist/core/limpieza/reparacion.d.ts +77 -0
  528. package/dist/core/limpieza/reparacion.d.ts.map +1 -0
  529. package/dist/core/limpieza/reparacion.js +254 -0
  530. package/dist/core/limpieza/reparacion.js.map +1 -0
  531. package/dist/core/limpieza/tipos.d.ts +56 -0
  532. package/dist/core/limpieza/tipos.d.ts.map +1 -0
  533. package/dist/core/limpieza/tipos.js +9 -0
  534. package/dist/core/limpieza/tipos.js.map +1 -0
  535. package/dist/core/lsp/cliente.d.ts +52 -0
  536. package/dist/core/lsp/cliente.d.ts.map +1 -0
  537. package/dist/core/lsp/cliente.js +232 -0
  538. package/dist/core/lsp/cliente.js.map +1 -0
  539. package/dist/core/lsp/descubrimiento.d.ts +62 -0
  540. package/dist/core/lsp/descubrimiento.d.ts.map +1 -0
  541. package/dist/core/lsp/descubrimiento.js +152 -0
  542. package/dist/core/lsp/descubrimiento.js.map +1 -0
  543. package/dist/core/lsp/ediciones.d.ts +59 -0
  544. package/dist/core/lsp/ediciones.d.ts.map +1 -0
  545. package/dist/core/lsp/ediciones.js +89 -0
  546. package/dist/core/lsp/ediciones.js.map +1 -0
  547. package/dist/core/lsp/extension.d.ts +28 -0
  548. package/dist/core/lsp/extension.d.ts.map +1 -0
  549. package/dist/core/lsp/extension.js +34 -0
  550. package/dist/core/lsp/extension.js.map +1 -0
  551. package/dist/core/lsp/tools.d.ts +45 -0
  552. package/dist/core/lsp/tools.d.ts.map +1 -0
  553. package/dist/core/lsp/tools.js +265 -0
  554. package/dist/core/lsp/tools.js.map +1 -0
  555. package/dist/core/mcp/client.d.ts +60 -0
  556. package/dist/core/mcp/client.d.ts.map +1 -0
  557. package/dist/core/mcp/client.js +139 -0
  558. package/dist/core/mcp/client.js.map +1 -0
  559. package/dist/core/mcp/manager.d.ts +86 -0
  560. package/dist/core/mcp/manager.d.ts.map +1 -0
  561. package/dist/core/mcp/manager.js +124 -0
  562. package/dist/core/mcp/manager.js.map +1 -0
  563. package/dist/core/mcp/tools.d.ts +15 -0
  564. package/dist/core/mcp/tools.d.ts.map +1 -0
  565. package/dist/core/mcp/tools.js +84 -0
  566. package/dist/core/mcp/tools.js.map +1 -0
  567. package/dist/core/memory-engine/audit-export.d.ts +12 -10
  568. package/dist/core/memory-engine/audit-export.d.ts.map +1 -1
  569. package/dist/core/memory-engine/audit-export.js +15 -0
  570. package/dist/core/memory-engine/audit-export.js.map +1 -1
  571. package/dist/core/memory-engine/audit-indice.d.ts +153 -0
  572. package/dist/core/memory-engine/audit-indice.d.ts.map +1 -0
  573. package/dist/core/memory-engine/audit-indice.js +271 -0
  574. package/dist/core/memory-engine/audit-indice.js.map +1 -0
  575. package/dist/core/memory-engine/audit.d.ts +18 -6
  576. package/dist/core/memory-engine/audit.d.ts.map +1 -1
  577. package/dist/core/memory-engine/audit.js +25 -42
  578. package/dist/core/memory-engine/audit.js.map +1 -1
  579. package/dist/core/memory-engine/engine.d.ts +19 -1
  580. package/dist/core/memory-engine/engine.d.ts.map +1 -1
  581. package/dist/core/memory-engine/engine.js +71 -5
  582. package/dist/core/memory-engine/engine.js.map +1 -1
  583. package/dist/core/memory-engine/observation-store.d.ts +0 -2
  584. package/dist/core/memory-engine/observation-store.d.ts.map +1 -1
  585. package/dist/core/memory-engine/observation-store.js +4 -5
  586. package/dist/core/memory-engine/observation-store.js.map +1 -1
  587. package/dist/core/memory-engine/refinements.d.ts +51 -0
  588. package/dist/core/memory-engine/refinements.d.ts.map +1 -0
  589. package/dist/core/memory-engine/refinements.js +99 -0
  590. package/dist/core/memory-engine/refinements.js.map +1 -0
  591. package/dist/core/memory-engine/tools.d.ts.map +1 -1
  592. package/dist/core/memory-engine/tools.js +27 -1
  593. package/dist/core/memory-engine/tools.js.map +1 -1
  594. package/dist/core/memory-engine/types.d.ts +2 -0
  595. package/dist/core/memory-engine/types.d.ts.map +1 -1
  596. package/dist/core/memory-engine/types.js.map +1 -1
  597. package/dist/core/model-resolver.d.ts.map +1 -1
  598. package/dist/core/model-resolver.js +7 -1
  599. package/dist/core/model-resolver.js.map +1 -1
  600. package/dist/core/muestreo-restringido.d.ts +49 -0
  601. package/dist/core/muestreo-restringido.d.ts.map +1 -0
  602. package/dist/core/muestreo-restringido.js +65 -0
  603. package/dist/core/muestreo-restringido.js.map +1 -0
  604. package/dist/core/orphan-process-journal.d.ts +48 -0
  605. package/dist/core/orphan-process-journal.d.ts.map +1 -0
  606. package/dist/core/orphan-process-journal.js +116 -0
  607. package/dist/core/orphan-process-journal.js.map +1 -0
  608. package/dist/core/privacidad/categorias-especiales.d.ts +186 -0
  609. package/dist/core/privacidad/categorias-especiales.d.ts.map +1 -0
  610. package/dist/core/privacidad/categorias-especiales.js +745 -0
  611. package/dist/core/privacidad/categorias-especiales.js.map +1 -0
  612. package/dist/core/privacidad/tapar.d.ts +48 -0
  613. package/dist/core/privacidad/tapar.d.ts.map +1 -0
  614. package/dist/core/privacidad/tapar.js +66 -0
  615. package/dist/core/privacidad/tapar.js.map +1 -0
  616. package/dist/core/prompt-cache/diagnostics.d.ts +33 -0
  617. package/dist/core/prompt-cache/diagnostics.d.ts.map +1 -0
  618. package/dist/core/prompt-cache/diagnostics.js +100 -0
  619. package/dist/core/prompt-cache/diagnostics.js.map +1 -0
  620. package/dist/core/prompt-cache/index.d.ts +33 -0
  621. package/dist/core/prompt-cache/index.d.ts.map +1 -0
  622. package/dist/core/prompt-cache/index.js +189 -0
  623. package/dist/core/prompt-cache/index.js.map +1 -0
  624. package/dist/core/prompt-cache/payload.d.ts +58 -0
  625. package/dist/core/prompt-cache/payload.d.ts.map +1 -0
  626. package/dist/core/prompt-cache/payload.js +122 -0
  627. package/dist/core/prompt-cache/payload.js.map +1 -0
  628. package/dist/core/prompt-cache/stabilize.d.ts +65 -0
  629. package/dist/core/prompt-cache/stabilize.d.ts.map +1 -0
  630. package/dist/core/prompt-cache/stabilize.js +137 -0
  631. package/dist/core/prompt-cache/stabilize.js.map +1 -0
  632. package/dist/core/prompt-cache/stats.d.ts +55 -0
  633. package/dist/core/prompt-cache/stats.d.ts.map +1 -0
  634. package/dist/core/prompt-cache/stats.js +158 -0
  635. package/dist/core/prompt-cache/stats.js.map +1 -0
  636. package/dist/core/prompt-eleccion.d.ts +38 -0
  637. package/dist/core/prompt-eleccion.d.ts.map +1 -0
  638. package/dist/core/prompt-eleccion.js +46 -0
  639. package/dist/core/prompt-eleccion.js.map +1 -0
  640. package/dist/core/prompts/montar.d.ts +75 -0
  641. package/dist/core/prompts/montar.d.ts.map +1 -0
  642. package/dist/core/prompts/montar.js +146 -0
  643. package/dist/core/prompts/montar.js.map +1 -0
  644. package/dist/core/prompts/plantilla.d.ts +54 -0
  645. package/dist/core/prompts/plantilla.d.ts.map +1 -0
  646. package/dist/core/prompts/plantilla.js +153 -0
  647. package/dist/core/prompts/plantilla.js.map +1 -0
  648. package/dist/core/prompts/sistema.md +134 -0
  649. package/dist/core/provider-attribution.d.ts +24 -2
  650. package/dist/core/provider-attribution.d.ts.map +1 -1
  651. package/dist/core/provider-attribution.js +24 -42
  652. package/dist/core/provider-attribution.js.map +1 -1
  653. package/dist/core/remoto/destino.d.ts +38 -0
  654. package/dist/core/remoto/destino.d.ts.map +1 -0
  655. package/dist/core/remoto/destino.js +105 -0
  656. package/dist/core/remoto/destino.js.map +1 -0
  657. package/dist/core/remoto/ejecutor.d.ts +59 -0
  658. package/dist/core/remoto/ejecutor.d.ts.map +1 -0
  659. package/dist/core/remoto/ejecutor.js +225 -0
  660. package/dist/core/remoto/ejecutor.js.map +1 -0
  661. package/dist/core/remoto/ficheros.d.ts +29 -0
  662. package/dist/core/remoto/ficheros.d.ts.map +1 -0
  663. package/dist/core/remoto/ficheros.js +90 -0
  664. package/dist/core/remoto/ficheros.js.map +1 -0
  665. package/dist/core/remoto/registro-extension.d.ts +15 -0
  666. package/dist/core/remoto/registro-extension.d.ts.map +1 -0
  667. package/dist/core/remoto/registro-extension.js +17 -0
  668. package/dist/core/remoto/registro-extension.js.map +1 -0
  669. package/dist/core/remoto/tools.d.ts +28 -0
  670. package/dist/core/remoto/tools.d.ts.map +1 -0
  671. package/dist/core/remoto/tools.js +31 -0
  672. package/dist/core/remoto/tools.js.map +1 -0
  673. package/dist/core/resource-loader.d.ts +8 -0
  674. package/dist/core/resource-loader.d.ts.map +1 -1
  675. package/dist/core/resource-loader.js +93 -1
  676. package/dist/core/resource-loader.js.map +1 -1
  677. package/dist/core/revision/hallazgo.d.ts +51 -0
  678. package/dist/core/revision/hallazgo.d.ts.map +1 -0
  679. package/dist/core/revision/hallazgo.js +73 -0
  680. package/dist/core/revision/hallazgo.js.map +1 -0
  681. package/dist/core/revision/revisor.d.ts +81 -0
  682. package/dist/core/revision/revisor.d.ts.map +1 -0
  683. package/dist/core/revision/revisor.js +132 -0
  684. package/dist/core/revision/revisor.js.map +1 -0
  685. package/dist/core/revision/sarif.d.ts +30 -0
  686. package/dist/core/revision/sarif.d.ts.map +1 -0
  687. package/dist/core/revision/sarif.js +83 -0
  688. package/dist/core/revision/sarif.js.map +1 -0
  689. package/dist/core/scheduler/scheduler.d.ts +87 -0
  690. package/dist/core/scheduler/scheduler.d.ts.map +1 -0
  691. package/dist/core/scheduler/scheduler.js +178 -0
  692. package/dist/core/scheduler/scheduler.js.map +1 -0
  693. package/dist/core/sesion/cerrar-llamadas-abiertas.d.ts +49 -0
  694. package/dist/core/sesion/cerrar-llamadas-abiertas.d.ts.map +1 -0
  695. package/dist/core/sesion/cerrar-llamadas-abiertas.js +77 -0
  696. package/dist/core/sesion/cerrar-llamadas-abiertas.js.map +1 -0
  697. package/dist/core/settings-manager.d.ts +110 -6
  698. package/dist/core/settings-manager.d.ts.map +1 -1
  699. package/dist/core/settings-manager.js +53 -2
  700. package/dist/core/settings-manager.js.map +1 -1
  701. package/dist/core/slash-commands.d.ts.map +1 -1
  702. package/dist/core/slash-commands.js +3 -3
  703. package/dist/core/slash-commands.js.map +1 -1
  704. package/dist/core/system-prompt.d.ts +17 -0
  705. package/dist/core/system-prompt.d.ts.map +1 -1
  706. package/dist/core/system-prompt.js +13 -5
  707. package/dist/core/system-prompt.js.map +1 -1
  708. package/dist/core/telemetria/otlp.d.ts +122 -0
  709. package/dist/core/telemetria/otlp.d.ts.map +1 -0
  710. package/dist/core/telemetria/otlp.js +373 -0
  711. package/dist/core/telemetria/otlp.js.map +1 -0
  712. package/dist/core/tools/coercion-argumentos.d.ts +48 -0
  713. package/dist/core/tools/coercion-argumentos.d.ts.map +1 -0
  714. package/dist/core/tools/coercion-argumentos.js +99 -0
  715. package/dist/core/tools/coercion-argumentos.js.map +1 -0
  716. package/dist/core/tools/edit-diff.d.ts +0 -7
  717. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  718. package/dist/core/tools/edit-diff.js +232 -7
  719. package/dist/core/tools/edit-diff.js.map +1 -1
  720. package/dist/core/tools/edit.d.ts.map +1 -1
  721. package/dist/core/tools/edit.js +8 -1
  722. package/dist/core/tools/edit.js.map +1 -1
  723. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  724. package/dist/core/tools/file-mutation-queue.js +5 -0
  725. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  726. package/dist/core/tools/json-tolerante.d.ts +30 -0
  727. package/dist/core/tools/json-tolerante.d.ts.map +1 -0
  728. package/dist/core/tools/json-tolerante.js +70 -0
  729. package/dist/core/tools/json-tolerante.js.map +1 -0
  730. package/dist/core/tools/read.d.ts.map +1 -1
  731. package/dist/core/tools/read.js +17 -0
  732. package/dist/core/tools/read.js.map +1 -1
  733. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -1
  734. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  735. package/dist/core/tools/tool-definition-wrapper.js +17 -1
  736. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  737. package/dist/core/turno-vacio/detectar.d.ts +38 -0
  738. package/dist/core/turno-vacio/detectar.d.ts.map +1 -0
  739. package/dist/core/turno-vacio/detectar.js +66 -0
  740. package/dist/core/turno-vacio/detectar.js.map +1 -0
  741. package/dist/core/undo/journal.d.ts +57 -0
  742. package/dist/core/undo/journal.d.ts.map +1 -0
  743. package/dist/core/undo/journal.js +178 -0
  744. package/dist/core/undo/journal.js.map +1 -0
  745. package/dist/core/urls-internas/auditoria.d.ts +10 -0
  746. package/dist/core/urls-internas/auditoria.d.ts.map +1 -0
  747. package/dist/core/urls-internas/auditoria.js +42 -0
  748. package/dist/core/urls-internas/auditoria.js.map +1 -0
  749. package/dist/core/urls-internas/boveda.d.ts +13 -0
  750. package/dist/core/urls-internas/boveda.d.ts.map +1 -0
  751. package/dist/core/urls-internas/boveda.js +40 -0
  752. package/dist/core/urls-internas/boveda.js.map +1 -0
  753. package/dist/core/urls-internas/lector.d.ts +30 -0
  754. package/dist/core/urls-internas/lector.d.ts.map +1 -0
  755. package/dist/core/urls-internas/lector.js +56 -0
  756. package/dist/core/urls-internas/lector.js.map +1 -0
  757. package/dist/core/urls-internas/memoria.d.ts +11 -0
  758. package/dist/core/urls-internas/memoria.d.ts.map +1 -0
  759. package/dist/core/urls-internas/memoria.js +25 -0
  760. package/dist/core/urls-internas/memoria.js.map +1 -0
  761. package/dist/core/urls-internas/parse.d.ts +28 -0
  762. package/dist/core/urls-internas/parse.d.ts.map +1 -0
  763. package/dist/core/urls-internas/parse.js +32 -0
  764. package/dist/core/urls-internas/parse.js.map +1 -0
  765. package/dist/core/urls-internas/reglas.d.ts +10 -0
  766. package/dist/core/urls-internas/reglas.d.ts.map +1 -0
  767. package/dist/core/urls-internas/reglas.js +31 -0
  768. package/dist/core/urls-internas/reglas.js.map +1 -0
  769. package/dist/core/usage/aggregate.d.ts +68 -0
  770. package/dist/core/usage/aggregate.d.ts.map +1 -0
  771. package/dist/core/usage/aggregate.js +93 -0
  772. package/dist/core/usage/aggregate.js.map +1 -0
  773. package/dist/core/usage/cuota/anthropic.d.ts +10 -0
  774. package/dist/core/usage/cuota/anthropic.d.ts.map +1 -0
  775. package/dist/core/usage/cuota/anthropic.js +63 -0
  776. package/dist/core/usage/cuota/anthropic.js.map +1 -0
  777. package/dist/core/usage/cuota/cache.d.ts +20 -0
  778. package/dist/core/usage/cuota/cache.d.ts.map +1 -0
  779. package/dist/core/usage/cuota/cache.js +36 -0
  780. package/dist/core/usage/cuota/cache.js.map +1 -0
  781. package/dist/core/usage/cuota/github-copilot.d.ts +9 -0
  782. package/dist/core/usage/cuota/github-copilot.d.ts.map +1 -0
  783. package/dist/core/usage/cuota/github-copilot.js +67 -0
  784. package/dist/core/usage/cuota/github-copilot.js.map +1 -0
  785. package/dist/core/usage/cuota/google-gemini.d.ts +9 -0
  786. package/dist/core/usage/cuota/google-gemini.d.ts.map +1 -0
  787. package/dist/core/usage/cuota/google-gemini.js +72 -0
  788. package/dist/core/usage/cuota/google-gemini.js.map +1 -0
  789. package/dist/core/usage/cuota/index.d.ts +25 -0
  790. package/dist/core/usage/cuota/index.d.ts.map +1 -0
  791. package/dist/core/usage/cuota/index.js +50 -0
  792. package/dist/core/usage/cuota/index.js.map +1 -0
  793. package/dist/core/usage/cuota/openai-codex.d.ts +9 -0
  794. package/dist/core/usage/cuota/openai-codex.d.ts.map +1 -0
  795. package/dist/core/usage/cuota/openai-codex.js +59 -0
  796. package/dist/core/usage/cuota/openai-codex.js.map +1 -0
  797. package/dist/core/usage/cuota/openrouter.d.ts +10 -0
  798. package/dist/core/usage/cuota/openrouter.d.ts.map +1 -0
  799. package/dist/core/usage/cuota/openrouter.js +47 -0
  800. package/dist/core/usage/cuota/openrouter.js.map +1 -0
  801. package/dist/core/usage/cuota/tipos.d.ts +50 -0
  802. package/dist/core/usage/cuota/tipos.d.ts.map +1 -0
  803. package/dist/core/usage/cuota/tipos.js +25 -0
  804. package/dist/core/usage/cuota/tipos.js.map +1 -0
  805. package/dist/core/web/busqueda-nativa.d.ts +82 -0
  806. package/dist/core/web/busqueda-nativa.d.ts.map +1 -0
  807. package/dist/core/web/busqueda-nativa.js +163 -0
  808. package/dist/core/web/busqueda-nativa.js.map +1 -0
  809. package/dist/core/web/destino.d.ts +58 -0
  810. package/dist/core/web/destino.d.ts.map +1 -0
  811. package/dist/core/web/destino.js +127 -0
  812. package/dist/core/web/destino.js.map +1 -0
  813. package/dist/core/web/proveedores/brave.d.ts +6 -0
  814. package/dist/core/web/proveedores/brave.d.ts.map +1 -0
  815. package/dist/core/web/proveedores/brave.js +20 -0
  816. package/dist/core/web/proveedores/brave.js.map +1 -0
  817. package/dist/core/web/proveedores/claves.d.ts +19 -0
  818. package/dist/core/web/proveedores/claves.d.ts.map +1 -0
  819. package/dist/core/web/proveedores/claves.js +36 -0
  820. package/dist/core/web/proveedores/claves.js.map +1 -0
  821. package/dist/core/web/proveedores/duckduckgo.d.ts +3 -0
  822. package/dist/core/web/proveedores/duckduckgo.d.ts.map +1 -0
  823. package/dist/core/web/proveedores/duckduckgo.js +109 -0
  824. package/dist/core/web/proveedores/duckduckgo.js.map +1 -0
  825. package/dist/core/web/proveedores/ecosia.d.ts +3 -0
  826. package/dist/core/web/proveedores/ecosia.d.ts.map +1 -0
  827. package/dist/core/web/proveedores/ecosia.js +72 -0
  828. package/dist/core/web/proveedores/ecosia.js.map +1 -0
  829. package/dist/core/web/proveedores/exa.d.ts +6 -0
  830. package/dist/core/web/proveedores/exa.d.ts.map +1 -0
  831. package/dist/core/web/proveedores/exa.js +24 -0
  832. package/dist/core/web/proveedores/exa.js.map +1 -0
  833. package/dist/core/web/proveedores/mojeek.d.ts +3 -0
  834. package/dist/core/web/proveedores/mojeek.d.ts.map +1 -0
  835. package/dist/core/web/proveedores/mojeek.js +65 -0
  836. package/dist/core/web/proveedores/mojeek.js.map +1 -0
  837. package/dist/core/web/proveedores/navegador.d.ts +10 -0
  838. package/dist/core/web/proveedores/navegador.d.ts.map +1 -0
  839. package/dist/core/web/proveedores/navegador.js +13 -0
  840. package/dist/core/web/proveedores/navegador.js.map +1 -0
  841. package/dist/core/web/proveedores/registro.d.ts +43 -0
  842. package/dist/core/web/proveedores/registro.d.ts.map +1 -0
  843. package/dist/core/web/proveedores/registro.js +49 -0
  844. package/dist/core/web/proveedores/registro.js.map +1 -0
  845. package/dist/core/web/proveedores/searxng.d.ts +9 -0
  846. package/dist/core/web/proveedores/searxng.d.ts.map +1 -0
  847. package/dist/core/web/proveedores/searxng.js +17 -0
  848. package/dist/core/web/proveedores/searxng.js.map +1 -0
  849. package/dist/core/web/proveedores/serper.d.ts +9 -0
  850. package/dist/core/web/proveedores/serper.d.ts.map +1 -0
  851. package/dist/core/web/proveedores/serper.js +19 -0
  852. package/dist/core/web/proveedores/serper.js.map +1 -0
  853. package/dist/core/web/proveedores/tavily.d.ts +6 -0
  854. package/dist/core/web/proveedores/tavily.d.ts.map +1 -0
  855. package/dist/core/web/proveedores/tavily.js +19 -0
  856. package/dist/core/web/proveedores/tavily.js.map +1 -0
  857. package/dist/core/web/proveedores/tipos.d.ts +36 -0
  858. package/dist/core/web/proveedores/tipos.d.ts.map +1 -0
  859. package/dist/core/web/proveedores/tipos.js +10 -0
  860. package/dist/core/web/proveedores/tipos.js.map +1 -0
  861. package/dist/core/web/registro-red.d.ts +43 -0
  862. package/dist/core/web/registro-red.d.ts.map +1 -0
  863. package/dist/core/web/registro-red.js +86 -0
  864. package/dist/core/web/registro-red.js.map +1 -0
  865. package/dist/core/web/scrapers/cisa-kev.d.ts +10 -0
  866. package/dist/core/web/scrapers/cisa-kev.d.ts.map +1 -0
  867. package/dist/core/web/scrapers/cisa-kev.js +38 -0
  868. package/dist/core/web/scrapers/cisa-kev.js.map +1 -0
  869. package/dist/core/web/scrapers/crates-io.d.ts +11 -0
  870. package/dist/core/web/scrapers/crates-io.d.ts.map +1 -0
  871. package/dist/core/web/scrapers/crates-io.js +29 -0
  872. package/dist/core/web/scrapers/crates-io.js.map +1 -0
  873. package/dist/core/web/scrapers/docs-rs.d.ts +10 -0
  874. package/dist/core/web/scrapers/docs-rs.d.ts.map +1 -0
  875. package/dist/core/web/scrapers/docs-rs.js +35 -0
  876. package/dist/core/web/scrapers/docs-rs.js.map +1 -0
  877. package/dist/core/web/scrapers/github.d.ts +3 -0
  878. package/dist/core/web/scrapers/github.d.ts.map +1 -0
  879. package/dist/core/web/scrapers/github.js +72 -0
  880. package/dist/core/web/scrapers/github.js.map +1 -0
  881. package/dist/core/web/scrapers/go-pkg.d.ts +7 -0
  882. package/dist/core/web/scrapers/go-pkg.d.ts.map +1 -0
  883. package/dist/core/web/scrapers/go-pkg.js +30 -0
  884. package/dist/core/web/scrapers/go-pkg.js.map +1 -0
  885. package/dist/core/web/scrapers/hex.d.ts +6 -0
  886. package/dist/core/web/scrapers/hex.d.ts.map +1 -0
  887. package/dist/core/web/scrapers/hex.js +27 -0
  888. package/dist/core/web/scrapers/hex.js.map +1 -0
  889. package/dist/core/web/scrapers/maven.d.ts +8 -0
  890. package/dist/core/web/scrapers/maven.d.ts.map +1 -0
  891. package/dist/core/web/scrapers/maven.js +41 -0
  892. package/dist/core/web/scrapers/maven.js.map +1 -0
  893. package/dist/core/web/scrapers/mdn.d.ts +6 -0
  894. package/dist/core/web/scrapers/mdn.d.ts.map +1 -0
  895. package/dist/core/web/scrapers/mdn.js +28 -0
  896. package/dist/core/web/scrapers/mdn.js.map +1 -0
  897. package/dist/core/web/scrapers/npm.d.ts +11 -0
  898. package/dist/core/web/scrapers/npm.d.ts.map +1 -0
  899. package/dist/core/web/scrapers/npm.js +57 -0
  900. package/dist/core/web/scrapers/npm.js.map +1 -0
  901. package/dist/core/web/scrapers/nuget.d.ts +8 -0
  902. package/dist/core/web/scrapers/nuget.d.ts.map +1 -0
  903. package/dist/core/web/scrapers/nuget.js +22 -0
  904. package/dist/core/web/scrapers/nuget.js.map +1 -0
  905. package/dist/core/web/scrapers/nvd.d.ts +7 -0
  906. package/dist/core/web/scrapers/nvd.d.ts.map +1 -0
  907. package/dist/core/web/scrapers/nvd.js +37 -0
  908. package/dist/core/web/scrapers/nvd.js.map +1 -0
  909. package/dist/core/web/scrapers/pypi.d.ts +6 -0
  910. package/dist/core/web/scrapers/pypi.d.ts.map +1 -0
  911. package/dist/core/web/scrapers/pypi.js +31 -0
  912. package/dist/core/web/scrapers/pypi.js.map +1 -0
  913. package/dist/core/web/scrapers/registro.d.ts +13 -0
  914. package/dist/core/web/scrapers/registro.d.ts.map +1 -0
  915. package/dist/core/web/scrapers/registro.js +65 -0
  916. package/dist/core/web/scrapers/registro.js.map +1 -0
  917. package/dist/core/web/scrapers/rubygems.d.ts +6 -0
  918. package/dist/core/web/scrapers/rubygems.d.ts.map +1 -0
  919. package/dist/core/web/scrapers/rubygems.js +23 -0
  920. package/dist/core/web/scrapers/rubygems.js.map +1 -0
  921. package/dist/core/web/scrapers/stackoverflow.d.ts +3 -0
  922. package/dist/core/web/scrapers/stackoverflow.d.ts.map +1 -0
  923. package/dist/core/web/scrapers/stackoverflow.js +46 -0
  924. package/dist/core/web/scrapers/stackoverflow.js.map +1 -0
  925. package/dist/core/web/scrapers/tipos.d.ts +42 -0
  926. package/dist/core/web/scrapers/tipos.d.ts.map +1 -0
  927. package/dist/core/web/scrapers/tipos.js +23 -0
  928. package/dist/core/web/scrapers/tipos.js.map +1 -0
  929. package/dist/core/web/texto.d.ts +10 -0
  930. package/dist/core/web/texto.d.ts.map +1 -0
  931. package/dist/core/web/texto.js +26 -0
  932. package/dist/core/web/texto.js.map +1 -0
  933. package/dist/core/web/tools.d.ts +91 -0
  934. package/dist/core/web/tools.d.ts.map +1 -0
  935. package/dist/core/web/tools.js +304 -0
  936. package/dist/core/web/tools.js.map +1 -0
  937. package/dist/core/wiki/almacen.d.ts +33 -0
  938. package/dist/core/wiki/almacen.d.ts.map +1 -0
  939. package/dist/core/wiki/almacen.js +93 -0
  940. package/dist/core/wiki/almacen.js.map +1 -0
  941. package/dist/core/wiki/citas.d.ts +111 -0
  942. package/dist/core/wiki/citas.d.ts.map +1 -0
  943. package/dist/core/wiki/citas.js +146 -0
  944. package/dist/core/wiki/citas.js.map +1 -0
  945. package/dist/core/workflows/agent-runner.d.ts +2 -0
  946. package/dist/core/workflows/agent-runner.d.ts.map +1 -1
  947. package/dist/core/workflows/agent-runner.js +131 -44
  948. package/dist/core/workflows/agent-runner.js.map +1 -1
  949. package/dist/core/workflows/builtins.d.ts.map +1 -1
  950. package/dist/core/workflows/builtins.js +1 -0
  951. package/dist/core/workflows/builtins.js.map +1 -1
  952. package/dist/core/workflows/contrato/esquema.d.ts +32 -0
  953. package/dist/core/workflows/contrato/esquema.d.ts.map +1 -0
  954. package/dist/core/workflows/contrato/esquema.js +25 -0
  955. package/dist/core/workflows/contrato/esquema.js.map +1 -0
  956. package/dist/core/workflows/contrato/reparar-argumentos.d.ts +69 -0
  957. package/dist/core/workflows/contrato/reparar-argumentos.d.ts.map +1 -0
  958. package/dist/core/workflows/contrato/reparar-argumentos.js +117 -0
  959. package/dist/core/workflows/contrato/reparar-argumentos.js.map +1 -0
  960. package/dist/core/workflows/contrato/validador.d.ts +30 -0
  961. package/dist/core/workflows/contrato/validador.d.ts.map +1 -0
  962. package/dist/core/workflows/contrato/validador.js +56 -0
  963. package/dist/core/workflows/contrato/validador.js.map +1 -0
  964. package/dist/core/workflows/contrato/yield.d.ts +65 -0
  965. package/dist/core/workflows/contrato/yield.d.ts.map +1 -0
  966. package/dist/core/workflows/contrato/yield.js +80 -0
  967. package/dist/core/workflows/contrato/yield.js.map +1 -0
  968. package/dist/core/workflows/goal-engine/engine.d.ts +17 -0
  969. package/dist/core/workflows/goal-engine/engine.d.ts.map +1 -1
  970. package/dist/core/workflows/goal-engine/engine.js +41 -0
  971. package/dist/core/workflows/goal-engine/engine.js.map +1 -1
  972. package/dist/core/workflows/index.d.ts +8 -0
  973. package/dist/core/workflows/index.d.ts.map +1 -1
  974. package/dist/core/workflows/index.js +4 -0
  975. package/dist/core/workflows/index.js.map +1 -1
  976. package/dist/core/workflows/manager.d.ts +10 -0
  977. package/dist/core/workflows/manager.d.ts.map +1 -1
  978. package/dist/core/workflows/manager.js +35 -11
  979. package/dist/core/workflows/manager.js.map +1 -1
  980. package/dist/core/workflows/runtime.d.ts +13 -0
  981. package/dist/core/workflows/runtime.d.ts.map +1 -1
  982. package/dist/core/workflows/runtime.js +80 -1
  983. package/dist/core/workflows/runtime.js.map +1 -1
  984. package/dist/core/workflows/save-as-skill.d.ts +27 -0
  985. package/dist/core/workflows/save-as-skill.d.ts.map +1 -0
  986. package/dist/core/workflows/save-as-skill.js +54 -0
  987. package/dist/core/workflows/save-as-skill.js.map +1 -0
  988. package/dist/core/workflows/types.d.ts +49 -0
  989. package/dist/core/workflows/types.d.ts.map +1 -1
  990. package/dist/core/workflows/types.js.map +1 -1
  991. package/dist/extensions/remoto/index.d.ts +22 -0
  992. package/dist/extensions/remoto/index.d.ts.map +1 -0
  993. package/dist/extensions/remoto/index.js +54 -0
  994. package/dist/extensions/remoto/index.js.map +1 -0
  995. package/dist/index.d.ts +1 -17
  996. package/dist/index.d.ts.map +1 -1
  997. package/dist/index.js +7 -16
  998. package/dist/index.js.map +1 -1
  999. package/dist/main.d.ts.map +1 -1
  1000. package/dist/main.js +6 -0
  1001. package/dist/main.js.map +1 -1
  1002. package/dist/modes/acp/acp-mode.d.ts +42 -0
  1003. package/dist/modes/acp/acp-mode.d.ts.map +1 -0
  1004. package/dist/modes/acp/acp-mode.js +190 -0
  1005. package/dist/modes/acp/acp-mode.js.map +1 -0
  1006. package/dist/modes/acp/events.d.ts +74 -0
  1007. package/dist/modes/acp/events.d.ts.map +1 -0
  1008. package/dist/modes/acp/events.js +116 -0
  1009. package/dist/modes/acp/events.js.map +1 -0
  1010. package/dist/modes/interactive/components/model-selector.d.ts +8 -1
  1011. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  1012. package/dist/modes/interactive/components/model-selector.js +41 -7
  1013. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  1014. package/dist/modes/interactive/components/settings-selector.d.ts +1 -2
  1015. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  1016. package/dist/modes/interactive/components/settings-selector.js +9 -86
  1017. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  1018. package/dist/modes/interactive/components/thinking-selector.d.ts +8 -1
  1019. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  1020. package/dist/modes/interactive/components/thinking-selector.js +48 -17
  1021. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  1022. package/dist/modes/interactive/interactive-mode.d.ts +3 -7
  1023. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  1024. package/dist/modes/interactive/interactive-mode.js +137 -146
  1025. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  1026. package/dist/modes/print-mode.d.ts.map +1 -1
  1027. package/dist/modes/print-mode.js +11 -0
  1028. package/dist/modes/print-mode.js.map +1 -1
  1029. package/dist/package-manager-cli.d.ts.map +1 -1
  1030. package/dist/package-manager-cli.js +27 -5
  1031. package/dist/package-manager-cli.js.map +1 -1
  1032. package/dist/server/attach.d.ts +56 -0
  1033. package/dist/server/attach.d.ts.map +1 -0
  1034. package/dist/server/attach.js +130 -0
  1035. package/dist/server/attach.js.map +1 -0
  1036. package/dist/server/extension-ops.d.ts +40 -0
  1037. package/dist/server/extension-ops.d.ts.map +1 -0
  1038. package/dist/server/extension-ops.js +146 -0
  1039. package/dist/server/extension-ops.js.map +1 -0
  1040. package/dist/server/pi-server-service.d.ts +85 -0
  1041. package/dist/server/pi-server-service.d.ts.map +1 -0
  1042. package/dist/server/pi-server-service.js +213 -0
  1043. package/dist/server/pi-server-service.js.map +1 -0
  1044. package/dist/server/scheduler-tick.d.ts +32 -0
  1045. package/dist/server/scheduler-tick.d.ts.map +1 -0
  1046. package/dist/server/scheduler-tick.js +47 -0
  1047. package/dist/server/scheduler-tick.js.map +1 -0
  1048. package/dist/server/serve.d.ts +25 -0
  1049. package/dist/server/serve.d.ts.map +1 -0
  1050. package/dist/server/serve.js +83 -0
  1051. package/dist/server/serve.js.map +1 -0
  1052. package/dist/server/transcript.d.ts +38 -0
  1053. package/dist/server/transcript.d.ts.map +1 -0
  1054. package/dist/server/transcript.js +176 -0
  1055. package/dist/server/transcript.js.map +1 -0
  1056. package/dist/skills/skill-creator/SKILL.md +90 -0
  1057. package/dist/telegram/api.d.ts +75 -0
  1058. package/dist/telegram/api.d.ts.map +1 -0
  1059. package/dist/telegram/api.js +104 -0
  1060. package/dist/telegram/api.js.map +1 -0
  1061. package/dist/telegram/bridge.d.ts +85 -0
  1062. package/dist/telegram/bridge.d.ts.map +1 -0
  1063. package/dist/telegram/bridge.js +182 -0
  1064. package/dist/telegram/bridge.js.map +1 -0
  1065. package/dist/telegram/journal.d.ts +67 -0
  1066. package/dist/telegram/journal.d.ts.map +1 -0
  1067. package/dist/telegram/journal.js +119 -0
  1068. package/dist/telegram/journal.js.map +1 -0
  1069. package/dist/telegram/servidor.d.ts +15 -0
  1070. package/dist/telegram/servidor.d.ts.map +1 -0
  1071. package/dist/telegram/servidor.js +74 -0
  1072. package/dist/telegram/servidor.js.map +1 -0
  1073. package/dist/utils/shell.d.ts +11 -0
  1074. package/dist/utils/shell.d.ts.map +1 -1
  1075. package/dist/utils/shell.js +11 -0
  1076. package/dist/utils/shell.js.map +1 -1
  1077. package/dist/utils/version-check.d.ts.map +1 -1
  1078. package/dist/utils/version-check.js +29 -1
  1079. package/dist/utils/version-check.js.map +1 -1
  1080. package/docs/compaction.md +10 -10
  1081. package/docs/compliance.md +241 -0
  1082. package/docs/containerization.md +24 -24
  1083. package/docs/custom-provider.md +10 -10
  1084. package/docs/development.md +47 -10
  1085. package/docs/docs.json +14 -2
  1086. package/docs/environment-variables.md +20 -17
  1087. package/docs/extensions.md +51 -49
  1088. package/docs/index.md +15 -21
  1089. package/docs/json.md +3 -3
  1090. package/docs/keybindings.md +5 -5
  1091. package/docs/llama-cpp.md +7 -7
  1092. package/docs/models.md +12 -12
  1093. package/docs/packages.md +45 -45
  1094. package/docs/prompt-templates.md +5 -5
  1095. package/docs/providers.md +12 -12
  1096. package/docs/quickstart.md +39 -39
  1097. package/docs/rpc.md +12 -12
  1098. package/docs/sdk.md +38 -38
  1099. package/docs/security.md +26 -21
  1100. package/docs/session-format.md +7 -7
  1101. package/docs/sessions.md +14 -14
  1102. package/docs/settings.md +45 -20
  1103. package/docs/shell-aliases.md +2 -2
  1104. package/docs/skills.md +11 -11
  1105. package/docs/terminal-setup.md +14 -14
  1106. package/docs/termux.md +7 -7
  1107. package/docs/themes.md +11 -11
  1108. package/docs/tmux.md +4 -4
  1109. package/docs/tui.md +3 -3
  1110. package/docs/usage.md +54 -54
  1111. package/docs/windows.md +2 -2
  1112. package/examples/sdk/12-full-control.ts +9 -0
  1113. package/npm-shrinkwrap.json +35 -251
  1114. package/package.json +10 -4
@@ -0,0 +1,65 @@
1
+ /**
2
+ * La decodificación restringida, con su propio interruptor.
3
+ *
4
+ * QUÉ ES. Cuando el proveedor lo admite, el esquema de cada herramienta se le
5
+ * pasa en modo estricto, de forma que el modelo **no puede** emitir una llamada
6
+ * que no encaje: no es que la rechacemos después, es que no llega a generarse.
7
+ *
8
+ * POR QUÉ IMPORTA AQUÍ. El fallo más caro que medimos contra un modelo
9
+ * gratuito fue exactamente de esa clase: mandó `edits` como cadena de JSON con
10
+ * tabuladores crudos dentro, y el turno entero se perdió. Con decodificación
11
+ * restringida ese estado no existe. La tolerancia de
12
+ * `parsearJsonTolerante` repara el daño; esto lo evita.
13
+ *
14
+ * POR QUÉ NO VIENE ENCENDIDA. Porque no está medida de punta a punta, y en
15
+ * este proyecto encender algo por lo bien que suena es como se llega a una
16
+ * casilla verde que no protege de nada. Lo que SÍ está medido, ejecutándolo:
17
+ *
18
+ * - las cuatro herramientas que la declaran —`edit`, `write`, `read`,
19
+ * `bash`— admiten esquema estricto, así que la palanca está conectada y
20
+ * no es decorativa;
21
+ * - la comparación con el modelo real no se pudo completar: el nivel
22
+ * gratuito de OpenRouter contesta a un ping de cinco tokens pero no
23
+ * sostiene un turno de trece mil, y dos intentos se agotaron.
24
+ *
25
+ * Así que se deja apagada y se dice por qué, en vez de encenderla a ciegas o
26
+ * fingir que la decisión está tomada.
27
+ *
28
+ * LO QUE SÍ CAMBIA. Antes solo se activaba con `PI_EXPERIMENTAL=1`, que
29
+ * enciende TODO lo experimental a la vez. Quien quiera probar solo esto tenía
30
+ * que aceptar lo demás, y en un equipo con control de cambios eso significa no
31
+ * probarlo nunca. Ahora tiene su propio interruptor.
32
+ */
33
+ /** La variable dedicada. No hay ajuste en `settings.json` todavía, a propósito:
34
+ * un ajuste persistido para algo sin medir invita a olvidarlo encendido. */
35
+ export const VARIABLE = "ADA_MUESTREO_RESTRINGIDO";
36
+ function encendidaPor(valor) {
37
+ return valor === "1" || valor === "true" || valor === "yes";
38
+ }
39
+ export function estadoDelMuestreo(env = process.env) {
40
+ const propia = env[VARIABLE];
41
+ if (propia !== undefined) {
42
+ // Un valor explícito manda sobre `PI_EXPERIMENTAL`, incluso para APAGARLA:
43
+ // quien enciende todo lo experimental pero apaga esto a mano ha tomado una
44
+ // decisión, y respetarla es lo contrario de un defecto silencioso.
45
+ return encendidaPor(propia)
46
+ ? { activo: true, origen: "propio", motivo: `${VARIABLE}=${propia}` }
47
+ : { activo: false, origen: "apagada", motivo: `${VARIABLE}=${propia} la apaga explícitamente` };
48
+ }
49
+ // Se lee del `env` recibido y no de `process.env` a través de
50
+ // `areExperimentalFeaturesEnabled()`: esa función lee el entorno del proceso
51
+ // directamente, así que la rama de compatibilidad no se podía probar sin
52
+ // ensuciar el proceso entero. Lo cazó la propia prueba.
53
+ if (env.PI_EXPERIMENTAL === "1") {
54
+ return { activo: true, origen: "experimental", motivo: "PI_EXPERIMENTAL=1 enciende todo lo experimental" };
55
+ }
56
+ return {
57
+ activo: false,
58
+ origen: "apagada",
59
+ motivo: `apagada por defecto: no está medida de punta a punta. Enciéndela con ${VARIABLE}=1`,
60
+ };
61
+ }
62
+ export function muestreoRestringidoActivo(env = process.env) {
63
+ return estadoDelMuestreo(env).activo;
64
+ }
65
+ //# sourceMappingURL=muestreo-restringido.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muestreo-restringido.js","sourceRoot":"","sources":["../../src/core/muestreo-restringido.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAcH;4EAC4E;AAC5E,MAAM,CAAC,MAAM,QAAQ,GAAG,0BAA0B,CAAC;AAEnD,SAAS,YAAY,CAAC,KAAyB,EAAW;IACzD,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,CAAC;AAAA,CAC5D;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAqB;IAC1F,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,4EAA2E;QAC3E,2EAA2E;QAC3E,oEAAmE;QACnE,OAAO,YAAY,CAAC,MAAM,CAAC;YAC1B,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,QAAQ,IAAI,MAAM,EAAE,EAAE;YACrE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,QAAQ,IAAI,MAAM,2BAA0B,EAAE,CAAC;IAClG,CAAC;IACD,+DAA8D;IAC9D,8EAA6E;IAC7E,2EAAyE;IACzE,yDAAwD;IACxD,IAAI,GAAG,CAAC,eAAe,KAAK,GAAG,EAAE,CAAC;QACjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,iDAAiD,EAAE,CAAC;IAC5G,CAAC;IACD,OAAO;QACN,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,0EAAwE,QAAQ,IAAI;KAC5F,CAAC;AAAA,CACF;AAED,MAAM,UAAU,yBAAyB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAW;IACxF,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;AAAA,CACrC","sourcesContent":["/**\n * La decodificación restringida, con su propio interruptor.\n *\n * QUÉ ES. Cuando el proveedor lo admite, el esquema de cada herramienta se le\n * pasa en modo estricto, de forma que el modelo **no puede** emitir una llamada\n * que no encaje: no es que la rechacemos después, es que no llega a generarse.\n *\n * POR QUÉ IMPORTA AQUÍ. El fallo más caro que medimos contra un modelo\n * gratuito fue exactamente de esa clase: mandó `edits` como cadena de JSON con\n * tabuladores crudos dentro, y el turno entero se perdió. Con decodificación\n * restringida ese estado no existe. La tolerancia de\n * `parsearJsonTolerante` repara el daño; esto lo evita.\n *\n * POR QUÉ NO VIENE ENCENDIDA. Porque no está medida de punta a punta, y en\n * este proyecto encender algo por lo bien que suena es como se llega a una\n * casilla verde que no protege de nada. Lo que SÍ está medido, ejecutándolo:\n *\n * - las cuatro herramientas que la declaran —`edit`, `write`, `read`,\n * `bash`— admiten esquema estricto, así que la palanca está conectada y\n * no es decorativa;\n * - la comparación con el modelo real no se pudo completar: el nivel\n * gratuito de OpenRouter contesta a un ping de cinco tokens pero no\n * sostiene un turno de trece mil, y dos intentos se agotaron.\n *\n * Así que se deja apagada y se dice por qué, en vez de encenderla a ciegas o\n * fingir que la decisión está tomada.\n *\n * LO QUE SÍ CAMBIA. Antes solo se activaba con `PI_EXPERIMENTAL=1`, que\n * enciende TODO lo experimental a la vez. Quien quiera probar solo esto tenía\n * que aceptar lo demás, y en un equipo con control de cambios eso significa no\n * probarlo nunca. Ahora tiene su propio interruptor.\n */\n\n/** Cómo quedó activada, o por qué no lo está. Tres estados y no dos. */\nexport interface EstadoDelMuestreo {\n\tactivo: boolean;\n\t/**\n\t * `propio` — encendida por su variable, sin arrastrar lo demás.\n\t * `experimental`— encendida de rebote por `PI_EXPERIMENTAL=1`.\n\t * `apagada` — ninguna de las dos.\n\t */\n\torigen: \"propio\" | \"experimental\" | \"apagada\";\n\tmotivo: string;\n}\n\n/** La variable dedicada. No hay ajuste en `settings.json` todavía, a propósito:\n * un ajuste persistido para algo sin medir invita a olvidarlo encendido. */\nexport const VARIABLE = \"ADA_MUESTREO_RESTRINGIDO\";\n\nfunction encendidaPor(valor: string | undefined): boolean {\n\treturn valor === \"1\" || valor === \"true\" || valor === \"yes\";\n}\n\nexport function estadoDelMuestreo(env: NodeJS.ProcessEnv = process.env): EstadoDelMuestreo {\n\tconst propia = env[VARIABLE];\n\tif (propia !== undefined) {\n\t\t// Un valor explícito manda sobre `PI_EXPERIMENTAL`, incluso para APAGARLA:\n\t\t// quien enciende todo lo experimental pero apaga esto a mano ha tomado una\n\t\t// decisión, y respetarla es lo contrario de un defecto silencioso.\n\t\treturn encendidaPor(propia)\n\t\t\t? { activo: true, origen: \"propio\", motivo: `${VARIABLE}=${propia}` }\n\t\t\t: { activo: false, origen: \"apagada\", motivo: `${VARIABLE}=${propia} la apaga explícitamente` };\n\t}\n\t// Se lee del `env` recibido y no de `process.env` a través de\n\t// `areExperimentalFeaturesEnabled()`: esa función lee el entorno del proceso\n\t// directamente, así que la rama de compatibilidad no se podía probar sin\n\t// ensuciar el proceso entero. Lo cazó la propia prueba.\n\tif (env.PI_EXPERIMENTAL === \"1\") {\n\t\treturn { activo: true, origen: \"experimental\", motivo: \"PI_EXPERIMENTAL=1 enciende todo lo experimental\" };\n\t}\n\treturn {\n\t\tactivo: false,\n\t\torigen: \"apagada\",\n\t\tmotivo: `apagada por defecto: no está medida de punta a punta. Enciéndela con ${VARIABLE}=1`,\n\t};\n}\n\nexport function muestreoRestringidoActivo(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn estadoDelMuestreo(env).activo;\n}\n"]}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Journal de procesos huérfanos — no dejar dev servers colgados tras un crash.
3
+ *
4
+ * `utils/shell.ts` guarda los pids detached en un `Set` en memoria y los mata en
5
+ * las señales de apagado limpio. En SIGKILL, OOM o un force-quit de la app de
6
+ * escritorio ese Set se evapora, y el watcher, el dev server o el test runner
7
+ * siguen vivos ocupando puertos hasta que alguien los encuentra a mano.
8
+ *
9
+ * Esto persiste los pids a disco para poder barrerlos en el siguiente arranque.
10
+ *
11
+ * LA VERIFICACIÓN DE IDENTIDAD NO ES OPCIONAL. Los pids se reciclan: matar por
12
+ * pid a secas puede matar un proceso ajeno que heredó el número, que es
13
+ * estrictamente peor que la fuga que arreglamos. Por eso se guarda además un
14
+ * identificador de arranque del proceso (hora de inicio) y solo se mata si
15
+ * coincide.
16
+ */
17
+ export interface OrphanRecord {
18
+ pid: number;
19
+ /** Identidad del arranque: distingue un pid reciclado del original. */
20
+ startId?: string;
21
+ active: boolean;
22
+ ts: string;
23
+ }
24
+ /**
25
+ * Identificador del arranque de un proceso. `undefined` si no existe o no se
26
+ * puede determinar — y en ese caso NO se mata nada.
27
+ */
28
+ export declare function processStartId(pid: number): string | undefined;
29
+ export declare class OrphanProcessJournal {
30
+ private path;
31
+ /** La ruta deriva de agentDir, NO de una variable de entorno: un subagente
32
+ * que hereda el entorno no debe appendear en el journal de su padre. */
33
+ constructor(agentDir: string);
34
+ track(pid: number): Promise<void>;
35
+ untrack(pid: number): Promise<void>;
36
+ private write;
37
+ /** Último estado conocido de cada pid; solo los que quedaron activos. */
38
+ pending(): Promise<Array<{
39
+ pid: number;
40
+ startId: string;
41
+ }>>;
42
+ /**
43
+ * Mata los huérfanos cuya identidad AÚN coincide y limpia el journal.
44
+ * Devuelve los pids realmente matados.
45
+ */
46
+ reap(kill: (pid: number) => void): Promise<number[]>;
47
+ }
48
+ //# sourceMappingURL=orphan-process-journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-process-journal.d.ts","sourceRoot":"","sources":["../../src/core/orphan-process-journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACX;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmB9D;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,IAAI,CAAS;IAErB;4EACwE;IACxE,YAAY,QAAQ,EAAE,MAAM,EAE3B;IAEK,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtC;IAEK,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExC;YAEa,KAAK;IASnB,0EAAyE;IACnE,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAmBhE;IAED;;;OAGG;IACG,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAczD;CACD","sourcesContent":["/**\n * Journal de procesos huérfanos — no dejar dev servers colgados tras un crash.\n *\n * `utils/shell.ts` guarda los pids detached en un `Set` en memoria y los mata en\n * las señales de apagado limpio. En SIGKILL, OOM o un force-quit de la app de\n * escritorio ese Set se evapora, y el watcher, el dev server o el test runner\n * siguen vivos ocupando puertos hasta que alguien los encuentra a mano.\n *\n * Esto persiste los pids a disco para poder barrerlos en el siguiente arranque.\n *\n * LA VERIFICACIÓN DE IDENTIDAD NO ES OPCIONAL. Los pids se reciclan: matar por\n * pid a secas puede matar un proceso ajeno que heredó el número, que es\n * estrictamente peor que la fuga que arreglamos. Por eso se guarda además un\n * identificador de arranque del proceso (hora de inicio) y solo se mata si\n * coincide.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport { appendFile, mkdir, readFile, rm } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nexport interface OrphanRecord {\n\tpid: number;\n\t/** Identidad del arranque: distingue un pid reciclado del original. */\n\tstartId?: string;\n\tactive: boolean;\n\tts: string;\n}\n\n/**\n * Identificador del arranque de un proceso. `undefined` si no existe o no se\n * puede determinar — y en ese caso NO se mata nada.\n */\nexport function processStartId(pid: number): string | undefined {\n\tif (!Number.isInteger(pid) || pid <= 0) return undefined;\n\t// Linux: campo 22 de /proc/<pid>/stat es starttime en jiffies.\n\ttry {\n\t\tconst stat = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n\t\tconst fields = stat.slice(stat.lastIndexOf(\")\") + 2).split(\" \");\n\t\tif (fields[19]) return `proc:${fields[19]}`;\n\t} catch {\n\t\t// macOS/BSD no tienen /proc: se usa ps.\n\t}\n\ttry {\n\t\tconst out = execFileSync(\"ps\", [\"-p\", String(pid), \"-o\", \"lstart=\"], {\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t}).trim();\n\t\treturn out ? `ps:${out}` : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class OrphanProcessJournal {\n\tprivate path: string;\n\n\t/** La ruta deriva de agentDir, NO de una variable de entorno: un subagente\n\t * que hereda el entorno no debe appendear en el journal de su padre. */\n\tconstructor(agentDir: string) {\n\t\tthis.path = join(agentDir, \"orphan-processes.jsonl\");\n\t}\n\n\tasync track(pid: number): Promise<void> {\n\t\tawait this.write({ pid, startId: processStartId(pid), active: true, ts: new Date().toISOString() });\n\t}\n\n\tasync untrack(pid: number): Promise<void> {\n\t\tawait this.write({ pid, active: false, ts: new Date().toISOString() });\n\t}\n\n\tprivate async write(record: OrphanRecord): Promise<void> {\n\t\ttry {\n\t\t\tawait mkdir(dirname(this.path), { recursive: true });\n\t\t\tawait appendFile(this.path, `${JSON.stringify(record)}\\n`, \"utf-8\");\n\t\t} catch {\n\t\t\t// El journal nunca debe romper el lanzamiento de un proceso.\n\t\t}\n\t}\n\n\t/** Último estado conocido de cada pid; solo los que quedaron activos. */\n\tasync pending(): Promise<Array<{ pid: number; startId: string }>> {\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = await readFile(this.path, \"utf-8\");\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tconst latest = new Map<number, OrphanRecord>();\n\t\tfor (const line of raw.split(\"\\n\").filter(Boolean)) {\n\t\t\ttry {\n\t\t\t\tconst record = JSON.parse(line) as OrphanRecord;\n\t\t\t\tlatest.set(record.pid, record);\n\t\t\t} catch {\n\t\t\t\t// Un crash puede truncar el último append; el resto sigue siendo válido.\n\t\t\t}\n\t\t}\n\t\treturn [...latest.values()]\n\t\t\t.filter((r): r is OrphanRecord & { startId: string } => r.active && typeof r.startId === \"string\")\n\t\t\t.map((r) => ({ pid: r.pid, startId: r.startId }));\n\t}\n\n\t/**\n\t * Mata los huérfanos cuya identidad AÚN coincide y limpia el journal.\n\t * Devuelve los pids realmente matados.\n\t */\n\tasync reap(kill: (pid: number) => void): Promise<number[]> {\n\t\tconst killed: number[] = [];\n\t\tfor (const orphan of await this.pending()) {\n\t\t\t// Si el pid se recicló, el startId ya no coincide: no es nuestro.\n\t\t\tif (processStartId(orphan.pid) !== orphan.startId) continue;\n\t\t\ttry {\n\t\t\t\tkill(orphan.pid);\n\t\t\t\tkilled.push(orphan.pid);\n\t\t\t} catch {\n\t\t\t\t// ya muerto / sin permisos\n\t\t\t}\n\t\t}\n\t\tawait rm(this.path, { force: true }).catch(() => {});\n\t\treturn killed;\n\t}\n}\n"]}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Journal de procesos huérfanos — no dejar dev servers colgados tras un crash.
3
+ *
4
+ * `utils/shell.ts` guarda los pids detached en un `Set` en memoria y los mata en
5
+ * las señales de apagado limpio. En SIGKILL, OOM o un force-quit de la app de
6
+ * escritorio ese Set se evapora, y el watcher, el dev server o el test runner
7
+ * siguen vivos ocupando puertos hasta que alguien los encuentra a mano.
8
+ *
9
+ * Esto persiste los pids a disco para poder barrerlos en el siguiente arranque.
10
+ *
11
+ * LA VERIFICACIÓN DE IDENTIDAD NO ES OPCIONAL. Los pids se reciclan: matar por
12
+ * pid a secas puede matar un proceso ajeno que heredó el número, que es
13
+ * estrictamente peor que la fuga que arreglamos. Por eso se guarda además un
14
+ * identificador de arranque del proceso (hora de inicio) y solo se mata si
15
+ * coincide.
16
+ */
17
+ import { execFileSync } from "node:child_process";
18
+ import { readFileSync } from "node:fs";
19
+ import { appendFile, mkdir, readFile, rm } from "node:fs/promises";
20
+ import { dirname, join } from "node:path";
21
+ /**
22
+ * Identificador del arranque de un proceso. `undefined` si no existe o no se
23
+ * puede determinar — y en ese caso NO se mata nada.
24
+ */
25
+ export function processStartId(pid) {
26
+ if (!Number.isInteger(pid) || pid <= 0)
27
+ return undefined;
28
+ // Linux: campo 22 de /proc/<pid>/stat es starttime en jiffies.
29
+ try {
30
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
31
+ const fields = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
32
+ if (fields[19])
33
+ return `proc:${fields[19]}`;
34
+ }
35
+ catch {
36
+ // macOS/BSD no tienen /proc: se usa ps.
37
+ }
38
+ try {
39
+ const out = execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
40
+ encoding: "utf-8",
41
+ stdio: ["ignore", "pipe", "ignore"],
42
+ }).trim();
43
+ return out ? `ps:${out}` : undefined;
44
+ }
45
+ catch {
46
+ return undefined;
47
+ }
48
+ }
49
+ export class OrphanProcessJournal {
50
+ path;
51
+ /** La ruta deriva de agentDir, NO de una variable de entorno: un subagente
52
+ * que hereda el entorno no debe appendear en el journal de su padre. */
53
+ constructor(agentDir) {
54
+ this.path = join(agentDir, "orphan-processes.jsonl");
55
+ }
56
+ async track(pid) {
57
+ await this.write({ pid, startId: processStartId(pid), active: true, ts: new Date().toISOString() });
58
+ }
59
+ async untrack(pid) {
60
+ await this.write({ pid, active: false, ts: new Date().toISOString() });
61
+ }
62
+ async write(record) {
63
+ try {
64
+ await mkdir(dirname(this.path), { recursive: true });
65
+ await appendFile(this.path, `${JSON.stringify(record)}\n`, "utf-8");
66
+ }
67
+ catch {
68
+ // El journal nunca debe romper el lanzamiento de un proceso.
69
+ }
70
+ }
71
+ /** Último estado conocido de cada pid; solo los que quedaron activos. */
72
+ async pending() {
73
+ let raw;
74
+ try {
75
+ raw = await readFile(this.path, "utf-8");
76
+ }
77
+ catch {
78
+ return [];
79
+ }
80
+ const latest = new Map();
81
+ for (const line of raw.split("\n").filter(Boolean)) {
82
+ try {
83
+ const record = JSON.parse(line);
84
+ latest.set(record.pid, record);
85
+ }
86
+ catch {
87
+ // Un crash puede truncar el último append; el resto sigue siendo válido.
88
+ }
89
+ }
90
+ return [...latest.values()]
91
+ .filter((r) => r.active && typeof r.startId === "string")
92
+ .map((r) => ({ pid: r.pid, startId: r.startId }));
93
+ }
94
+ /**
95
+ * Mata los huérfanos cuya identidad AÚN coincide y limpia el journal.
96
+ * Devuelve los pids realmente matados.
97
+ */
98
+ async reap(kill) {
99
+ const killed = [];
100
+ for (const orphan of await this.pending()) {
101
+ // Si el pid se recicló, el startId ya no coincide: no es nuestro.
102
+ if (processStartId(orphan.pid) !== orphan.startId)
103
+ continue;
104
+ try {
105
+ kill(orphan.pid);
106
+ killed.push(orphan.pid);
107
+ }
108
+ catch {
109
+ // ya muerto / sin permisos
110
+ }
111
+ }
112
+ await rm(this.path, { force: true }).catch(() => { });
113
+ return killed;
114
+ }
115
+ }
116
+ //# sourceMappingURL=orphan-process-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-process-journal.js","sourceRoot":"","sources":["../../src/core/orphan-process-journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAU1C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW,EAAsB;IAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACzD,+DAA+D;IAC/D,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,EAAE,CAAC;YAAE,OAAO,QAAQ,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACR,wCAAwC;IACzC,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE;YACpE,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACnC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AAAA,CACD;AAED,MAAM,OAAO,oBAAoB;IACxB,IAAI,CAAS;IAErB;4EACwE;IACxE,YAAY,QAAgB,EAAE;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAAA,CACrD;IAED,KAAK,CAAC,KAAK,CAAC,GAAW,EAAiB;QACvC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAAA,CACpG;IAED,KAAK,CAAC,OAAO,CAAC,GAAW,EAAiB;QACzC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAAA,CACvE;IAEO,KAAK,CAAC,KAAK,CAAC,MAAoB,EAAiB;QACxD,IAAI,CAAC;YACJ,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACR,6DAA6D;QAC9D,CAAC;IAAA,CACD;IAED,0EAAyE;IACzE,KAAK,CAAC,OAAO,GAAqD;QACjE,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACJ,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC;gBAChD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACR,2EAAyE;YAC1E,CAAC;QACF,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;aACzB,MAAM,CAAC,CAAC,CAAC,EAA2C,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC;aACjG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAAA,CACnD;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,IAA2B,EAAqB;QAC1D,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,MAAM,IAAI,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3C,mEAAkE;YAClE,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO;gBAAE,SAAS;YAC5D,IAAI,CAAC;gBACJ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;gBACR,2BAA2B;YAC5B,CAAC;QACF,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAAA,CACd;CACD","sourcesContent":["/**\n * Journal de procesos huérfanos — no dejar dev servers colgados tras un crash.\n *\n * `utils/shell.ts` guarda los pids detached en un `Set` en memoria y los mata en\n * las señales de apagado limpio. En SIGKILL, OOM o un force-quit de la app de\n * escritorio ese Set se evapora, y el watcher, el dev server o el test runner\n * siguen vivos ocupando puertos hasta que alguien los encuentra a mano.\n *\n * Esto persiste los pids a disco para poder barrerlos en el siguiente arranque.\n *\n * LA VERIFICACIÓN DE IDENTIDAD NO ES OPCIONAL. Los pids se reciclan: matar por\n * pid a secas puede matar un proceso ajeno que heredó el número, que es\n * estrictamente peor que la fuga que arreglamos. Por eso se guarda además un\n * identificador de arranque del proceso (hora de inicio) y solo se mata si\n * coincide.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport { appendFile, mkdir, readFile, rm } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nexport interface OrphanRecord {\n\tpid: number;\n\t/** Identidad del arranque: distingue un pid reciclado del original. */\n\tstartId?: string;\n\tactive: boolean;\n\tts: string;\n}\n\n/**\n * Identificador del arranque de un proceso. `undefined` si no existe o no se\n * puede determinar — y en ese caso NO se mata nada.\n */\nexport function processStartId(pid: number): string | undefined {\n\tif (!Number.isInteger(pid) || pid <= 0) return undefined;\n\t// Linux: campo 22 de /proc/<pid>/stat es starttime en jiffies.\n\ttry {\n\t\tconst stat = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n\t\tconst fields = stat.slice(stat.lastIndexOf(\")\") + 2).split(\" \");\n\t\tif (fields[19]) return `proc:${fields[19]}`;\n\t} catch {\n\t\t// macOS/BSD no tienen /proc: se usa ps.\n\t}\n\ttry {\n\t\tconst out = execFileSync(\"ps\", [\"-p\", String(pid), \"-o\", \"lstart=\"], {\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t}).trim();\n\t\treturn out ? `ps:${out}` : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class OrphanProcessJournal {\n\tprivate path: string;\n\n\t/** La ruta deriva de agentDir, NO de una variable de entorno: un subagente\n\t * que hereda el entorno no debe appendear en el journal de su padre. */\n\tconstructor(agentDir: string) {\n\t\tthis.path = join(agentDir, \"orphan-processes.jsonl\");\n\t}\n\n\tasync track(pid: number): Promise<void> {\n\t\tawait this.write({ pid, startId: processStartId(pid), active: true, ts: new Date().toISOString() });\n\t}\n\n\tasync untrack(pid: number): Promise<void> {\n\t\tawait this.write({ pid, active: false, ts: new Date().toISOString() });\n\t}\n\n\tprivate async write(record: OrphanRecord): Promise<void> {\n\t\ttry {\n\t\t\tawait mkdir(dirname(this.path), { recursive: true });\n\t\t\tawait appendFile(this.path, `${JSON.stringify(record)}\\n`, \"utf-8\");\n\t\t} catch {\n\t\t\t// El journal nunca debe romper el lanzamiento de un proceso.\n\t\t}\n\t}\n\n\t/** Último estado conocido de cada pid; solo los que quedaron activos. */\n\tasync pending(): Promise<Array<{ pid: number; startId: string }>> {\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = await readFile(this.path, \"utf-8\");\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tconst latest = new Map<number, OrphanRecord>();\n\t\tfor (const line of raw.split(\"\\n\").filter(Boolean)) {\n\t\t\ttry {\n\t\t\t\tconst record = JSON.parse(line) as OrphanRecord;\n\t\t\t\tlatest.set(record.pid, record);\n\t\t\t} catch {\n\t\t\t\t// Un crash puede truncar el último append; el resto sigue siendo válido.\n\t\t\t}\n\t\t}\n\t\treturn [...latest.values()]\n\t\t\t.filter((r): r is OrphanRecord & { startId: string } => r.active && typeof r.startId === \"string\")\n\t\t\t.map((r) => ({ pid: r.pid, startId: r.startId }));\n\t}\n\n\t/**\n\t * Mata los huérfanos cuya identidad AÚN coincide y limpia el journal.\n\t * Devuelve los pids realmente matados.\n\t */\n\tasync reap(kill: (pid: number) => void): Promise<number[]> {\n\t\tconst killed: number[] = [];\n\t\tfor (const orphan of await this.pending()) {\n\t\t\t// Si el pid se recicló, el startId ya no coincide: no es nuestro.\n\t\t\tif (processStartId(orphan.pid) !== orphan.startId) continue;\n\t\t\ttry {\n\t\t\t\tkill(orphan.pid);\n\t\t\t\tkilled.push(orphan.pid);\n\t\t\t} catch {\n\t\t\t\t// ya muerto / sin permisos\n\t\t\t}\n\t\t}\n\t\tawait rm(this.path, { force: true }).catch(() => {});\n\t\treturn killed;\n\t}\n}\n"]}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Detectar las CATEGORÍAS ESPECIALES del artículo 9 del RGPD (y las condenas
3
+ * del artículo 10) en un texto, sin repetir el texto en el hallazgo.
4
+ *
5
+ * POR QUÉ EXISTE, medido antes de escribir nada. El escáner de
6
+ * `memory-engine/security.ts` tiene cinco patrones de datos personales
7
+ * (correo, teléfono, DNI/NIE, IBAN, fecha de nacimiento) y CERO del artículo 9.
8
+ * Sobre un corpus de 24 cadenas que sí deberían saltar, en nivel `strict`
9
+ * fallaban 20. Entre las 20: «baja por depresión», «afiliado a CCOO»,
10
+ * «HIV positive», «huella dactilar registrada», «tiene antecedentes penales».
11
+ * Ninguna de ellas tiene hoy categoría en `SensitiveCategory`, así que
12
+ * `redactSensitive` las devuelve idénticas, sin un solo bloque: hoy una
13
+ * categoría especial se escribe EN CLARO en el libro de auditoría
14
+ * (`audit/libro.ts`), en la exportación y en el diario de edición.
15
+ *
16
+ * El coste no es simétrico con el de un correo. Tratar datos de salud,
17
+ * afiliación sindical, origen étnico, religión, opinión política, vida sexual,
18
+ * biometría o genética está PROHIBIDO salvo excepción tasada (art. 9.1 y 9.2),
19
+ * y las condenas penales sólo pueden tratarse bajo control de la autoridad
20
+ * (art. 10). Filtrar uno de estos no es un incidente de privacidad: es un
21
+ * tratamiento ilícito.
22
+ *
23
+ * LAS DOS MITADES. Un detector de vocabulario ingenuo es peor que ninguno.
24
+ * «diagnóstico» sale de cualquier compilador, «union» de cualquier SQL,
25
+ * «race» de cualquier `race condition`, y un identificador interno de ocho
26
+ * cifras no es un DNI. Un detector que grita sobre todo se desactiva en una
27
+ * semana y entonces no protege de nada. Por eso aquí hay dos mecanismos, y
28
+ * los dos se miden contra el corpus benigno:
29
+ *
30
+ * 1. Los IDENTIFICADORES se VALIDAN, no se reconocen por su forma. DNI y NIE
31
+ * por la letra de control (módulo 23 sobre TRWAGMYFPDXBNJZSQVHLCKE), IBAN
32
+ * y número de la Seguridad Social por módulo 97. Esto no es sólo rigor:
33
+ * es lo que hace desaparecer el único falso positivo medido del escáner
34
+ * actual —el UUID `550e8400-e29b-41d4-a716-446655440000`, cuyo fragmento
35
+ * `446655440000` tiene forma de NSS pero da 56 donde debería dar 00—.
36
+ *
37
+ * 2. El VOCABULARIO ambiguo exige CO-OCURRENCIA con un marcador de persona.
38
+ * «diagnóstico» solo no dispara; «su diagnóstico» sí. Ver `VENTANA`.
39
+ *
40
+ * LA VENTANA es de 60 caracteres entre los bordes más cercanos del término y
41
+ * del marcador. Una oración simple en español ronda las 10-12 palabras, unos
42
+ * 60-70 caracteres; dentro de eso el marcador y el término suelen compartir
43
+ * sujeto. Más allá ya son dos frases distintas y la co-ocurrencia deja de
44
+ * significar nada: el marcador habla de una persona y el término, de otra cosa.
45
+ * Medido sobre el corpus: con 60 caracteres las 12 cadenas benignas salen
46
+ * limpias y las 19 sensibles por vocabulario salen todas.
47
+ *
48
+ * QUÉ NO HACE, y conviene que conste:
49
+ *
50
+ * · No entiende negación ni hipótesis. «no está de baja por depresión» y
51
+ * «si estuviera de baja por depresión» disparan igual. Es deliberado: en
52
+ * un detector de fugas el falso negativo se paga más caro que el falso
53
+ * positivo POR CADA CASO, y la negación en texto libre no se resuelve con
54
+ * una lista de palabras.
55
+ * · No cubre `fingerprint` ni `huella digital` como biometría, porque en
56
+ * este repositorio son la huella de un certificado o de un fichero. Sí
57
+ * cubre «huella dactilar», que no tiene lectura técnica.
58
+ * · La matrícula española no tiene dígito de control: es la única forma sin
59
+ * validar de las cinco. Se compensa exigiendo el alfabeto real de las
60
+ * placas (consonantes, sin vocales ni Ñ ni Q), que descarta casi cualquier
61
+ * token accidental de cuatro cifras y tres letras.
62
+ * · No sustituye a `classifySensitive`: es complementario. Aquí no hay
63
+ * correos, ni teléfonos, ni tarjetas.
64
+ */
65
+ /** Las diez categorías que este módulo sabe nombrar. */
66
+ export type CategoriaEspecial = "salud" | "sindical" | "origen-etnico" | "religion" | "opinion-politica" | "vida-sexual" | "biometrico" | "genetico" | "condenas" | "identificador-nacional";
67
+ export interface HallazgoEspecial {
68
+ categoria: CategoriaEspecial;
69
+ /**
70
+ * El artículo del RGPD que hace especial al dato. Es lo que el DPO necesita
71
+ * en su informe: el 9 exige una de las excepciones del 9.2, el 10 exige
72
+ * control de la autoridad pública.
73
+ *
74
+ * `identificador-nacional` se marca como "9" porque la API sólo admite dos
75
+ * valores, pero su base real es el art. 87 (número de identificación
76
+ * nacional, condiciones específicas de cada Estado miembro). Quien redacte
77
+ * el informe debe leerlo así.
78
+ */
79
+ articulo: "9" | "10";
80
+ /** Posición inicial en el texto, para poder redactar sólo ese trozo. */
81
+ desde: number;
82
+ /** Posición final (exclusiva). */
83
+ hasta: number;
84
+ /**
85
+ * La FORMA que lo disparó. NUNCA el texto detectado: un informe de fuga que
86
+ * cita la fuga es otra fuga, y estos hallazgos van a un libro de auditoría
87
+ * que se exporta.
88
+ */
89
+ porque: string;
90
+ }
91
+ /**
92
+ * El tercer estado: «no he podido mirar».
93
+ *
94
+ * Una lista vacía significa «he mirado el texto entero y no hay nada». Si el
95
+ * módulo no puede analizar, devolver `[]` convertiría un fallo en un permiso:
96
+ * quien llama guardaría la nota creyendo que está limpia. Por eso se LANZA.
97
+ *
98
+ * Se lanza en dos casos, y sólo en dos:
99
+ * · `no-es-cadena`: llega algo que no es `string` (un `null` de una API, un
100
+ * objeto que alguien esperaba serializado).
101
+ * · `demasiado-largo`: por encima de `LIMITE_CARACTERES`. El barrido es
102
+ * lineal por patrón, pero son ~80 patrones y la búsqueda de marcadores es
103
+ * cuadrática en el número de coincidencias; con un volcado de megabytes el
104
+ * detector deja de responder y quien llama se queda colgado sin saber por
105
+ * qué. Falla rápido y explícito.
106
+ */
107
+ export declare class TextoNoAnalizable extends Error {
108
+ readonly motivo: "no-es-cadena" | "demasiado-largo";
109
+ constructor(motivo: "no-es-cadena" | "demasiado-largo", detalle: string);
110
+ }
111
+ /** 200.000 caracteres ≈ 200 KB. Una nota de memoria razonable no llega a 10 KB. */
112
+ export declare const LIMITE_CARACTERES = 200000;
113
+ /** Caracteres de distancia máxima entre el término y su marcador de persona. */
114
+ export declare const VENTANA = 60;
115
+ /**
116
+ * Devuelve el texto en minúsculas, sin acentos y con TODO espacio en blanco
117
+ * convertido en un espacio simple, con la MISMA longitud.
118
+ *
119
+ * Lo del salto de línea no es cosmético y se midió: con el salto intacto,
120
+ * «perfil\ngenético» y «trade\nunion» salían LIMPIOS —los patrones de varias
121
+ * palabras llevan un espacio literal— y un dato de categoría especial partido
122
+ * por un ajuste de línea es exactamente lo que produce cualquier editor, todo
123
+ * correo citado y todo comentario de código. Se arregla aquí, en el plegado,
124
+ * y no patrón a patrón: son ~30 patrones de varias palabras y arreglar sólo
125
+ * los que uno recuerda deja el resto igual de ciegos.
126
+ */
127
+ export declare function plegar(texto: string): string;
128
+ /**
129
+ * Letra de control del DNI: módulo 23 sobre la tabla oficial.
130
+ *
131
+ * Acepta los puntos de millar («12.345.678»), que es como se imprime en la
132
+ * tarjeta y como lo teclea la mitad de la gente.
133
+ */
134
+ export declare function dniValido(numero: string, letra: string): boolean;
135
+ /** NIE: la inicial X/Y/Z vale 0/1/2 y luego es el mismo módulo 23. */
136
+ export declare function nieValido(inicial: string, numero: string, letra: string): boolean;
137
+ /** IBAN: mover los cuatro primeros al final, letra → número, y módulo 97 = 1. */
138
+ export declare function ibanValido(iban: string): boolean;
139
+ /**
140
+ * Número de la Seguridad Social: provincia (2) + número (8) + control (2),
141
+ * donde el control es el módulo 97 de los diez primeros dígitos.
142
+ *
143
+ * La excepción documentada: cuando el número de afiliación es menor que
144
+ * 10.000.000 —es decir, empieza por cero— el código de provincia se coloca
145
+ * DETRÁS. Se prueban las dos lecturas y basta con que una cuadre; probar sólo
146
+ * la principal perdería a todos los afiliados antiguos.
147
+ */
148
+ export declare function nssValido(provincia: string, numero: string, control: string): boolean;
149
+ /**
150
+ * Busca categorías especiales del art. 9 y condenas del art. 10.
151
+ *
152
+ * TRES ESTADOS, no dos:
153
+ * · lista con hallazgos → hay datos de categoría especial;
154
+ * · lista vacía → he mirado el texto entero y no hay;
155
+ * · `TextoNoAnalizable` → no he podido mirar. Nunca se confunde con la vacía.
156
+ *
157
+ * Ningún campo del hallazgo lleva el texto detectado; sólo su posición y la
158
+ * forma que lo disparó.
159
+ */
160
+ export declare function categoriasEspeciales(texto: string): HallazgoEspecial[];
161
+ /**
162
+ * Devuelve el texto con los tramos hallados —y SÓLO ésos— sustituidos por
163
+ * bloques.
164
+ *
165
+ * Es lo que le falta hoy a `redactSensitive`: medido,
166
+ * `redactSensitive("baja por depresión, afiliado a CCOO, HIV positive",
167
+ * "strict")` devuelve la cadena idéntica, y esa función alimenta el libro de
168
+ * auditoría y el diario de edición.
169
+ *
170
+ * DOS DECISIONES, las dos deliberadas:
171
+ *
172
+ * · El bloque tiene la MISMA longitud que el tramo. Un texto tapado que
173
+ * encoge delata dónde estaba el dato al comparar con el original, y además
174
+ * rompe cualquier índice que alguien haya guardado sobre el texto.
175
+ * · No se escribe la categoría en el hueco. Poner «[salud]» taparía el dato y
176
+ * publicaría el diagnóstico: que hay información de salud sobre esta
177
+ * persona ya es, por sí solo, una categoría especial. La categoría va en el
178
+ * hallazgo, que es para el DPO; el texto tapado es para todos los demás.
179
+ *
180
+ * Un texto sin hallazgos sale idéntico byte a byte —se devuelve el mismo
181
+ * objeto—, y `TextoNoAnalizable` sube igual que en `categoriasEspeciales`:
182
+ * devolver aquí el texto sin tocar sería devolver el original en claro
183
+ * creyendo haberlo tapado.
184
+ */
185
+ export declare function taparCategoriasEspeciales(texto: string): string;
186
+ //# sourceMappingURL=categorias-especiales.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categorias-especiales.d.ts","sourceRoot":"","sources":["../../../src/core/privacidad/categorias-especiales.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,0DAAwD;AACxD,MAAM,MAAM,iBAAiB,GAC1B,OAAO,GACP,UAAU,GACV,eAAe,GACf,UAAU,GACV,kBAAkB,GAClB,aAAa,GACb,YAAY,GACZ,UAAU,GACV,UAAU,GACV,wBAAwB,CAAC;AAE5B,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,iBAAiB,CAAC;IAC7B;;;;;;;;;OASG;IACH,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IACrB,0EAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,mCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,iBAAiB,CAAC;IACpD,YAAY,MAAM,EAAE,cAAc,GAAG,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAItE;CACD;AAED,qFAAmF;AACnF,eAAO,MAAM,iBAAiB,SAAU,CAAC;AAEzC,kFAAgF;AAChF,eAAO,MAAM,OAAO,KAAK,CAAC;AA2D1B;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAmB5C;AAQD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED,uEAAsE;AACtE,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIjF;AASD,qFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAShD;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAKrF;AA8aD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAkFtE;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB/D","sourcesContent":["/**\n * Detectar las CATEGORÍAS ESPECIALES del artículo 9 del RGPD (y las condenas\n * del artículo 10) en un texto, sin repetir el texto en el hallazgo.\n *\n * POR QUÉ EXISTE, medido antes de escribir nada. El escáner de\n * `memory-engine/security.ts` tiene cinco patrones de datos personales\n * (correo, teléfono, DNI/NIE, IBAN, fecha de nacimiento) y CERO del artículo 9.\n * Sobre un corpus de 24 cadenas que sí deberían saltar, en nivel `strict`\n * fallaban 20. Entre las 20: «baja por depresión», «afiliado a CCOO»,\n * «HIV positive», «huella dactilar registrada», «tiene antecedentes penales».\n * Ninguna de ellas tiene hoy categoría en `SensitiveCategory`, así que\n * `redactSensitive` las devuelve idénticas, sin un solo bloque: hoy una\n * categoría especial se escribe EN CLARO en el libro de auditoría\n * (`audit/libro.ts`), en la exportación y en el diario de edición.\n *\n * El coste no es simétrico con el de un correo. Tratar datos de salud,\n * afiliación sindical, origen étnico, religión, opinión política, vida sexual,\n * biometría o genética está PROHIBIDO salvo excepción tasada (art. 9.1 y 9.2),\n * y las condenas penales sólo pueden tratarse bajo control de la autoridad\n * (art. 10). Filtrar uno de estos no es un incidente de privacidad: es un\n * tratamiento ilícito.\n *\n * LAS DOS MITADES. Un detector de vocabulario ingenuo es peor que ninguno.\n * «diagnóstico» sale de cualquier compilador, «union» de cualquier SQL,\n * «race» de cualquier `race condition`, y un identificador interno de ocho\n * cifras no es un DNI. Un detector que grita sobre todo se desactiva en una\n * semana y entonces no protege de nada. Por eso aquí hay dos mecanismos, y\n * los dos se miden contra el corpus benigno:\n *\n * 1. Los IDENTIFICADORES se VALIDAN, no se reconocen por su forma. DNI y NIE\n * por la letra de control (módulo 23 sobre TRWAGMYFPDXBNJZSQVHLCKE), IBAN\n * y número de la Seguridad Social por módulo 97. Esto no es sólo rigor:\n * es lo que hace desaparecer el único falso positivo medido del escáner\n * actual —el UUID `550e8400-e29b-41d4-a716-446655440000`, cuyo fragmento\n * `446655440000` tiene forma de NSS pero da 56 donde debería dar 00—.\n *\n * 2. El VOCABULARIO ambiguo exige CO-OCURRENCIA con un marcador de persona.\n * «diagnóstico» solo no dispara; «su diagnóstico» sí. Ver `VENTANA`.\n *\n * LA VENTANA es de 60 caracteres entre los bordes más cercanos del término y\n * del marcador. Una oración simple en español ronda las 10-12 palabras, unos\n * 60-70 caracteres; dentro de eso el marcador y el término suelen compartir\n * sujeto. Más allá ya son dos frases distintas y la co-ocurrencia deja de\n * significar nada: el marcador habla de una persona y el término, de otra cosa.\n * Medido sobre el corpus: con 60 caracteres las 12 cadenas benignas salen\n * limpias y las 19 sensibles por vocabulario salen todas.\n *\n * QUÉ NO HACE, y conviene que conste:\n *\n * · No entiende negación ni hipótesis. «no está de baja por depresión» y\n * «si estuviera de baja por depresión» disparan igual. Es deliberado: en\n * un detector de fugas el falso negativo se paga más caro que el falso\n * positivo POR CADA CASO, y la negación en texto libre no se resuelve con\n * una lista de palabras.\n * · No cubre `fingerprint` ni `huella digital` como biometría, porque en\n * este repositorio son la huella de un certificado o de un fichero. Sí\n * cubre «huella dactilar», que no tiene lectura técnica.\n * · La matrícula española no tiene dígito de control: es la única forma sin\n * validar de las cinco. Se compensa exigiendo el alfabeto real de las\n * placas (consonantes, sin vocales ni Ñ ni Q), que descarta casi cualquier\n * token accidental de cuatro cifras y tres letras.\n * · No sustituye a `classifySensitive`: es complementario. Aquí no hay\n * correos, ni teléfonos, ni tarjetas.\n */\n\n/** Las diez categorías que este módulo sabe nombrar. */\nexport type CategoriaEspecial =\n\t| \"salud\"\n\t| \"sindical\"\n\t| \"origen-etnico\"\n\t| \"religion\"\n\t| \"opinion-politica\"\n\t| \"vida-sexual\"\n\t| \"biometrico\"\n\t| \"genetico\"\n\t| \"condenas\"\n\t| \"identificador-nacional\";\n\nexport interface HallazgoEspecial {\n\tcategoria: CategoriaEspecial;\n\t/**\n\t * El artículo del RGPD que hace especial al dato. Es lo que el DPO necesita\n\t * en su informe: el 9 exige una de las excepciones del 9.2, el 10 exige\n\t * control de la autoridad pública.\n\t *\n\t * `identificador-nacional` se marca como \"9\" porque la API sólo admite dos\n\t * valores, pero su base real es el art. 87 (número de identificación\n\t * nacional, condiciones específicas de cada Estado miembro). Quien redacte\n\t * el informe debe leerlo así.\n\t */\n\tarticulo: \"9\" | \"10\";\n\t/** Posición inicial en el texto, para poder redactar sólo ese trozo. */\n\tdesde: number;\n\t/** Posición final (exclusiva). */\n\thasta: number;\n\t/**\n\t * La FORMA que lo disparó. NUNCA el texto detectado: un informe de fuga que\n\t * cita la fuga es otra fuga, y estos hallazgos van a un libro de auditoría\n\t * que se exporta.\n\t */\n\tporque: string;\n}\n\n/**\n * El tercer estado: «no he podido mirar».\n *\n * Una lista vacía significa «he mirado el texto entero y no hay nada». Si el\n * módulo no puede analizar, devolver `[]` convertiría un fallo en un permiso:\n * quien llama guardaría la nota creyendo que está limpia. Por eso se LANZA.\n *\n * Se lanza en dos casos, y sólo en dos:\n * · `no-es-cadena`: llega algo que no es `string` (un `null` de una API, un\n * objeto que alguien esperaba serializado).\n * · `demasiado-largo`: por encima de `LIMITE_CARACTERES`. El barrido es\n * lineal por patrón, pero son ~80 patrones y la búsqueda de marcadores es\n * cuadrática en el número de coincidencias; con un volcado de megabytes el\n * detector deja de responder y quien llama se queda colgado sin saber por\n * qué. Falla rápido y explícito.\n */\nexport class TextoNoAnalizable extends Error {\n\treadonly motivo: \"no-es-cadena\" | \"demasiado-largo\";\n\tconstructor(motivo: \"no-es-cadena\" | \"demasiado-largo\", detalle: string) {\n\t\tsuper(`No se pudo analizar el texto (${motivo}): ${detalle}`);\n\t\tthis.name = \"TextoNoAnalizable\";\n\t\tthis.motivo = motivo;\n\t}\n}\n\n/** 200.000 caracteres ≈ 200 KB. Una nota de memoria razonable no llega a 10 KB. */\nexport const LIMITE_CARACTERES = 200_000;\n\n/** Caracteres de distancia máxima entre el término y su marcador de persona. */\nexport const VENTANA = 60;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plegado: quitar acentos y mayúsculas SIN mover ni un índice\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * `NFD` + quitar diacríticos cambiaría la longitud y con ella `desde`/`hasta`,\n * que dejarían de servir para redactar el original. Aquí se mapea carácter a\n * carácter, uno a uno, para que el texto plegado y el original compartan\n * índices exactamente.\n */\nconst EQUIVALENTES: Record<string, string> = {\n\tá: \"a\",\n\tà: \"a\",\n\tä: \"a\",\n\tâ: \"a\",\n\té: \"e\",\n\tè: \"e\",\n\të: \"e\",\n\tê: \"e\",\n\tí: \"i\",\n\tì: \"i\",\n\tï: \"i\",\n\tî: \"i\",\n\tó: \"o\",\n\tò: \"o\",\n\tö: \"o\",\n\tô: \"o\",\n\tú: \"u\",\n\tù: \"u\",\n\tü: \"u\",\n\tû: \"u\",\n\tñ: \"n\",\n\tç: \"c\",\n\tÁ: \"a\",\n\tÀ: \"a\",\n\tÄ: \"a\",\n\tÂ: \"a\",\n\tÉ: \"e\",\n\tÈ: \"e\",\n\tË: \"e\",\n\tÊ: \"e\",\n\tÍ: \"i\",\n\tÌ: \"i\",\n\tÏ: \"i\",\n\tÎ: \"i\",\n\tÓ: \"o\",\n\tÒ: \"o\",\n\tÖ: \"o\",\n\tÔ: \"o\",\n\tÚ: \"u\",\n\tÙ: \"u\",\n\tÜ: \"u\",\n\tÛ: \"u\",\n\tÑ: \"n\",\n\tÇ: \"c\",\n};\n\n/**\n * Devuelve el texto en minúsculas, sin acentos y con TODO espacio en blanco\n * convertido en un espacio simple, con la MISMA longitud.\n *\n * Lo del salto de línea no es cosmético y se midió: con el salto intacto,\n * «perfil\\ngenético» y «trade\\nunion» salían LIMPIOS —los patrones de varias\n * palabras llevan un espacio literal— y un dato de categoría especial partido\n * por un ajuste de línea es exactamente lo que produce cualquier editor, todo\n * correo citado y todo comentario de código. Se arregla aquí, en el plegado,\n * y no patrón a patrón: son ~30 patrones de varias palabras y arreglar sólo\n * los que uno recuerda deja el resto igual de ciegos.\n */\nexport function plegar(texto: string): string {\n\tlet salida = \"\";\n\tfor (let i = 0; i < texto.length; i++) {\n\t\tconst c = texto[i] as string;\n\t\tif (c === \"\\n\" || c === \"\\r\" || c === \"\\t\" || c === \"\\f\" || c === \"\\v\") {\n\t\t\tsalida += \" \";\n\t\t\tcontinue;\n\t\t}\n\t\tconst equivalente = EQUIVALENTES[c];\n\t\tif (equivalente !== undefined) {\n\t\t\tsalida += equivalente;\n\t\t\tcontinue;\n\t\t}\n\t\tconst minuscula = c.toLowerCase();\n\t\t// Hay caracteres cuya minúscula ocupa dos unidades ('İ' → 'i̇'). Ésos se\n\t\t// dejan como están: mover un índice cuesta más que perder una coincidencia.\n\t\tsalida += minuscula.length === 1 ? minuscula : c;\n\t}\n\treturn salida;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Validación de identificadores\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst LETRAS_DNI = \"TRWAGMYFPDXBNJZSQVHLCKE\";\n\n/**\n * Letra de control del DNI: módulo 23 sobre la tabla oficial.\n *\n * Acepta los puntos de millar («12.345.678»), que es como se imprime en la\n * tarjeta y como lo teclea la mitad de la gente.\n */\nexport function dniValido(numero: string, letra: string): boolean {\n\tconst digitos = numero.replace(/\\./g, \"\");\n\tif (!/^\\d{8}$/.test(digitos)) return false;\n\treturn LETRAS_DNI[Number(digitos) % 23] === letra.toUpperCase();\n}\n\n/** NIE: la inicial X/Y/Z vale 0/1/2 y luego es el mismo módulo 23. */\nexport function nieValido(inicial: string, numero: string, letra: string): boolean {\n\tconst prefijo = { X: \"0\", Y: \"1\", Z: \"2\" }[inicial.toUpperCase()];\n\tif (prefijo === undefined) return false;\n\treturn dniValido(prefijo + numero, letra);\n}\n\n/** Resto módulo 97 de una cadena de dígitos, sin desbordar el entero. */\nfunction modulo97(digitos: string): number {\n\tlet resto = 0;\n\tfor (const d of digitos) resto = (resto * 10 + Number(d)) % 97;\n\treturn resto;\n}\n\n/** IBAN: mover los cuatro primeros al final, letra → número, y módulo 97 = 1. */\nexport function ibanValido(iban: string): boolean {\n\tconst limpio = iban.replace(/\\s/g, \"\").toUpperCase();\n\tif (!/^[A-Z]{2}\\d{2}[A-Z0-9]{10,30}$/.test(limpio)) return false;\n\tconst rotado = limpio.slice(4) + limpio.slice(0, 4);\n\tlet digitos = \"\";\n\tfor (const c of rotado) {\n\t\tdigitos += c >= \"A\" && c <= \"Z\" ? String(c.charCodeAt(0) - 55) : c;\n\t}\n\treturn modulo97(digitos) === 1;\n}\n\n/**\n * Número de la Seguridad Social: provincia (2) + número (8) + control (2),\n * donde el control es el módulo 97 de los diez primeros dígitos.\n *\n * La excepción documentada: cuando el número de afiliación es menor que\n * 10.000.000 —es decir, empieza por cero— el código de provincia se coloca\n * DETRÁS. Se prueban las dos lecturas y basta con que una cuadre; probar sólo\n * la principal perdería a todos los afiliados antiguos.\n */\nexport function nssValido(provincia: string, numero: string, control: string): boolean {\n\tconst esperado = Number(control);\n\tif (modulo97(provincia + numero) === esperado) return true;\n\tif (numero.startsWith(\"0\")) return modulo97(numero + provincia) === esperado;\n\treturn false;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Marcadores de persona\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Lo que sitúa un dato EN UNA PERSONA. Sin uno de éstos cerca, el vocabulario\n * ambiguo no dispara.\n *\n * No están los artículos («el», «la», «los»): son tan frecuentes que\n * convertirían la co-ocurrencia en un adorno —todo texto en español tiene un\n * artículo a menos de 60 caracteres de cualquier cosa—. Sí están los posesivos\n * y los pronombres, que es lo que atribuye el dato a alguien.\n *\n * «de baja» / «baja por» entran porque una baja es siempre de una persona; es\n * el marcador que sostiene «baja por depresión», donde no hay ningún pronombre.\n */\nconst MARCADORES: RegExp[] = [\n\t/\\b(?:yo|tu|ella|ellos|ellas|nosotros|nosotras|vosotros|usted|ustedes)\\b/g,\n\t// SIN `su` ni `sus`, y es una corrección medida. En español el posesivo de\n\t// tercera persona vale para CUALQUIER antecedente, animado o no: «agrega sus\n\t// diagnósticos» habla de un comprobador, no de un paciente. Con `su`/`sus`\n\t// dentro, 7 de los 10 falsos positivos que quedaban sobre `src` venían de\n\t// ahí. Los de primera y segunda persona sí implican a alguien.\n\t/\\b(?:mi|mis|tus|nuestro|nuestra|nuestros|nuestras)\\b/g,\n\t// SIN `i`: es la variable de bucle de todo el código escrito jamás, y sobre\n\t// el plegado no hay forma de distinguirla del pronombre inglés.\n\t/\\b(?:he|she|they|we|my|his|her|their|our|your|him|them)\\b/g,\n\t/\\b(?:paciente|pacientes|enfermo|enferma|empleado|empleada|empleados|empleadas)\\b/g,\n\t/\\b(?:trabajador|trabajadora|trabajadores|usuario|usuaria|usuarios|cliente|clientes)\\b/g,\n\t/\\b(?:candidato|candidata|afiliado|afiliada|socio|socia|miembro|companero|companera|colega)\\b/g,\n\t/\\b(?:patient|employee|employees|worker|workers|user|users|customer|member|colleague)\\b/g,\n\t/\\b(?:don|dona|sr|sra|senor|senora|mr|mrs|ms)\\b/g,\n\t/\\bde baja\\b|\\bbaja por\\b|\\bsick leave\\b|\\bon leave\\b/g,\n];\n\n/**\n * Nombre y apellido SEGUIDOS: dos palabras capitalizadas pegadas, ni al\n * principio del texto ni tras un punto.\n *\n * MEDIDO, y es la corrección más cara de este módulo. Antes bastaba UNA palabra\n * capitalizada. Sobre los 469 ficheros `.ts` reales de `src` eso daba 20.272\n * marcadores: en un repositorio documentado en español toda palabra que abre\n * frase dentro de un bloque de documentación y todo nombre de tipo\n * (`Comprobador`, `Deteccion`, `Diagnostico`) valía por «una persona». El\n * resultado era que la co-ocurrencia no filtraba nada y el detector marcaba 51\n * veces palabras como `diagnóstico` y `positivo` —la segunda dentro de la\n * expresión «falso positivo», que es justo lo que este módulo intenta evitar—.\n * Exigiendo las dos palabras seguidas quedan 351 candidatos sobre el mismo\n * corpus, y ninguno acaba produciendo un hallazgo.\n *\n * Lo que se paga: «Ana padece esclerosis» ya no tiene marcador por el nombre.\n * Se acepta a sabiendas —un nombre de pila suelto es indistinguible de un\n * identificador de código— y se compensa con el vocabulario sin marcador.\n */\nconst NOMBRE_COMPLETO = /\\b[A-ZÁÉÍÓÚÑ][a-záéíóúñ]{2,} [A-ZÁÉÍÓÚÑ][a-záéíóúñ]{2,}\\b/g;\n\ninterface Tramo {\n\tdesde: number;\n\thasta: number;\n}\n\nfunction marcadoresDe(plegado: string, original: string): Tramo[] {\n\tconst tramos: Tramo[] = [];\n\tfor (const patron of MARCADORES) {\n\t\tfor (const m of plegado.matchAll(patron)) {\n\t\t\ttramos.push({ desde: m.index, hasta: m.index + m[0].length });\n\t\t}\n\t}\n\tfor (const m of original.matchAll(NOMBRE_COMPLETO)) {\n\t\tconst antes = original.slice(0, m.index).trimEnd();\n\t\tif (antes.length === 0) continue; // primera palabra del texto\n\t\tif (/[.!?¿¡:]$/.test(antes)) continue; // primera palabra de la oración\n\t\ttramos.push({ desde: m.index, hasta: m.index + m[0].length });\n\t}\n\treturn tramos;\n}\n\n/** ¿Hay algún marcador a menos de `VENTANA` del término, sin solaparlo? */\nfunction tieneMarcadorCerca(termino: Tramo, marcadores: Tramo[]): boolean {\n\tfor (const m of marcadores) {\n\t\tif (m.desde < termino.hasta && termino.desde < m.hasta) continue; // se solapan: es el propio término\n\t\tconst distancia = m.desde >= termino.hasta ? m.desde - termino.hasta : termino.desde - m.hasta;\n\t\tif (distancia <= VENTANA) return true;\n\t}\n\treturn false;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Vocabulario\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface Termino {\n\tcategoria: CategoriaEspecial;\n\tpatron: RegExp;\n\t/** `true` = ambiguo fuera de contexto, exige marcador de persona cerca. */\n\texigeMarcador: boolean;\n\t/**\n\t * `true` = el patrón corre sobre el texto ORIGINAL, no sobre el plegado.\n\t *\n\t * Es para las siglas: un sindicato se escribe SIEMPRE en mayúsculas, y sobre\n\t * el plegado `USO` es indistinguible de «uso» y `LAB` de «lab». Medido: la\n\t * lista de siglas sobre el plegado producía 64 hallazgos sobre los ficheros\n\t * reales de `src` —todos «uso» y «usó»—; la misma lista en mayúsculas sobre\n\t * el original produce CERO, sin perder «afiliado a CCOO».\n\t */\n\tsobreOriginal?: boolean;\n}\n\n/**\n * Español e inglés en la misma tabla. Lo que entra sin marcador es lo que no\n * tiene otra lectura en un repositorio de software: `diabetes` no sale de un\n * compilador. Lo que exige marcador es lo que sí sale: `diagnostico`,\n * `depresion`, `positivo`.\n *\n * Ausencias deliberadas, cada una por un falso positivo concreto:\n * · `union` a secas → `union type`, `UNION ALL`. Sólo entra en locuciones\n * («union member», «trade union»).\n * · `race` a secas → `race condition`. Sólo entra «racial origin».\n * · `podemos` como partido → es la primera persona del plural de «poder».\n * Se cubre por la locución «votante de», que revela la opinión política\n * sea cual sea el partido.\n * · `master`, `slave`, `blacklist` → vocabulario técnico, no étnico.\n */\nconst TERMINOS: Termino[] = [\n\t// ── Salud (art. 9) ──\n\t{ categoria: \"salud\", patron: /\\bdiabetes\\b|\\bdiabetic(?:o|a|os|as)?\\b/g, exigeMarcador: false },\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\balergi(?:a|as)\\b|\\balergic(?:o|a)\\b|\\ballerg(?:y|ic|ies)\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{ categoria: \"salud\", patron: /\\b(?:vih|hiv|sida|aids|hepatitis|tuberculosis)\\b/g, exigeMarcador: false },\n\t{ categoria: \"salud\", patron: /\\bcancer\\b|\\bleucemia\\b|\\bleukemia\\b|\\btumor(?:es)?\\b/g, exigeMarcador: false },\n\t{ categoria: \"salud\", patron: /\\bgrupo sanguineo\\b|\\bblood (?:type|group)\\b/g, exigeMarcador: false },\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\ben tratamiento (?:con|por|de)\\b|\\bunder treatment for\\b|\\bon medication\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\b(?:sertralina|fluoxetina|paroxetina|litio|insulina|metformina|antidepresiv(?:o|os)|antirretroviral(?:es)?|quimioterapia|chemotherapy)\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\bhistoria clinica\\b|\\bhistorial medico\\b|\\bmedical (?:record|history)\\b|\\binforme medico\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\bembarazad(?:a|as)\\b|\\bpregnan(?:t|cy)\\b|\\bdiscapacidad\\b|\\bminusvalia\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t// `diagnostico` PARTIDO EN DOS, y es la lección más cara del módulo. En un\n\t// agente de programación «diagnóstico» es lo que escupe el compilador: sobre\n\t// `src` aparece 46 veces y ninguna habla de la salud de nadie. La forma que\n\t// sí es art. 9 no es la palabra suelta, es la CONSTRUCCIÓN: a alguien se le\n\t// diagnostica ALGO. Ésa no exige marcador porque ya lo lleva dentro.\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\bdiagnosticad(?:o|a|os|as) (?:de|con)\\b|\\bdiagnos(?:ed with|is of)\\b|\\bdiagnostico (?:medico|clinico|psiquiatrico|psicologico|de cancer)\\b|\\bmedical diagnosis\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\bdiagnostic(?:o|os|ado|ada|ados|adas)\\b|\\bdiagnos(?:is|ed)\\b/g,\n\t\texigeMarcador: true,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\bdepresion\\b|\\bansiedad\\b|\\bdepression\\b|\\banxiety\\b|\\bburnout\\b/g,\n\t\texigeMarcador: true,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\benfermedad(?:es)?\\b|\\bdolencia\\b|\\billness\\b|\\bdisease\\b|\\bsintomas\\b/g,\n\t\texigeMarcador: true,\n\t},\n\t// `positivo` va sin «falso» ni «false» delante: «falso positivo» es la\n\t// expresión de oficio de este repositorio —medido, 5 hallazgos en `src`, uno\n\t// de ellos en un comentario que explica cómo evitar falsos positivos— y no\n\t// habla de la serología de nadie.\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /(?<!\\bfals[oa]s? )(?<!\\bfalse )(?:\\bpositiv(?:o|a)\\b|\\bpositive\\b|\\bseropositiv(?:o|a)\\b)/g,\n\t\texigeMarcador: true,\n\t},\n\t// Patologías sin lectura técnica: no salen de un compilador, así que no\n\t// exigen marcador. Coste medido sobre los 469 ficheros de `src` y sobre 200\n\t// commits: CERO hallazgos.\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\besquizofrenia\\b|\\bbipolar\\b|\\bepilep(?:sia|tic(?:o|a))\\b|\\balzheimer\\b|\\bparkinson\\b|\\bdialisis\\b|\\besclerosis\\b|\\bfibromialgia\\b|\\bcelia(?:co|ca)\\b|\\basma\\b|\\bictus\\b|\\binfarto\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\bsuicidi(?:o|os|arse)\\b|\\bautolesion(?:es)?\\b|\\bsalud mental\\b|\\bmental health\\b|\\bingreso psiquiatric(?:o|a)\\b|\\bpsiquiatric(?:o|a)\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\badict(?:o|a) a\\b|\\balcoholi(?:co|ca|smo)\\b|\\bdrogodependien\\w*\\b|\\bdesintoxicacion\\b|\\brehabilitacion\\b|\\btoxicoman\\w*\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\bbaja medica\\b|\\bbaja laboral\\b|\\bincapacidad (?:temporal|permanente|laboral)\\b|\\bsick leave\\b|\\bmedical leave\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron:\n\t\t\t/\\babortion\\b|\\binterrupcion (?:voluntaria )?del embarazo\\b|\\btratamiento de fertilidad\\b|\\bmiscarriage\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t// Siglas clínicas, en mayúsculas y sobre el original. Sólo las que no\n\t// colisionan con vocabulario técnico: fuera `IAM` (AWS), `ACV`, `TOC` (tabla\n\t// de contenidos) y `SNS`, que en un repositorio son otra cosa.\n\t{\n\t\tcategoria: \"salud\",\n\t\tpatron: /\\b(?:TDAH|TEPT|EPOC|VHC|VHB)\\b/g,\n\t\texigeMarcador: false,\n\t\tsobreOriginal: true,\n\t},\n\n\t// ── Afiliación sindical (art. 9) ──\n\t// EN MAYÚSCULAS y sobre el original: ver `sobreOriginal`. `uso`, `lab`, `cnt`\n\t// y `ela` en minúsculas son palabras corrientes, no sindicatos.\n\t{\n\t\tcategoria: \"sindical\",\n\t\tpatron: /\\b(?:CCOO|UGT|CGT|CNT|USO|ELA|LAB|CIG|SATSE|CSIF)\\b/g,\n\t\texigeMarcador: false,\n\t\tsobreOriginal: true,\n\t},\n\t// `liberado sindical` y `seccion sindical` llevan la palabra dentro: no hay\n\t// otra lectura. `huelga` sí la tiene —«huelga decir»— y además una huelga\n\t// convocada no es un dato de nadie; lo que revela afiliación es que una\n\t// PERSONA aparezca al lado. De ahí el marcador sólo en la segunda.\n\t{\n\t\tcategoria: \"sindical\",\n\t\tpatron: /\\bliberad(?:o|a) sindical\\b|\\bseccion sindical\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{ categoria: \"sindical\", patron: /\\bhuelga\\b|\\bpiquete\\b/g, exigeMarcador: true },\n\t{\n\t\tcategoria: \"sindical\",\n\t\tpatron:\n\t\t\t/\\bsindicat(?:o|os)\\b|\\bsindicalista\\b|\\bafiliacion sindical\\b|\\bdelegad(?:o|a) sindical\\b|\\bcomite de empresa\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"sindical\",\n\t\tpatron: /\\bunion member(?:ship)?\\b|\\btrade union\\b|\\blabou?r union\\b|\\bunioni[sz]ed\\b|\\bshop steward\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Origen étnico o racial (art. 9) ──\n\t{\n\t\tcategoria: \"origen-etnico\",\n\t\tpatron:\n\t\t\t/\\bde origen (?:marroqui|gitan(?:o|a)|magrebi|subsaharian(?:o|a)|arabe|bereber|judi(?:o|a)|latin(?:o|a)|rumen(?:o|a)|rumano|rumana|chin(?:o|a)|african(?:o|a)|asiatic(?:o|a)|indi(?:o|a)|turc(?:o|a)|paquistani|senegales|ecuatorian(?:o|a)|bolivian(?:o|a)|etnic(?:o|a))\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"origen-etnico\",\n\t\tpatron:\n\t\t\t/\\betnia\\b|\\bgitan(?:o|a|os|as)\\b|\\bracial origin\\b|\\bethnic (?:origin|group|background|minority)\\b|\\bethnicity\\b|\\borigen racial\\b|\\bminoria etnica\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Religión o creencias (art. 9) ──\n\t{\n\t\tcategoria: \"religion\",\n\t\tpatron:\n\t\t\t/\\bmusulman(?:a|es|as)?\\b|\\bmuslim\\b|\\bislamic(?:o|a)?\\b|\\bcatolic(?:o|a|os|as)\\b|\\bcatholic\\b|\\bevangelic(?:o|a)\\b|\\bprotestante\\b|\\bjudi(?:o|a)\\b|\\bjewish\\b|\\bhindu\\b|\\bbudista\\b|\\bbuddhist\\b|\\btestigo de jehova\\b|\\bate(?:o|a)\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t// `agnostico` sale de la lista: medido, en `src` aparece una vez y es\n\t// «agnóstico de proveedor». La creencia religiosa que hay que cazar es la\n\t// que se declara, no la que se niega con una palabra que además es jerga.\n\t{\n\t\tcategoria: \"religion\",\n\t\tpatron:\n\t\t\t/\\bcreencias religiosas\\b|\\breligious belief(?:s)?\\b|\\bconviccion religiosa\\b|\\bpractica religiosa\\b|\\bmotivos religiosos\\b|\\bramadan\\b|\\bkosher\\b|\\bhalal\\b|\\bva a misa\\b|\\bbautizad(?:o|a)\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Opiniones políticas (art. 9) ──\n\t{\n\t\tcategoria: \"opinion-politica\",\n\t\tpatron:\n\t\t\t/\\bvotante de\\b|\\bvot(?:a|o|e) a\\b|\\bvoted for\\b|\\bmilitante de\\b|\\bsimpatizante de\\b|\\bafiliad(?:o|a) al partido\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"opinion-politica\",\n\t\tpatron:\n\t\t\t/\\bpartido popular\\b|\\bpsoe\\b|\\bizquierda unida\\b|\\bpartido comunista\\b|\\bideologia politica\\b|\\bpolitical (?:opinion|affiliation|party)\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Vida sexual u orientación sexual (art. 9) ──\n\t{\n\t\tcategoria: \"vida-sexual\",\n\t\tpatron:\n\t\t\t/\\bgay\\b|\\blesbian(?:a|as)?\\b|\\bbisexual\\b|\\bhomosexual\\b|\\bheterosexual\\b|\\btransexual\\b|\\btransgener(?:o|a)\\b|\\btransgender\\b|\\bqueer\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"vida-sexual\",\n\t\tpatron:\n\t\t\t/\\borientacion sexual\\b|\\bsexual orientation\\b|\\bidentidad de genero\\b|\\bgender identity\\b|\\bpareja de hecho\\b|\\bcivil partnership\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Datos biométricos (art. 9) ──\n\t{\n\t\tcategoria: \"biometrico\",\n\t\tpatron:\n\t\t\t/\\bhuella(?:s)? dactilar(?:es)?\\b|\\breconocimiento facial\\b|\\bfacial recognition\\b|\\bfingerprint scan(?:ner)?\\b|\\biris scan\\b|\\bescaneo de iris\\b|\\bvoiceprint\\b|\\bhuella de voz\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"biometrico\",\n\t\tpatron: /\\bdatos biometricos\\b|\\bbiometric data\\b|\\bplantilla biometrica\\b|\\bbiometric template\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Datos genéticos (art. 9) ──\n\t{\n\t\tcategoria: \"genetico\",\n\t\tpatron:\n\t\t\t/\\bperfil genetic(?:o|a)\\b|\\bgenetic (?:profile|test|testing|data|marker)\\b|\\btest genetico\\b|\\bsecuenciacion (?:genetica|del genoma)\\b|\\bgenoma\\b|\\bcariotipo\\b|\\bbrca[12]\\b/g,\n\t\texigeMarcador: false,\n\t},\n\n\t// ── Condenas e infracciones penales (art. 10) ──\n\t{\n\t\tcategoria: \"condenas\",\n\t\tpatron: /\\bantecedentes penales\\b|\\bcriminal record\\b|\\bcertificado de penales\\b|\\bregistro de delincuentes\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t{\n\t\tcategoria: \"condenas\",\n\t\tpatron:\n\t\t\t/\\bcondenad(?:o|a) por\\b|\\bconvicted of\\b|\\bsentenciad(?:o|a) a\\b|\\bsentenced to\\b|\\bimputad(?:o|a) por\\b|\\bproceso penal\\b|\\ben prision por\\b/g,\n\t\texigeMarcador: false,\n\t},\n\t// Las formas que faltaban, medidas: «cumplió condena por robo», «detenido\n\t// por», «orden de alejamiento» y «violencia de género» salían LIMPIAS. Coste\n\t// sobre los 469 ficheros de `src` y 200 commits: CERO.\n\t{\n\t\tcategoria: \"condenas\",\n\t\tpatron:\n\t\t\t/\\bcondena por\\b|\\bcumplio condena\\b|\\bdetenid(?:o|a) por\\b|\\borden de alejamiento\\b|\\bdelito de\\b|\\bviolencia de genero\\b|\\bjuicio penal\\b|\\barrested for\\b|\\bon probation\\b|\\bparole\\b/g,\n\t\texigeMarcador: false,\n\t},\n];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Identificadores\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Van sobre el texto ORIGINAL, no sobre el plegado —el plegado ya no distingue\n * `X` de `x`— pero SÍ aceptan minúsculas y los puntos de millar.\n *\n * MEDIDO, y era un agujero de los grandes: `dni 12345678z`, `nie z1234567r`,\n * `es9121000418450200051332` y `DNI 12.345.678-Z` salían LIMPIOS. Las cuatro\n * son formas que produce cualquiera: el punto de millar es como se imprime un\n * DNI en España, y la minúscula es lo que sale de un `toLowerCase()` en\n * cualquier campo de formulario, de un `JSON` normalizado o de una URL.\n *\n * El coste se midió, y no salió gratis: `/Users/31017423z/...` —un directorio\n * de trabajo real, citado en dos ficheros de `src`— tiene ocho cifras y una\n * letra, y PASA el módulo 23. De ahí el `(?<![/\\\\])` y el `(?![/\\\\])`: un token\n * pegado a una barra es un segmento de ruta, no un documento. Con ese guardián\n * la forma insensible a mayúsculas produce CERO hallazgos sobre los 469\n * ficheros `.ts` de `src` y sobre 200 commits.\n */\nconst DNI = /(?<![/\\\\])\\b(\\d{2}\\.?\\d{3}\\.?\\d{3})[ .-]?([A-Za-z])\\b(?![/\\\\])/g;\nconst NIE = /(?<![/\\\\])\\b([XYZxyz])[ .-]?(\\d{7})[ .-]?([A-Za-z])\\b(?![/\\\\])/g;\nconst IBAN = /\\b([A-Za-z]{2}\\d{2}(?:[ ]?[A-Za-z0-9]{4}){3,7}[ ]?[A-Za-z0-9]{0,4})\\b/g;\nconst NSS = /\\b(\\d{2})[ -]?(\\d{8})[ -]?(\\d{2})\\b/g;\n/** Matrícula española desde 2000: cuatro cifras y tres consonantes, sin Ñ ni Q. */\nconst MATRICULA = /\\b\\d{4}[ -]?[BCDFGHJKLMNPRSTVWXYZ]{3}\\b/g;\n\nconst PORQUE_MODULO_23 = \"identificador nacional con letra de control correcta (comprobada, modulo 23)\";\nconst PORQUE_MODULO_97 = \"identificador nacional con digito de control correcto (comprobado, modulo 97)\";\nconst PORQUE_FORMA_PLACA =\n\t\"identificador nacional con la forma exacta de una placa (cuatro cifras y tres consonantes; sin control que comprobar)\";\nconst PORQUE_VOCABULARIO = \"vocabulario de categoria especial sin otra lectura tecnica\";\nconst PORQUE_CON_MARCADOR = `vocabulario ambiguo con un marcador de persona a menos de ${VENTANA} caracteres`;\n\nfunction articuloDe(categoria: CategoriaEspecial): \"9\" | \"10\" {\n\treturn categoria === \"condenas\" ? \"10\" : \"9\";\n}\n\n/**\n * Funde los hallazgos de la MISMA categoría que se solapan.\n *\n * «afiliado al partido popular» dispara dos patrones políticos sobre tramos\n * que se pisan; dos hallazgos para un solo dato inflan el informe del DPO y\n * hacen que redactar sea redactar dos veces lo mismo.\n */\nfunction fundir(hallazgos: HallazgoEspecial[]): HallazgoEspecial[] {\n\tconst ordenados = [...hallazgos].sort((a, b) => a.desde - b.desde || a.hasta - b.hasta);\n\tconst salida: HallazgoEspecial[] = [];\n\tfor (const h of ordenados) {\n\t\tconst previo = salida.find((p) => p.categoria === h.categoria && h.desde < p.hasta && p.desde < h.hasta);\n\t\tif (previo) {\n\t\t\tprevio.desde = Math.min(previo.desde, h.desde);\n\t\t\tprevio.hasta = Math.max(previo.hasta, h.hasta);\n\t\t\tcontinue;\n\t\t}\n\t\tsalida.push({ ...h });\n\t}\n\treturn salida.sort((a, b) => a.desde - b.desde);\n}\n\n/**\n * Busca categorías especiales del art. 9 y condenas del art. 10.\n *\n * TRES ESTADOS, no dos:\n * · lista con hallazgos → hay datos de categoría especial;\n * · lista vacía → he mirado el texto entero y no hay;\n * · `TextoNoAnalizable` → no he podido mirar. Nunca se confunde con la vacía.\n *\n * Ningún campo del hallazgo lleva el texto detectado; sólo su posición y la\n * forma que lo disparó.\n */\nexport function categoriasEspeciales(texto: string): HallazgoEspecial[] {\n\tif (typeof texto !== \"string\") {\n\t\tthrow new TextoNoAnalizable(\"no-es-cadena\", `llego un ${texto === null ? \"null\" : typeof texto}`);\n\t}\n\tif (texto.length > LIMITE_CARACTERES) {\n\t\tthrow new TextoNoAnalizable(\"demasiado-largo\", `${texto.length} caracteres, el limite es ${LIMITE_CARACTERES}`);\n\t}\n\n\tconst hallazgos: HallazgoEspecial[] = [];\n\tconst plegado = plegar(texto);\n\tconst marcadores = marcadoresDe(plegado, texto);\n\n\tfor (const termino of TERMINOS) {\n\t\t// Plegado y original tienen la MISMA longitud, así que los índices de uno\n\t\t// sirven para el otro y para el cálculo de distancia al marcador.\n\t\tconst donde = termino.sobreOriginal ? texto : plegado;\n\t\tfor (const m of donde.matchAll(termino.patron)) {\n\t\t\tconst tramo = { desde: m.index, hasta: m.index + m[0].length };\n\t\t\tif (termino.exigeMarcador && !tieneMarcadorCerca(tramo, marcadores)) continue;\n\t\t\thallazgos.push({\n\t\t\t\tcategoria: termino.categoria,\n\t\t\t\tarticulo: articuloDe(termino.categoria),\n\t\t\t\tdesde: tramo.desde,\n\t\t\t\thasta: tramo.hasta,\n\t\t\t\tporque: termino.exigeMarcador ? PORQUE_CON_MARCADOR : PORQUE_VOCABULARIO,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Identificadores: la forma sólo abre la puerta; entra el que valida.\n\tfor (const m of texto.matchAll(DNI)) {\n\t\tif (!dniValido(m[1] as string, m[2] as string)) continue;\n\t\thallazgos.push({\n\t\t\tcategoria: \"identificador-nacional\",\n\t\t\tarticulo: \"9\",\n\t\t\tdesde: m.index,\n\t\t\thasta: m.index + m[0].length,\n\t\t\tporque: PORQUE_MODULO_23,\n\t\t});\n\t}\n\tfor (const m of texto.matchAll(NIE)) {\n\t\tif (!nieValido(m[1] as string, m[2] as string, m[3] as string)) continue;\n\t\thallazgos.push({\n\t\t\tcategoria: \"identificador-nacional\",\n\t\t\tarticulo: \"9\",\n\t\t\tdesde: m.index,\n\t\t\thasta: m.index + m[0].length,\n\t\t\tporque: PORQUE_MODULO_23,\n\t\t});\n\t}\n\tfor (const m of texto.matchAll(IBAN)) {\n\t\tconst candidato = (m[1] as string).trimEnd();\n\t\tif (!ibanValido(candidato)) continue;\n\t\thallazgos.push({\n\t\t\tcategoria: \"identificador-nacional\",\n\t\t\tarticulo: \"9\",\n\t\t\tdesde: m.index,\n\t\t\thasta: m.index + candidato.length,\n\t\t\tporque: PORQUE_MODULO_97,\n\t\t});\n\t}\n\tfor (const m of texto.matchAll(NSS)) {\n\t\tif (!nssValido(m[1] as string, m[2] as string, m[3] as string)) continue;\n\t\thallazgos.push({\n\t\t\tcategoria: \"identificador-nacional\",\n\t\t\tarticulo: \"9\",\n\t\t\tdesde: m.index,\n\t\t\thasta: m.index + m[0].length,\n\t\t\tporque: PORQUE_MODULO_97,\n\t\t});\n\t}\n\tfor (const m of texto.matchAll(MATRICULA)) {\n\t\thallazgos.push({\n\t\t\tcategoria: \"identificador-nacional\",\n\t\t\tarticulo: \"9\",\n\t\t\tdesde: m.index,\n\t\t\thasta: m.index + m[0].length,\n\t\t\tporque: PORQUE_FORMA_PLACA,\n\t\t});\n\t}\n\n\treturn fundir(hallazgos);\n}\n\n/** Con lo que se sustituye cada tramo. El mismo bloque que usa `redactSensitive`. */\nconst BLOQUE = \"█\";\n\n/**\n * Devuelve el texto con los tramos hallados —y SÓLO ésos— sustituidos por\n * bloques.\n *\n * Es lo que le falta hoy a `redactSensitive`: medido,\n * `redactSensitive(\"baja por depresión, afiliado a CCOO, HIV positive\",\n * \"strict\")` devuelve la cadena idéntica, y esa función alimenta el libro de\n * auditoría y el diario de edición.\n *\n * DOS DECISIONES, las dos deliberadas:\n *\n * · El bloque tiene la MISMA longitud que el tramo. Un texto tapado que\n * encoge delata dónde estaba el dato al comparar con el original, y además\n * rompe cualquier índice que alguien haya guardado sobre el texto.\n * · No se escribe la categoría en el hueco. Poner «[salud]» taparía el dato y\n * publicaría el diagnóstico: que hay información de salud sobre esta\n * persona ya es, por sí solo, una categoría especial. La categoría va en el\n * hallazgo, que es para el DPO; el texto tapado es para todos los demás.\n *\n * Un texto sin hallazgos sale idéntico byte a byte —se devuelve el mismo\n * objeto—, y `TextoNoAnalizable` sube igual que en `categoriasEspeciales`:\n * devolver aquí el texto sin tocar sería devolver el original en claro\n * creyendo haberlo tapado.\n */\nexport function taparCategoriasEspeciales(texto: string): string {\n\tconst hallazgos = categoriasEspeciales(texto);\n\tif (hallazgos.length === 0) return texto;\n\n\t// Los hallazgos vienen ordenados por `desde`, pero `fundir` sólo une los de\n\t// la MISMA categoría: dos categorías distintas pueden pisarse («judío» es\n\t// origen étnico y religión a la vez). El cursor evita tapar dos veces el\n\t// mismo trozo, que duplicaría bloques y alargaría el texto.\n\tlet salida = \"\";\n\tlet cursor = 0;\n\tfor (const h of hallazgos) {\n\t\tif (h.hasta <= cursor) continue;\n\t\tconst desde = Math.max(h.desde, cursor);\n\t\tsalida += texto.slice(cursor, desde) + BLOQUE.repeat(h.hasta - desde);\n\t\tcursor = h.hasta;\n\t}\n\treturn salida + texto.slice(cursor);\n}\n"]}