@north-light/cli 0.3.530 → 0.3.532

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 (495) hide show
  1. package/dist/clients/attach/session/connection.js +1 -1
  2. package/dist/clients/attach/session/reconnect.js +1 -1
  3. package/dist/clients/attach/viewer.js +508 -508
  4. package/dist/core/async-array.d.ts +7 -0
  5. package/dist/core/async-array.js +1 -0
  6. package/dist/core/audit.d.ts +1 -1
  7. package/dist/core/audit.js +2 -2
  8. package/dist/core/canvas/attention.d.ts +4 -4
  9. package/dist/core/canvas/attention.js +1 -1
  10. package/dist/core/canvas/boot.d.ts +4 -4
  11. package/dist/core/canvas/boot.js +1 -1
  12. package/dist/core/canvas/canvas.d.ts +59 -59
  13. package/dist/core/canvas/canvas.js +19 -19
  14. package/dist/core/canvas/context-strip.js +2 -2
  15. package/dist/core/canvas/crons.d.ts +27 -27
  16. package/dist/core/canvas/crons.js +11 -11
  17. package/dist/core/canvas/daemon-actions.d.ts +10 -10
  18. package/dist/core/canvas/daemon-actions.js +8 -8
  19. package/dist/core/canvas/daemon-owner.d.ts +3 -3
  20. package/dist/core/canvas/daemon-owner.js +2 -2
  21. package/dist/core/canvas/db.d.ts +19 -30
  22. package/dist/core/canvas/db.js +3 -2
  23. package/dist/core/canvas/deliveries.d.ts +16 -16
  24. package/dist/core/canvas/deliveries.js +24 -24
  25. package/dist/core/canvas/executions.d.ts +8 -8
  26. package/dist/core/canvas/executions.js +1 -1
  27. package/dist/core/canvas/focuses.d.ts +8 -8
  28. package/dist/core/canvas/focuses.js +1 -1
  29. package/dist/core/canvas/history.d.ts +3 -3
  30. package/dist/core/canvas/history.js +9 -9
  31. package/dist/core/canvas/install-id.d.ts +1 -1
  32. package/dist/core/canvas/install-id.js +1 -1
  33. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
  34. package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
  35. package/dist/core/canvas/memory-reads.d.ts +6 -6
  36. package/dist/core/canvas/memory-reads.js +1 -1
  37. package/dist/core/canvas/nav-model.d.ts +13 -13
  38. package/dist/core/canvas/nav-model.js +1 -1
  39. package/dist/core/canvas/node-agent-paths.d.ts +6 -6
  40. package/dist/core/canvas/node-agent-paths.js +1 -1
  41. package/dist/core/canvas/node-tokens.d.ts +7 -7
  42. package/dist/core/canvas/node-tokens.js +3 -3
  43. package/dist/core/canvas/outcome-actions.d.ts +5 -5
  44. package/dist/core/canvas/outcome-actions.js +3 -3
  45. package/dist/core/canvas/recovery.d.ts +26 -26
  46. package/dist/core/canvas/recovery.js +2 -2
  47. package/dist/core/canvas/render-source.d.ts +1 -1
  48. package/dist/core/canvas/render-source.js +1 -1
  49. package/dist/core/canvas/sessions.d.ts +10 -10
  50. package/dist/core/canvas/sessions.js +4 -4
  51. package/dist/core/canvas/source.js +1 -1
  52. package/dist/core/canvas/structured-requests.d.ts +15 -15
  53. package/dist/core/canvas/structured-requests.js +5 -5
  54. package/dist/core/canvas/tree.d.ts +9 -9
  55. package/dist/core/canvas/tree.js +5 -5
  56. package/dist/core/canvas/waits.d.ts +13 -13
  57. package/dist/core/canvas/waits.js +6 -6
  58. package/dist/core/canvas/worktrees.d.ts +15 -15
  59. package/dist/core/canvas/worktrees.js +1 -1
  60. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  61. package/dist/core/conversation-store/file-store.d.ts +7 -7
  62. package/dist/core/conversation-store/file-store.js +9 -9
  63. package/dist/core/conversation-store/index.d.ts +16 -14
  64. package/dist/core/conversation-store/index.js +1 -1
  65. package/dist/core/conversation-store/listener.js +5 -5
  66. package/dist/core/conversation-store/patch.d.ts +3 -1
  67. package/dist/core/conversation-store/patch.js +1 -1
  68. package/dist/core/feed/feed.js +3 -3
  69. package/dist/core/feed/inbox.d.ts +2 -2
  70. package/dist/core/feed/inbox.js +1 -1
  71. package/dist/core/feed/messages.d.ts +11 -12
  72. package/dist/core/feed/messages.js +5 -5
  73. package/dist/core/feed/reports.d.ts +4 -4
  74. package/dist/core/feed/reports.js +2 -2
  75. package/dist/core/grants/cover.d.ts +1 -1
  76. package/dist/core/grants/cover.js +1 -1
  77. package/dist/core/grants/local.d.ts +1 -1
  78. package/dist/core/grants/local.js +1 -1
  79. package/dist/core/grants/mirror.d.ts +19 -19
  80. package/dist/core/grants/mirror.js +2 -2
  81. package/dist/core/grants/on-sync.d.ts +1 -1
  82. package/dist/core/grants/on-sync.js +1 -1
  83. package/dist/core/grants/remove.js +1 -1
  84. package/dist/core/grants/sync.js +1 -1
  85. package/dist/core/graph/access.d.ts +17 -17
  86. package/dist/core/graph/access.js +3 -3
  87. package/dist/core/graph/custom.d.ts +16 -16
  88. package/dist/core/graph/custom.js +9 -9
  89. package/dist/core/graph/deletion.d.ts +3 -7
  90. package/dist/core/graph/deletion.js +4 -4
  91. package/dist/core/graph/documents.d.ts +24 -27
  92. package/dist/core/graph/documents.js +7 -7
  93. package/dist/core/graph/edges.d.ts +13 -13
  94. package/dist/core/graph/edges.js +1 -1
  95. package/dist/core/graph/events.d.ts +7 -9
  96. package/dist/core/graph/events.js +8 -8
  97. package/dist/core/graph/exposures.d.ts +6 -6
  98. package/dist/core/graph/exposures.js +4 -4
  99. package/dist/core/graph/jobs.d.ts +6 -8
  100. package/dist/core/graph/jobs.js +2 -2
  101. package/dist/core/graph/kinds/action.js +1 -1
  102. package/dist/core/graph/kinds/custom.js +2 -2
  103. package/dist/core/graph/kinds/document.d.ts +1 -0
  104. package/dist/core/graph/kinds/document.js +4 -4
  105. package/dist/core/graph/kinds/dto.d.ts +2 -2
  106. package/dist/core/graph/kinds/dto.js +1 -1
  107. package/dist/core/graph/kinds/job.js +2 -2
  108. package/dist/core/graph/kinds/kind.d.ts +6 -8
  109. package/dist/core/graph/kinds/kind.js +1 -1
  110. package/dist/core/graph/kinds/node.js +5 -5
  111. package/dist/core/graph/kinds/owner.js +2 -2
  112. package/dist/core/graph/kinds/registry.d.ts +6 -9
  113. package/dist/core/graph/kinds/registry.js +1 -1
  114. package/dist/core/graph/names.d.ts +6 -6
  115. package/dist/core/graph/names.js +3 -3
  116. package/dist/core/graph/object-waits.d.ts +4 -7
  117. package/dist/core/graph/object-waits.js +1 -1
  118. package/dist/core/graph/objects.d.ts +14 -14
  119. package/dist/core/graph/objects.js +9 -9
  120. package/dist/core/graph/package-docs.d.ts +2 -7
  121. package/dist/core/graph/package-docs.js +5 -5
  122. package/dist/core/graph/package-kinds.d.ts +2 -5
  123. package/dist/core/graph/package-kinds.js +1 -1
  124. package/dist/core/graph/package-reconcile.d.ts +2 -5
  125. package/dist/core/graph/package-reconcile.js +1 -1
  126. package/dist/core/graph/reader.d.ts +18 -18
  127. package/dist/core/graph/reader.js +3 -3
  128. package/dist/core/graph/receivers.d.ts +4 -4
  129. package/dist/core/graph/receivers.js +5 -5
  130. package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
  131. package/dist/core/graph/repo-sync/exchange.js +2 -2
  132. package/dist/core/graph/repo-sync/repos.d.ts +7 -5
  133. package/dist/core/graph/repo-sync/repos.js +3 -3
  134. package/dist/core/graph/repo-sync/sync.d.ts +3 -6
  135. package/dist/core/graph/repo-sync/sync.js +2 -2
  136. package/dist/core/graph/rules.d.ts +5 -5
  137. package/dist/core/graph/rules.js +3 -3
  138. package/dist/core/graph/spaces/app.js +1 -1
  139. package/dist/core/graph/spaces/index.d.ts +4 -5
  140. package/dist/core/graph/spaces/index.js +1 -1
  141. package/dist/core/graph/spaces/own-memory.d.ts +4 -4
  142. package/dist/core/graph/spaces/own-memory.js +1 -1
  143. package/dist/core/graph/spaces/person.js +3 -3
  144. package/dist/core/graph/spaces/repo.d.ts +1 -1
  145. package/dist/core/graph/spaces/repo.js +1 -1
  146. package/dist/core/graph/watches.d.ts +15 -15
  147. package/dist/core/graph/watches.js +10 -10
  148. package/dist/core/human/feedback-companion.d.ts +2 -2
  149. package/dist/core/human/feedback-companion.js +1 -1
  150. package/dist/core/human/feedback.d.ts +3 -3
  151. package/dist/core/human/feedback.js +1 -1
  152. package/dist/core/human/requests.d.ts +34 -33
  153. package/dist/core/human/requests.js +20 -20
  154. package/dist/core/human/scan.d.ts +2 -2
  155. package/dist/core/human/scan.js +1 -1
  156. package/dist/core/human/tickets.d.ts +9 -9
  157. package/dist/core/human/tickets.js +1 -1
  158. package/dist/core/llm/app-rungs.d.ts +1 -1
  159. package/dist/core/llm/app-rungs.js +1 -1
  160. package/dist/core/llm/run.js +2 -2
  161. package/dist/core/peer/directory.d.ts +1 -1
  162. package/dist/core/peer/directory.js +1 -1
  163. package/dist/core/peer/envelope.d.ts +3 -3
  164. package/dist/core/peer/envelope.js +1 -1
  165. package/dist/core/peer/home.d.ts +13 -7
  166. package/dist/core/peer/home.js +2 -2
  167. package/dist/core/peer/ingest.d.ts +6 -6
  168. package/dist/core/peer/ingest.js +1 -1
  169. package/dist/core/peer/outbox-store.d.ts +14 -14
  170. package/dist/core/peer/outbox-store.js +5 -5
  171. package/dist/core/peer/receiver.d.ts +2 -2
  172. package/dist/core/peer/receiver.js +1 -1
  173. package/dist/core/peer/stubs.d.ts +10 -10
  174. package/dist/core/peer/stubs.js +1 -1
  175. package/dist/core/providers/approval.d.ts +2 -2
  176. package/dist/core/providers/approval.js +2 -2
  177. package/dist/core/providers/audit.d.ts +3 -3
  178. package/dist/core/providers/audit.js +2 -2
  179. package/dist/core/providers/bundles.js +2 -2
  180. package/dist/core/providers/call.d.ts +2 -2
  181. package/dist/core/providers/call.js +1 -1
  182. package/dist/core/providers/files.d.ts +1 -1
  183. package/dist/core/providers/files.js +1 -1
  184. package/dist/core/providers/mint.js +1 -1
  185. package/dist/core/providers/receipts.d.ts +1 -1
  186. package/dist/core/providers/receipts.js +2 -2
  187. package/dist/core/review/birth.js +1 -1
  188. package/dist/core/review/comments.d.ts +19 -19
  189. package/dist/core/review/comments.js +5 -5
  190. package/dist/core/review/companion.d.ts +1 -1
  191. package/dist/core/review/companion.js +1 -1
  192. package/dist/core/review/document.d.ts +3 -3
  193. package/dist/core/review/document.js +2 -2
  194. package/dist/core/review/fork.js +2 -2
  195. package/dist/core/review/realize.js +1 -1
  196. package/dist/core/review/remap.d.ts +2 -2
  197. package/dist/core/review/remap.js +4 -4
  198. package/dist/core/review/stage.d.ts +1 -1
  199. package/dist/core/review/stage.js +1 -1
  200. package/dist/core/review/store.d.ts +21 -21
  201. package/dist/core/review/store.js +1 -1
  202. package/dist/core/runs/activity.d.ts +1 -1
  203. package/dist/core/runs/activity.js +5 -5
  204. package/dist/core/runs/confinement.d.ts +7 -7
  205. package/dist/core/runs/confinement.js +2 -2
  206. package/dist/core/runs/events.d.ts +12 -12
  207. package/dist/core/runs/events.js +4 -4
  208. package/dist/core/runs/operations.d.ts +11 -11
  209. package/dist/core/runs/operations.js +5 -5
  210. package/dist/core/runs/questions.d.ts +10 -10
  211. package/dist/core/runs/questions.js +3 -3
  212. package/dist/core/runtime/auth-reload.js +1 -1
  213. package/dist/core/runtime/bearings.d.ts +5 -5
  214. package/dist/core/runtime/bearings.js +6 -6
  215. package/dist/core/runtime/broker-inventory.js +1 -1
  216. package/dist/core/runtime/broker-request.js +1 -1
  217. package/dist/core/runtime/broker.js +1 -1
  218. package/dist/core/runtime/close.d.ts +3 -3
  219. package/dist/core/runtime/close.js +1 -1
  220. package/dist/core/runtime/deliver-live.js +1 -1
  221. package/dist/core/runtime/fleet.d.ts +2 -2
  222. package/dist/core/runtime/host.d.ts +3 -3
  223. package/dist/core/runtime/host.js +3 -3
  224. package/dist/core/runtime/kickoff.d.ts +12 -12
  225. package/dist/core/runtime/kickoff.js +17 -17
  226. package/dist/core/runtime/launch-target.d.ts +1 -1
  227. package/dist/core/runtime/launch-target.js +1 -1
  228. package/dist/core/runtime/ledger.d.ts +3 -3
  229. package/dist/core/runtime/ledger.js +3 -3
  230. package/dist/core/runtime/lifecycle.d.ts +1 -1
  231. package/dist/core/runtime/lifecycle.js +2 -2
  232. package/dist/core/runtime/memory-admission.js +1 -1
  233. package/dist/core/runtime/model-swap.d.ts +2 -2
  234. package/dist/core/runtime/model-swap.js +1 -1
  235. package/dist/core/runtime/node-read.d.ts +1 -1
  236. package/dist/core/runtime/node-read.js +2 -2
  237. package/dist/core/runtime/nodes.d.ts +6 -6
  238. package/dist/core/runtime/nodes.js +1 -1
  239. package/dist/core/runtime/outcome-document.d.ts +1 -1
  240. package/dist/core/runtime/outcome-document.js +1 -1
  241. package/dist/core/runtime/persona.d.ts +3 -3
  242. package/dist/core/runtime/persona.js +2 -2
  243. package/dist/core/runtime/placement.d.ts +11 -11
  244. package/dist/core/runtime/placement.js +1 -1
  245. package/dist/core/runtime/promote.d.ts +3 -3
  246. package/dist/core/runtime/promote.js +1 -1
  247. package/dist/core/runtime/recycle.js +1 -1
  248. package/dist/core/runtime/reopen.d.ts +5 -5
  249. package/dist/core/runtime/reopen.js +1 -1
  250. package/dist/core/runtime/reset.d.ts +4 -4
  251. package/dist/core/runtime/reset.js +1 -1
  252. package/dist/core/runtime/revive-all.d.ts +2 -2
  253. package/dist/core/runtime/revive-all.js +1 -1
  254. package/dist/core/runtime/revive.d.ts +4 -4
  255. package/dist/core/runtime/revive.js +2 -2
  256. package/dist/core/runtime/roadmap.d.ts +6 -6
  257. package/dist/core/runtime/roadmap.js +5 -5
  258. package/dist/core/runtime/session-branch.d.ts +1 -1
  259. package/dist/core/runtime/session-branch.js +1 -1
  260. package/dist/core/runtime/session-list-cache.js +1 -1
  261. package/dist/core/runtime/situational-live.js +1 -1
  262. package/dist/core/runtime/spawn.d.ts +2 -2
  263. package/dist/core/runtime/spawn.js +2 -2
  264. package/dist/core/runtime/stop-guard.d.ts +2 -2
  265. package/dist/core/runtime/stop-guard.js +3 -3
  266. package/dist/core/runtime/warm-pool.d.ts +2 -2
  267. package/dist/core/runtime/warm-pool.js +1 -1
  268. package/dist/core/spaces/mounts.d.ts +2 -2
  269. package/dist/core/spaces/mounts.js +1 -1
  270. package/dist/core/spaces/permissions.d.ts +1 -1
  271. package/dist/core/spaces/permissions.js +1 -1
  272. package/dist/core/spaces/process.d.ts +1 -1
  273. package/dist/core/spaces/process.js +1 -1
  274. package/dist/core/spaces/space.js +1 -1
  275. package/dist/core/spaces/stop.d.ts +3 -3
  276. package/dist/core/spaces/stop.js +2 -2
  277. package/dist/core/spaces/users.d.ts +6 -6
  278. package/dist/core/spaces/users.js +1 -1
  279. package/dist/core/storage/attachments.d.ts +2 -2
  280. package/dist/core/storage/attachments.js +1 -1
  281. package/dist/core/storage/shares.d.ts +2 -2
  282. package/dist/core/storage/shares.js +1 -1
  283. package/dist/core/storage/tables.d.ts +21 -21
  284. package/dist/core/storage/tables.js +3 -3
  285. package/dist/core/substrate/delivery/corpus.d.ts +5 -8
  286. package/dist/core/substrate/delivery/corpus.js +3 -3
  287. package/dist/core/substrate/delivery/deliver.d.ts +10 -15
  288. package/dist/core/substrate/delivery/deliver.js +3 -3
  289. package/dist/core/substrate/delivery/plan.d.ts +2 -12
  290. package/dist/core/substrate/delivery/plan.js +3 -3
  291. package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
  292. package/dist/core/substrate/delivery/render-boot.js +18 -18
  293. package/dist/core/substrate/delivery/render-event.d.ts +7 -14
  294. package/dist/core/substrate/delivery/render-event.js +4 -4
  295. package/dist/core/substrate/subject.d.ts +2 -2
  296. package/dist/core/substrate/subject.js +1 -1
  297. package/dist/core/usage/ledger.d.ts +6 -6
  298. package/dist/core/usage/ledger.js +4 -4
  299. package/dist/core/worktree-close.js +4 -4
  300. package/dist/core/worktree-mutation-async.js +7 -7
  301. package/dist/core/worktree-quarantine.js +1 -1
  302. package/dist/core/worktree-sweep.d.ts +1 -1
  303. package/dist/core/worktree-sweep.js +6 -6
  304. package/dist/core/worktree.d.ts +5 -5
  305. package/dist/core/worktree.js +13 -13
  306. package/dist/daemon/analytics/compute.d.ts +2 -2
  307. package/dist/daemon/analytics/compute.js +1 -1
  308. package/dist/daemon/api/app-listener.d.ts +4 -4
  309. package/dist/daemon/api/app-listener.js +13 -13
  310. package/dist/daemon/api/bridge.js +5 -5
  311. package/dist/daemon/api/document-listener.js +6 -6
  312. package/dist/daemon/api/handlers/analytics.js +1 -1
  313. package/dist/daemon/api/handlers/attach.js +1 -1
  314. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  315. package/dist/daemon/api/handlers/bash.js +1 -1
  316. package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
  317. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  318. package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
  319. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  320. package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
  321. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  322. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  323. package/dist/daemon/api/handlers/canvas.js +4 -4
  324. package/dist/daemon/api/handlers/chat-inventory.js +1 -1
  325. package/dist/daemon/api/handlers/crons.js +1 -1
  326. package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
  327. package/dist/daemon/api/handlers/custom-objects.js +3 -3
  328. package/dist/daemon/api/handlers/delivery-retry.js +1 -1
  329. package/dist/daemon/api/handlers/delivery.js +1 -1
  330. package/dist/daemon/api/handlers/docs.d.ts +4 -4
  331. package/dist/daemon/api/handlers/docs.js +1 -1
  332. package/dist/daemon/api/handlers/feedback-comments.js +3 -3
  333. package/dist/daemon/api/handlers/files.js +1 -1
  334. package/dist/daemon/api/handlers/focus.js +1 -1
  335. package/dist/daemon/api/handlers/health.js +3 -3
  336. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  337. package/dist/daemon/api/handlers/human-requests.js +1 -1
  338. package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
  339. package/dist/daemon/api/handlers/inbox-page.js +1 -1
  340. package/dist/daemon/api/handlers/inbox.d.ts +1 -1
  341. package/dist/daemon/api/handlers/inbox.js +1 -1
  342. package/dist/daemon/api/handlers/llm.d.ts +1 -1
  343. package/dist/daemon/api/handlers/llm.js +3 -3
  344. package/dist/daemon/api/handlers/memory-reads.js +1 -1
  345. package/dist/daemon/api/handlers/memory.d.ts +5 -5
  346. package/dist/daemon/api/handlers/memory.js +5 -5
  347. package/dist/daemon/api/handlers/messages.js +2 -2
  348. package/dist/daemon/api/handlers/node-events.d.ts +2 -2
  349. package/dist/daemon/api/handlers/node-events.js +3 -3
  350. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  351. package/dist/daemon/api/handlers/node-records.js +2 -2
  352. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  353. package/dist/daemon/api/handlers/nodes.js +1 -1
  354. package/dist/daemon/api/handlers/objects.js +3 -3
  355. package/dist/daemon/api/handlers/package-docs.js +1 -1
  356. package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
  357. package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
  358. package/dist/daemon/api/handlers/profiles.d.ts +3 -3
  359. package/dist/daemon/api/handlers/profiles.js +1 -1
  360. package/dist/daemon/api/handlers/providers.d.ts +1 -1
  361. package/dist/daemon/api/handlers/providers.js +1 -1
  362. package/dist/daemon/api/handlers/questions.js +1 -1
  363. package/dist/daemon/api/handlers/reports.d.ts +1 -1
  364. package/dist/daemon/api/handlers/reports.js +5 -5
  365. package/dist/daemon/api/handlers/review-comments.js +1 -1
  366. package/dist/daemon/api/handlers/reviews.js +1 -1
  367. package/dist/daemon/api/handlers/runs.js +1 -1
  368. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  369. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  370. package/dist/daemon/api/handlers/transfer.js +1 -1
  371. package/dist/daemon/api/map.d.ts +3 -3
  372. package/dist/daemon/api/map.js +1 -1
  373. package/dist/daemon/api/principal.d.ts +1 -1
  374. package/dist/daemon/api/principal.js +1 -1
  375. package/dist/daemon/api/reader.d.ts +5 -5
  376. package/dist/daemon/api/reader.js +1 -1
  377. package/dist/daemon/api/router.d.ts +5 -5
  378. package/dist/daemon/api/router.js +1 -1
  379. package/dist/daemon/api/server.js +1 -1
  380. package/dist/daemon/broker-signals/bus.d.ts +1 -1
  381. package/dist/daemon/broker-signals/bus.js +1 -1
  382. package/dist/daemon/companion-retire.js +1 -1
  383. package/dist/daemon/cron/armed-context.d.ts +2 -2
  384. package/dist/daemon/cron/armed-context.js +1 -1
  385. package/dist/daemon/cron/authority.d.ts +2 -2
  386. package/dist/daemon/cron/authority.js +1 -1
  387. package/dist/daemon/cron/disposition.js +1 -1
  388. package/dist/daemon/cron/ended.d.ts +1 -1
  389. package/dist/daemon/cron/ended.js +2 -2
  390. package/dist/daemon/cron/escalation.js +3 -3
  391. package/dist/daemon/cron/folders.d.ts +1 -1
  392. package/dist/daemon/cron/folders.js +1 -1
  393. package/dist/daemon/cron/held.d.ts +1 -1
  394. package/dist/daemon/cron/held.js +1 -1
  395. package/dist/daemon/cron/lease-recovery.d.ts +1 -1
  396. package/dist/daemon/cron/lease-recovery.js +1 -1
  397. package/dist/daemon/cron/passes.d.ts +2 -2
  398. package/dist/daemon/cron/passes.js +1 -1
  399. package/dist/daemon/cron/run-socket.d.ts +1 -1
  400. package/dist/daemon/cron/run-socket.js +1 -1
  401. package/dist/daemon/cron/settle.js +1 -1
  402. package/dist/daemon/cron/sinks.d.ts +1 -1
  403. package/dist/daemon/cron/sinks.js +2 -2
  404. package/dist/daemon/cron-run.d.ts +12 -3
  405. package/dist/daemon/cron-run.js +2 -2
  406. package/dist/daemon/crtrd.js +6 -6
  407. package/dist/daemon/delivery/run-delivery.js +1 -1
  408. package/dist/daemon/due-sources.d.ts +3 -3
  409. package/dist/daemon/due-sources.js +1 -1
  410. package/dist/daemon/due.d.ts +3 -3
  411. package/dist/daemon/due.js +7 -7
  412. package/dist/daemon/fleet.d.ts +2 -2
  413. package/dist/daemon/fleet.js +11 -11
  414. package/dist/daemon/human/finish.js +3 -3
  415. package/dist/daemon/human/settle.d.ts +1 -1
  416. package/dist/daemon/human/settle.js +1 -1
  417. package/dist/daemon/human/sweep.js +1 -1
  418. package/dist/daemon/joined-owner.d.ts +2 -2
  419. package/dist/daemon/joined-owner.js +1 -1
  420. package/dist/daemon/messaging/node-message.js +1 -1
  421. package/dist/daemon/park-activity.d.ts +2 -2
  422. package/dist/daemon/park-activity.js +1 -1
  423. package/dist/daemon/peer/authority.js +1 -1
  424. package/dist/daemon/peer/forward.d.ts +13 -6
  425. package/dist/daemon/peer/forward.js +1 -1
  426. package/dist/daemon/peer/handlers.js +1 -1
  427. package/dist/daemon/peer/ingress.d.ts +4 -4
  428. package/dist/daemon/peer/ingress.js +1 -1
  429. package/dist/daemon/peer/outbox.d.ts +2 -2
  430. package/dist/daemon/peer/outbox.js +1 -1
  431. package/dist/daemon/peer/relay-service.js +1 -1
  432. package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
  433. package/dist/daemon/plugin-objects/read-leaf.js +2 -2
  434. package/dist/daemon/profile-delete.js +1 -1
  435. package/dist/daemon/readiness.d.ts +2 -2
  436. package/dist/daemon/readiness.js +1 -1
  437. package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
  438. package/dist/daemon/reconcilers/action-lane.js +1 -1
  439. package/dist/daemon/reconcilers/bash-deadline.js +2 -2
  440. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  441. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  442. package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
  443. package/dist/daemon/reconcilers/controller-death.js +1 -1
  444. package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
  445. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  446. package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
  447. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  448. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
  449. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  450. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
  451. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  452. package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
  453. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  454. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  455. package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
  456. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  457. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  458. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
  459. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
  460. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
  461. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  462. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
  463. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  464. package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
  465. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  466. package/dist/daemon/reconcilers/storage-due-work.js +1 -1
  467. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
  468. package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
  469. package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
  470. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  471. package/dist/daemon/review/comment-notify.js +2 -2
  472. package/dist/daemon/review/companion.d.ts +3 -3
  473. package/dist/daemon/review/companion.js +1 -1
  474. package/dist/daemon/review/finish.js +1 -1
  475. package/dist/daemon/review/sweep.js +1 -1
  476. package/dist/daemon/run-notices.d.ts +4 -4
  477. package/dist/daemon/run-notices.js +1 -1
  478. package/dist/daemon/runs/append-section.d.ts +2 -2
  479. package/dist/daemon/runs/append-section.js +2 -2
  480. package/dist/daemon/runs/observer.d.ts +2 -2
  481. package/dist/daemon/runs/observer.js +2 -2
  482. package/dist/daemon/structured-requests/boot.d.ts +1 -1
  483. package/dist/daemon/structured-requests/boot.js +1 -1
  484. package/dist/daemon/structured-requests/effects.js +1 -1
  485. package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
  486. package/dist/daemon/structured-requests/sidecar.js +1 -1
  487. package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
  488. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  489. package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
  490. package/dist/migrations/004-canvas-documents/index.js +2 -2
  491. package/dist/migrations/activation.js +2 -2
  492. package/docs/public-api.md +11 -0
  493. package/package.json +3 -2
  494. package/packages/crouter-identity/package.json +1 -1
  495. package/runtime.lock.json +12 -12
