@reticlehq/server 2.1.0 → 2.2.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 (436) hide show
  1. package/LICENSE-ENTERPRISE +37 -0
  2. package/README.md +5 -1
  3. package/dist/bridge-security.d.ts +1 -1
  4. package/dist/bridge-security.js +1 -1
  5. package/dist/bridge.d.ts +7 -0
  6. package/dist/bridge.d.ts.map +1 -1
  7. package/dist/bridge.js +22 -3
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/bridge.test-harness.d.ts +5 -0
  10. package/dist/bridge.test-harness.d.ts.map +1 -1
  11. package/dist/bridge.test-harness.js +4 -0
  12. package/dist/bridge.test-harness.js.map +1 -1
  13. package/dist/capsule/capsule-store.d.ts +66 -0
  14. package/dist/capsule/capsule-store.d.ts.map +1 -0
  15. package/dist/capsule/capsule-store.js +110 -0
  16. package/dist/capsule/capsule-store.js.map +1 -0
  17. package/dist/capsule/capsule.d.ts +19 -0
  18. package/dist/capsule/capsule.d.ts.map +1 -0
  19. package/dist/capsule/capsule.js +36 -0
  20. package/dist/capsule/capsule.js.map +1 -0
  21. package/dist/capsule/causal-summary.d.ts +36 -0
  22. package/dist/capsule/causal-summary.d.ts.map +1 -0
  23. package/dist/capsule/causal-summary.js +111 -0
  24. package/dist/capsule/causal-summary.js.map +1 -0
  25. package/dist/capsule/divergence.d.ts +31 -0
  26. package/dist/capsule/divergence.d.ts.map +1 -0
  27. package/dist/capsule/divergence.js +41 -0
  28. package/dist/capsule/divergence.js.map +1 -0
  29. package/dist/capsule/minimize.d.ts +13 -0
  30. package/dist/capsule/minimize.d.ts.map +1 -0
  31. package/dist/capsule/minimize.js +23 -0
  32. package/dist/capsule/minimize.js.map +1 -0
  33. package/dist/capsule/predicate-to-links.d.ts +9 -0
  34. package/dist/capsule/predicate-to-links.d.ts.map +1 -0
  35. package/dist/capsule/predicate-to-links.js +31 -0
  36. package/dist/capsule/predicate-to-links.js.map +1 -0
  37. package/dist/cli-flow-commands.d.ts +31 -0
  38. package/dist/cli-flow-commands.d.ts.map +1 -0
  39. package/dist/cli-flow-commands.js +207 -0
  40. package/dist/cli-flow-commands.js.map +1 -0
  41. package/dist/cli-parse.d.ts +18 -2
  42. package/dist/cli-parse.d.ts.map +1 -1
  43. package/dist/cli-parse.js +57 -0
  44. package/dist/cli-parse.js.map +1 -1
  45. package/dist/cli-port.d.ts +10 -4
  46. package/dist/cli-port.d.ts.map +1 -1
  47. package/dist/cli-port.js +32 -6
  48. package/dist/cli-port.js.map +1 -1
  49. package/dist/cli-verify.d.ts.map +1 -1
  50. package/dist/cli-verify.js +29 -10
  51. package/dist/cli-verify.js.map +1 -1
  52. package/dist/cli.d.ts.map +1 -1
  53. package/dist/cli.js +81 -2
  54. package/dist/cli.js.map +1 -1
  55. package/dist/crawl/crawl-tools.d.ts.map +1 -1
  56. package/dist/crawl/crawl-tools.js +12 -0
  57. package/dist/crawl/crawl-tools.js.map +1 -1
  58. package/dist/crawl/crawl.d.ts +23 -1
  59. package/dist/crawl/crawl.d.ts.map +1 -1
  60. package/dist/crawl/crawl.js +36 -9
  61. package/dist/crawl/crawl.js.map +1 -1
  62. package/dist/daemon-resilience.d.ts +5 -5
  63. package/dist/daemon-resilience.js +5 -5
  64. package/dist/daemon.d.ts +1 -1
  65. package/dist/daemon.js +1 -1
  66. package/dist/domain/domain-tools.d.ts.map +1 -1
  67. package/dist/domain/domain-tools.js +11 -1
  68. package/dist/domain/domain-tools.js.map +1 -1
  69. package/dist/domain/flow-risk.d.ts +4 -4
  70. package/dist/domain/flow-risk.js +4 -4
  71. package/dist/ee/audit-log.d.ts +2 -2
  72. package/dist/ee/audit-log.js +2 -2
  73. package/dist/events/event-filters.d.ts +29 -1
  74. package/dist/events/event-filters.d.ts.map +1 -1
  75. package/dist/events/event-filters.js +75 -1
  76. package/dist/events/event-filters.js.map +1 -1
  77. package/dist/events/predicate-eval.d.ts +15 -0
  78. package/dist/events/predicate-eval.d.ts.map +1 -1
  79. package/dist/events/predicate-eval.js +97 -18
  80. package/dist/events/predicate-eval.js.map +1 -1
  81. package/dist/events/predicate.d.ts +22 -1
  82. package/dist/events/predicate.d.ts.map +1 -1
  83. package/dist/events/predicate.js +154 -20
  84. package/dist/events/predicate.js.map +1 -1
  85. package/dist/events/ring-buffer.d.ts +3 -3
  86. package/dist/events/ring-buffer.d.ts.map +1 -1
  87. package/dist/events/ring-buffer.js +54 -8
  88. package/dist/events/ring-buffer.js.map +1 -1
  89. package/dist/flows/affected.d.ts +25 -0
  90. package/dist/flows/affected.d.ts.map +1 -0
  91. package/dist/flows/affected.js +36 -0
  92. package/dist/flows/affected.js.map +1 -0
  93. package/dist/flows/annotate.d.ts +4 -4
  94. package/dist/flows/annotate.js +4 -4
  95. package/dist/flows/assertion-integrity.d.ts +24 -0
  96. package/dist/flows/assertion-integrity.d.ts.map +1 -0
  97. package/dist/flows/assertion-integrity.js +27 -0
  98. package/dist/flows/assertion-integrity.js.map +1 -0
  99. package/dist/flows/assertion-tiers-store.d.ts +80 -0
  100. package/dist/flows/assertion-tiers-store.d.ts.map +1 -0
  101. package/dist/flows/assertion-tiers-store.js +99 -0
  102. package/dist/flows/assertion-tiers-store.js.map +1 -0
  103. package/dist/flows/buddy-status.d.ts +25 -0
  104. package/dist/flows/buddy-status.d.ts.map +1 -0
  105. package/dist/flows/buddy-status.js +33 -0
  106. package/dist/flows/buddy-status.js.map +1 -0
  107. package/dist/flows/coverage.d.ts +28 -0
  108. package/dist/flows/coverage.d.ts.map +1 -0
  109. package/dist/flows/coverage.js +22 -0
  110. package/dist/flows/coverage.js.map +1 -0
  111. package/dist/flows/decision.d.ts.map +1 -1
  112. package/dist/flows/decision.js +16 -8
  113. package/dist/flows/decision.js.map +1 -1
  114. package/dist/flows/flake-store.d.ts +20 -0
  115. package/dist/flows/flake-store.d.ts.map +1 -0
  116. package/dist/flows/flake-store.js +59 -0
  117. package/dist/flows/flake-store.js.map +1 -0
  118. package/dist/flows/flake.d.ts +58 -0
  119. package/dist/flows/flake.d.ts.map +1 -0
  120. package/dist/flows/flake.js +36 -0
  121. package/dist/flows/flake.js.map +1 -0
  122. package/dist/flows/flow-classify.d.ts +8 -8
  123. package/dist/flows/flow-classify.js +8 -8
  124. package/dist/flows/flow-replay-run.d.ts.map +1 -1
  125. package/dist/flows/flow-replay-run.js +36 -0
  126. package/dist/flows/flow-replay-run.js.map +1 -1
  127. package/dist/flows/flow-replay.d.ts +9 -0
  128. package/dist/flows/flow-replay.d.ts.map +1 -1
  129. package/dist/flows/flow-replay.js +48 -13
  130. package/dist/flows/flow-replay.js.map +1 -1
  131. package/dist/flows/flow-report.d.ts +4 -4
  132. package/dist/flows/flow-sources.d.ts +20 -0
  133. package/dist/flows/flow-sources.d.ts.map +1 -0
  134. package/dist/flows/flow-sources.js +33 -0
  135. package/dist/flows/flow-sources.js.map +1 -0
  136. package/dist/flows/flow-tools.d.ts +13 -1
  137. package/dist/flows/flow-tools.d.ts.map +1 -1
  138. package/dist/flows/flow-tools.js +92 -5
  139. package/dist/flows/flow-tools.js.map +1 -1
  140. package/dist/flows/flows.d.ts +9 -4
  141. package/dist/flows/flows.d.ts.map +1 -1
  142. package/dist/flows/flows.js +38 -21
  143. package/dist/flows/flows.js.map +1 -1
  144. package/dist/flows/gate.d.ts +39 -0
  145. package/dist/flows/gate.d.ts.map +1 -0
  146. package/dist/flows/gate.js +34 -0
  147. package/dist/flows/gate.js.map +1 -0
  148. package/dist/flows/git-changed.d.ts +9 -0
  149. package/dist/flows/git-changed.d.ts.map +1 -0
  150. package/dist/flows/git-changed.js +25 -0
  151. package/dist/flows/git-changed.js.map +1 -0
  152. package/dist/flows/heal-run.d.ts +1 -1
  153. package/dist/flows/heal-run.js +1 -1
  154. package/dist/flows/parallel-suite.d.ts +27 -0
  155. package/dist/flows/parallel-suite.d.ts.map +1 -0
  156. package/dist/flows/parallel-suite.js +51 -0
  157. package/dist/flows/parallel-suite.js.map +1 -0
  158. package/dist/flows/replay.d.ts.map +1 -1
  159. package/dist/flows/replay.js +33 -11
  160. package/dist/flows/replay.js.map +1 -1
  161. package/dist/flows/watch-batcher.d.ts +18 -0
  162. package/dist/flows/watch-batcher.d.ts.map +1 -0
  163. package/dist/flows/watch-batcher.js +20 -0
  164. package/dist/flows/watch-batcher.js.map +1 -0
  165. package/dist/honesty/blind-spots.d.ts +37 -0
  166. package/dist/honesty/blind-spots.d.ts.map +1 -0
  167. package/dist/honesty/blind-spots.js +57 -0
  168. package/dist/honesty/blind-spots.js.map +1 -0
  169. package/dist/honesty/honesty.d.ts +57 -0
  170. package/dist/honesty/honesty.d.ts.map +1 -0
  171. package/dist/honesty/honesty.js +63 -0
  172. package/dist/honesty/honesty.js.map +1 -0
  173. package/dist/http-server.d.ts +5 -5
  174. package/dist/http-server.js +4 -4
  175. package/dist/idle-shutdown.d.ts +2 -2
  176. package/dist/idle-shutdown.js +2 -2
  177. package/dist/index.d.ts +3 -2
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +98 -13
  180. package/dist/index.js.map +1 -1
  181. package/dist/init/agent-rules.d.ts +38 -0
  182. package/dist/init/agent-rules.d.ts.map +1 -0
  183. package/dist/init/agent-rules.js +65 -0
  184. package/dist/init/agent-rules.js.map +1 -0
  185. package/dist/init/plan.d.ts +6 -0
  186. package/dist/init/plan.d.ts.map +1 -1
  187. package/dist/init/plan.js +79 -3
  188. package/dist/init/plan.js.map +1 -1
  189. package/dist/init/run.d.ts.map +1 -1
  190. package/dist/init/run.js +4 -0
  191. package/dist/init/run.js.map +1 -1
  192. package/dist/init/snippets.js +1 -1
  193. package/dist/init/vite-config.d.ts +1 -1
  194. package/dist/init/vite-config.js +2 -2
  195. package/dist/init/vite-config.js.map +1 -1
  196. package/dist/input/network-detail.d.ts +74 -0
  197. package/dist/input/network-detail.d.ts.map +1 -0
  198. package/dist/input/network-detail.js +160 -0
  199. package/dist/input/network-detail.js.map +1 -0
  200. package/dist/input/network-mock.d.ts +4 -4
  201. package/dist/input/real-input.d.ts +44 -11
  202. package/dist/input/real-input.d.ts.map +1 -1
  203. package/dist/input/real-input.js +57 -9
  204. package/dist/input/real-input.js.map +1 -1
  205. package/dist/journal/ambient-store.d.ts +16 -0
  206. package/dist/journal/ambient-store.d.ts.map +1 -0
  207. package/dist/journal/ambient-store.js +46 -0
  208. package/dist/journal/ambient-store.js.map +1 -0
  209. package/dist/journal/ambient.d.ts +48 -0
  210. package/dist/journal/ambient.d.ts.map +1 -0
  211. package/dist/journal/ambient.js +48 -0
  212. package/dist/journal/ambient.js.map +1 -0
  213. package/dist/journal/attach-journal.d.ts +22 -0
  214. package/dist/journal/attach-journal.d.ts.map +1 -0
  215. package/dist/journal/attach-journal.js +20 -0
  216. package/dist/journal/attach-journal.js.map +1 -0
  217. package/dist/journal/deviation-report.d.ts +28 -0
  218. package/dist/journal/deviation-report.d.ts.map +1 -0
  219. package/dist/journal/deviation-report.js +54 -0
  220. package/dist/journal/deviation-report.js.map +1 -0
  221. package/dist/journal/deviation-service.d.ts +12 -0
  222. package/dist/journal/deviation-service.d.ts.map +1 -0
  223. package/dist/journal/deviation-service.js +32 -0
  224. package/dist/journal/deviation-service.js.map +1 -0
  225. package/dist/journal/envelope-store.d.ts +19 -0
  226. package/dist/journal/envelope-store.d.ts.map +1 -0
  227. package/dist/journal/envelope-store.js +62 -0
  228. package/dist/journal/envelope-store.js.map +1 -0
  229. package/dist/journal/envelope.d.ts +232 -0
  230. package/dist/journal/envelope.d.ts.map +1 -0
  231. package/dist/journal/envelope.js +94 -0
  232. package/dist/journal/envelope.js.map +1 -0
  233. package/dist/journal/journal-query.d.ts +20 -0
  234. package/dist/journal/journal-query.d.ts.map +1 -0
  235. package/dist/journal/journal-query.js +28 -0
  236. package/dist/journal/journal-query.js.map +1 -0
  237. package/dist/journal/journal-recorder.d.ts +38 -0
  238. package/dist/journal/journal-recorder.d.ts.map +1 -0
  239. package/dist/journal/journal-recorder.js +81 -0
  240. package/dist/journal/journal-recorder.js.map +1 -0
  241. package/dist/journal/retention.d.ts +21 -0
  242. package/dist/journal/retention.d.ts.map +1 -0
  243. package/dist/journal/retention.js +50 -0
  244. package/dist/journal/retention.js.map +1 -0
  245. package/dist/journal/rollups.d.ts +49 -0
  246. package/dist/journal/rollups.d.ts.map +1 -0
  247. package/dist/journal/rollups.js +83 -0
  248. package/dist/journal/rollups.js.map +1 -0
  249. package/dist/journal/session-end.d.ts +32 -0
  250. package/dist/journal/session-end.d.ts.map +1 -0
  251. package/dist/journal/session-end.js +52 -0
  252. package/dist/journal/session-end.js.map +1 -0
  253. package/dist/journal/session-journal.d.ts +25 -0
  254. package/dist/journal/session-journal.d.ts.map +1 -0
  255. package/dist/journal/session-journal.js +168 -0
  256. package/dist/journal/session-journal.js.map +1 -0
  257. package/dist/license/license.d.ts +8 -3
  258. package/dist/license/license.d.ts.map +1 -1
  259. package/dist/license/license.js +34 -11
  260. package/dist/license/license.js.map +1 -1
  261. package/dist/mcp-proxy.d.ts +20 -0
  262. package/dist/mcp-proxy.d.ts.map +1 -1
  263. package/dist/mcp-proxy.js +45 -27
  264. package/dist/mcp-proxy.js.map +1 -1
  265. package/dist/mcp.d.ts +14 -0
  266. package/dist/mcp.d.ts.map +1 -1
  267. package/dist/mcp.js +79 -9
  268. package/dist/mcp.js.map +1 -1
  269. package/dist/oracles/flow-instrument-gaps.d.ts +19 -0
  270. package/dist/oracles/flow-instrument-gaps.d.ts.map +1 -0
  271. package/dist/oracles/flow-instrument-gaps.js +45 -0
  272. package/dist/oracles/flow-instrument-gaps.js.map +1 -0
  273. package/dist/oracles/propose-consequences.d.ts +22 -0
  274. package/dist/oracles/propose-consequences.d.ts.map +1 -0
  275. package/dist/oracles/propose-consequences.js +93 -0
  276. package/dist/oracles/propose-consequences.js.map +1 -0
  277. package/dist/oracles/self-instrument.d.ts +32 -0
  278. package/dist/oracles/self-instrument.d.ts.map +1 -0
  279. package/dist/oracles/self-instrument.js +44 -0
  280. package/dist/oracles/self-instrument.js.map +1 -0
  281. package/dist/pairing-token.d.ts +1 -1
  282. package/dist/phenomena/phenomena.d.ts +27 -0
  283. package/dist/phenomena/phenomena.d.ts.map +1 -0
  284. package/dist/phenomena/phenomena.js +102 -0
  285. package/dist/phenomena/phenomena.js.map +1 -0
  286. package/dist/pool/browser-pool.d.ts +5 -3
  287. package/dist/pool/browser-pool.d.ts.map +1 -1
  288. package/dist/pool/browser-pool.js +21 -3
  289. package/dist/pool/browser-pool.js.map +1 -1
  290. package/dist/pool/playwright-launcher.d.ts.map +1 -1
  291. package/dist/pool/playwright-launcher.js +9 -2
  292. package/dist/pool/playwright-launcher.js.map +1 -1
  293. package/dist/project/file-lock.d.ts +2 -0
  294. package/dist/project/file-lock.d.ts.map +1 -0
  295. package/dist/project/file-lock.js +24 -0
  296. package/dist/project/file-lock.js.map +1 -0
  297. package/dist/project/fs-port.d.ts +18 -0
  298. package/dist/project/fs-port.d.ts.map +1 -1
  299. package/dist/project/fs-port.js +24 -2
  300. package/dist/project/fs-port.js.map +1 -1
  301. package/dist/project/project-store.d.ts.map +1 -1
  302. package/dist/project/project-store.js +13 -7
  303. package/dist/project/project-store.js.map +1 -1
  304. package/dist/project/project-tools.d.ts +0 -6
  305. package/dist/project/project-tools.d.ts.map +1 -1
  306. package/dist/project/project-tools.js +24 -1
  307. package/dist/project/project-tools.js.map +1 -1
  308. package/dist/project/reticle-dir.d.ts +39 -14
  309. package/dist/project/reticle-dir.d.ts.map +1 -1
  310. package/dist/project/reticle-dir.js +30 -4
  311. package/dist/project/reticle-dir.js.map +1 -1
  312. package/dist/runs/build-verification-run.d.ts +1 -1
  313. package/dist/runs/build-verification-run.js +1 -1
  314. package/dist/runs/repair-prompt.d.ts +2 -0
  315. package/dist/runs/repair-prompt.d.ts.map +1 -1
  316. package/dist/runs/repair-prompt.js +14 -1
  317. package/dist/runs/repair-prompt.js.map +1 -1
  318. package/dist/runs/reticle-runner.d.ts +1 -1
  319. package/dist/runs/reticle-runner.d.ts.map +1 -1
  320. package/dist/runs/run-diff.d.ts +34 -0
  321. package/dist/runs/run-diff.d.ts.map +1 -0
  322. package/dist/runs/run-diff.js +71 -0
  323. package/dist/runs/run-diff.js.map +1 -0
  324. package/dist/runs/run-store.d.ts +6 -1
  325. package/dist/runs/run-store.d.ts.map +1 -1
  326. package/dist/runs/run-store.js +22 -2
  327. package/dist/runs/run-store.js.map +1 -1
  328. package/dist/runs/run-tools.d.ts.map +1 -1
  329. package/dist/runs/run-tools.js +16 -3
  330. package/dist/runs/run-tools.js.map +1 -1
  331. package/dist/runs/verify-server.js +1 -1
  332. package/dist/runs/verify-server.js.map +1 -1
  333. package/dist/session/control-envelope.d.ts +9 -1
  334. package/dist/session/control-envelope.d.ts.map +1 -1
  335. package/dist/session/control-envelope.js +13 -1
  336. package/dist/session/control-envelope.js.map +1 -1
  337. package/dist/session/live-control-tools.d.ts +1 -1
  338. package/dist/session/live-control-tools.js +1 -1
  339. package/dist/session/live-control.d.ts +38 -0
  340. package/dist/session/live-control.d.ts.map +1 -0
  341. package/dist/session/live-control.js +64 -0
  342. package/dist/session/live-control.js.map +1 -0
  343. package/dist/session/observed-state.d.ts +46 -0
  344. package/dist/session/observed-state.d.ts.map +1 -0
  345. package/dist/session/observed-state.js +76 -0
  346. package/dist/session/observed-state.js.map +1 -0
  347. package/dist/session/output-budget.d.ts +9 -0
  348. package/dist/session/output-budget.d.ts.map +1 -1
  349. package/dist/session/output-budget.js +9 -0
  350. package/dist/session/output-budget.js.map +1 -1
  351. package/dist/session/review-store.d.ts +1 -1
  352. package/dist/session/review-store.d.ts.map +1 -1
  353. package/dist/session/review-store.js +2 -2
  354. package/dist/session/review-store.js.map +1 -1
  355. package/dist/session/session-manager.d.ts +9 -7
  356. package/dist/session/session-manager.d.ts.map +1 -1
  357. package/dist/session/session-manager.js +8 -8
  358. package/dist/session/session-manager.js.map +1 -1
  359. package/dist/session/session-readiness.js +1 -1
  360. package/dist/session/session-readiness.js.map +1 -1
  361. package/dist/session/session-reaper.d.ts +1 -1
  362. package/dist/session/session-reaper.js +1 -1
  363. package/dist/session/session-recommendation.d.ts +1 -1
  364. package/dist/session/session-recommendation.js +1 -1
  365. package/dist/session/session-tools.js +1 -1
  366. package/dist/session/session-tools.js.map +1 -1
  367. package/dist/session/session.d.ts +43 -11
  368. package/dist/session/session.d.ts.map +1 -1
  369. package/dist/session/session.js +115 -46
  370. package/dist/session/session.js.map +1 -1
  371. package/dist/tools/act-tools.d.ts.map +1 -1
  372. package/dist/tools/act-tools.js +252 -70
  373. package/dist/tools/act-tools.js.map +1 -1
  374. package/dist/tools/act-view.d.ts +4 -4
  375. package/dist/tools/act-view.js +4 -4
  376. package/dist/tools/browser-tools.d.ts.map +1 -1
  377. package/dist/tools/browser-tools.js +32 -8
  378. package/dist/tools/browser-tools.js.map +1 -1
  379. package/dist/tools/contract-tools.d.ts.map +1 -1
  380. package/dist/tools/contract-tools.js +5 -0
  381. package/dist/tools/contract-tools.js.map +1 -1
  382. package/dist/tools/dynamic-tools.d.ts.map +1 -1
  383. package/dist/tools/dynamic-tools.js +7 -6
  384. package/dist/tools/dynamic-tools.js.map +1 -1
  385. package/dist/tools/invoke-tool.d.ts.map +1 -1
  386. package/dist/tools/invoke-tool.js +32 -29
  387. package/dist/tools/invoke-tool.js.map +1 -1
  388. package/dist/tools/lease-tools.d.ts +16 -0
  389. package/dist/tools/lease-tools.d.ts.map +1 -1
  390. package/dist/tools/lease-tools.js +11 -0
  391. package/dist/tools/lease-tools.js.map +1 -1
  392. package/dist/tools/merge-tools.d.ts +43 -0
  393. package/dist/tools/merge-tools.d.ts.map +1 -0
  394. package/dist/tools/merge-tools.js +66 -0
  395. package/dist/tools/merge-tools.js.map +1 -0
  396. package/dist/tools/observe-tools.d.ts.map +1 -1
  397. package/dist/tools/observe-tools.js +172 -29
  398. package/dist/tools/observe-tools.js.map +1 -1
  399. package/dist/tools/profiles.d.ts +18 -13
  400. package/dist/tools/profiles.d.ts.map +1 -1
  401. package/dist/tools/profiles.js +39 -33
  402. package/dist/tools/profiles.js.map +1 -1
  403. package/dist/tools/query-paginate.d.ts +9 -2
  404. package/dist/tools/query-paginate.d.ts.map +1 -1
  405. package/dist/tools/query-paginate.js +21 -4
  406. package/dist/tools/query-paginate.js.map +1 -1
  407. package/dist/tools/read-tools.d.ts.map +1 -1
  408. package/dist/tools/read-tools.js +30 -1
  409. package/dist/tools/read-tools.js.map +1 -1
  410. package/dist/tools/snapshot-delta.d.ts +2 -0
  411. package/dist/tools/snapshot-delta.d.ts.map +1 -1
  412. package/dist/tools/snapshot-delta.js +0 -0
  413. package/dist/tools/snapshot-delta.js.map +1 -1
  414. package/dist/tools/tool-kit.d.ts +3 -2
  415. package/dist/tools/tool-kit.d.ts.map +1 -1
  416. package/dist/tools/tool-kit.js +11 -1
  417. package/dist/tools/tool-kit.js.map +1 -1
  418. package/dist/tools/tool-names.d.ts +18 -10
  419. package/dist/tools/tool-names.d.ts.map +1 -1
  420. package/dist/tools/tool-names.js +22 -13
  421. package/dist/tools/tool-names.js.map +1 -1
  422. package/dist/tools/tools-helpers.d.ts +12 -0
  423. package/dist/tools/tools-helpers.d.ts.map +1 -1
  424. package/dist/tools/tools-helpers.js +20 -0
  425. package/dist/tools/tools-helpers.js.map +1 -1
  426. package/dist/tools/tools.d.ts.map +1 -1
  427. package/dist/tools/tools.js +162 -12
  428. package/dist/tools/tools.js.map +1 -1
  429. package/dist/update/updater.d.ts +1 -1
  430. package/dist/update/updater.js +2 -2
  431. package/dist/update/updater.js.map +1 -1
  432. package/package.json +8 -3
  433. package/dist/update/update-tools.d.ts +0 -3
  434. package/dist/update/update-tools.d.ts.map +0 -1
  435. package/dist/update/update-tools.js +0 -94
  436. package/dist/update/update-tools.js.map +0 -1