@@ -14,8 +14,8 @@ type GroveExecution = {
14
14
  };
15
15
  export interface GroveInstanceSweepOperations {
16
16
  resolveBinary(): string | null;
17
- listTerminalNodes(): NodeRow[];
18
- getNodeRow(nodeId: string): NodeRow | null;
17
+ listTerminalNodes(): Promise<NodeRow[]>;
18
+ getNodeRow(nodeId: string): Promise<NodeRow | null>;
19
19
  execute(binary: string, args: readonly string[]): Promise<GroveExecution>;
20
20
  captureLiveness(): Promise<PsLivenessSnapshot | null>;
21
21
  }
@@ -1 +1 @@
1
- var A=Object.defineProperty;var l=(e,t)=>A(e,"name",{value:t,configurable:!0});import{spawn as S}from"node:child_process";import{statSync as I}from"node:fs";import{delimiter as T,join as j}from"node:path";import{getRow as G,listNodes as R}from"../../core/canvas/index.js";import{isSafeNodeId as w}from"../../core/canvas/paths.js";import{captureLivenessSnapshotAsync as b,recordedPidLiveness as x}from"../../core/canvas/pid.js";import{emitEvent as p}from"../../core/events/emit.js";import{operationIdContext as h}from"../../core/events/operation-id.js";import{isParked as C}from"../../core/runtime/lifecycle.js";const F=60*1e3,P=3,L=300*1e3,E=["done","dead","canceled"];function _(e){return E.includes(e.status)&&!C(e)}l(_,"isClosed");function M(){const e=process.env.PATH;if(e===void 0)return null;for(const t of e.split(T)){const i=j(t===""?process.cwd():t,"grove");try{const r=I(i);if(r.isFile()&&(r.mode&73)!==0)return i}catch{}}return null}l(M,"resolveGroveBinary");function O(e,t){return new Promise(i=>{let r;try{r=S(e,[...t],{stdio:["ignore","pipe","pipe"]})}catch(n){i({code:null,signal:null,stdout:"",stderr:"",error:n instanceof Error?n:new Error(String(n))});return}let a="",s="",c=!1;const u=l(n=>{c||(c=!0,i(n))},"settle");r.stdout.on("data",n=>{a+=n.toString()}),r.stderr.on("data",n=>{s+=n.toString()}),r.on("error",n=>u({code:null,signal:null,stdout:a,stderr:s,error:n})),r.on("close",(n,f)=>u({code:n,signal:f,stdout:a,stderr:s}))})}l(O,"executeGrove");const V={resolveBinary:M,listTerminalNodes:l(()=>R({status:[...E]}),"listTerminalNodes"),getNodeRow:G,execute:O,captureLiveness:b};function B(e){let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!="object"||t===null||!Array.isArray(t.projects))return null;const i=[];for(const r of t.projects){if(typeof r!="object"||r===null)continue;const a=r.name,s=r.instances;if(!(typeof a!="string"||!Array.isArray(s)))for(const c of s){if(typeof c!="object"||c===null)continue;const u=c.name,n=c.slot,f=c.spec?.labels,m=typeof f=="object"&&f!==null?f.owner:void 0;typeof u=="string"&&typeof n=="number"&&typeof m=="string"&&i.push({project:a,name:u,slot:n,owner:m})}}return i}l(B,"instancesFromInventory");function k(e,t,i){return _(e)&&!t.isClaimed(e.node_id)&&e.frozen_at===null&&x(e.pi_pid,e.pi_pid_identity,i)==="dead"}l(k,"engineIsGone");function D(e,t,i){if(t.isClaimed(e.node_id))return!1;const r=i(e.node_id);return r!==null&&_(r)&&r.frozen_at===null&&r.pi_pid===e.pi_pid&&r.pi_pid_identity===e.pi_pid_identity}l(D,"stillEligible");function N(e){if(e.error!==void 0)return e.error;const t=e.stderr.trim()||e.stdout.trim()||`Grove exited with ${e.signal??e.code??"an unknown status"}`;return new Error(t)}l(N,"executionError");function g(e){return`${e.project}/${e.name}`}l(g,"instanceKey");class X{static{l(this,"GroveInstanceSweepReconciler")}operations;lastSweepAt=Number.NEGATIVE_INFINITY;inFlight=!1;cursor=0;retryAfter=new Map;constructor(t=V){this.operations=t}run(t,i){if(this.inFlight||t-this.lastSweepAt<F||!i.lifecycle.acceptsDetachedWork())return;this.lastSweepAt=t,this.inFlight=!0;const r=Promise.resolve().then(()=>this.sweep(t,i.fleet)).finally(()=>{this.inFlight=!1});i.lifecycle.registerDetached(r)}async sweep(t,i){const r=this.operations.resolveBinary();if(r===null)return;let a;try{a=this.operations.listTerminalNodes().filter(_)}catch(o){h.fresh(()=>{p({level:"error",event:"grove.sweep.scan_failed",error:o})});return}if(a.length===0)return;const s=await this.operations.execute(r,["list","--json"]);if(s.error!==void 0||s.code!==0||s.signal!==null){h.fresh(()=>{p({level:"error",event:"grove.sweep.list_failed",error:N(s)})});return}const c=B(s.stdout);if(c===null){h.fresh(()=>{p({level:"error",event:"grove.sweep.list_failed",error:new Error("grove list --json returned invalid inventory JSON")})});return}const u=new Map(a.map(o=>[o.node_id,o])),n=c.filter(o=>u.get(o.owner)!==void 0&&(this.retryAfter.get(g(o))??Number.NEGATIVE_INFINITY)<=t).sort((o,d)=>o.project.localeCompare(d.project)||o.slot-d.slot||o.name.localeCompare(d.name));if(n.length===0)return;this.cursor>=n.length&&(this.cursor=0);const f=Math.min(P,n.length),m=Array.from({length:f},(o,d)=>n[(this.cursor+d)%n.length]);this.cursor=(this.cursor+f)%n.length;const v=await this.operations.captureLiveness();if(v!==null)for(const o of m){const d=u.get(o.owner);if(!k(d,i,v)||!D(d,i,this.operations.getNodeRow))continue;const y=await this.operations.execute(r,["uproot",g(o),"--force"]);if(y.error===void 0&&y.code===0&&y.signal===null){this.retryAfter.delete(g(o)),h.fresh(()=>{p({level:"info",event:"grove.sweep.reconciled",outcome:"succeeded",...w(o.owner)?{node_id:o.owner}:{fields:{affected_node_id:o.owner}}})});continue}this.retryAfter.set(g(o),t+L),h.fresh(()=>{p({level:"error",event:"grove.sweep.failed",outcome:"failed",...w(o.owner)?{node_id:o.owner}:{fields:{affected_node_id:o.owner}},error:N(y)})})}}}export{P as GROVE_INSTANCE_SWEEP_BUDGET,F as GROVE_INSTANCE_SWEEP_INTERVAL_MS,L as GROVE_INSTANCE_SWEEP_RETRY_DELAY_MS,X as GroveInstanceSweepReconciler};
1
+ var A=Object.defineProperty;var c=(e,t)=>A(e,"name",{value:t,configurable:!0});import{spawn as S}from"node:child_process";import{statSync as I}from"node:fs";import{delimiter as T,join as j}from"node:path";import{getRow as G,listNodes as R}from"../../core/canvas/index.js";import{isSafeNodeId as w}from"../../core/canvas/paths.js";import{captureLivenessSnapshotAsync as b,recordedPidLiveness as x}from"../../core/canvas/pid.js";import{emitEvent as p}from"../../core/events/emit.js";import{operationIdContext as h}from"../../core/events/operation-id.js";import{isParked as C}from"../../core/runtime/lifecycle.js";const F=60*1e3,P=3,L=300*1e3,E=["done","dead","canceled"];function _(e){return E.includes(e.status)&&!C(e)}c(_,"isClosed");function M(){const e=process.env.PATH;if(e===void 0)return null;for(const t of e.split(T)){const i=j(t===""?process.cwd():t,"grove");try{const r=I(i);if(r.isFile()&&(r.mode&73)!==0)return i}catch{}}return null}c(M,"resolveGroveBinary");function O(e,t){return new Promise(i=>{let r;try{r=S(e,[...t],{stdio:["ignore","pipe","pipe"]})}catch(n){i({code:null,signal:null,stdout:"",stderr:"",error:n instanceof Error?n:new Error(String(n))});return}let a="",s="",l=!1;const u=c(n=>{l||(l=!0,i(n))},"settle");r.stdout.on("data",n=>{a+=n.toString()}),r.stderr.on("data",n=>{s+=n.toString()}),r.on("error",n=>u({code:null,signal:null,stdout:a,stderr:s,error:n})),r.on("close",(n,f)=>u({code:n,signal:f,stdout:a,stderr:s}))})}c(O,"executeGrove");const V={resolveBinary:M,listTerminalNodes:c(async()=>await R({status:[...E]}),"listTerminalNodes"),getNodeRow:G,execute:O,captureLiveness:b};function B(e){let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!="object"||t===null||!Array.isArray(t.projects))return null;const i=[];for(const r of t.projects){if(typeof r!="object"||r===null)continue;const a=r.name,s=r.instances;if(!(typeof a!="string"||!Array.isArray(s)))for(const l of s){if(typeof l!="object"||l===null)continue;const u=l.name,n=l.slot,f=l.spec?.labels,m=typeof f=="object"&&f!==null?f.owner:void 0;typeof u=="string"&&typeof n=="number"&&typeof m=="string"&&i.push({project:a,name:u,slot:n,owner:m})}}return i}c(B,"instancesFromInventory");function k(e,t,i){return _(e)&&!t.isClaimed(e.node_id)&&e.frozen_at===null&&x(e.pi_pid,e.pi_pid_identity,i)==="dead"}c(k,"engineIsGone");async function D(e,t,i){if(t.isClaimed(e.node_id))return!1;const r=await i(e.node_id);return r!==null&&_(r)&&r.frozen_at===null&&r.pi_pid===e.pi_pid&&r.pi_pid_identity===e.pi_pid_identity}c(D,"stillEligible");function N(e){if(e.error!==void 0)return e.error;const t=e.stderr.trim()||e.stdout.trim()||`Grove exited with ${e.signal??e.code??"an unknown status"}`;return new Error(t)}c(N,"executionError");function g(e){return`${e.project}/${e.name}`}c(g,"instanceKey");class X{static{c(this,"GroveInstanceSweepReconciler")}operations;lastSweepAt=Number.NEGATIVE_INFINITY;inFlight=!1;cursor=0;retryAfter=new Map;constructor(t=V){this.operations=t}run(t,i){if(this.inFlight||t-this.lastSweepAt<F||!i.lifecycle.acceptsDetachedWork())return;this.lastSweepAt=t,this.inFlight=!0;const r=Promise.resolve().then(()=>this.sweep(t,i.fleet)).finally(()=>{this.inFlight=!1});i.lifecycle.registerDetached(r)}async sweep(t,i){const r=this.operations.resolveBinary();if(r===null)return;let a;try{a=(await this.operations.listTerminalNodes()).filter(_)}catch(o){h.fresh(()=>{p({level:"error",event:"grove.sweep.scan_failed",error:o})});return}if(a.length===0)return;const s=await this.operations.execute(r,["list","--json"]);if(s.error!==void 0||s.code!==0||s.signal!==null){h.fresh(()=>{p({level:"error",event:"grove.sweep.list_failed",error:N(s)})});return}const l=B(s.stdout);if(l===null){h.fresh(()=>{p({level:"error",event:"grove.sweep.list_failed",error:new Error("grove list --json returned invalid inventory JSON")})});return}const u=new Map(a.map(o=>[o.node_id,o])),n=l.filter(o=>u.get(o.owner)!==void 0&&(this.retryAfter.get(g(o))??Number.NEGATIVE_INFINITY)<=t).sort((o,d)=>o.project.localeCompare(d.project)||o.slot-d.slot||o.name.localeCompare(d.name));if(n.length===0)return;this.cursor>=n.length&&(this.cursor=0);const f=Math.min(P,n.length),m=Array.from({length:f},(o,d)=>n[(this.cursor+d)%n.length]);this.cursor=(this.cursor+f)%n.length;const v=await this.operations.captureLiveness();if(v!==null)for(const o of m){const d=u.get(o.owner);if(!k(d,i,v)||!await D(d,i,this.operations.getNodeRow))continue;const y=await this.operations.execute(r,["uproot",g(o),"--force"]);if(y.error===void 0&&y.code===0&&y.signal===null){this.retryAfter.delete(g(o)),h.fresh(()=>{p({level:"info",event:"grove.sweep.reconciled",outcome:"succeeded",...w(o.owner)?{node_id:o.owner}:{fields:{affected_node_id:o.owner}}})});continue}this.retryAfter.set(g(o),t+L),h.fresh(()=>{p({level:"error",event:"grove.sweep.failed",outcome:"failed",...w(o.owner)?{node_id:o.owner}:{fields:{affected_node_id:o.owner}},error:N(y)})})}}}export{P as GROVE_INSTANCE_SWEEP_BUDGET,F as GROVE_INSTANCE_SWEEP_INTERVAL_MS,L as GROVE_INSTANCE_SWEEP_RETRY_DELAY_MS,X as GroveInstanceSweepReconciler};
@@ -2,7 +2,7 @@ import { type Lifecycle } from '../../core/canvas/index.js';
2
2
  import { type LifecycleEvent } from '../../core/runtime/lifecycle.js';
3
3
  import type { FleetRegistry } from '../../core/runtime/fleet.js';
4
4
  /** Durable work that requires a node to remain automatically wakeable. */
5
- export declare function hasLiveObligation(nodeId: string): boolean;
5
+ export declare function hasLiveObligation(nodeId: string): Promise<boolean>;
6
6
  /** Whether anything would drive a turn if this node's engine came back right
7
7
  * now: durable work that must wake it, mail it has not seen, or a human
8
8
  * already looking at it. The negative is what makes re-launching a dead
@@ -11,19 +11,19 @@ export declare function hasLiveObligation(nodeId: string): boolean;
11
11
  *
12
12
  * Deferred mail deliberately does not count: it rides the node's next natural
13
13
  * cycle rather than causing one. */
14
- export declare function hasPendingWake(nodeId: string): boolean;
14
+ export declare function hasPendingWake(nodeId: string): Promise<boolean>;
15
15
  /** The retention sweep's hold: a node with a launch claim, durable work that
16
16
  * must wake it, or a person looking at it is never pruned, whatever its age.
17
17
  * Unseen mail is deliberately not a hold: it never wakes a terminal node, and
18
18
  * children keep writing a finished manager's inbox, so it would retain most
19
19
  * finished history forever. The stale sweep checks unseen mail itself. */
20
- export declare function retentionHold(fleet: Pick<FleetRegistry, 'isClaimed'>): (nodeId: string) => boolean;
20
+ export declare function retentionHold(fleet: Pick<FleetRegistry, 'isClaimed'>): Promise<(nodeId: string) => Promise<boolean>>;
21
21
  /** Whether a person is looking at this node right now: a focused viewer pane,
22
22
  * or a broker client that declared itself attending. A client that hellos with
23
23
  * `attends: false` is a system observer and deliberately does not count, which
24
24
  * is how Northlight identifies itself — so an open product page is
25
25
  * invisible here, while crouter's own local and remote viewers are not. */
26
- export declare function hasHumanViewer(nodeId: string): boolean;
26
+ export declare function hasHumanViewer(nodeId: string): Promise<boolean>;
27
27
  /** What parking an unattended node actually amounts to — the one rule both the
28
28
  * live-broker park clock and the lifecycle tick apply.
29
29
  *
@@ -48,7 +48,7 @@ export declare function hasHumanViewer(nodeId: string): boolean;
48
48
  * invariant is that content a sender already handed over is never dropped.
49
49
  */
50
50
  export type ParkEvent = Extract<LifecycleEvent, 'release' | 'park' | 'cancel'>;
51
- export declare function parkEvent(nodeId: string, lifecycle: Lifecycle): ParkEvent;
51
+ export declare function parkEvent(nodeId: string, lifecycle: Lifecycle): Promise<ParkEvent>;
52
52
  /** Apply an unattended decision and notify subscribers of automatic completion.
53
53
  * This is the DEGRADED enactment: no summary turn ran, so subscribers get the
54
54
  * doctrine notice instead of the node's own report. The live clock's good path
@@ -62,4 +62,4 @@ export declare function parkEvent(nodeId: string, lifecycle: Lifecycle): ParkEve
62
62
  * Only `park` fans, and only a resident parks, so the notice speaks about a
63
63
  * resident throughout: its conversation ended without a final report, its state
64
64
  * lives in whatever report it did leave, and a message reopens it. */
65
- export declare function applyParkEvent(nodeId: string, event: ParkEvent): void;
65
+ export declare function applyParkEvent(nodeId: string, event: ParkEvent): Promise<void>;
@@ -1 +1 @@
1
- var f=Object.defineProperty;var e=(r,t)=>f(r,"name",{value:t,configurable:!0});import{hasActiveLiveSubscription as l,hasLiveSubscriber as p,hasPendingCronWake as m}from"../../core/canvas/index.js";import{fullName as h}from"../../core/canvas/labels.js";import{hasLiveControllerWait as k,hasLiveObjectWait as b}from"../../core/canvas/waits.js";import{newestReportName as w}from"../../core/feed/reports.js";import{countTickets as g}from"../../core/canvas/attention.js";import{hasUnseenWakeMail as a}from"../../core/canvas/deliveries.js";import{readOutputRequest as v}from"../../core/runtime/structured-output.js";import{focusOf as x}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as L}from"../api/viewer-presence.js";import{publishNotice as W}from"../../core/runtime/close.js";import{readFault as $}from"../../core/canvas/recovery.js";import{transition as u}from"../../core/runtime/lifecycle.js";function o(r){return l(r)||k(r)||b(r)||m(r)||g(r)>0||v(r).state!=="absent"}e(o,"hasLiveObligation");function B(r){return o(r)||a(r)?!0:s(r)}e(B,"hasPendingWake");function F(r){return t=>r.isClaimed(t)||o(t)||s(t)}e(F,"retentionHold");function s(r){return x(r)!==null||L(r)}e(s,"hasHumanViewer");function M(r,t){if(s(r)||o(r))return"release";const i=$(r);return i?.link==="pi\u2192provider"&&i.retry.disposition==="fatal"?"release":t==="resident"?a(r)?"release":"park":a(r)||p(r)?"release":"cancel"}e(M,"parkEvent");function T(r,t){const i=t==="cancel"?u(r,t,{reason:"stranded"}):u(r,t);if(t!=="park")return;const n=w(r),c=n===null?`It left no report behind; \`crtr node inspect show ${r}\` shows where it stands.`:`Its latest report is where it left things: \`crtr canvas read ${n}\`.`;W(r,"notice.close",`Resident concluded \u2014 ${h(i)} (${r}) had nothing left to wake it through its unattended grace, so its conversation was concluded. It submitted no final report. ${c} A message to it reopens it on a fresh cycle.`,{reason:"child-auto-done",child:r},"deferred")}e(T,"applyParkEvent");export{T as applyParkEvent,s as hasHumanViewer,o as hasLiveObligation,B as hasPendingWake,M as parkEvent,F as retentionHold};
1
+ var f=Object.defineProperty;var a=(t,r)=>f(t,"name",{value:r,configurable:!0});import{hasActiveLiveSubscription as l,hasLiveSubscriber as p,hasPendingCronWake as m}from"../../core/canvas/index.js";import{fullName as w}from"../../core/canvas/labels.js";import{hasLiveControllerWait as h,hasLiveObjectWait as k}from"../../core/canvas/waits.js";import{newestReportName as y}from"../../core/feed/reports.js";import{countTickets as b}from"../../core/canvas/attention.js";import{hasUnseenWakeMail as i}from"../../core/canvas/deliveries.js";import{readOutputRequest as g}from"../../core/runtime/structured-output.js";import{focusOf as v}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as x}from"../api/viewer-presence.js";import{publishNotice as L}from"../../core/runtime/close.js";import{readFault as W}from"../../core/canvas/recovery.js";import{transition as c}from"../../core/runtime/lifecycle.js";async function s(t){return await l(t)||await h(t)||await k(t)||await m(t)||await b(t)>0||g(t).state!=="absent"}a(s,"hasLiveObligation");async function B(t){return await s(t)||await i(t)?!0:await n(t)}a(B,"hasPendingWake");async function F(t){return async r=>t.isClaimed(r)||await s(r)||await n(r)}a(F,"retentionHold");async function n(t){return await v(t)!==null||x(t)}a(n,"hasHumanViewer");async function M(t,r){if(await n(t)||await s(t))return"release";const e=await W(t);return e?.link==="pi\u2192provider"&&e.retry.disposition==="fatal"?"release":r==="resident"?await i(t)?"release":"park":await i(t)||await p(t)?"release":"cancel"}a(M,"parkEvent");async function T(t,r){const e=r==="cancel"?await c(t,r,{reason:"stranded"}):await c(t,r);if(r!=="park")return;const o=await y(t),u=o===null?`It left no report behind; \`crtr node inspect show ${t}\` shows where it stands.`:`Its latest report is where it left things: \`crtr canvas read ${o}\`.`;await L(t,"notice.close",`Resident concluded \u2014 ${w(e)} (${t}) had nothing left to wake it through its unattended grace, so its conversation was concluded. It submitted no final report. ${u} A message to it reopens it on a fresh cycle.`,{reason:"child-auto-done",child:t},"deferred")}a(T,"applyParkEvent");export{T as applyParkEvent,n as hasHumanViewer,s as hasLiveObligation,B as hasPendingWake,M as parkEvent,F as retentionHold};
@@ -1 +1 @@
1
- var E=Object.defineProperty;var o=(t,e)=>E(t,"name",{value:e,configurable:!0});import{getNode as p,getRow as h}from"../../core/canvas/index.js";import{managedWorktreeSweepCandidates as k}from"../../core/canvas/managed-worktree-sweep-candidates.js";import{isSafeNodeId as _}from"../../core/canvas/paths.js";import{captureLivenessSnapshotAsync as S,recordedPidLiveness as y}from"../../core/canvas/pid.js";import{emitEvent as c}from"../../core/events/emit.js";import{operationIdContext as u}from"../../core/events/operation-id.js";import{reconcileManagedWorktree as w}from"../../core/worktree-sweep.js";const I=60*1e3,v=3,T=["done","dead","canceled"];function m(t){return T.includes(t.status)}o(m,"isTerminal");function g(t,e){return e?.state==="closed"||e?.state==="open"&&t.status==="done"&&t.final_report!==null}o(g,"hasSweepDisposition");function A(t,e,i){return e.isClaimed(t.node_id)||t.frozen_at!==null||!m(t)||!g(t,p(t.node_id)?.managed_worktree)?!1:y(t.pi_pid,t.pi_pid_identity,i)==="dead"}o(A,"engineIsGone");function N(t,e){const i=t.node_id,n=t.pi_pid,a=t.pi_pid_identity;return{stillEligible:o(()=>{if(e.isClaimed(i))return!1;const s=h(i);return s===null||!m(s)||s.frozen_at!==null||!g(s,p(i)?.managed_worktree)?!1:s.pi_pid===n&&s.pi_pid_identity===a},"stillEligible")}}o(N,"eligibilityGuard");class L{static{o(this,"ManagedWorktreeSweepReconciler")}lastSweepAt=Number.NEGATIVE_INFINITY;inFlight=!1;cursor=0;run(e,i){if(this.inFlight||e-this.lastSweepAt<I||!i.lifecycle.acceptsDetachedWork())return;this.lastSweepAt=e,this.inFlight=!0;const n=this.sweep(e,i.fleet).finally(()=>{this.inFlight=!1});i.lifecycle.registerDetached(n)}candidates(e){try{return k(e)}catch(i){return u.fresh(()=>{c({level:"error",event:"worktree.sweep.scan_failed",error:i})}),null}}async sweep(e,i){const n=this.candidates(e);if(n===null||n.length===0)return;this.cursor>=n.length&&(this.cursor=0);const a=this.cursor,s=Math.min(v,n.length),d=[];for(let l=0;l<s;l+=1)d.push(n[(a+l)%n.length]);this.cursor=(a+s)%n.length;const r=await S();if(r!==null)for(const l of d){const f=h(l);f===null||!A(f,i,r)||await this.reconcileOne(f,e,i)}}async reconcileOne(e,i,n){const a=e.node_id,s=_(a)?{node_id:a}:{},d=_(a)?{}:{affected_node_id:a};try{const r=await w(a,N(e,n),i);u.fresh(()=>{if(r.status==="complete"){c({level:"info",event:"worktree.sweep.reconciled",outcome:"succeeded",...s,fields:{...d,...r.stash===void 0?{}:{base_checkout_stash:r.stash}}});return}r.status!=="skipped"&&(r.status==="refused"&&r.unchanged===!0||c({level:r.status==="failed"?"error":"warn",event:r.status==="failed"?"worktree.sweep.failed":"worktree.sweep.refused",outcome:r.status==="failed"?"failed":"skipped",...s,fields:{...d,reason:r.reason,...r.detail===void 0?{}:{detail:r.detail}}}))})}catch(r){u.fresh(()=>{c({level:"error",event:"worktree.sweep.failed",...s,error:r,fields:d})})}}}export{L as ManagedWorktreeSweepReconciler,v as WORKTREE_SWEEP_BUDGET,I as WORKTREE_SWEEP_INTERVAL_MS};
1
+ var w=Object.defineProperty;var o=(t,e)=>w(t,"name",{value:e,configurable:!0});import{getNode as p,getRow as h}from"../../core/canvas/index.js";import{managedWorktreeSweepCandidates as y}from"../../core/canvas/managed-worktree-sweep-candidates.js";import{isSafeNodeId as _}from"../../core/canvas/paths.js";import{captureLivenessSnapshotAsync as E,recordedPidLiveness as k}from"../../core/canvas/pid.js";import{emitEvent as c}from"../../core/events/emit.js";import{operationIdContext as u}from"../../core/events/operation-id.js";import{reconcileManagedWorktree as S}from"../../core/worktree-sweep.js";const I=60*1e3,v=3,T=["done","dead","canceled"];function m(t){return T.includes(t.status)}o(m,"isTerminal");function g(t,e){return e?.state==="closed"||e?.state==="open"&&t.status==="done"&&t.final_report!==null}o(g,"hasSweepDisposition");async function A(t,e,n){return e.isClaimed(t.node_id)||t.frozen_at!==null||!m(t)||!g(t,(await p(t.node_id))?.managed_worktree)?!1:k(t.pi_pid,t.pi_pid_identity,n)==="dead"}o(A,"engineIsGone");function N(t,e){const n=t.node_id,r=t.pi_pid,a=t.pi_pid_identity;return{stillEligible:o(async()=>{if(e.isClaimed(n))return!1;const s=await h(n);return s===null||!m(s)||s.frozen_at!==null||!g(s,(await p(n))?.managed_worktree)?!1:s.pi_pid===r&&s.pi_pid_identity===a},"stillEligible")}}o(N,"eligibilityGuard");class L{static{o(this,"ManagedWorktreeSweepReconciler")}lastSweepAt=Number.NEGATIVE_INFINITY;inFlight=!1;cursor=0;run(e,n){if(this.inFlight||e-this.lastSweepAt<I||!n.lifecycle.acceptsDetachedWork())return;this.lastSweepAt=e,this.inFlight=!0;const r=this.sweep(e,n.fleet).finally(()=>{this.inFlight=!1});n.lifecycle.registerDetached(r)}async candidates(e){try{return await y(e)}catch(n){return u.fresh(()=>{c({level:"error",event:"worktree.sweep.scan_failed",error:n})}),null}}async sweep(e,n){const r=await this.candidates(e);if(r===null||r.length===0)return;this.cursor>=r.length&&(this.cursor=0);const a=this.cursor,s=Math.min(v,r.length),d=[];for(let l=0;l<s;l+=1)d.push(r[(a+l)%r.length]);this.cursor=(a+s)%r.length;const i=await E();if(i!==null)for(const l of d){const f=await h(l);f===null||!await A(f,n,i)||await this.reconcileOne(f,e,n)}}async reconcileOne(e,n,r){const a=e.node_id,s=_(a)?{node_id:a}:{},d=_(a)?{}:{affected_node_id:a};try{const i=await S(a,N(e,r),n);u.fresh(()=>{if(i.status==="complete"){c({level:"info",event:"worktree.sweep.reconciled",outcome:"succeeded",...s,fields:{...d,...i.stash===void 0?{}:{base_checkout_stash:i.stash}}});return}i.status!=="skipped"&&(i.status==="refused"&&i.unchanged===!0||c({level:i.status==="failed"?"error":"warn",event:i.status==="failed"?"worktree.sweep.failed":"worktree.sweep.refused",outcome:i.status==="failed"?"failed":"skipped",...s,fields:{...d,reason:i.reason,...i.detail===void 0?{}:{detail:i.detail}}}))})}catch(i){u.fresh(()=>{c({level:"error",event:"worktree.sweep.failed",...s,error:i,fields:d})})}}}export{L as ManagedWorktreeSweepReconciler,v as WORKTREE_SWEEP_BUDGET,I as WORKTREE_SWEEP_INTERVAL_MS};
@@ -1,6 +1,6 @@
1
1
  /** Enforce absolute spawn deadlines independently of the tick's live-row scan. */
2
2
  export declare class NodeDeadlineReconciler {
3
- run(now: number): void;
3
+ run(now: number): Promise<void>;
4
4
  }
5
5
  /** The one deadline terminalization path. Structured-request expiry reuses it
6
6
  * even when a profile is paused, because its dedicated broker must not resume. */