@@ -0,0 +1,81 @@
1
+ import { EventAttribution, JOURNAL_FILE_VERSION, } from '@reticlehq/core';
2
+ const DEFAULT_FLUSH_AT = 64;
3
+ /**
4
+ * Owns action-window attribution and batched, order-preserving journaling — the durable half of the
5
+ * causal spine, kept out of Session so neither file bloats. Every stamped event is `observe`d: if an
6
+ * action is active (dispatch→settle), the event is attributed to it (`attribution:"window"` — a time
7
+ * heuristic, never presented as dataflow truth) and its seq folds into the action's range. Writes are
8
+ * serialized on one chain so `events.jsonl` never interleaves and an action is always persisted after
9
+ * the events it closed. Sink writes are best-effort: a failed local journal write must never break the
10
+ * live session, so errors are swallowed.
11
+ */
12
+ export class JournalRecorder {
13
+ #sink;
14
+ #now;
15
+ #flushAt;
16
+ #pending = [];
17
+ #active;
18
+ #chain = Promise.resolve();
19
+ constructor(sink, options) {
20
+ this.#sink = sink;
21
+ this.#now = options.now;
22
+ this.#flushAt = options.flushAt ?? DEFAULT_FLUSH_AT;
23
+ }
24
+ /** Attribute (if an action is active), enqueue for journaling, and return the possibly-stamped event. */
25
+ observe(event) {
26
+ let out = event;
27
+ const active = this.#active;
28
+ if (active !== undefined) {
29
+ out = { ...event, actionId: active.actionId, attribution: EventAttribution.WINDOW };
30
+ if (typeof event.seq === 'number') {
31
+ active.seqFrom =
32
+ active.seqFrom === undefined ? event.seq : Math.min(active.seqFrom, event.seq);
33
+ active.seqTo = active.seqTo === undefined ? event.seq : Math.max(active.seqTo, event.seq);
34
+ }
35
+ }
36
+ this.#pending.push(out);
37
+ if (this.#pending.length >= this.#flushAt)
38
+ this.#enqueueFlush();
39
+ return out;
40
+ }
41
+ /** Open an attribution window. One action is active at a time (the agent drives sequentially). */
42
+ beginAction(actionId, tool, args) {
43
+ this.#active = { actionId, tool, args, tStart: this.#now() };
44
+ }
45
+ /** Close the active window: persist its buffered events, then the action record. No-op if none active. */
46
+ finishAction(effect, settled, settledInMs) {
47
+ const active = this.#active;
48
+ if (active === undefined)
49
+ return;
50
+ this.#active = undefined;
51
+ const action = {
52
+ v: JOURNAL_FILE_VERSION,
53
+ actionId: active.actionId,
54
+ tool: active.tool,
55
+ args: active.args,
56
+ effect,
57
+ settled,
58
+ settledInMs,
59
+ seqRange: active.seqFrom === undefined || active.seqTo === undefined
60
+ ? undefined
61
+ : { from: active.seqFrom, to: active.seqTo },
62
+ tRange: { from: active.tStart, to: this.#now() },
63
+ at: active.tStart,
64
+ };
65
+ this.#enqueueFlush();
66
+ this.#chain = this.#chain.then(() => this.#sink.appendAction(action)).catch(() => undefined);
67
+ }
68
+ /** Persist any buffered events now (call on session end). Awaits the write chain to settle. */
69
+ async flush() {
70
+ this.#enqueueFlush();
71
+ await this.#chain;
72
+ }
73
+ #enqueueFlush() {
74
+ if (this.#pending.length === 0)
75
+ return;
76
+ const batch = this.#pending;
77
+ this.#pending = [];
78
+ this.#chain = this.#chain.then(() => this.#sink.appendEvents(batch)).catch(() => undefined);
79
+ }
80
+ }
81
+ //# sourceMappingURL=journal-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-recorder.js","sourceRoot":"","sources":["../../src/journal/journal-recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { FileSystemPort } from '../project/fs-port.js';
2
+ /** Keep at most this many session journals on disk; older ones are pruned by recency. */
3
+ export declare const DEFAULT_SESSION_RETENTION = 20;
4
+ interface DatedDir {
5
+ name: string;
6
+ mtimeMs: number;
7
+ }
8
+ /**
9
+ * Pure: given session dirs with their mtimes, the names to remove so only the `retention` most-recent
10
+ * remain. Oldest-first. Exported for testing (no IO).
11
+ */
12
+ export declare function selectPrunable(dirs: readonly DatedDir[], retention: number): string[];
13
+ /**
14
+ * Bound the journal on disk: keep the `retention` most-recent session directories under
15
+ * `.reticle/sessions/`, remove the rest by mtime. Never throws — retention is best-effort maintenance,
16
+ * so a stat/rm failure on one dir (or a missing sessions/ dir) is swallowed, never crashing a session.
17
+ * Mirrors RunStore's amortized pruning; run on daemon start.
18
+ */
19
+ export declare function pruneSessions(fs: FileSystemPort, root: string, retention?: number): Promise<void>;
20
+ export {};
21
+ //# sourceMappingURL=retention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/journal/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAMrF;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAkC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAwBf"}
@@ -0,0 +1,50 @@
1
+ import { reticleDirPaths, sessionDirPath } from '../project/reticle-dir.js';
2
+ /** Keep at most this many session journals on disk; older ones are pruned by recency. */
3
+ export const DEFAULT_SESSION_RETENTION = 20;
4
+ /**
5
+ * Pure: given session dirs with their mtimes, the names to remove so only the `retention` most-recent
6
+ * remain. Oldest-first. Exported for testing (no IO).
7
+ */
8
+ export function selectPrunable(dirs, retention) {
9
+ if (dirs.length <= retention)
10
+ return [];
11
+ return [...dirs]
12
+ .sort((a, b) => a.mtimeMs - b.mtimeMs)
13
+ .slice(0, dirs.length - retention)
14
+ .map((d) => d.name);
15
+ }
16
+ /**
17
+ * Bound the journal on disk: keep the `retention` most-recent session directories under
18
+ * `.reticle/sessions/`, remove the rest by mtime. Never throws — retention is best-effort maintenance,
19
+ * so a stat/rm failure on one dir (or a missing sessions/ dir) is swallowed, never crashing a session.
20
+ * Mirrors RunStore's amortized pruning; run on daemon start.
21
+ */
22
+ export async function pruneSessions(fs, root, retention = DEFAULT_SESSION_RETENTION) {
23
+ const sessionsDir = reticleDirPaths(root).sessions;
24
+ let names;
25
+ try {
26
+ names = await fs.readdir(sessionsDir);
27
+ }
28
+ catch {
29
+ return; // no sessions dir yet
30
+ }
31
+ const dated = [];
32
+ for (const name of names) {
33
+ try {
34
+ const { mtimeMs } = await fs.stat(sessionDirPath(root, name));
35
+ dated.push({ name, mtimeMs });
36
+ }
37
+ catch {
38
+ /* unstattable entry — skip */
39
+ }
40
+ }
41
+ for (const name of selectPrunable(dated, retention)) {
42
+ try {
43
+ await fs.rm(sessionDirPath(root, name));
44
+ }
45
+ catch {
46
+ /* best-effort */
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=retention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/journal/retention.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE5E,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAO5C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAyB,EAAE,SAAiB;IACzE,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,CAAC,GAAG,IAAI,CAAC;SACb,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;SACrC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAkB,EAClB,IAAY,EACZ,YAAoB,yBAAyB;IAE7C,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;IACnD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,sBAAsB;IAChC,CAAC;IACD,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { type ReticleEvent } from '@reticlehq/core';
2
+ /**
3
+ * A route-segment rollup: what happened between two ROUTE_CHANGE events. Aggregated, not raw — the
4
+ * unit the deviation report compares against an expected envelope. Computed by folding the
5
+ * journal's events; per the plan's risk note this runs lazily on query rather than threading a
6
+ * stateful accumulator through the hot write path.
7
+ */
8
+ export interface SegmentRollup {
9
+ /** The route (pathname) this segment is on, from its opening ROUTE_CHANGE. Absent for the first. */
10
+ route?: string;
11
+ /** Elapsed-ms of the first and last event in the segment. */
12
+ from: number;
13
+ to: number;
14
+ /** Wall span of the segment (to - from). */
15
+ durationMs: number;
16
+ /** Distinct attributed actions observed in the segment. */
17
+ actions: number;
18
+ /** Network request totals and error count (status >= 400 or ok === false). */
19
+ net: {
20
+ total: number;
21
+ errors: number;
22
+ };
23
+ /** console.error + uncaught errors/rejections. */
24
+ consoleErrors: number;
25
+ /** Unique state-change paths touched, in first-seen order. */
26
+ statePathsChanged: string[];
27
+ /**
28
+ * WS/SSE frame activity in the segment — on a stream-first app the network story IS the stream story.
29
+ * Directions: opens (connections), in (server→client), out (client→server). Absent when no streams.
30
+ */
31
+ streams?: {
32
+ frames: number;
33
+ opened: number;
34
+ in: number;
35
+ out: number;
36
+ };
37
+ /**
38
+ * True when a cap dropped events in this segment (a TRUNCATED or transport-overflow event landed in
39
+ * it). The segment's counts UNDERSTATE reality — the deviation judge must not read a nominal count as
40
+ * proof, and the envelope should not learn from a truncated sample.
41
+ */
42
+ truncated?: boolean;
43
+ }
44
+ /**
45
+ * Fold an ordered event list into route segments split at each ROUTE_CHANGE. Pure: no clock, no IO —
46
+ * the events carry their own `t`. The events must be in journal order (seq/t ascending).
47
+ */
48
+ export declare function computeSegments(events: readonly ReticleEvent[]): SegmentRollup[];
49
+ //# sourceMappingURL=rollups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollups.d.ts","sourceRoot":"","sources":["../../src/journal/rollups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,oGAAoG;IACpG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA0CD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,aAAa,EAAE,CAmDhF"}
@@ -0,0 +1,83 @@
1
+ import { EventType } from '@reticlehq/core';
2
+ function finalize(acc) {
3
+ return {
4
+ ...(acc.route === undefined ? {} : { route: acc.route }),
5
+ from: acc.from,
6
+ to: acc.to,
7
+ durationMs: acc.to - acc.from,
8
+ actions: acc.actionIds.size,
9
+ net: { total: acc.netTotal, errors: acc.netErrors },
10
+ consoleErrors: acc.consoleErrors,
11
+ statePathsChanged: acc.statePaths,
12
+ ...(acc.streams.frames === 0 ? {} : { streams: acc.streams }),
13
+ ...(acc.truncated ? { truncated: true } : {}),
14
+ };
15
+ }
16
+ function isNetError(event) {
17
+ const status = event.data['status'];
18
+ return event.data['ok'] === false || (typeof status === 'number' && status >= 400);
19
+ }
20
+ /**
21
+ * Fold an ordered event list into route segments split at each ROUTE_CHANGE. Pure: no clock, no IO —
22
+ * the events carry their own `t`. The events must be in journal order (seq/t ascending).
23
+ */
24
+ export function computeSegments(events) {
25
+ const segments = [];
26
+ let acc;
27
+ const open = (route, t) => ({
28
+ ...(route === undefined ? {} : { route }),
29
+ from: t,
30
+ to: t,
31
+ actionIds: new Set(),
32
+ netTotal: 0,
33
+ netErrors: 0,
34
+ consoleErrors: 0,
35
+ statePaths: [],
36
+ streams: { frames: 0, opened: 0, in: 0, out: 0 },
37
+ truncated: false,
38
+ });
39
+ for (const event of events) {
40
+ if (event.type === EventType.ROUTE_CHANGE) {
41
+ if (acc !== undefined)
42
+ segments.push(finalize(acc));
43
+ const pathname = event.data['pathname'];
44
+ acc = open(typeof pathname === 'string' ? pathname : undefined, event.t);
45
+ continue;
46
+ }
47
+ if (acc === undefined)
48
+ acc = open(undefined, event.t);
49
+ acc.to = event.t;
50
+ if (typeof event.actionId === 'string')
51
+ acc.actionIds.add(event.actionId);
52
+ if (event.type === EventType.NET_REQUEST) {
53
+ acc.netTotal += 1;
54
+ if (isNetError(event))
55
+ acc.netErrors += 1;
56
+ }
57
+ if (event.type === EventType.CONSOLE_ERROR || event.type === EventType.ERROR_UNCAUGHT) {
58
+ acc.consoleErrors += 1;
59
+ }
60
+ if (event.type === EventType.STATE_CHANGE) {
61
+ const name = event.data['name'];
62
+ if (typeof name === 'string' && !acc.statePaths.includes(name))
63
+ acc.statePaths.push(name);
64
+ }
65
+ if (event.type === EventType.NET_STREAM) {
66
+ acc.streams.frames += 1;
67
+ const direction = event.data['direction'];
68
+ if (direction === 'open')
69
+ acc.streams.opened += 1;
70
+ else if (direction === 'in')
71
+ acc.streams.in += 1;
72
+ else if (direction === 'out')
73
+ acc.streams.out += 1;
74
+ }
75
+ if (event.type === EventType.TRUNCATED || event.type === EventType.TRANSPORT_OVERFLOW) {
76
+ acc.truncated = true;
77
+ }
78
+ }
79
+ if (acc !== undefined)
80
+ segments.push(finalize(acc));
81
+ return segments;
82
+ }
83
+ //# sourceMappingURL=rollups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollups.js","sourceRoot":"","sources":["../../src/journal/rollups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { AmbientCounts } from './ambient.js';
2
+ import type { FileSystemPort } from '../project/fs-port.js';
3
+ /**
4
+ * Session teardown: the durable half of ending a session. Two things must happen when a tab disconnects,
5
+ * and neither did before — the journal batches events and only writes at its flush threshold, so the tail
6
+ * of every session (< one batch) was silently lost from disk, and the learned ambient map was never
7
+ * persisted at all, so every session re-learned the page's churn from zero.
8
+ *
9
+ * Both are best-effort: a teardown failure must never surface as a session error (the tab is already gone).
10
+ */
11
+ /** The minimal Session surface teardown needs (Session satisfies it structurally). */
12
+ export interface SessionEndTarget {
13
+ readonly id: string;
14
+ /** Write any batched journal events to disk. */
15
+ flushJournal(): Promise<void>;
16
+ /** The ambient-churn counts learned during this session. */
17
+ ambientCounts(): AmbientCounts;
18
+ ownAmbientCounts(): AmbientCounts;
19
+ }
20
+ export interface SessionEndDeps {
21
+ fs: FileSystemPort;
22
+ reticleRoot: string;
23
+ /** Journaling/persistence off (opt-out) → teardown is a no-op. */
24
+ enabled: boolean;
25
+ }
26
+ /**
27
+ * Build the teardown handler the bridge fires when a session is removed. Flushes the journal first (so no
28
+ * evidence is lost), then folds this session's ambient counts into the persisted map so the NEXT session
29
+ * starts already knowing which regions churn.
30
+ */
31
+ export declare function makeSessionEnd(deps: SessionEndDeps): (session: SessionEndTarget) => Promise<void>;
32
+ //# sourceMappingURL=session-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.d.ts","sourceRoot":"","sources":["../../src/journal/session-end.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D;;;;;;;GAOG;AAEH,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,4DAA4D;IAC5D,aAAa,IAAI,aAAa,CAAC;IAC/B,gBAAgB,IAAI,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,cAAc,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAuCjG"}
@@ -0,0 +1,52 @@
1
+ import { AmbientStore } from './ambient-store.js';
2
+ import { pruneSessions } from './retention.js';
3
+ /**
4
+ * Build the teardown handler the bridge fires when a session is removed. Flushes the journal first (so no
5
+ * evidence is lost), then folds this session's ambient counts into the persisted map so the NEXT session
6
+ * starts already knowing which regions churn.
7
+ */
8
+ export function makeSessionEnd(deps) {
9
+ return async (session) => {
10
+ if (!deps.enabled)
11
+ return;
12
+ try {
13
+ await session.flushJournal();
14
+ }
15
+ catch {
16
+ // a failed flush must not block ambient persistence, and must never throw at teardown
17
+ }
18
+ try {
19
+ const store = new AmbientStore(deps.fs, deps.reticleRoot);
20
+ const persisted = await store.load();
21
+ // Accumulate history + what is NEW. `ownAmbientCounts` excludes the map this session was
22
+ // seeded from at startup; `ambientCounts` includes it, and adding that onto `persisted` wrote
23
+ // `2 x persisted + own` on every teardown — a doubling per session that had driven the
24
+ // committed map to ~9.1e23.
25
+ const merged = { ...persisted };
26
+ for (const [ref, count] of Object.entries(session.ownAmbientCounts())) {
27
+ merged[ref] = (merged[ref] ?? 0) + count;
28
+ }
29
+ await store.save(merged);
30
+ }
31
+ catch {
32
+ // ambient learning is an optimization; a disk failure never breaks teardown
33
+ }
34
+ try {
35
+ // Bound the journal on disk HERE, not only at daemon start.
36
+ //
37
+ // Pruning ran exactly once, during wiring. A daemon that stays up — which is the normal case for
38
+ // a dev session, and the whole point of the pool — therefore never pruned again, so session
39
+ // directories accumulated without bound for as long as it lived. Session end is the right moment
40
+ // because it is precisely when a new directory has just been created, which makes this amortized
41
+ // rather than periodic (no timer to leak) and mirrors what RunStore already does.
42
+ //
43
+ // Safe against deleting the session that just ended: pruning selects the OLDEST by mtime, and the
44
+ // directory written moments ago is the newest.
45
+ await pruneSessions(deps.fs, deps.reticleRoot);
46
+ }
47
+ catch {
48
+ // retention is best-effort maintenance; never surface at teardown
49
+ }
50
+ };
51
+ }
52
+ //# sourceMappingURL=session-end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.js","sourceRoot":"","sources":["../../src/journal/session-end.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AA4B/C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAoB;IACjD,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;QACxF,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1D,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACrC,yFAAyF;YACzF,8FAA8F;YAC9F,uFAAuF;YACvF,4BAA4B;YAC5B,MAAM,MAAM,GAAkB,EAAE,GAAG,SAAS,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,EAAE,CAAC;gBACtE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC;YAC3C,CAAC;YACD,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,4EAA4E;QAC9E,CAAC;QACD,IAAI,CAAC;YACH,4DAA4D;YAC5D,EAAE;YACF,iGAAiG;YACjG,4FAA4F;YAC5F,iGAAiG;YACjG,iGAAiG;YACjG,kFAAkF;YAClF,EAAE;YACF,kGAAkG;YAClG,+CAA+C;YAC/C,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type JournalAction, type ReticleEvent } from '@reticlehq/core';
2
+ import type { FileSystemPort } from '../project/fs-port.js';
3
+ /**
4
+ * The durable per-session journal: append-only JSONL for events and actions, the ledger the ring
5
+ * buffer becomes a hot cache over. Writes are batched (the caller flushes ring-buffer windows), so a
6
+ * batch is one syscall — not one per event. Reads never throw: a missing file is `[]`, a malformed or
7
+ * schema-invalid line is skipped, matching the never-throw discipline of the run store.
8
+ *
9
+ * Events are already browser-edge-redacted (network/storage/DOM) before they reach the wire, so the
10
+ * journal stores redacted payloads; the ledger is local-only. A server-side second-pass event redactor
11
+ * is defense-in-depth for a later commit, not a correctness gate here.
12
+ *
13
+ * ponytail: append-per-batch, no retention yet. Bounded-disk pruning (cap session dirs / file size,
14
+ * "pruned like runs/") is a dedicated follow-up — see the build ledger. Perf ceiling: if the <3%
15
+ * main-thread overhead budget is threatened at high event rates, coalesce batches behind a flush timer.
16
+ */
17
+ export declare class SessionJournal {
18
+ #private;
19
+ constructor(fs: FileSystemPort, root: string, sessionId: string);
20
+ appendEvents(events: readonly ReticleEvent[]): Promise<void>;
21
+ appendAction(action: JournalAction): Promise<void>;
22
+ readEvents(): Promise<ReticleEvent[]>;
23
+ readActions(): Promise<JournalAction[]>;
24
+ }
25
+ //# sourceMappingURL=session-journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-journal.d.ts","sourceRoot":"","sources":["../../src/journal/session-journal.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;;gBAeb,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IASzD,YAAY,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5D,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlD,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA0ErC,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAiC9C"}
@@ -0,0 +1,168 @@
1
+ import { JournalActionSchema, ReticleEventSchema, } from '@reticlehq/core';
2
+ import { isValidSessionId, journalActionsPath, journalEventsPath, sessionDirPath, } from '../project/reticle-dir.js';
3
+ /**
4
+ * The durable per-session journal: append-only JSONL for events and actions, the ledger the ring
5
+ * buffer becomes a hot cache over. Writes are batched (the caller flushes ring-buffer windows), so a
6
+ * batch is one syscall — not one per event. Reads never throw: a missing file is `[]`, a malformed or
7
+ * schema-invalid line is skipped, matching the never-throw discipline of the run store.
8
+ *
9
+ * Events are already browser-edge-redacted (network/storage/DOM) before they reach the wire, so the
10
+ * journal stores redacted payloads; the ledger is local-only. A server-side second-pass event redactor
11
+ * is defense-in-depth for a later commit, not a correctness gate here.
12
+ *
13
+ * ponytail: append-per-batch, no retention yet. Bounded-disk pruning (cap session dirs / file size,
14
+ * "pruned like runs/") is a dedicated follow-up — see the build ledger. Perf ceiling: if the <3%
15
+ * main-thread overhead budget is threatened at high event rates, coalesce batches behind a flush timer.
16
+ */
17
+ export class SessionJournal {
18
+ #fs;
19
+ #root;
20
+ #sessionId;
21
+ #dirEnsured = false;
22
+ // Parse-cache for the append-only EVENTS journal. queryEvents falls through to readEvents on every
23
+ // observe/network/console call once the ring buffer has evicted (permanent ~60s into any session), so
24
+ // a naive readEvents re-read + re-JSON.parse + re-zod-validated the WHOLE file each time — measured at
25
+ // a 1-hour 100 ev/s session as ~1.5s CPU + ~300MB transient heap PER tool call, growing with age. The
26
+ // journal only ever grows and is always a run of complete '\n'-terminated lines, so we keep the parsed
27
+ // events and the char count already consumed, and parse only the tail written since the last read.
28
+ #eventCache;
29
+ #eventCharsConsumed = 0; // fallback (whole-file) path: UTF-16 code units consumed
30
+ #eventBytesConsumed = 0; // fast (bounded-read) path: UTF-8 bytes consumed, always at a '\n' boundary
31
+ constructor(fs, root, sessionId) {
32
+ if (!isValidSessionId(sessionId)) {
33
+ throw new Error(`refusing to journal an unsafe session id: ${sessionId}`);
34
+ }
35
+ this.#fs = fs;
36
+ this.#root = root;
37
+ this.#sessionId = sessionId;
38
+ }
39
+ async appendEvents(events) {
40
+ if (events.length === 0)
41
+ return;
42
+ await this.#ensureDir();
43
+ const text = `${events.map((e) => JSON.stringify(e)).join('\n')}\n`;
44
+ await this.#fs.appendFile(journalEventsPath(this.#root, this.#sessionId), text);
45
+ }
46
+ async appendAction(action) {
47
+ await this.#ensureDir();
48
+ await this.#fs.appendFile(journalActionsPath(this.#root, this.#sessionId), `${JSON.stringify(action)}\n`);
49
+ }
50
+ async readEvents() {
51
+ const path = journalEventsPath(this.#root, this.#sessionId);
52
+ if (this.#eventCache === undefined)
53
+ this.#eventCache = [];
54
+ // Fast path: read only the BYTES appended since the last read, so cost tracks the tail, not the
55
+ // whole (unboundedly growing) file. Falls back to a whole-file read for a FileSystemPort that omits
56
+ // readFileFrom (test stubs).
57
+ const readFrom = this.#fs.readFileFrom?.bind(this.#fs);
58
+ if (readFrom !== undefined) {
59
+ let chunk;
60
+ try {
61
+ chunk = await readFrom(path, this.#eventBytesConsumed);
62
+ }
63
+ catch (error) {
64
+ if (this.#fs.isNotFound(error))
65
+ return this.#eventCache.slice();
66
+ throw error;
67
+ }
68
+ // Shrink/rotation guard (not done today): if the file is smaller than what we consumed, the offset
69
+ // is meaningless — reset and re-read from 0.
70
+ if (chunk.size < this.#eventBytesConsumed) {
71
+ this.#eventCache = [];
72
+ this.#eventBytesConsumed = 0;
73
+ chunk = await readFrom(path, 0);
74
+ }
75
+ this.#eventBytesConsumed += this.#ingestTail(chunk.text);
76
+ return this.#eventCache.slice();
77
+ }
78
+ let text;
79
+ try {
80
+ text = await this.#fs.readFile(path);
81
+ }
82
+ catch (error) {
83
+ if (this.#fs.isNotFound(error))
84
+ return this.#eventCache.slice();
85
+ throw error;
86
+ }
87
+ // Fallback (whole-file) path: #eventCharsConsumed is a UTF-16 offset into the whole text. Shrink
88
+ // guard, then ingest the un-consumed tail up to its last newline (see #ingestTail for the
89
+ // partial-line rationale).
90
+ if (text.length < this.#eventCharsConsumed) {
91
+ this.#eventCache = [];
92
+ this.#eventCharsConsumed = 0;
93
+ }
94
+ const end = text.lastIndexOf('\n') + 1;
95
+ if (end > this.#eventCharsConsumed) {
96
+ this.#ingestTail(text.slice(this.#eventCharsConsumed, end));
97
+ this.#eventCharsConsumed = end;
98
+ }
99
+ return this.#eventCache.slice();
100
+ }
101
+ /**
102
+ * Parse complete ('\n'-terminated) JSON event lines from `tail` into #eventCache, stopping at the LAST
103
+ * newline. A concurrent append can be observed mid-record (reads and writes run on separate libuv
104
+ * threads), and consuming a partial trailing line would splice its tail onto the next read's head, fail
105
+ * to parse, and drop that event forever — so the partial tail is left for the next read. Returns the
106
+ * UTF-8 BYTES consumed, which the bounded-read path uses to advance its byte offset.
107
+ */
108
+ #ingestTail(tail) {
109
+ const cache = this.#eventCache ?? (this.#eventCache = []);
110
+ const end = tail.lastIndexOf('\n') + 1;
111
+ if (end === 0)
112
+ return 0; // no complete line yet
113
+ const complete = tail.slice(0, end);
114
+ for (const line of complete.split('\n')) {
115
+ if (line.length === 0)
116
+ continue;
117
+ let parsed;
118
+ try {
119
+ parsed = JSON.parse(line);
120
+ }
121
+ catch {
122
+ continue;
123
+ }
124
+ const result = ReticleEventSchema.safeParse(parsed);
125
+ if (result.success)
126
+ cache.push(result.data);
127
+ }
128
+ return Buffer.byteLength(complete, 'utf8');
129
+ }
130
+ async readActions() {
131
+ return this.#readLines(journalActionsPath(this.#root, this.#sessionId), JournalActionSchema);
132
+ }
133
+ async #ensureDir() {
134
+ if (this.#dirEnsured)
135
+ return;
136
+ await this.#fs.mkdir(sessionDirPath(this.#root, this.#sessionId));
137
+ this.#dirEnsured = true;
138
+ }
139
+ async #readLines(path, schema) {
140
+ let text;
141
+ try {
142
+ text = await this.#fs.readFile(path);
143
+ }
144
+ catch (error) {
145
+ if (this.#fs.isNotFound(error))
146
+ return [];
147
+ throw error;
148
+ }
149
+ const out = [];
150
+ for (const line of text.split('\n')) {
151
+ if (line.length === 0)
152
+ continue;
153
+ let parsed;
154
+ try {
155
+ parsed = JSON.parse(line);
156
+ }
157
+ catch {
158
+ continue;
159
+ }
160
+ const result = schema.safeParse(parsed);
161
+ // Validated at this boundary; ZodTypeAny widens `.data` to any, so re-narrow to the schema output.
162
+ if (result.success)
163
+ out.push(result.data);
164
+ }
165
+ return out;
166
+ }
167
+ }
168
+ //# sourceMappingURL=session-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-journal.js","sourceRoot":"","sources":["../../src/journal/session-journal.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Enterprise license-key verification + the assertEnterprise gate. ENTERPRISE CODE (Reticle Enterprise
3
- * License — see ./LICENSE), not the FSL that covers the rest of the server.
3
+ * License — see./LICENSE), not the FSL that covers the rest of the server.
4
4
  *
5
5
  * Offline + no phone-home (preserves the no-telemetry brand): a key is a signed payload Reticle issues
6
6
  * with its private key; this verifies it against the issuer's PUBLIC key with Ed25519. Dev/eval is a
@@ -100,8 +100,13 @@ interface LicenseReport {
100
100
  */
101
101
  export declare function describeLicense(now: number, env?: NodeJS.ProcessEnv, baked?: string): LicenseReport;
102
102
  /**
103
- * Gate an enterprise feature using env-resolved activation. Enforcement is ON only when the issuer
104
- * public key is configured (i.e. a real release); without it (dev/repo) features run free in eval mode.
103
+ * Gate an enterprise feature using env-resolved activation. Enforcement is ON when the issuer public key
104
+ * is configured (a real release). Without it, behaviour splits on runtime:
105
+ * - dev/eval (NODE_ENV ≠ production): features run FREE — never blocks a contributor or CI.
106
+ * - production (NODE_ENV = production): FAIL CLOSED — a release that reaches production with no
107
+ * resolvable issuer key was mis-built (the baked key wasn't stamped in, BAKED_ISSUER_PUBLIC_KEY_PEM
108
+ * is still ''), and silently unlocking every ee feature with no key and no warning is the worst
109
+ * outcome. Deny instead, with a distinct reason so the misconfiguration is obvious.
105
110
  */
106
111
  export declare function assertEnterpriseFromEnv(feature: string, now: number, env?: NodeJS.ProcessEnv, baked?: string): void;
107
112
  export {};