@@ -1 +1 @@
1
- var m=Object.defineProperty;var s=(r,t)=>m(r,"name",{value:t,configurable:!0});import{dueNodeDeadlines as _,getNode as u}from"../../core/canvas/index.js";import{emitEvent as i}from"../../core/events/emit.js";import{isProfilePaused as p}from"../../core/profiles/manifest.js";import{operationIdContext as w}from"../../core/events/operation-id.js";import{errorClassFromFault as h}from"../../core/fault-classifier.js";import{publishNotice as v}from"../../core/runtime/close.js";import{readFault as x}from"../../core/canvas/recovery.js";import{requestBrokerTeardown as f}from"../../core/runtime/host.js";import{transition as y}from"../../core/runtime/lifecycle.js";class z{static{s(this,"NodeDeadlineReconciler")}run(t){let a;try{a=_(new Date(t).toISOString())}catch(e){i({level:"error",event:"node_deadline.scan_failed",error:e});return}for(const e of a)p(e.profile_id)||e.deadline_at===null||e.deadline_at===void 0||w.fresh(()=>{D(e.node_id,e.deadline_at,t).catch(d=>{i({level:"error",event:"node_deadline.expire_failed",node_id:e.node_id,error:d,fields:{deadline_at:e.deadline_at}})})})}}async function D(r,t,a){const e=u(r);if(e===null||e.status==="done")return;if(e.status==="canceled"||e.status==="dead"){const o=await f(r);if(!o.confirmed)throw o.error??new Error("broker teardown was not confirmed");return}const d=x(r),n=d?.retry.disposition==="fatal"?d:null;let l;try{l=y(r,"cancel",{reason:"deadline_exceeded",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",deadline:{deadline_at:t,elapsed_ms:a-Date.parse(t)},...n===null?{}:{message:n.message,fault_kind:n.kind,error_class:h(n).class}}}})}catch(o){throw i({level:"error",event:"node_deadline.terminalize_failed",node_id:r,error:o,fields:{deadline_at:t}}),o}if(l.status!=="canceled"||l.outcome_reason!=="deadline_exceeded")return;const c=await f(r);if(!c.confirmed)throw c.error??new Error("broker teardown was not confirmed");try{v(r,"notice.deadline","child-deadline-exceeded",{reason:"child-deadline-exceeded",child:r})}catch(o){i({level:"error",event:"node_deadline.notify_failed",node_id:r,error:o,fields:{deadline_at:t}})}try{i({level:"error",event:"node_deadline.expired",node_id:r,fields:{deadline_at:t,elapsed_ms:a-Date.parse(t)}})}catch{}}s(D,"expireNodeDeadline");export{z as NodeDeadlineReconciler,D as expireNodeDeadline};
1
+ var m=Object.defineProperty;var s=(r,a)=>m(r,"name",{value:a,configurable:!0});import{dueNodeDeadlines as _,getNode as u}from"../../core/canvas/index.js";import{emitEvent as i}from"../../core/events/emit.js";import{isProfilePaused as p}from"../../core/profiles/manifest.js";import{operationIdContext as w}from"../../core/events/operation-id.js";import{errorClassFromFault as h}from"../../core/fault-classifier.js";import{publishNotice as v}from"../../core/runtime/close.js";import{readFault as x}from"../../core/canvas/recovery.js";import{requestBrokerTeardown as f}from"../../core/runtime/host.js";import{transition as y}from"../../core/runtime/lifecycle.js";class z{static{s(this,"NodeDeadlineReconciler")}async run(a){let o;try{o=await _(new Date(a).toISOString())}catch(e){i({level:"error",event:"node_deadline.scan_failed",error:e});return}for(const e of o)p(e.profile_id)||e.deadline_at===null||e.deadline_at===void 0||w.fresh(()=>{D(e.node_id,e.deadline_at,a).catch(d=>{i({level:"error",event:"node_deadline.expire_failed",node_id:e.node_id,error:d,fields:{deadline_at:e.deadline_at}})})})}}async function D(r,a,o){const e=await u(r);if(e===null||e.status==="done")return;if(e.status==="canceled"||e.status==="dead"){const t=await f(r);if(!t.confirmed)throw t.error??new Error("broker teardown was not confirmed");return}const d=await x(r),n=d?.retry.disposition==="fatal"?d:null;let l;try{l=await y(r,"cancel",{reason:"deadline_exceeded",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",deadline:{deadline_at:a,elapsed_ms:o-Date.parse(a)},...n===null?{}:{message:n.message,fault_kind:n.kind,error_class:h(n).class}}}})}catch(t){throw i({level:"error",event:"node_deadline.terminalize_failed",node_id:r,error:t,fields:{deadline_at:a}}),t}if(l.status!=="canceled"||l.outcome_reason!=="deadline_exceeded")return;const c=await f(r);if(!c.confirmed)throw c.error??new Error("broker teardown was not confirmed");try{await v(r,"notice.deadline","child-deadline-exceeded",{reason:"child-deadline-exceeded",child:r})}catch(t){i({level:"error",event:"node_deadline.notify_failed",node_id:r,error:t,fields:{deadline_at:a}})}try{i({level:"error",event:"node_deadline.expired",node_id:r,fields:{deadline_at:a,elapsed_ms:o-Date.parse(a)}})}catch{}}s(D,"expireNodeDeadline");export{z as NodeDeadlineReconciler,D as expireNodeDeadline};
@@ -1 +1 @@
1
- var E=Object.defineProperty;var d=(i,t)=>E(i,"name",{value:t,configurable:!0});import{clearFrozen as m,getNode as _,getRow as g}from"../../../core/canvas/index.js";import{fullName as y}from"../../../core/canvas/labels.js";import{isSafeNodeId as s}from"../../../core/canvas/paths.js";import{emitEvent as l}from"../../../core/events/emit.js";import{operationIdContext as A}from"../../../core/events/operation-id.js";import{acknowledgedNodeMailCount as S}from"../../../core/canvas/deliveries.js";import{publishNotice as k}from"../../../core/runtime/close.js";import{transition as u}from"../../../core/runtime/lifecycle.js";import{reviveNode as h}from"../../../core/runtime/revive.js";import{hasPendingWake as v}from"../live-obligation.js";import{readInterruptedTurn as z}from"../../../core/canvas/recovery.js";const f=6,R=10*6e4,L=2e4;function M(i,t){if(t)return 2;const r=i.launched_at;if(r==null)return 1;const e=i.last_settled_at;return e==null?2:Date.parse(e)>Date.parse(r)?1:2}d(M,"thawTier");function C(i,t){if(i.tier!==t.tier)return i.tier-t.tier;const r=i.row.frozen_at,e=t.row.frozen_at;return r==null?e==null?0:1:e==null?-1:Date.parse(r)-Date.parse(e)}d(C,"compareThaw");class B{static{d(this,"FreezeLaneReconciler")}relaunchState=new Map;endEpisode(t){this.relaunchState.delete(t)}async run(t,r){const e=r.candidates.map(a=>({...a,tier:M(a.row,v(a.row.node_id))}));e.sort(C);const n={stalled:0,waitingOnMail:0};for(const a of e)await A.fresh(()=>this.enact(t,a,r.fleet))==="frozen"&&(a.tier===1?n.stalled+=1:n.waitingOnMail+=1);return n}async enact(t,r,e){const n=r.row.node_id;try{return r.enact==="thaw"?await this.enactThaw(r.row):r.enact==="idle-release"?await this.enactIdleRelease(t,r.row):(await e.applyDeadRowPolicy(n),e.has(n)?"launched":g(n)?.frozen_at!=null?"frozen":"skipped")}catch(a){return l({level:"error",event:"node.lifecycle.enact_failed",...s(n)?{node_id:n}:{},error:a,fields:{...s(n)?{}:{affected_node_id:n},enact:r.enact}}),"skipped"}}async enactThaw(t){const r=z(t.node_id)?.interrupted===!0;if(!r&&t.lifecycle==="resident"&&_(t.node_id)?.pi_session_id!=null&&!v(t.node_id))return u(t.node_id,"release"),m(t.node_id),"skipped";try{return(await h(t.node_id,{resume:!0,capacity:"freeze",recovery:!0,...r?{wakeReason:"runtime-restart-abort"}:{}})).outcome==="frozen"?"frozen":"launched"}catch(e){const n=_(t.node_id);throw n!==null&&(n.status==="active"||n.status==="idle")&&(u(t.node_id,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}),m(t.node_id)),e}}async enactIdleRelease(t,r){const e=r.node_id,n=S(e),a=this.relaunchState.get(e),c=a===void 0||a.acknowledgedCount!==n,o=c?0:a.attempts;if(o>=f)return this.relaunchState.delete(e),l({level:"warn",event:"broker.idle_release.exhausted",...s(e)?{node_id:e}:{},fields:{...s(e)?{}:{affected_node_id:e},attempts:o,max_attempts:f}}),u(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",respawn_failures:o}}}),k(e,"notice.crash",`Child crashed \u2014 ${y(r)} (${e}) failed to relaunch after ${o} attempts while trying to deliver a pending inbox message (no delivery progress across any attempt), and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e}),"skipped";const p=c?void 0:a?.lastAttempt,w=Math.min(L*2**o,R);return p!==void 0&&t-p<w?"skipped":(await h(e,{resume:!0,capacity:"freeze"})).outcome==="frozen"?"frozen":(this.relaunchState.set(e,{acknowledgedCount:n,attempts:o+1,lastAttempt:t}),l({level:"info",event:"broker.revive.idle_release",...s(e)?{node_id:e}:{},attempt:o+1,fields:{...s(e)?{}:{affected_node_id:e},attempts:o+1,max_attempts:f}}),"launched")}}export{B as FreezeLaneReconciler,C as compareThaw,M as thawTier};
1
+ var E=Object.defineProperty;var d=(i,t)=>E(i,"name",{value:t,configurable:!0});import{clearFrozen as p,getNode as _,getRow as y}from"../../../core/canvas/index.js";import{fullName as g}from"../../../core/canvas/labels.js";import{isSafeNodeId as s}from"../../../core/canvas/paths.js";import{emitEvent as l}from"../../../core/events/emit.js";import{operationIdContext as A}from"../../../core/events/operation-id.js";import{acknowledgedNodeMailCount as S}from"../../../core/canvas/deliveries.js";import{publishNotice as k}from"../../../core/runtime/close.js";import{transition as u}from"../../../core/runtime/lifecycle.js";import{reviveNode as h}from"../../../core/runtime/revive.js";import{hasPendingWake as w}from"../live-obligation.js";import{readInterruptedTurn as z}from"../../../core/canvas/recovery.js";import{mapAsync as R}from"../../../core/async-array.js";const f=6,L=10*6e4,M=2e4;function C(i,t){if(t)return 2;const a=i.launched_at;if(a==null)return 1;const e=i.last_settled_at;return e==null?2:Date.parse(e)>Date.parse(a)?1:2}d(C,"thawTier");function I(i,t){if(i.tier!==t.tier)return i.tier-t.tier;const a=i.row.frozen_at,e=t.row.frozen_at;return a==null?e==null?0:1:e==null?-1:Date.parse(a)-Date.parse(e)}d(I,"compareThaw");class K{static{d(this,"FreezeLaneReconciler")}relaunchState=new Map;endEpisode(t){this.relaunchState.delete(t)}async run(t,a){const e=await R(a.candidates,async n=>({...n,tier:C(n.row,await w(n.row.node_id))}));e.sort(I);const r={stalled:0,waitingOnMail:0};for(const n of e)await A.fresh(()=>this.enact(t,n,a.fleet))==="frozen"&&(n.tier===1?r.stalled+=1:r.waitingOnMail+=1);return r}async enact(t,a,e){const r=a.row.node_id;try{return a.enact==="thaw"?await this.enactThaw(a.row):a.enact==="idle-release"?await this.enactIdleRelease(t,a.row):(await e.applyDeadRowPolicy(r),e.has(r)?"launched":(await y(r))?.frozen_at!=null?"frozen":"skipped")}catch(n){return l({level:"error",event:"node.lifecycle.enact_failed",...s(r)?{node_id:r}:{},error:n,fields:{...s(r)?{}:{affected_node_id:r},enact:a.enact}}),"skipped"}}async enactThaw(t){const a=(await z(t.node_id))?.interrupted===!0;if(!a&&t.lifecycle==="resident"&&(await _(t.node_id))?.pi_session_id!=null&&!await w(t.node_id))return await u(t.node_id,"release"),await p(t.node_id),"skipped";try{return(await h(t.node_id,{resume:!0,capacity:"freeze",recovery:!0,...a?{wakeReason:"runtime-restart-abort"}:{}})).outcome==="frozen"?"frozen":"launched"}catch(e){const r=await _(t.node_id);throw r!==null&&(r.status==="active"||r.status==="idle")&&(await u(t.node_id,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}),await p(t.node_id)),e}}async enactIdleRelease(t,a){const e=a.node_id,r=await S(e),n=this.relaunchState.get(e),c=n===void 0||n.acknowledgedCount!==r,o=c?0:n.attempts;if(o>=f)return this.relaunchState.delete(e),l({level:"warn",event:"broker.idle_release.exhausted",...s(e)?{node_id:e}:{},fields:{...s(e)?{}:{affected_node_id:e},attempts:o,max_attempts:f}}),await u(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",respawn_failures:o}}}),await k(e,"notice.crash",`Child crashed \u2014 ${g(a)} (${e}) failed to relaunch after ${o} attempts while trying to deliver a pending inbox message (no delivery progress across any attempt), and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e}),"skipped";const m=c?void 0:n?.lastAttempt,v=Math.min(M*2**o,L);return m!==void 0&&t-m<v?"skipped":(await h(e,{resume:!0,capacity:"freeze"})).outcome==="frozen"?"frozen":(this.relaunchState.set(e,{acknowledgedCount:r,attempts:o+1,lastAttempt:t}),l({level:"info",event:"broker.revive.idle_release",...s(e)?{node_id:e}:{},attempt:o+1,fields:{...s(e)?{}:{affected_node_id:e},attempts:o+1,max_attempts:f}}),"launched")}}export{K as FreezeLaneReconciler,I as compareThaw,C as thawTier};
@@ -24,7 +24,7 @@ export declare function decideRespawnAttempt(row: Pick<NodeRow, 'last_settled_at
24
24
  * a human revive brings it back. Re-arming instead parks it: the row stays
25
25
  * active, the tick re-enters this policy after the window, and the first
26
26
  * launch made once the network returns resumes the interrupted turn. */
27
- export declare function deferRespawnWhileOffline(nodeId: string, failures: number, now: number): RespawnAttempt;
27
+ export declare function deferRespawnWhileOffline(nodeId: string, failures: number, now: number): Promise<RespawnAttempt>;
28
28
  /** Persist the policy decision through the daemon-only canvas writer. */
29
- export declare function recordRespawnPolicy(row: NodeRow, now: number): RespawnAttempt;
30
- export declare function clearRespawnPolicy(nodeId: string): void;
29
+ export declare function recordRespawnPolicy(row: NodeRow, now: number): Promise<RespawnAttempt>;
30
+ export declare function clearRespawnPolicy(nodeId: string): Promise<void>;
@@ -1 +1 @@
1
- var f=Object.defineProperty;var o=(e,n)=>f(e,"name",{value:n,configurable:!0});import{recordRespawnAttempt as s}from"../../../core/canvas/index.js";const u=6,i=5e3,l=10*6e4,c=3e4;function _(e){return e<=0?0:Math.min(i*2**(e-1),l)}o(_,"respawnBackoffMs");function N(e,n){const t=e.respawn_not_before;if(t==null)return!1;const r=Date.parse(t);return Number.isFinite(r)&&n<r}o(N,"isInBackoff");function p(e,n){const t=e.last_settled_at==null?Number.NaN:Date.parse(e.last_settled_at),r=e.launched_at==null?Number.NaN:Date.parse(e.launched_at);if(Number.isFinite(t)&&Number.isFinite(r)&&t>r)return{failures:0,notBefore:null,exhausted:!1};const a=(e.respawn_failures??0)+1;return{failures:a,notBefore:new Date(n+_(a)).toISOString(),exhausted:a>=u}}o(p,"decideRespawnAttempt");function S(e,n,t){const r=new Date(t+c).toISOString();return s(e,{failures:n,notBefore:r}),{failures:n,notBefore:r,exhausted:!1}}o(S,"deferRespawnWhileOffline");function B(e,n){const t=p(e,n);return s(e.node_id,{failures:t.failures,notBefore:t.notBefore}),t}o(B,"recordRespawnPolicy");function m(e){s(e,{failures:0,notBefore:null})}o(m,"clearRespawnPolicy");export{u as MAX_RESPAWN_ATTEMPTS,c as OFFLINE_RESPAWN_RETRY_MS,m as clearRespawnPolicy,p as decideRespawnAttempt,S as deferRespawnWhileOffline,N as isInBackoff,B as recordRespawnPolicy,_ as respawnBackoffMs};
1
+ var i=Object.defineProperty;var r=(e,n)=>i(e,"name",{value:n,configurable:!0});import{recordRespawnAttempt as s}from"../../../core/canvas/index.js";const f=6,u=5e3,l=10*6e4,c=3e4;function _(e){return e<=0?0:Math.min(u*2**(e-1),l)}r(_,"respawnBackoffMs");function N(e,n){const t=e.respawn_not_before;if(t==null)return!1;const a=Date.parse(t);return Number.isFinite(a)&&n<a}r(N,"isInBackoff");function p(e,n){const t=e.last_settled_at==null?Number.NaN:Date.parse(e.last_settled_at),a=e.launched_at==null?Number.NaN:Date.parse(e.launched_at);if(Number.isFinite(t)&&Number.isFinite(a)&&t>a)return{failures:0,notBefore:null,exhausted:!1};const o=(e.respawn_failures??0)+1;return{failures:o,notBefore:new Date(n+_(o)).toISOString(),exhausted:o>=f}}r(p,"decideRespawnAttempt");async function S(e,n,t){const a=new Date(t+c).toISOString();return await s(e,{failures:n,notBefore:a}),{failures:n,notBefore:a,exhausted:!1}}r(S,"deferRespawnWhileOffline");async function B(e,n){const t=p(e,n);return await s(e.node_id,{failures:t.failures,notBefore:t.notBefore}),t}r(B,"recordRespawnPolicy");async function m(e){await s(e,{failures:0,notBefore:null})}r(m,"clearRespawnPolicy");export{f as MAX_RESPAWN_ATTEMPTS,c as OFFLINE_RESPAWN_RETRY_MS,m as clearRespawnPolicy,p as decideRespawnAttempt,S as deferRespawnWhileOffline,N as isInBackoff,B as recordRespawnPolicy,_ as respawnBackoffMs};
@@ -1 +1 @@
1
- var n=Object.defineProperty;var r=(e,i)=>n(e,"name",{value:i,configurable:!0});import{recordedPidLiveness as d}from"../../../core/canvas/pid.js";import{requestBrokerTeardown as t}from"../../../core/runtime/host.js";function a(e,i){return!i&&(e.pi_pid==null||d(e.pi_pid,e.pi_pid_identity)!=="alive")?!1:(t(e.node_id),!0)}r(a,"handleTerminatingRow");export{a as handleTerminatingRow};
1
+ var d=Object.defineProperty;var r=(i,e)=>d(i,"name",{value:e,configurable:!0});import{recordedPidLiveness as n}from"../../../core/canvas/pid.js";import{requestBrokerTeardown as t}from"../../../core/runtime/host.js";function a(i,e){return!e&&(i.pi_pid==null||n(i.pi_pid,i.pi_pid_identity)!=="alive")?!1:(t(i.node_id),!0)}r(a,"handleTerminatingRow");export{a as handleTerminatingRow};
@@ -1 +1 @@
1
- var m=Object.defineProperty;var f=(r,i)=>m(r,"name",{value:i,configurable:!0});import{clearFrozen as l,endLiveExecution as o,getNode as h}from"../../../core/canvas/index.js";import{isSafeNodeId as _}from"../../../core/canvas/paths.js";import{recordedPidLiveness as p}from"../../../core/canvas/pid.js";import{emitEvent as u}from"../../../core/events/emit.js";import{operationIdContext as y}from"../../../core/events/operation-id.js";import{readInterruptedTurn as P}from"../../../core/canvas/recovery.js";import{isProfilePaused as c}from"../../../core/profiles/manifest.js";import{isRecoveryHeld as v}from"../../../core/runtime/recovery-hold.js";import{hasUnseenWakeMail as k}from"../../../core/canvas/deliveries.js";import{hasIdleReleaseIntent as L}from"../../../core/runtime/lifecycle.js";import{classifyDeadNode as z}from"../../fleet.js";import{applyParkEvent as I,hasPendingWake as R,parkEvent as E}from"../live-obligation.js";import{FreezeLaneReconciler as M}from"./freeze-lane.js";import{isInBackoff as g}from"./respawn-policy.js";import{handleTerminatingRow as N}from"./terminating.js";import{wantsExecution as b}from"./wants-execution.js";function C(r){return r.status==="done"||r.status==="canceled"||r.status==="dead"}f(C,"isTerminal");const D=12e4;function F(r,i){const e=Math.max(...[r.created,r.launched_at].map(n=>n==null?0:Date.parse(n)||0));return e>0&&i-e<D}f(F,"isLaunchInFlight");class Y{static{f(this,"NodeLifecycleReconciler")}freezeLane=new M;async run(i,e){const n=[];for(const a of e.rows)await y.fresh(async()=>{try{await this.classifyRow(i,a,e,n)}catch(t){const s=a.node_id;u({level:"error",event:"node.lifecycle.classify_failed",..._(s)?{node_id:s}:{fields:{affected_node_id:s}},error:t})}});return this.freezeLane.run(i,{fleet:e.fleet,candidates:n})}async classifyRow(i,e,n,a){const t=e.node_id;if(C(e)){if(N(e,n.fleet.has(t)))return;e.pi_pid!=null&&p(e.pi_pid,e.pi_pid_identity)==="dead"&&o(t,{reason:"observed-dead"}),e.frozen_at!=null&&(e.final_report!=null?l(t):a.push({row:e,enact:"thaw"}));return}if(n.fleet.has(t)){c(e.profile_id)?n.fleet.interruptForProfilePause(t):this.thawMark(e);return}if(c(e.profile_id)){this.freezeLane.endEpisode(t);return}if(v(t))return;const s=e.pi_pid!=null&&p(e.pi_pid,e.pi_pid_identity)==="dead";if(s&&!n.fleet.hasProfilePauseInterruption(t)&&o(t,{reason:"observed-dead"}),!b(e)){this.thawMark(e),this.settleParked(e);return}if(g(e,i))return;if(e.status==="idle"&&L(e)&&k(t)){a.push({row:e,enact:"idle-release"});return}if(e.pi_pid==null){if(e.respawn_not_before!=null){a.push({row:e,enact:"policy"});return}if(e.frozen_at!=null){a.push({row:e,enact:"thaw"});return}if(n.fleet.isClaimed(t)||F(e,i))return;u({level:"warn",event:"node.lifecycle.stranded_launch",node_id:t}),a.push({row:e,enact:"thaw"});return}if(!s)return;const d=z(h(t),P(t)?.interrupted===!0,R(t));if(d==="respawn-fresh"||d==="respawn-cycle"||d==="respawn-resume"){a.push({row:e,enact:"policy"});return}await n.fleet.applyDeadRowPolicy(t),this.thawMark(e)}thawMark(i){i.frozen_at!=null&&l(i.node_id)}settleParked(i){if(i.status!=="idle")return;this.freezeLane.endEpisode(i.node_id);const e=E(i.node_id,i.lifecycle);e!=="release"&&I(i.node_id,e)}}export{D as LAUNCH_GRACE_MS,Y as NodeLifecycleReconciler,F as isLaunchInFlight};
1
+ var m=Object.defineProperty;var f=(n,i)=>m(n,"name",{value:i,configurable:!0});import{clearFrozen as l,endLiveExecution as o,getNode as h}from"../../../core/canvas/index.js";import{isSafeNodeId as _}from"../../../core/canvas/paths.js";import{recordedPidLiveness as p}from"../../../core/canvas/pid.js";import{emitEvent as u}from"../../../core/events/emit.js";import{operationIdContext as y}from"../../../core/events/operation-id.js";import{readInterruptedTurn as P}from"../../../core/canvas/recovery.js";import{isProfilePaused as c}from"../../../core/profiles/manifest.js";import{isRecoveryHeld as v}from"../../../core/runtime/recovery-hold.js";import{hasUnseenWakeMail as k}from"../../../core/canvas/deliveries.js";import{hasIdleReleaseIntent as L}from"../../../core/runtime/lifecycle.js";import{classifyDeadNode as z}from"../../fleet.js";import{applyParkEvent as I,hasPendingWake as R,parkEvent as E}from"../live-obligation.js";import{FreezeLaneReconciler as M}from"./freeze-lane.js";import{isInBackoff as g}from"./respawn-policy.js";import{handleTerminatingRow as N}from"./terminating.js";import{wantsExecution as b}from"./wants-execution.js";function C(n){return n.status==="done"||n.status==="canceled"||n.status==="dead"}f(C,"isTerminal");const D=12e4;function F(n,i){const e=Math.max(...[n.created,n.launched_at].map(a=>a==null?0:Date.parse(a)||0));return e>0&&i-e<D}f(F,"isLaunchInFlight");class Y{static{f(this,"NodeLifecycleReconciler")}freezeLane=new M;async run(i,e){const a=[];for(const r of e.rows)await y.fresh(async()=>{try{await this.classifyRow(i,r,e,a)}catch(t){const s=r.node_id;u({level:"error",event:"node.lifecycle.classify_failed",..._(s)?{node_id:s}:{fields:{affected_node_id:s}},error:t})}});return this.freezeLane.run(i,{fleet:e.fleet,candidates:a})}async classifyRow(i,e,a,r){const t=e.node_id;if(C(e)){if(N(e,a.fleet.has(t)))return;e.pi_pid!=null&&p(e.pi_pid,e.pi_pid_identity)==="dead"&&await o(t,{reason:"observed-dead"}),e.frozen_at!=null&&(e.final_report!=null?await l(t):r.push({row:e,enact:"thaw"}));return}if(a.fleet.has(t)){c(e.profile_id)?a.fleet.interruptForProfilePause(t):await this.thawMark(e);return}if(c(e.profile_id)){this.freezeLane.endEpisode(t);return}if(v(t))return;const s=e.pi_pid!=null&&p(e.pi_pid,e.pi_pid_identity)==="dead";if(s&&!a.fleet.hasProfilePauseInterruption(t)&&await o(t,{reason:"observed-dead"}),!await b(e)){await this.thawMark(e),await this.settleParked(e);return}if(g(e,i))return;if(e.status==="idle"&&L(e)&&await k(t)){r.push({row:e,enact:"idle-release"});return}if(e.pi_pid==null){if(e.respawn_not_before!=null){r.push({row:e,enact:"policy"});return}if(e.frozen_at!=null){r.push({row:e,enact:"thaw"});return}if(a.fleet.isClaimed(t)||F(e,i))return;u({level:"warn",event:"node.lifecycle.stranded_launch",node_id:t}),r.push({row:e,enact:"thaw"});return}if(!s)return;const d=z(await h(t),(await P(t))?.interrupted===!0,await R(t));if(d==="respawn-fresh"||d==="respawn-cycle"||d==="respawn-resume"){r.push({row:e,enact:"policy"});return}await a.fleet.applyDeadRowPolicy(t),await this.thawMark(e)}async thawMark(i){i.frozen_at!=null&&await l(i.node_id)}async settleParked(i){if(i.status!=="idle")return;this.freezeLane.endEpisode(i.node_id);const e=await E(i.node_id,i.lifecycle);e!=="release"&&await I(i.node_id,e)}}export{D as LAUNCH_GRACE_MS,Y as NodeLifecycleReconciler,F as isLaunchInFlight};
@@ -5,4 +5,4 @@ import type { NodeRow } from '../../../core/canvas/index.js';
5
5
  * handler calls this after appending its entry. */
6
6
  export declare function wantsExecution(row: Pick<NodeRow, 'node_id' | 'status'> & {
7
7
  intent?: NodeRow['intent'];
8
- }): boolean;
8
+ }): Promise<boolean>;
@@ -1 +1 @@
1
- var a=Object.defineProperty;var t=(e,n)=>a(e,"name",{value:n,configurable:!0});import{hasUnseenWakeMail as i}from"../../../core/canvas/deliveries.js";import{hasIdleReleaseIntent as s}from"../../../core/runtime/lifecycle.js";function l(e){return e.status==="active"?!0:e.status!=="idle"?!1:!s(e)||i(e.node_id)}t(l,"wantsExecution");export{l as wantsExecution};
1
+ var n=Object.defineProperty;var t=(e,a)=>n(e,"name",{value:a,configurable:!0});import{hasUnseenWakeMail as i}from"../../../core/canvas/deliveries.js";import{hasIdleReleaseIntent as s}from"../../../core/runtime/lifecycle.js";async function l(e){return e.status==="active"?!0:e.status!=="idle"?!1:!s(e)||await i(e.node_id)}t(l,"wantsExecution");export{l as wantsExecution};
@@ -3,5 +3,5 @@ export interface PendingReviewSubmitContext {
3
3
  lifecycle: DetachedWorkLifecycle;
4
4
  }
5
5
  export declare class PendingReviewSubmitReconciler {
6
- run(now: number, ctx: PendingReviewSubmitContext): void;
6
+ run(now: number, ctx: PendingReviewSubmitContext): Promise<void>;
7
7
  }
@@ -1 +1 @@
1
- var l=Object.defineProperty;var n=(t,e)=>l(t,"name",{value:e,configurable:!0});import{emitEvent as s}from"../../core/events/emit.js";import{operationIdContext as d}from"../../core/events/operation-id.js";import{listSubmitRequestedRequests as m}from"../../core/human/requests.js";import{completeRequestedSubmit as c}from"../review/finish.js";class b{static{n(this,"PendingReviewSubmitReconciler")}run(e,i){if(!i.lifecycle.acceptsDetachedWork())return;let o;try{o=m()}catch(r){d.fresh(()=>{s({level:"error",event:"review.deferred_submit.scan_failed",error:r})});return}for(const r of o)i.lifecycle.registerDetached(c(r.request_id,{atCompanionTurnEnd:!1}).then(()=>{},f=>{d.fresh(()=>{s({level:"error",event:"review.deferred_submit.failed",error:f})})}))}}export{b as PendingReviewSubmitReconciler};
1
+ var f=Object.defineProperty;var n=(t,e)=>f(t,"name",{value:e,configurable:!0});import{emitEvent as s}from"../../core/events/emit.js";import{operationIdContext as c}from"../../core/events/operation-id.js";import{listSubmitRequestedRequests as l}from"../../core/human/requests.js";import{completeRequestedSubmit as m}from"../review/finish.js";class b{static{n(this,"PendingReviewSubmitReconciler")}async run(e,i){if(!i.lifecycle.acceptsDetachedWork())return;let o;try{o=await l()}catch(r){c.fresh(()=>{s({level:"error",event:"review.deferred_submit.scan_failed",error:r})});return}for(const r of o)i.lifecycle.registerDetached(m(r.request_id,{atCompanionTurnEnd:!1}).then(()=>{},d=>{c.fresh(()=>{s({level:"error",event:"review.deferred_submit.failed",error:d})})}))}}export{b as PendingReviewSubmitReconciler};
@@ -1 +1 @@
1
- var v=Object.defineProperty;var d=(l,t)=>v(l,"name",{value:t,configurable:!0});import{withCanvasWrite as E}from"../../core/canvas/db.js";import{emitEvent as c}from"../../core/events/emit.js";import{operationIdContext as p}from"../../core/events/operation-id.js";import{RunError as S}from"../../core/runs/operations.js";import{storageClient as k,storageConfig as O}from"../../core/storage/client.js";import{deleteUploadRow as U,expireShares as w,markShareObjectDeleted as R,markUploadsDeletePending as b,pendingUploadDeletes as A,sharesOwingObjectDelete as T,staleUnusedUploads as x}from"../../core/storage/tables.js";const I=6e4,y=1440*6e4,D=200,N=3,F=d(l=>l instanceof S&&l.code==="storage_unavailable","unavailable");class M{static{d(this,"StorageDueWorkReconciler")}deps;lastPassAt=Number.NEGATIVE_INFINITY;inFlight=!1;constructor(t={config:O,client:k}){this.deps=t}run(t,o){if(this.inFlight||t-this.lastPassAt<I||!o.lifecycle.acceptsDetachedWork())return;this.lastPassAt=t;let i;try{i=this.deps.config()}catch(e){p.fresh(()=>c({level:"error",event:"storage.due_work.failed",error:e}));return}if(!i)return;this.inFlight=!0;const f=p.fresh(()=>this.pass(t)).then(()=>{}).catch(e=>{p.fresh(()=>c({level:"error",event:"storage.due_work.failed",error:e}))}).finally(()=>{this.inFlight=!1});o.lifecycle.registerDetached(f)}async pass(t){const o=new Date(t).toISOString(),{marked:i,expired:f}=E(s=>{const a=x(new Date(t-y).toISOString(),s);return b(a,s,o),{marked:a.length,expired:w(o,s).length}}),e={marked_uploads:i,expired_shares:f,deleted_uploads:0,deleted_share_objects:0,failed:0},h=A().slice(0,D),_=T().slice(0,D);if(h.length||_.length){const s=this.deps.client();let a,n=0,u=!1;const g=d(async r=>{if(u)return!1;try{return await r(),n=0,!0}catch(m){return e.failed++,a??=m,n=F(m)?n+1:0,n>=N&&(u=!0),!1}},"attempt");for(const r of h)await g(()=>s.deleteUpload(r.upload_id))&&(U(r.upload_id),e.deleted_uploads++);for(const r of _)await g(()=>s.deleteShare(r.share_id))&&(R(r.share_id),e.deleted_share_objects++);a!==void 0&&c({level:"warn",event:"storage.due_work.deletes_failed",error:a,fields:{failed:e.failed,storage_unavailable:u}})}return(e.marked_uploads||e.expired_shares||e.deleted_uploads||e.deleted_share_objects)&&c({level:"info",event:"storage.due_work.settled",outcome:"succeeded",fields:{...e}}),e}}export{N as STORAGE_DOWN_AFTER,D as STORAGE_DUE_WORK_BUDGET,I as STORAGE_DUE_WORK_INTERVAL_MS,M as StorageDueWorkReconciler,y as UNUSED_UPLOAD_TTL_MS};
1
+ var D=Object.defineProperty;var d=(i,t)=>D(i,"name",{value:t,configurable:!0});import{withCanvasWrite as v}from"../../core/canvas/db.js";import{emitEvent as c}from"../../core/events/emit.js";import{operationIdContext as p}from"../../core/events/operation-id.js";import{RunError as E}from"../../core/runs/operations.js";import{storageClient as S,storageConfig as k}from"../../core/storage/client.js";import{deleteUploadRow as O,expireShares as U,markShareObjectDeleted as R,markUploadsDeletePending as b,pendingUploadDeletes as A,sharesOwingObjectDelete as T,staleUnusedUploads as x}from"../../core/storage/tables.js";const y=6e4,I=1440*6e4,w=200,N=3,F=d(i=>i instanceof E&&i.code==="storage_unavailable","unavailable");class M{static{d(this,"StorageDueWorkReconciler")}deps;lastPassAt=Number.NEGATIVE_INFINITY;inFlight=!1;constructor(t={config:k,client:S}){this.deps=t}run(t,l){if(this.inFlight||t-this.lastPassAt<y||!l.lifecycle.acceptsDetachedWork())return;this.lastPassAt=t;let o;try{o=this.deps.config()}catch(e){p.fresh(()=>c({level:"error",event:"storage.due_work.failed",error:e}));return}if(!o)return;this.inFlight=!0;const f=p.fresh(()=>this.pass(t)).then(()=>{}).catch(e=>{p.fresh(()=>c({level:"error",event:"storage.due_work.failed",error:e}))}).finally(()=>{this.inFlight=!1});l.lifecycle.registerDetached(f)}async pass(t){const l=new Date(t).toISOString(),{marked:o,expired:f}=await v(async r=>{const s=await x(new Date(t-I).toISOString(),r);return await b(s,r,l),{marked:s.length,expired:(await U(l,r)).length}}),e={marked_uploads:o,expired_shares:f,deleted_uploads:0,deleted_share_objects:0,failed:0},h=(await A()).slice(0,w),_=(await T()).slice(0,w);if(h.length||_.length){const r=this.deps.client();let s,n=0,u=!1;const g=d(async a=>{if(u)return!1;try{return await a(),n=0,!0}catch(m){return e.failed++,s??=m,n=F(m)?n+1:0,n>=N&&(u=!0),!1}},"attempt");for(const a of h)await g(()=>r.deleteUpload(a.upload_id))&&(await O(a.upload_id),e.deleted_uploads++);for(const a of _)await g(()=>r.deleteShare(a.share_id))&&(await R(a.share_id),e.deleted_share_objects++);s!==void 0&&c({level:"warn",event:"storage.due_work.deletes_failed",error:s,fields:{failed:e.failed,storage_unavailable:u}})}return(e.marked_uploads||e.expired_shares||e.deleted_uploads||e.deleted_share_objects)&&c({level:"info",event:"storage.due_work.settled",outcome:"succeeded",fields:{...e}}),e}}export{N as STORAGE_DOWN_AFTER,w as STORAGE_DUE_WORK_BUDGET,y as STORAGE_DUE_WORK_INTERVAL_MS,M as StorageDueWorkReconciler,I as UNUSED_UPLOAD_TTL_MS};
@@ -34,7 +34,7 @@ export declare class StorageMaintenanceReconciler {
34
34
  private cachePassInFlight;
35
35
  private readonly worktreeSweep;
36
36
  private readonly groveInstanceSweep;
37
- run(now: number, ctx: StorageMaintenanceContext): void;
37
+ run(now: number, ctx: StorageMaintenanceContext): Promise<void>;
38
38
  /** Ask the launcher for one purge of every app's cache folder: at boot, then at most hourly. It is off the due lanes (a sleeping runtime is never woken for it) and skipped where no launcher exists. */
39
39
  private scheduleCachePass;
40
40
  private scheduleWalCheckpoint;
@@ -1,8 +1,8 @@
1
- var I=Object.defineProperty;var u=(f,t)=>I(f,"name",{value:t,configurable:!0});import{rm as E,stat as A}from"node:fs/promises";import{Worker as S}from"node:worker_threads";import{closeFocusRow as N,getFocusById as y,listFocuses as g,listNodes as R}from"../../core/canvas/index.js";import{pruneExpiredIdempotencyKeys as T}from"../../core/runs/operations.js";import{getNode as C,lastActivityMs as h,listTerminalPlacementResidue as w,pruneExpiredCreateRequests as F,pruneNodes as P}from"../../core/canvas/canvas.js";import{lastContextStripMs as D,stripContextDir as k}from"../../core/canvas/context-strip.js";import{isAppRun as x}from"../../core/canvas/app-run.js";import{isSafeNodeId as c}from"../../core/canvas/paths.js";import{emitEvent as n}from"../../core/events/emit.js";import{operationIdContext as a}from"../../core/events/operation-id.js";import{listLivePanesAsync as b,tearDownNode as W}from"../../core/runtime/placement.js";import{reapStaleSpares as G}from"../../core/runtime/warm-pool.js";import{GroveInstanceSweepReconciler as M}from"./grove-instance-sweep.js";import{ManagedWorktreeSweepReconciler as V}from"./managed-worktree-sweep.js";import{compactRunEvents as L,expireRunEvents as Y}from"../../core/runs/events.js";import{openDb as q}from"../../core/canvas/db.js";import{canvasDbPath as O}from"../../core/canvas/paths.js";import{retentionHold as _}from"./live-obligation.js";import{pruneMemoryReads as z}from"../../core/canvas/memory-reads.js";import{existsSync as H}from"node:fs";import{launcherRequest as K}from"../../launcher/client.js";import{LAUNCHER_SOCKET as U}from"../../launcher/spec.js";import{cachePassDue as $}from"../../launcher/limits/policy.js";const B=10*6e4,Q=60*1e3,X=60*1e3,m=5*6e4,Z=14,j=1440*6e4,J=2e3,ee=5*6e4,te=16*1024*1024;async function re(f){return await A(`${f}-wal`).then(r=>r.size).catch(r=>{if(r.code==="ENOENT")return 0;throw r})<te?!1:new Promise((r,e)=>{const i=new S(`import { DatabaseSync } from 'node:sqlite';
1
+ var I=Object.defineProperty;var u=(f,t)=>I(f,"name",{value:t,configurable:!0});import{rm as E,stat as A}from"node:fs/promises";import{Worker as y}from"node:worker_threads";import{closeFocusRow as w,getFocusById as S,listFocuses as N,listNodes as g}from"../../core/canvas/index.js";import{pruneExpiredIdempotencyKeys as R}from"../../core/runs/operations.js";import{getNode as T,lastActivityMs as h,listTerminalPlacementResidue as C,pruneExpiredCreateRequests as F,pruneNodes as P}from"../../core/canvas/canvas.js";import{lastContextStripMs as D,stripContextDir as k}from"../../core/canvas/context-strip.js";import{isAppRun as x}from"../../core/canvas/app-run.js";import{isSafeNodeId as c}from"../../core/canvas/paths.js";import{emitEvent as i}from"../../core/events/emit.js";import{operationIdContext as o}from"../../core/events/operation-id.js";import{listLivePanesAsync as b,tearDownNode as W}from"../../core/runtime/placement.js";import{reapStaleSpares as G}from"../../core/runtime/warm-pool.js";import{GroveInstanceSweepReconciler as M}from"./grove-instance-sweep.js";import{ManagedWorktreeSweepReconciler as V}from"./managed-worktree-sweep.js";import{compactRunEvents as L,expireRunEvents as Y}from"../../core/runs/events.js";import{openDb as q}from"../../core/canvas/db.js";import{canvasDbPath as O}from"../../core/canvas/paths.js";import{retentionHold as _}from"./live-obligation.js";import{pruneMemoryReads as z}from"../../core/canvas/memory-reads.js";import{existsSync as H}from"node:fs";import{launcherRequest as K}from"../../launcher/client.js";import{LAUNCHER_SOCKET as U}from"../../launcher/spec.js";import{cachePassDue as $}from"../../launcher/limits/policy.js";const B=10*6e4,Q=60*1e3,X=60*1e3,m=5*6e4,Z=14,j=1440*6e4,J=2e3,ee=5*6e4,te=16*1024*1024;async function re(f){return await A(`${f}-wal`).then(r=>r.size).catch(r=>{if(r.code==="ENOENT")return 0;throw r})<te?!1:new Promise((r,e)=>{const n=new y(`import { DatabaseSync } from 'node:sqlite';
2
2
  import { parentPort, workerData } from 'node:worker_threads';
3
3
  const db = new DatabaseSync(workerData);
4
4
  try {
5
5
  db.exec('PRAGMA busy_timeout = 250');
6
6
  const rows = db.prepare('PRAGMA wal_checkpoint(TRUNCATE)').all();
7
7
  parentPort.postMessage(rows[0]?.busy === 0);
8
- } finally { db.close(); }`,{eval:!0,workerData:f});let o=!1;const l=u(d=>{o||(o=!0,clearTimeout(s),r(d))},"finish"),s=setTimeout(()=>{i.terminate(),l(!1)},3e3);i.once("message",l),i.once("error",d=>{o||(o=!0,clearTimeout(s),e(d))}),i.once("exit",()=>l(!1))})}u(re,"checkpointCanvasWal");class Ce{static{u(this,"StorageMaintenanceReconciler")}lastSpareSweepAt=Number.NEGATIVE_INFINITY;lastCreateRequestSweepAt=Number.NEGATIVE_INFINITY;lastRunExpiryAt=Number.NEGATIVE_INFINITY;lastRunEventPassAt=Number.NEGATIVE_INFINITY;runEventCursor=0;lastWalCheckpointAt=Number.NEGATIVE_INFINITY;walCheckpointInFlight=!1;lastAnalyzeAt=Number.NEGATIVE_INFINITY;lastRetentionSweepAt=Number.NEGATIVE_INFINITY;lastContextStripAt=Number.NEGATIVE_INFINITY;contextStripInFlight=!1;focusGcInFlight=!1;lastCachePassAt=null;cachePassInFlight=!1;worktreeSweep=new V;groveInstanceSweep=new M;run(t,r){if(this.reapDeadResidue(t),this.scheduleFocusGc(r),this.gcWarmPool(t),this.gcCreateRequests(t),t-this.lastRunEventPassAt>=J){this.lastRunEventPassAt=t;try{Y(t);const e=L(t,this.runEventCursor);this.runEventCursor=e.cursor}catch(e){console.warn(`run event maintenance failed: ${String(e)}`)}}if(t-this.lastRunExpiryAt>=60*6e4){try{z(t)}catch(e){console.warn(`memory-read log prune failed: ${String(e)}`)}this.lastRunExpiryAt=t}t-this.lastAnalyzeAt>=1440*6e4&&(q().exec("ANALYZE"),this.lastAnalyzeAt=t),this.sweepRetention(t,r),this.scheduleCachePass(t,r),this.scheduleContextStrip(t,r),this.scheduleWalCheckpoint(t,r),this.worktreeSweep.run(t,r),this.groveInstanceSweep.run(t,r)}scheduleCachePass(t,r){this.cachePassInFlight||!$(this.lastCachePassAt,t)||process.platform!=="linux"||!H(U)||r.lifecycle.acceptsDetachedWork()&&(this.lastCachePassAt=t,this.cachePassInFlight=!0,r.lifecycle.registerDetached(K({operation:"cache.purge"}).then(()=>{}).catch(e=>{a.fresh(()=>{n({level:"warn",event:"app.cache.pass_failed",error:e})})}).then(()=>{this.cachePassInFlight=!1})))}scheduleWalCheckpoint(t,r){this.walCheckpointInFlight||t-this.lastWalCheckpointAt<ee||r.lifecycle.acceptsDetachedWork()&&(this.lastWalCheckpointAt=t,this.walCheckpointInFlight=!0,r.lifecycle.registerDetached(re(O()).catch(e=>{console.warn(`canvas WAL checkpoint failed: ${String(e)}`)}).then(()=>{this.walCheckpointInFlight=!1})))}msSinceTerminalActivity(t,r){const e=h(t);return e===0?Number.POSITIVE_INFINITY:r-e}sweepRetention(t,r){t-this.lastRetentionSweepAt<m||r.lifecycle.acceptsDetachedWork()&&(this.lastRetentionSweepAt=t,a.fresh(()=>{try{const e=P({ttlDays:Z,held:_(r.fleet),removeDirs:u(i=>{r.lifecycle.registerDetached(Promise.all(i.map(o=>E(o,{recursive:!0,force:!0}))).then(()=>{}).catch(o=>{a.fresh(()=>{n({level:"error",event:"canvas.retention.failed",error:o})})}))},"removeDirs")});e.pruned.length>0&&n({level:"info",event:"canvas.retention.pruned",outcome:"succeeded",fields:{pruned_count:e.pruned.length}})}catch(e){n({level:"error",event:"canvas.retention.failed",error:e})}}))}scheduleContextStrip(t,r){if(this.contextStripInFlight||t-this.lastContextStripAt<m||!r.lifecycle.acceptsDetachedWork())return;this.lastContextStripAt=t,this.contextStripInFlight=!0;const e=this.stripFinishedContexts(t,r).finally(()=>{this.contextStripInFlight=!1});r.lifecycle.registerDetached(e)}async stripFinishedContexts(t,r){const e=_(r.fleet),i=u(s=>s!==null&&["done","canceled","dead"].includes(s.status)&&(s.pi_pid??null)===null&&(s.frozen_at??null)===null&&!x(s)&&h(s)<t-j&&!e(s.node_id),"eligible");let o=0,l=0;try{for(const s of R({status:["done","canceled","dead"]})){if(!c(s.node_id)||!i(s))continue;const d=await D(s.node_id);if(d!==null&&d>=h(s)||!i(C(s.node_id)))continue;let p;try{p=await k(s.node_id)}catch(v){a.fresh(()=>{n({level:"warn",event:"canvas.context_strip.node_failed",error:v,fields:{node_id:s.node_id}})});continue}p.removed.length>0&&(o+=1,l+=p.bytes)}}catch(s){a.fresh(()=>{n({level:"error",event:"canvas.context_strip.failed",error:s})})}o>0&&a.fresh(()=>{n({level:"info",event:"canvas.context_strip.completed",outcome:"succeeded",fields:{node_count:o,bytes:l}})})}reapDeadResidue(t){let r;try{r=w()}catch(e){a.fresh(()=>{n({level:"error",event:"residue.reap_scan.failed",error:e})});return}for(const e of r){try{if(this.msSinceTerminalActivity(e,t)<B)continue}catch(i){a.fresh(()=>{n({level:"error",event:"residue.reap.failed",...c(e.node_id)?{node_id:e.node_id}:{},error:i,fields:{...c(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})});continue}a.fresh(()=>{try{n({level:"info",event:"residue.reaped",...c(e.node_id)?{node_id:e.node_id}:{},fields:{...c(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}}),W(e.node_id)}catch(i){n({level:"error",event:"residue.reap.failed",...c(e.node_id)?{node_id:e.node_id}:{},error:i,fields:{...c(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})}})}}scheduleFocusGc(t){if(this.focusGcInFlight||!t.lifecycle.acceptsDetachedWork())return;this.focusGcInFlight=!0;const r=this.gcStaleFocuses().finally(()=>{this.focusGcInFlight=!1});t.lifecycle.registerDetached(r)}async gcStaleFocuses(){let t;try{t=g()}catch(e){a.fresh(()=>{n({level:"error",event:"focus.gc.failed",error:e})});return}if(t.length===0)return;let r;try{r=await b()}catch(e){a.fresh(()=>{n({level:"error",event:"focus.gc.failed",error:e})});return}if(r!==null)for(const e of t){if(e.pane===null||r.has(e.pane))continue;if(!a.fresh(()=>{try{return y(e.focus_id)?.pane!==e.pane||(n({level:"info",event:"focus.gc.removed",...c(e.node_id)?{node_id:e.node_id}:{},fields:{focus_id:e.focus_id,focus_node_id:e.node_id,pane:e.pane}}),N(e.focus_id)),!0}catch(o){return n({level:"error",event:"focus.gc.failed",error:o}),!1}}))return}}gcCreateRequests(t){t-this.lastCreateRequestSweepAt<X||(this.lastCreateRequestSweepAt=t,a.fresh(()=>{const r=F(t),e=T(t);e>0&&n({level:"info",event:"canvas.idempotency_keys.reaped",outcome:"succeeded",fields:{reaped_count:e}}),r>0&&n({level:"info",event:"canvas.create_requests.reaped",outcome:"succeeded",fields:{reaped_count:r}})}))}gcWarmPool(t){t-this.lastSpareSweepAt<Q||(this.lastSpareSweepAt=t,a.fresh(()=>{const r=G();r.length>0&&n({level:"info",event:"warm_pool.spares_reaped",outcome:"succeeded",fields:{reaped_count:r.length}})}))}}export{j as CONTEXT_STRIP_GRACE_MS,B as DEAD_REAP_GRACE_MS,m as RETENTION_SWEEP_INTERVAL_MS,Z as RETENTION_TTL_DAYS,Ce as StorageMaintenanceReconciler,re as checkpointCanvasWal};
8
+ } finally { db.close(); }`,{eval:!0,workerData:f});let a=!1;const l=u(d=>{a||(a=!0,clearTimeout(s),r(d))},"finish"),s=setTimeout(()=>{n.terminate(),l(!1)},3e3);n.once("message",l),n.once("error",d=>{a||(a=!0,clearTimeout(s),e(d))}),n.once("exit",()=>l(!1))})}u(re,"checkpointCanvasWal");class Te{static{u(this,"StorageMaintenanceReconciler")}lastSpareSweepAt=Number.NEGATIVE_INFINITY;lastCreateRequestSweepAt=Number.NEGATIVE_INFINITY;lastRunExpiryAt=Number.NEGATIVE_INFINITY;lastRunEventPassAt=Number.NEGATIVE_INFINITY;runEventCursor=0;lastWalCheckpointAt=Number.NEGATIVE_INFINITY;walCheckpointInFlight=!1;lastAnalyzeAt=Number.NEGATIVE_INFINITY;lastRetentionSweepAt=Number.NEGATIVE_INFINITY;lastContextStripAt=Number.NEGATIVE_INFINITY;contextStripInFlight=!1;focusGcInFlight=!1;lastCachePassAt=null;cachePassInFlight=!1;worktreeSweep=new V;groveInstanceSweep=new M;async run(t,r){if(await this.reapDeadResidue(t),this.scheduleFocusGc(r),await this.gcWarmPool(t),await this.gcCreateRequests(t),t-this.lastRunEventPassAt>=J){this.lastRunEventPassAt=t;try{await Y(t);const e=await L(t,this.runEventCursor);this.runEventCursor=e.cursor}catch(e){console.warn(`run event maintenance failed: ${String(e)}`)}}if(t-this.lastRunExpiryAt>=60*6e4){try{await z(t)}catch(e){console.warn(`memory-read log prune failed: ${String(e)}`)}this.lastRunExpiryAt=t}t-this.lastAnalyzeAt>=1440*6e4&&(await(await q()).exec("ANALYZE"),this.lastAnalyzeAt=t),await this.sweepRetention(t,r),this.scheduleCachePass(t,r),this.scheduleContextStrip(t,r),this.scheduleWalCheckpoint(t,r),this.worktreeSweep.run(t,r),this.groveInstanceSweep.run(t,r)}scheduleCachePass(t,r){this.cachePassInFlight||!$(this.lastCachePassAt,t)||process.platform!=="linux"||!H(U)||r.lifecycle.acceptsDetachedWork()&&(this.lastCachePassAt=t,this.cachePassInFlight=!0,r.lifecycle.registerDetached(K({operation:"cache.purge"}).then(()=>{}).catch(e=>{o.fresh(()=>{i({level:"warn",event:"app.cache.pass_failed",error:e})})}).then(()=>{this.cachePassInFlight=!1})))}scheduleWalCheckpoint(t,r){this.walCheckpointInFlight||t-this.lastWalCheckpointAt<ee||r.lifecycle.acceptsDetachedWork()&&(this.lastWalCheckpointAt=t,this.walCheckpointInFlight=!0,r.lifecycle.registerDetached(re(O()).catch(e=>{console.warn(`canvas WAL checkpoint failed: ${String(e)}`)}).then(()=>{this.walCheckpointInFlight=!1})))}msSinceTerminalActivity(t,r){const e=h(t);return e===0?Number.POSITIVE_INFINITY:r-e}async sweepRetention(t,r){t-this.lastRetentionSweepAt<m||r.lifecycle.acceptsDetachedWork()&&(this.lastRetentionSweepAt=t,await o.fresh(async()=>{try{const e=await P({ttlDays:Z,held:await _(r.fleet),removeDirs:u(n=>{r.lifecycle.registerDetached(Promise.all(n.map(a=>E(a,{recursive:!0,force:!0}))).then(()=>{}).catch(a=>{o.fresh(()=>{i({level:"error",event:"canvas.retention.failed",error:a})})}))},"removeDirs")});e.pruned.length>0&&i({level:"info",event:"canvas.retention.pruned",outcome:"succeeded",fields:{pruned_count:e.pruned.length}})}catch(e){i({level:"error",event:"canvas.retention.failed",error:e})}}))}scheduleContextStrip(t,r){if(this.contextStripInFlight||t-this.lastContextStripAt<m||!r.lifecycle.acceptsDetachedWork())return;this.lastContextStripAt=t,this.contextStripInFlight=!0;const e=this.stripFinishedContexts(t,r).finally(()=>{this.contextStripInFlight=!1});r.lifecycle.registerDetached(e)}async stripFinishedContexts(t,r){const e=await _(r.fleet),n=u(async s=>s!==null&&["done","canceled","dead"].includes(s.status)&&(s.pi_pid??null)===null&&(s.frozen_at??null)===null&&!x(s)&&h(s)<t-j&&!await e(s.node_id),"eligible");let a=0,l=0;try{for(const s of await g({status:["done","canceled","dead"]})){if(!c(s.node_id)||!await n(s))continue;const d=await D(s.node_id);if(d!==null&&d>=h(s)||!await n(await T(s.node_id)))continue;let p;try{p=await k(s.node_id)}catch(v){o.fresh(()=>{i({level:"warn",event:"canvas.context_strip.node_failed",error:v,fields:{node_id:s.node_id}})});continue}p.removed.length>0&&(a+=1,l+=p.bytes)}}catch(s){o.fresh(()=>{i({level:"error",event:"canvas.context_strip.failed",error:s})})}a>0&&o.fresh(()=>{i({level:"info",event:"canvas.context_strip.completed",outcome:"succeeded",fields:{node_count:a,bytes:l}})})}async reapDeadResidue(t){let r;try{r=await C()}catch(e){o.fresh(()=>{i({level:"error",event:"residue.reap_scan.failed",error:e})});return}for(const e of r){try{if(this.msSinceTerminalActivity(e,t)<B)continue}catch(n){o.fresh(()=>{i({level:"error",event:"residue.reap.failed",...c(e.node_id)?{node_id:e.node_id}:{},error:n,fields:{...c(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})});continue}await o.fresh(async()=>{try{i({level:"info",event:"residue.reaped",...c(e.node_id)?{node_id:e.node_id}:{},fields:{...c(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}}),await W(e.node_id)}catch(n){i({level:"error",event:"residue.reap.failed",...c(e.node_id)?{node_id:e.node_id}:{},error:n,fields:{...c(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})}})}}scheduleFocusGc(t){if(this.focusGcInFlight||!t.lifecycle.acceptsDetachedWork())return;this.focusGcInFlight=!0;const r=this.gcStaleFocuses().finally(()=>{this.focusGcInFlight=!1});t.lifecycle.registerDetached(r)}async gcStaleFocuses(){let t;try{t=await N()}catch(e){o.fresh(()=>{i({level:"error",event:"focus.gc.failed",error:e})});return}if(t.length===0)return;let r;try{r=await b()}catch(e){o.fresh(()=>{i({level:"error",event:"focus.gc.failed",error:e})});return}if(r!==null)for(const e of t){if(e.pane===null||r.has(e.pane))continue;if(!await o.fresh(async()=>{try{return(await S(e.focus_id))?.pane!==e.pane||(i({level:"info",event:"focus.gc.removed",...c(e.node_id)?{node_id:e.node_id}:{},fields:{focus_id:e.focus_id,focus_node_id:e.node_id,pane:e.pane}}),await w(e.focus_id)),!0}catch(a){return i({level:"error",event:"focus.gc.failed",error:a}),!1}}))return}}async gcCreateRequests(t){t-this.lastCreateRequestSweepAt<X||(this.lastCreateRequestSweepAt=t,await o.fresh(async()=>{const r=await F(t),e=await R(t);e>0&&i({level:"info",event:"canvas.idempotency_keys.reaped",outcome:"succeeded",fields:{reaped_count:e}}),r>0&&i({level:"info",event:"canvas.create_requests.reaped",outcome:"succeeded",fields:{reaped_count:r}})}))}async gcWarmPool(t){t-this.lastSpareSweepAt<Q||(this.lastSpareSweepAt=t,await o.fresh(async()=>{const r=await G();r.length>0&&i({level:"info",event:"warm_pool.spares_reaped",outcome:"succeeded",fields:{reaped_count:r.length}})}))}}export{j as CONTEXT_STRIP_GRACE_MS,B as DEAD_REAP_GRACE_MS,m as RETENTION_SWEEP_INTERVAL_MS,Z as RETENTION_TTL_DAYS,Te as StorageMaintenanceReconciler,re as checkpointCanvasWal};
@@ -1,4 +1,4 @@
1
1
  /** Settles rows whose waiter disappeared and retries every incomplete durable effect. */
2
2
  export declare class StructuredRequestReconciler {
3
- run(now: number): void;
3
+ run(now: number): Promise<void>;
4
4
  }
@@ -1 +1 @@
1
- var u=Object.defineProperty;var c=(o,t)=>u(o,"name",{value:t,configurable:!0});import{withCanvasWrite as n}from"../../core/canvas/db.js";import{incompleteStructuredRequestEffects as d,pendingStructuredRequestsPast as f,settleStructuredRequestIn as l}from"../../core/canvas/structured-requests.js";import{emitEvent as m}from"../../core/events/emit.js";import{applySettlementEffects as s}from"../structured-requests/effects.js";class S{static{c(this,"StructuredRequestReconciler")}run(t){try{for(const e of f(t)){const r=n(i=>l(i,e.request_id,{intended:"expired",now:t}));r.changed&&r.row!==null&&s(r.row)}for(const e of d())s(e)}catch(e){m({level:"error",event:"structured_request.reconcile_failed",error:e})}}}export{S as StructuredRequestReconciler};
1
+ var n=Object.defineProperty;var i=(o,t)=>n(o,"name",{value:t,configurable:!0});import{withCanvasWrite as a}from"../../core/canvas/db.js";import{incompleteStructuredRequestEffects as u,pendingStructuredRequestsPast as d,settleStructuredRequestIn as f}from"../../core/canvas/structured-requests.js";import{emitEvent as l}from"../../core/events/emit.js";import{applySettlementEffects as c}from"../structured-requests/effects.js";class R{static{i(this,"StructuredRequestReconciler")}async run(t){try{for(const e of await d(t)){const r=await a(async s=>await f(s,e.request_id,{intended:"expired",now:t}));r.changed&&r.row!==null&&c(r.row)}for(const e of await u())c(e)}catch(e){l({level:"error",event:"structured_request.reconcile_failed",error:e})}}}export{R as StructuredRequestReconciler};
@@ -1,2 +1,2 @@
1
- var v=Object.defineProperty;var t=(e,n)=>v(e,"name",{value:n,configurable:!0});import{appendDeliveryEvent as c}from"../../core/review/comments.js";import{deliverNodeMessage as l}from"../messaging/node-message.js";function m(e){switch(e){case"create":case"edit":case"reopen":return"wake";case"resolve":case"delete":return"quiet"}}t(m,"defaultDeliverMode");function _(e){return e.anchor.end_line>e.anchor.line?`L${e.anchor.line}-${e.anchor.end_line}`:`L${e.anchor.line}`}t(_,"range");function s(e){const n=e.anchor.quote;return n===void 0||n===""?e.anchor_line_text:n}t(s,"quotedSource");function f(e){switch(e){case"create":return"created";case"edit":return"edited";case"resolve":return"resolved";case"reopen":return"reopened";case"delete":return"deleted"}}t(f,"verbPastTense");function w(e,n,r){return[`Review comment ${n.comment_id} was ${f(r)} in review ${e.review_id}.`,"",`File: ${e.file}`,`Range: ${_(n)}`,"Quoted source:",s(n),"","Comment:",n.text].join(`
2
- `)}t(w,"renderCommentNotice");function p(e){return e instanceof Error?e.message:String(e)}t(p,"errorMessage");async function $(e){if(e.actor_node_id===e.review.companion_node_id&&e.deliver===void 0)return{attempted:!1,status:"skipped",woke:!1};const n=e.review.companion_node_id,r=e.deliver??m(e.verb),a=w(e.review,e.comment,e.verb);let i;try{i=await l({node_id:n,body:a,label:"review comment",from:"crtrd",mode:r==="wake"?"interactive":"quiet",data:{review_id:e.review.review_id,comment_id:e.comment.comment_id,verb:e.verb},runtime:{kind:"review-comment",facts:{}}})}catch(u){const d={attempted:!0,target_node_id:n,status:"failed",woke:!1,error:p(u)};return c({review_id:e.review.review_id,comment_id:e.comment.comment_id,kind:"notify_failed",payload:d,operation_id:e.operation_id}),d}const o={attempted:!0,target_node_id:n,status:"delivered",via:i.via,woke:i.revived,...i.reason===void 0?{}:{reason:i.reason}};return c({review_id:e.review.review_id,comment_id:e.comment.comment_id,kind:"notified",payload:o,operation_id:e.operation_id}),o}t($,"notifyComment");export{$ as notifyComment,w as renderCommentNotice};
1
+ var v=Object.defineProperty;var i=(e,t)=>v(e,"name",{value:t,configurable:!0});import{appendDeliveryEvent as a}from"../../core/review/comments.js";import{deliverNodeMessage as l}from"../messaging/node-message.js";function m(e){switch(e){case"create":case"edit":case"reopen":return"wake";case"resolve":case"delete":return"quiet"}}i(m,"defaultDeliverMode");function _(e){return e.anchor.end_line>e.anchor.line?`L${e.anchor.line}-${e.anchor.end_line}`:`L${e.anchor.line}`}i(_,"range");function s(e){const t=e.anchor.quote;return t===void 0||t===""?e.anchor_line_text:t}i(s,"quotedSource");function w(e){switch(e){case"create":return"created";case"edit":return"edited";case"resolve":return"resolved";case"reopen":return"reopened";case"delete":return"deleted"}}i(w,"verbPastTense");function f(e,t,r){return[`Review comment ${t.comment_id} was ${w(r)} in review ${e.review_id}.`,"",`File: ${e.file}`,`Range: ${_(t)}`,"Quoted source:",s(t),"","Comment:",t.text].join(`
2
+ `)}i(f,"renderCommentNotice");function p(e){return e instanceof Error?e.message:String(e)}i(p,"errorMessage");async function $(e){if(e.actor_node_id===e.review.companion_node_id&&e.deliver===void 0)return{attempted:!1,status:"skipped",woke:!1};const t=e.review.companion_node_id,r=e.deliver??m(e.verb),c=f(e.review,e.comment,e.verb);let n;try{n=await l({node_id:t,body:c,label:"review comment",from:"crtrd",mode:r==="wake"?"interactive":"quiet",data:{review_id:e.review.review_id,comment_id:e.comment.comment_id,verb:e.verb},runtime:{kind:"review-comment",facts:{}}})}catch(u){const d={attempted:!0,target_node_id:t,status:"failed",woke:!1,error:p(u)};return await a({review_id:e.review.review_id,comment_id:e.comment.comment_id,kind:"notify_failed",payload:d,operation_id:e.operation_id}),d}const o={attempted:!0,target_node_id:t,status:"delivered",via:n.via,woke:n.revived,...n.reason===void 0?{}:{reason:n.reason}};return await a({review_id:e.review.review_id,comment_id:e.comment.comment_id,kind:"notified",payload:o,operation_id:e.operation_id}),o}i($,"notifyComment");export{$ as notifyComment,f as renderCommentNotice};
@@ -1,8 +1,8 @@
1
1
  /** Is the companion inside a turn right now? */
2
- export declare function companionMidTurn(nodeId: string): boolean;
2
+ export declare function companionMidTurn(nodeId: string): Promise<boolean>;
3
3
  /** Does the companion hold work it has not yet consumed? A deferred entry is
4
4
  * excluded for the same reason the settlement policy excludes it: it never
5
5
  * starts a turn of its own. */
6
- export declare function companionHasQueuedWork(nodeId: string): boolean;
6
+ export declare function companionHasQueuedWork(nodeId: string): Promise<boolean>;
7
7
  /** Would submitting right now step on the companion's work? */
8
- export declare function companionStillWorking(nodeId: string): boolean;
8
+ export declare function companionStillWorking(nodeId: string): Promise<boolean>;
@@ -1 +1 @@
1
- var e=Object.defineProperty;var r=(n,o)=>e(n,"name",{value:o,configurable:!0});import{readLiveTurn as i}from"../../core/canvas/recovery.js";import{hasUnseenWakeMail as t}from"../../core/canvas/deliveries.js";function u(n){return i(n)?.busy??!1}r(u,"companionMidTurn");function a(n){return t(n)}r(a,"companionHasQueuedWork");function f(n){return u(n)||a(n)}r(f,"companionStillWorking");export{a as companionHasQueuedWork,u as companionMidTurn,f as companionStillWorking};
1
+ var i=Object.defineProperty;var a=(n,r)=>i(n,"name",{value:r,configurable:!0});import{readLiveTurn as o}from"../../core/canvas/recovery.js";import{hasUnseenWakeMail as t}from"../../core/canvas/deliveries.js";async function e(n){return(await o(n))?.busy??!1}a(e,"companionMidTurn");async function u(n){return await t(n)}a(u,"companionHasQueuedWork");async function m(n){return await e(n)||await u(n)}a(m,"companionStillWorking");export{u as companionHasQueuedWork,e as companionMidTurn,m as companionStillWorking};
@@ -1 +1 @@
1
- var g=Object.defineProperty;var n=(e,t)=>g(e,"name",{value:t,configurable:!0});import{withCanvasWrite as j}from"../../core/canvas/db.js";import{get as S}from"../../core/graph/bodies.js";import{documentById as q,editDocument as C,heads as $}from"../../core/graph/documents.js";import{readerFor as k}from"../../core/graph/reader.js";import{checkoutsForCwd as J}from"../../core/graph/repo-sync/repos.js";import{snapshotCommentsLocked as x}from"../../core/review/comments.js";import{readReviewSource as N}from"../../core/review/document.js";import{projectReviewCancellation as O,projectReviewResult as T,buildReviewResult as A}from"../../core/review/project.js";import{signalReviewActivity as p}from"../../core/review/signal.js";import{clearReviewSubmit as D,getReview as E,getReviewByCompanion as B,requestReviewSubmit as F,requireVisibleReview as u}from"../../core/review/store.js";import{ReviewOperationError as f}from"../../core/review/types.js";import{settleHumanRequest as w}from"../human/settle.js";import{retireCompanion as h}from"../companion-retire.js";import{companionHasQueuedWork as W,companionMidTurn as H,companionStillWorking as M}from"./companion.js";import{renderApprovalMessage as L}from"./deliver.js";function _(){return new Date().toISOString()}n(_,"now");function l(e,t){throw new f("review_terminal","review already has a terminal outcome",{state:e.state,requested:t,review:e})}n(l,"terminalConflict");function v(e){if(e.result_json===null)throw new Error(`approved review lacks its immutable result: ${e.review_id}`);return JSON.parse(e.result_json)}n(v,"approvedResult");function y(e){return`${e.review_dir}/result.json`}n(y,"resultPath");function P(e){return{project:n(t=>{T(u(t.request_id),e)},"project"),retire:n(async(t,o)=>{await h(t,o)},"retire")}}n(P,"effects");function Q(e){return{label:"review approved by the user",disposition:null,body_json:{review_id:e.review_id,result_path:y(e),body:L(e,y(e))}}}n(Q,"approvalNotification");function V(e,t,o){const s=o==="dismissed";return{label:s?"review dismissed":"review canceled",disposition:"human-canceled",body_json:{review_id:e.review_id,disposition:o,body:s?`The review of \`${e.document_name??e.file}\` was dismissed without approval.`:`The review of \`${e.document_name??e.file}\` was canceled${t===""?"":` \u2014 ${t}`}.`}}}n(V,"cancellationNotification");function z(e,t,o){if(t.document_id===null||t.document_base===null)return;const s=n(d=>J(e,d),"reposFn"),i=q(e,t.document_id),a=k(e,{class:"person"},s),c=C(e,a,i,{body:o},`edited in review ${t.review_id}`,t.document_base,{},s);if(!("stale"in c))return;const r=$(e,i);if(!(r.length===1&&S(r[0].body_hash)===o))throw new f("stale_revision",`${t.document_name??i.name} changed since the review began; the reviewed text was not saved`,{review_id:t.review_id,document:t.document_name??i.name,base:t.document_base,heads_key:c.stale.heads_key,revision:c.stale.revision,next:`Read the current revision with \`crtr canvas read ${i.id}\`, then start a new review of it.`})}n(z,"saveReviewedDocument");async function b(e){if(e.state==="canceled")return l(e,"submit");if(e.state==="approved")return{outcome:"already_settled",record:e,result:v(e)};const t=N(e.file,"submit"),{result:o,resultJson:s}=j(c=>{const r=u(e.review_id);if(r.state==="canceled")return l(r,"submit");if(r.state==="approved")return{result:v(r),resultJson:r.result_json};const d=x(c,r.review_id),m=A(r,d,t.sha256,_());return m.changed&&z(c,r,new TextDecoder("utf-8").decode(t.bytes)),{result:m,resultJson:JSON.stringify(m)}}),i=await w({request_id:e.review_id,outcome:"approved",result_json:s,notification:Q({...e,changed:o.changed}),post_commit:P(o)});i.outcome==="settled"&&p();const a=u(e.review_id);return i.outcome==="already_settled"&&a.state!=="approved"?l(a,"submit"):{outcome:i.outcome,record:a,result:i.outcome==="settled"?o:v(a)}}n(b,"approveReview");async function de(e){const t=u(e);return t.state==="canceled"?l(t,"submit"):t.state==="open"&&M(t.companion_node_id)?(F(e,_())&&p(),{outcome:"awaiting_companion",record:u(e)}):b(t)}n(de,"submitReviewApproval");async function G(e,t){const o=E(e);if(o===null||o.state!=="open"||o.submit_requested_at===null||W(o.companion_node_id)||!t.atCompanionTurnEnd&&H(o.companion_node_id))return null;try{return await b(o)}catch(s){throw s instanceof f&&s.code==="stale_revision"&&(D(e),p()),s}}n(G,"completeRequestedSubmit");async function me(e){const t=B(e);return t===null?null:G(t.review_id,{atCompanionTurnEnd:!0})}n(me,"completeCompanionRequestedSubmit");async function le(e,t={}){const o=u(e);if(o.state==="approved")return l(o,"cancel");const s=_(),i=t.reason??"",a=t.disposition??"canceled",c=JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:s,...i===""?{}:{reason:i},...t.actor===void 0?{}:{actor:t.actor},...a==="dismissed"?{disposition:a}:{}}),r=await w({request_id:e,outcome:a==="dismissed"?"dismissed":"canceled",result_json:c,notification:V(o,i,a),post_commit:{project:n(m=>{O(u(m.request_id),JSON.parse(c))},"project"),retire:n(async(m,R)=>{await h(m,R)},"retire")}});r.outcome==="settled"&&p();const d=u(e);return r.outcome==="already_settled"&&d.state==="approved"?l(d,"cancel"):{outcome:r.outcome,record:d}}n(le,"cancelReview");export{le as cancelReview,me as completeCompanionRequestedSubmit,G as completeRequestedSubmit,de as submitReviewApproval};
1
+ var g=Object.defineProperty;var n=(e,t)=>g(e,"name",{value:t,configurable:!0});import{withCanvasWrite as j}from"../../core/canvas/db.js";import{get as S}from"../../core/graph/bodies.js";import{documentById as q,editDocument as C,heads as $}from"../../core/graph/documents.js";import{readerFor as k}from"../../core/graph/reader.js";import{checkoutsForCwd as J}from"../../core/graph/repo-sync/repos.js";import{snapshotCommentsLocked as x}from"../../core/review/comments.js";import{readReviewSource as N}from"../../core/review/document.js";import{projectReviewCancellation as O,projectReviewResult as T,buildReviewResult as A}from"../../core/review/project.js";import{signalReviewActivity as p}from"../../core/review/signal.js";import{clearReviewSubmit as D,getReview as E,getReviewByCompanion as B,requestReviewSubmit as F,requireVisibleReview as u}from"../../core/review/store.js";import{ReviewOperationError as w}from"../../core/review/types.js";import{settleHumanRequest as v}from"../human/settle.js";import{retireCompanion as h}from"../companion-retire.js";import{companionHasQueuedWork as W,companionMidTurn as H,companionStillWorking as M}from"./companion.js";import{renderApprovalMessage as L}from"./deliver.js";function f(){return new Date().toISOString()}n(f,"now");function l(e,t){throw new w("review_terminal","review already has a terminal outcome",{state:e.state,requested:t,review:e})}n(l,"terminalConflict");function _(e){if(e.result_json===null)throw new Error(`approved review lacks its immutable result: ${e.review_id}`);return JSON.parse(e.result_json)}n(_,"approvedResult");function y(e){return`${e.review_dir}/result.json`}n(y,"resultPath");function P(e){return{project:n(async t=>{T(await u(t.request_id),e)},"project"),retire:n(async(t,o)=>{await h(t,o)},"retire")}}n(P,"effects");function Q(e){return{label:"review approved by the user",disposition:null,body_json:{review_id:e.review_id,result_path:y(e),body:L(e,y(e))}}}n(Q,"approvalNotification");function V(e,t,o){const a=o==="dismissed";return{label:a?"review dismissed":"review canceled",disposition:"human-canceled",body_json:{review_id:e.review_id,disposition:o,body:a?`The review of \`${e.document_name??e.file}\` was dismissed without approval.`:`The review of \`${e.document_name??e.file}\` was canceled${t===""?"":` \u2014 ${t}`}.`}}}n(V,"cancellationNotification");async function z(e,t,o){if(t.document_id===null||t.document_base===null)return;const a=n(async d=>await J(e,d),"reposFn"),i=await q(e,t.document_id),s=await k(e,{class:"person"},a),c=await C(e,s,i,{body:o},`edited in review ${t.review_id}`,t.document_base,{},a);if(!("stale"in c))return;const r=await $(e,i);if(!(r.length===1&&S(r[0].body_hash)===o))throw new w("stale_revision",`${t.document_name??i.name} changed since the review began; the reviewed text was not saved`,{review_id:t.review_id,document:t.document_name??i.name,base:t.document_base,heads_key:c.stale.heads_key,revision:c.stale.revision,next:`Read the current revision with \`crtr canvas read ${i.id}\`, then start a new review of it.`})}n(z,"saveReviewedDocument");async function b(e){if(e.state==="canceled")return l(e,"submit");if(e.state==="approved")return{outcome:"already_settled",record:e,result:_(e)};const t=N(e.file,"submit"),{result:o,resultJson:a}=await j(async c=>{const r=await u(e.review_id);if(r.state==="canceled")return l(r,"submit");if(r.state==="approved")return{result:_(r),resultJson:r.result_json};const d=await x(c,r.review_id),m=A(r,d,t.sha256,f());return m.changed&&await z(c,r,new TextDecoder("utf-8").decode(t.bytes)),{result:m,resultJson:JSON.stringify(m)}}),i=await v({request_id:e.review_id,outcome:"approved",result_json:a,notification:Q({...e,changed:o.changed}),post_commit:P(o)});i.outcome==="settled"&&p();const s=await u(e.review_id);return i.outcome==="already_settled"&&s.state!=="approved"?l(s,"submit"):{outcome:i.outcome,record:s,result:i.outcome==="settled"?o:_(s)}}n(b,"approveReview");async function de(e){const t=await u(e);return t.state==="canceled"?l(t,"submit"):t.state==="open"&&await M(t.companion_node_id)?(await F(e,f())&&p(),{outcome:"awaiting_companion",record:await u(e)}):b(t)}n(de,"submitReviewApproval");async function G(e,t){const o=await E(e);if(o===null||o.state!=="open"||o.submit_requested_at===null||await W(o.companion_node_id)||!t.atCompanionTurnEnd&&await H(o.companion_node_id))return null;try{return await b(o)}catch(a){throw a instanceof w&&a.code==="stale_revision"&&(await D(e),p()),a}}n(G,"completeRequestedSubmit");async function me(e){const t=await B(e);return t===null?null:G(t.review_id,{atCompanionTurnEnd:!0})}n(me,"completeCompanionRequestedSubmit");async function le(e,t={}){const o=await u(e);if(o.state==="approved")return l(o,"cancel");const a=f(),i=t.reason??"",s=t.disposition??"canceled",c=JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:a,...i===""?{}:{reason:i},...t.actor===void 0?{}:{actor:t.actor},...s==="dismissed"?{disposition:s}:{}}),r=await v({request_id:e,outcome:s==="dismissed"?"dismissed":"canceled",result_json:c,notification:V(o,i,s),post_commit:{project:n(async m=>{O(await u(m.request_id),JSON.parse(c))},"project"),retire:n(async(m,R)=>{await h(m,R)},"retire")}});r.outcome==="settled"&&p();const d=await u(e);return r.outcome==="already_settled"&&d.state==="approved"?l(d,"cancel"):{outcome:r.outcome,record:d}}n(le,"cancelReview");export{le as cancelReview,me as completeCompanionRequestedSubmit,G as completeRequestedSubmit,de as submitReviewApproval};
@@ -1 +1 @@
1
- var o=Object.defineProperty;var i=(r,e)=>o(r,"name",{value:e,configurable:!0});import{requireVisibleReview as t}from"../../core/review/store.js";import{projectReviewResult as s}from"../../core/review/project.js";import{realizeReview as m}from"../../core/review/realize.js";import{retireCompanion as n}from"../companion-retire.js";import{sweepHumanRequests as p}from"../human/sweep.js";async function f(){return p({realizeReview:m,projectReview:i(r=>{const e=t(r.request_id);if(e.result_json===null)throw new Error(`approved review lacks its immutable result: ${e.review_id}`);s(e,JSON.parse(e.result_json))},"projectReview"),retireCompanion:i(async(r,e)=>{await n(r,e)},"retireCompanion")})}i(f,"sweepReviews");export{f as sweepReviews};
1
+ var o=Object.defineProperty;var i=(r,e)=>o(r,"name",{value:e,configurable:!0});import{requireVisibleReview as t}from"../../core/review/store.js";import{projectReviewResult as s}from"../../core/review/project.js";import{realizeReview as n}from"../../core/review/realize.js";import{retireCompanion as a}from"../companion-retire.js";import{sweepHumanRequests as m}from"../human/sweep.js";async function f(){return m({realizeReview:n,projectReview:i(async r=>{const e=await t(r.request_id);if(e.result_json===null)throw new Error(`approved review lacks its immutable result: ${e.review_id}`);s(e,JSON.parse(e.result_json))},"projectReview"),retireCompanion:i(async(r,e)=>{await a(r,e)},"retireCompanion")})}i(f,"sweepReviews");export{f as sweepReviews};
@@ -17,9 +17,9 @@ export interface NoticeToken {
17
17
  }
18
18
  export interface RunNoticeDeps {
19
19
  /** The run's notice target, or null when the run never notifies. */
20
- target(runId: string): NoticeTarget | null;
20
+ target(runId: string): Promise<NoticeTarget | null>;
21
21
  /** The run's highest event sequence. */
22
- latest(runId: string): number | null;
22
+ latest(runId: string): Promise<number | null>;
23
23
  token(target: NoticeTarget): Promise<NoticeToken>;
24
24
  discard(key: string): void;
25
25
  fetch: typeof fetch;
@@ -35,9 +35,9 @@ export declare class RunNoticeOutbox {
35
35
  private state;
36
36
  private forget;
37
37
  /** A `run.events` stream opened on the run. Returns its release, called with the last sequence the stream wrote. */
38
- streamOpened(runId: string): (lastWritten: number) => void;
38
+ streamOpened(runId: string): Promise<(lastWritten: number) => Promise<void>>;
39
39
  /** An event was appended to the run's log. */
40
- appended(runId: string): void;
40
+ appended(runId: string): Promise<void>;
41
41
  private owe;
42
42
  private schedule;
43
43
  private deliver;
@@ -1 +1 @@
1
- var p=Object.defineProperty;var a=(n,t)=>p(n,"name",{value:t,configurable:!0});import{prepared as d}from"../core/sqlite-statements.js";import{openDb as f}from"../core/canvas/db.js";import{runNoticeTarget as m}from"../core/grants/mirror.js";import{emitEvent as w}from"../core/events/emit.js";import{discardFile as _}from"../core/providers/token-cache.js";import{outboundToken as g}from"../core/providers/mint.js";const y="crtr:run_notice",A=[3e3,5e3],E=5e3,T=6e4,k=1e4;class u extends Error{static{a(this,"Fault")}retryable;status;constructor(t,e,s){super(t),this.retryable=e,this.status=s}}class x{static{a(this,"RunNoticeOutbox")}deps;runs=new Map;constructor(t){this.deps=t}state(t){let e=this.runs.get(t);return e||(e={streams:0,owed:!1,inFlight:!1,timer:void 0,nextAllowedAt:0},this.runs.set(t,e)),e}forget(t,e){e.streams===0&&!e.owed&&!e.inFlight&&e.timer===void 0&&e.nextAllowedAt<=this.deps.now()&&this.runs.delete(t)}streamOpened(t){const e=this.state(t);e.streams++,e.owed=!1,e.nextAllowedAt=0,e.timer&&(clearTimeout(e.timer),e.timer=void 0);let s=!1;return l=>{if(s)return;s=!0,e.streams--;let o=null;try{o=this.deps.latest(t)}catch{}e.streams===0&&o!==null&&o>l?this.owe(t):this.forget(t,e)}}appended(t){const e=this.runs.get(t);e&&e.streams>0||this.owe(t)}owe(t){let e;try{e=this.deps.target(t)}catch{return}if(e===null)return;const s=this.state(t);s.streams>0||(s.owed=!0,this.schedule(t,s))}schedule(t,e){if(!e.owed||e.inFlight||e.timer!==void 0||e.streams>0)return;const s=Math.max(0,e.nextAllowedAt-this.deps.now());e.timer=setTimeout(()=>{e.timer=void 0,this.deliver(t,e)},s),e.timer.unref()}async deliver(t,e){if(!e.owed||e.streams>0){this.forget(t,e);return}const s=this.deps.target(t),l=this.deps.latest(t);if(s===null||l===null){e.owed=!1,this.forget(t,e);return}e.owed=!1,e.inFlight=!0;let o=0,r;try{for(;;){o++;try{await this.attempt(s,t,l),r=void 0;break}catch(i){r=i instanceof u?i:new u(i instanceof Error?i.message:String(i),!0);const c=this.deps.retryWaitsMs[o-1];if(!r.retryable||c===void 0)break;if(await new Promise(h=>{setTimeout(h,c).unref()}),e.streams>0){r=void 0;break}}}}finally{e.inFlight=!1}r?(e.nextAllowedAt=this.deps.now()+this.deps.failGapMs,w({level:"error",event:"run_notice.failed",fields:{run_id:t,url:s.url,grantee:s.grantee,attempts:o,latest_sequence:l,...r.status===void 0?{}:{status:r.status},error:r.message}})):e.streams===0&&(e.nextAllowedAt=this.deps.now()+this.deps.ackGapMs),this.schedule(t,e),this.forget(t,e)}async attempt(t,e,s){for(let l=0;;l++){let o;try{o=await this.deps.token(t)}catch(i){throw new u(`token mint failed: ${i instanceof Error?i.message:String(i)}`,!0)}let r;try{r=await this.deps.fetch(t.url,{method:"POST",redirect:"manual",signal:AbortSignal.timeout(k),headers:{Authorization:`Bearer ${o.access_token}`,"Content-Type":"application/json"},body:JSON.stringify({run_id:e,latest_sequence:s})})}catch(i){throw new u(`request failed: ${i instanceof Error?i.message:String(i)}`,!0)}if(r.body?.cancel().catch(()=>{}),r.status>=200&&r.status<300)return;if(r.status===401){if(this.deps.discard(o.key),l===0)continue;throw new u("the app refused the notice token twice (401)",!0,401)}throw r.status>=500?new u(`the app answered ${r.status}`,!0,r.status):new u(`contract_fault: the app answered ${r.status}`,!1,r.status)}}}function M(){return{target:a(n=>{const t=d(f(),"SELECT grant_id FROM nodes WHERE node_id = ? AND run_id = ?").get(n,n);return t?.grant_id?m(t.grant_id):null},"target"),latest:a(n=>{const t=d(f(),"SELECT event_cursor FROM nodes WHERE node_id = ? AND run_id = ?").get(n,n);return t?.event_cursor==null?null:t.event_cursor-1},"latest"),token:a(async n=>{const t=await g({audience:n.url,sub:n.sub,grantee:n.grantee,initiating_app:n.grantee,scope:[y]});return{access_token:t.access_token,key:t.key}},"token"),discard:_,fetch:a((n,t)=>fetch(n,t),"fetch"),now:Date.now,retryWaitsMs:A,ackGapMs:E,failGapMs:T}}a(M,"databaseDeps");let N;function P(){return N??=new x(M())}a(P,"runNotices");export{E as RUN_NOTICE_ACK_GAP_MS,k as RUN_NOTICE_ATTEMPT_TIMEOUT_MS,T as RUN_NOTICE_FAIL_GAP_MS,A as RUN_NOTICE_RETRY_WAITS_MS,y as RUN_NOTICE_SCOPE,x as RunNoticeOutbox,M as databaseDeps,P as runNotices};
1
+ var h=Object.defineProperty;var o=(i,t)=>h(i,"name",{value:t,configurable:!0});import{openDb as d}from"../core/canvas/db.js";import{runNoticeTarget as p}from"../core/grants/mirror.js";import{emitEvent as w}from"../core/events/emit.js";import{discardFile as m}from"../core/providers/token-cache.js";import{outboundToken as _}from"../core/providers/mint.js";const g="crtr:run_notice",y=[3e3,5e3],A=5e3,E=6e4,T=1e4;class c extends Error{static{o(this,"Fault")}retryable;status;constructor(t,e,r){super(t),this.retryable=e,this.status=r}}class k{static{o(this,"RunNoticeOutbox")}deps;runs=new Map;constructor(t){this.deps=t}state(t){let e=this.runs.get(t);return e||(e={streams:0,owed:!1,inFlight:!1,timer:void 0,nextAllowedAt:0},this.runs.set(t,e)),e}forget(t,e){e.streams===0&&!e.owed&&!e.inFlight&&e.timer===void 0&&e.nextAllowedAt<=this.deps.now()&&this.runs.delete(t)}async streamOpened(t){const e=this.state(t);e.streams++,e.owed=!1,e.nextAllowedAt=0,e.timer&&(clearTimeout(e.timer),e.timer=void 0);let r=!1;return async l=>{if(r)return;r=!0,e.streams--;let a=null;try{a=await this.deps.latest(t)}catch{}e.streams===0&&a!==null&&a>l?await this.owe(t):this.forget(t,e)}}async appended(t){const e=this.runs.get(t);e&&e.streams>0||await this.owe(t)}async owe(t){let e;try{e=await this.deps.target(t)}catch{return}if(e===null)return;const r=this.state(t);r.streams>0||(r.owed=!0,this.schedule(t,r))}schedule(t,e){if(!e.owed||e.inFlight||e.timer!==void 0||e.streams>0)return;const r=Math.max(0,e.nextAllowedAt-this.deps.now());e.timer=setTimeout(()=>{e.timer=void 0,this.deliver(t,e)},r),e.timer.unref()}async deliver(t,e){if(!e.owed||e.streams>0){this.forget(t,e);return}const r=await this.deps.target(t),l=await this.deps.latest(t);if(r===null||l===null){e.owed=!1,this.forget(t,e);return}e.owed=!1,e.inFlight=!0;let a=0,s;try{for(;;){a++;try{await this.attempt(r,t,l),s=void 0;break}catch(n){s=n instanceof c?n:new c(n instanceof Error?n.message:String(n),!0);const u=this.deps.retryWaitsMs[a-1];if(!s.retryable||u===void 0)break;if(await new Promise(f=>{setTimeout(f,u).unref()}),e.streams>0){s=void 0;break}}}}finally{e.inFlight=!1}s?(e.nextAllowedAt=this.deps.now()+this.deps.failGapMs,w({level:"error",event:"run_notice.failed",fields:{run_id:t,url:r.url,grantee:r.grantee,attempts:a,latest_sequence:l,...s.status===void 0?{}:{status:s.status},error:s.message}})):e.streams===0&&(e.nextAllowedAt=this.deps.now()+this.deps.ackGapMs),this.schedule(t,e),this.forget(t,e)}async attempt(t,e,r){for(let l=0;;l++){let a;try{a=await this.deps.token(t)}catch(n){throw new c(`token mint failed: ${n instanceof Error?n.message:String(n)}`,!0)}let s;try{s=await this.deps.fetch(t.url,{method:"POST",redirect:"manual",signal:AbortSignal.timeout(T),headers:{Authorization:`Bearer ${a.access_token}`,"Content-Type":"application/json"},body:JSON.stringify({run_id:e,latest_sequence:r})})}catch(n){throw new c(`request failed: ${n instanceof Error?n.message:String(n)}`,!0)}if(s.body?.cancel().catch(()=>{}),s.status>=200&&s.status<300)return;if(s.status===401){if(this.deps.discard(a.key),l===0)continue;throw new c("the app refused the notice token twice (401)",!0,401)}throw s.status>=500?new c(`the app answered ${s.status}`,!0,s.status):new c(`contract_fault: the app answered ${s.status}`,!1,s.status)}}}function x(){return{target:o(async i=>{const t=await(await d()).prepare("SELECT grant_id FROM nodes WHERE node_id = ? AND run_id = ?").get(i,i);return t?.grant_id?await p(t.grant_id):null},"target"),latest:o(async i=>{const t=await(await d()).prepare("SELECT event_cursor FROM nodes WHERE node_id = ? AND run_id = ?").get(i,i);return t?.event_cursor==null?null:t.event_cursor-1},"latest"),token:o(async i=>{const t=await _({audience:i.url,sub:i.sub,grantee:i.grantee,initiating_app:i.grantee,scope:[g]});return{access_token:t.access_token,key:t.key}},"token"),discard:m,fetch:o((i,t)=>fetch(i,t),"fetch"),now:Date.now,retryWaitsMs:y,ackGapMs:A,failGapMs:E}}o(x,"databaseDeps");let M;function F(){return M??=new k(x())}o(F,"runNotices");export{A as RUN_NOTICE_ACK_GAP_MS,T as RUN_NOTICE_ATTEMPT_TIMEOUT_MS,E as RUN_NOTICE_FAIL_GAP_MS,y as RUN_NOTICE_RETRY_WAITS_MS,g as RUN_NOTICE_SCOPE,k as RunNoticeOutbox,x as databaseDeps,F as runNotices};
@@ -1,6 +1,6 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import type { SessionEntry } from '../../core/conversation-store/index.js';
2
+ import type { CanvasDb } from '../../core/canvas/db.js';
3
3
  export declare const TURN_INPUT_TYPE = "crtr-turn-input";
4
4
  export declare const SYSTEM_PROMPT_TYPE = "crtr-system-prompt";
5
5
  export declare const TURN_END_TYPE = "crtr-turn-end";
6
- export declare function appendConversationEvents(db: DatabaseSync, runId: string, nodeId: string, entries: SessionEntry[], pendingInputIds: string[]): string[];
6
+ export declare function appendConversationEvents(db: CanvasDb, runId: string, nodeId: string, entries: SessionEntry[], pendingInputIds: string[]): Promise<string[]>;
@@ -1,2 +1,2 @@
1
- var T=Object.defineProperty;var u=(t,e)=>T(t,"name",{value:e,configurable:!0});import{prepared as d}from"../../core/sqlite-statements.js";import{appendRunEvent as p}from"../../core/runs/events.js";import{openQuestionIds as h}from"../../core/runs/questions.js";import{getNode as x}from"../../core/canvas/canvas.js";import{payerOfGrant as N}from"../../core/grants/mirror.js";import{runSchemaRepromptPending as S}from"../../core/runtime/stop-guard.js";const k="crtr-turn-input",w="crtr-system-prompt",D="crtr-turn-end",E=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"zero");function O(t){return typeof t=="string"?t:Array.isArray(t)?t.filter(e=>typeof e?.text=="string").map(e=>e.text).join(`
2
- `):""}u(O,"text");function j(t){if(t==null)return;const{code:e,message:r}=t;if(e!=="content_refused"&&e!=="model_error"||typeof r!="string")throw new Error("invalid crtr-turn-end error");return{code:e,message:r}}u(j,"turnEndError");function A(t){return{input_tokens:t.input??0,output_tokens:t.output??0,cache_read_tokens:t.cacheRead??0,cache_write_tokens:t.cacheWrite??0,cost_usd:t.cost?.total??0}}u(A,"usageParts");function Y(t,e,r,g,R){let l=R;for(const n of g){if(n.type==="custom"&&n.customType===k){const o=n.data?.message_ids;if(!Array.isArray(o)||!o.every(i=>typeof i=="string"))throw new Error("invalid crtr-turn-input message_ids");l=[...new Set([...l,...o])]}if(n.type==="custom"&&n.customType===w){const o=n.data?.text;if(typeof o!="string")throw new Error("invalid crtr-system-prompt text");p(t,e,r,"node.system_prompt.set",{entry_id:n.id,text:o})}if(n.type==="custom"&&n.customType===D){const o=n.data,i=o?.stop_reason;if(typeof i!="string")throw new Error("invalid crtr-turn-end stop_reason");const a=j(o?.error),s=d(t,"SELECT body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type = 'node.turn.started' ORDER BY sequence_number DESC LIMIT 1").get(e,r);if(!s)throw new Error("crtr-turn-end without node.turn.started");const{input:_}=JSON.parse(s.body_json),f=d(t,"SELECT status, pi_pid FROM node_rows WHERE run_id = ? AND node_id != ?").all(e,r),c=r===e?x(e):null,m=f.some(y=>y.pi_pid!==null&&y.status==="active")||c!==null&&S(c)?"running":h(e,t).length?"waiting_on_user":"idle";p(t,e,r,"node.turn.completed",{entry_id:n.id,message_ids:_.message_ids,run_status:m,stop_reason:i,...a?{error:a}:{}}),r===e&&d(t,"UPDATE nodes SET last_turn_error_json = ? WHERE node_id = ?").run(a?JSON.stringify(a):null,e)}if(n.type==="message"){const o=n.message;if(o.role==="user"){const i=d(t,"SELECT type, body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type IN ('node.turn.started', 'node.turn.completed') ORDER BY sequence_number DESC LIMIT 1").get(e,r),a=i?.type==="node.turn.started"?JSON.parse(i.body_json).input.message_ids:[];p(t,e,r,"node.turn.started",{entry_id:n.id,input:{text:O(o.content),message_ids:[...new Set([...a,...l])]}}),l=[]}if(o.role==="assistant"){let i=!1;const a=u(()=>{if(i)return;i=!0;const s=o.content.filter(_=>_.type==="text").map(_=>_.text).join("");p(t,e,r,"node.output_text.done",{entry_id:n.id,text:s,stop_reason:o.stopReason})},"doneText");for(const s of o.content)s.type==="thinking"&&p(t,e,r,"node.thinking.done",{entry_id:n.id,text:s.thinking}),s.type==="text"&&a(),s.type==="toolCall"&&(a(),p(t,e,r,"node.tool_call.started",{entry_id:n.id,tool_call_id:s.id,name:s.name,arguments:s.arguments}));if(a(),o.usage){const s=A(o.usage),_=d(t,"SELECT usage_json, grant_id FROM nodes WHERE node_id = ?").get(e),f=_.usage_json?JSON.parse(_.usage_json):E(),c=E();for(const m of Object.keys(c))c[m]=f[m]+s[m];d(t,"UPDATE nodes SET usage_json = ? WHERE node_id = ?").run(JSON.stringify(c),e),p(t,e,r,"usage",{entry_id:n.id,served_model:o.model,payer:N(_.grant_id),...s,usage:c})}d(t,"DELETE FROM run_events WHERE run_id = ? AND node_id = ? AND type IN ('node.thinking.delta', 'node.output_text.delta')").run(e,r)}o.role==="toolResult"&&p(t,e,r,"node.tool_call.completed",{entry_id:n.id,tool_call_id:o.toolCallId,name:o.toolName,result:o.content,status:o.isError?"error":"ok"})}}return l}u(Y,"appendConversationEvents");export{w as SYSTEM_PROMPT_TYPE,D as TURN_END_TYPE,k as TURN_INPUT_TYPE,Y as appendConversationEvents};
1
+ var w=Object.defineProperty;var u=(t,e)=>w(t,"name",{value:e,configurable:!0});import{appendRunEvent as _}from"../../core/runs/events.js";import{openQuestionIds as R}from"../../core/runs/questions.js";import{getNode as T}from"../../core/canvas/canvas.js";import{payerOfGrant as x}from"../../core/grants/mirror.js";import{runSchemaRepromptPending as N}from"../../core/runtime/stop-guard.js";const h="crtr-turn-input",S="crtr-system-prompt",k="crtr-turn-end",f=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"zero");function D(t){return typeof t=="string"?t:Array.isArray(t)?t.filter(e=>typeof e?.text=="string").map(e=>e.text).join(`
2
+ `):""}u(D,"text");function O(t){if(t==null)return;const{code:e,message:r}=t;if(e!=="content_refused"&&e!=="model_error"||typeof r!="string")throw new Error("invalid crtr-turn-end error");return{code:e,message:r}}u(O,"turnEndError");function j(t){return{input_tokens:t.input??0,output_tokens:t.output??0,cache_read_tokens:t.cacheRead??0,cache_write_tokens:t.cacheWrite??0,cost_usd:t.cost?.total??0}}u(j,"usageParts");async function H(t,e,r,E,g){let d=g;for(const o of E){if(o.type==="custom"&&o.customType===h){const n=o.data?.message_ids;if(!Array.isArray(n)||!n.every(i=>typeof i=="string"))throw new Error("invalid crtr-turn-input message_ids");d=[...new Set([...d,...n])]}if(o.type==="custom"&&o.customType===S){const n=o.data?.text;if(typeof n!="string")throw new Error("invalid crtr-system-prompt text");await _(t,e,r,"node.system_prompt.set",{entry_id:o.id,text:n})}if(o.type==="custom"&&o.customType===k){const n=o.data,i=n?.stop_reason;if(typeof i!="string")throw new Error("invalid crtr-turn-end stop_reason");const a=O(n?.error),s=await t.prepare("SELECT body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type = 'node.turn.started' ORDER BY sequence_number DESC LIMIT 1").get(e,r);if(!s)throw new Error("crtr-turn-end without node.turn.started");const{input:p}=JSON.parse(s.body_json),m=await t.prepare("SELECT status, pi_pid FROM node_rows WHERE run_id = ? AND node_id != ?").all(e,r),c=r===e?await T(e):null,l=m.some(y=>y.pi_pid!==null&&y.status==="active")||c!==null&&await N(c)?"running":(await R(e,t)).length?"waiting_on_user":"idle";await _(t,e,r,"node.turn.completed",{entry_id:o.id,message_ids:p.message_ids,run_status:l,stop_reason:i,...a?{error:a}:{}}),r===e&&await t.prepare("UPDATE nodes SET last_turn_error_json = ? WHERE node_id = ?").run(a?JSON.stringify(a):null,e)}if(o.type==="message"){const n=o.message;if(n.role==="user"){const i=await t.prepare("SELECT type, body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type IN ('node.turn.started', 'node.turn.completed') ORDER BY sequence_number DESC LIMIT 1").get(e,r),a=i?.type==="node.turn.started"?JSON.parse(i.body_json).input.message_ids:[];await _(t,e,r,"node.turn.started",{entry_id:o.id,input:{text:D(n.content),message_ids:[...new Set([...a,...d])]}}),d=[]}if(n.role==="assistant"){let i=!1;const a=u(async()=>{if(i)return;i=!0;const s=n.content.filter(p=>p.type==="text").map(p=>p.text).join("");await _(t,e,r,"node.output_text.done",{entry_id:o.id,text:s,stop_reason:n.stopReason})},"doneText");for(const s of n.content)s.type==="thinking"&&await _(t,e,r,"node.thinking.done",{entry_id:o.id,text:s.thinking}),s.type==="text"&&await a(),s.type==="toolCall"&&(await a(),await _(t,e,r,"node.tool_call.started",{entry_id:o.id,tool_call_id:s.id,name:s.name,arguments:s.arguments}));if(await a(),n.usage){const s=j(n.usage),p=await t.prepare("SELECT usage_json, grant_id FROM nodes WHERE node_id = ?").get(e),m=p.usage_json?JSON.parse(p.usage_json):f(),c=f();for(const l of Object.keys(c))c[l]=m[l]+s[l];await t.prepare("UPDATE nodes SET usage_json = ? WHERE node_id = ?").run(JSON.stringify(c),e),await _(t,e,r,"usage",{entry_id:o.id,served_model:n.model,payer:await x(p.grant_id),...s,usage:c})}await t.prepare("DELETE FROM run_events WHERE run_id = ? AND node_id = ? AND type IN ('node.thinking.delta', 'node.output_text.delta')").run(e,r)}n.role==="toolResult"&&await _(t,e,r,"node.tool_call.completed",{entry_id:o.id,tool_call_id:n.toolCallId,name:n.toolName,result:n.content,status:n.isError?"error":"ok"})}}return d}u(H,"appendConversationEvents");export{S as SYSTEM_PROMPT_TYPE,k as TURN_END_TYPE,h as TURN_INPUT_TYPE,H as appendConversationEvents};
@@ -8,7 +8,7 @@ export type OpenAssistantBlock = {
8
8
  };
9
9
  /** The newest block of the node's open assistant message; null when no message is open or nothing has streamed yet. */
10
10
  export declare function openAssistantBlock(nodeId: string): OpenAssistantBlock | null;
11
- export declare function ensureRunObserver(nodeId: string, runId: string): void;
11
+ export declare function ensureRunObserver(nodeId: string, runId: string): Promise<void>;
12
12
  /** Observes run nodes with a live broker, plus those whose current outcome
13
13
  * (settled within the event retention window) has no `node.settled` event yet. */
14
- export declare function pollRunObservers(): void;
14
+ export declare function pollRunObservers(): Promise<void>;