botmux 3.10.0 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (539) hide show
  1. package/dist/.runtime-build-id +1 -1
  2. package/dist/adapters/backend/herdr-backend.d.ts +4 -3
  3. package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
  4. package/dist/adapters/backend/herdr-backend.js +11 -8
  5. package/dist/adapters/backend/herdr-backend.js.map +1 -1
  6. package/dist/adapters/backend/pty-backend.d.ts +1 -1
  7. package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
  8. package/dist/adapters/backend/pty-backend.js +4 -1
  9. package/dist/adapters/backend/pty-backend.js.map +1 -1
  10. package/dist/adapters/backend/riff-backend.d.ts +29 -5
  11. package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
  12. package/dist/adapters/backend/riff-backend.js +302 -31
  13. package/dist/adapters/backend/riff-backend.js.map +1 -1
  14. package/dist/adapters/backend/sandbox.d.ts +6 -0
  15. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  16. package/dist/adapters/backend/sandbox.js +7 -0
  17. package/dist/adapters/backend/sandbox.js.map +1 -1
  18. package/dist/adapters/backend/tmux-backend.d.ts +1 -1
  19. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  20. package/dist/adapters/backend/tmux-backend.js +4 -1
  21. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  22. package/dist/adapters/backend/tmux-pipe-backend.d.ts +1 -1
  23. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  24. package/dist/adapters/backend/tmux-pipe-backend.js +1 -1
  25. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  26. package/dist/adapters/backend/types.d.ts +37 -3
  27. package/dist/adapters/backend/types.d.ts.map +1 -1
  28. package/dist/adapters/backend/types.js.map +1 -1
  29. package/dist/adapters/backend/zellij-backend.d.ts +3 -3
  30. package/dist/adapters/backend/zellij-backend.d.ts.map +1 -1
  31. package/dist/adapters/backend/zellij-backend.js +9 -3
  32. package/dist/adapters/backend/zellij-backend.js.map +1 -1
  33. package/dist/adapters/backend/zellij-observe-backend.d.ts +3 -3
  34. package/dist/adapters/backend/zellij-observe-backend.d.ts.map +1 -1
  35. package/dist/adapters/backend/zellij-observe-backend.js +12 -7
  36. package/dist/adapters/backend/zellij-observe-backend.js.map +1 -1
  37. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  38. package/dist/adapters/cli/codex-app.js +11 -2
  39. package/dist/adapters/cli/codex-app.js.map +1 -1
  40. package/dist/adapters/cli/read-isolation.d.ts +35 -2
  41. package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
  42. package/dist/adapters/cli/read-isolation.js +88 -7
  43. package/dist/adapters/cli/read-isolation.js.map +1 -1
  44. package/dist/adapters/cli/runner-input.d.ts +15 -14
  45. package/dist/adapters/cli/runner-input.d.ts.map +1 -1
  46. package/dist/adapters/cli/runner-input.js +64 -26
  47. package/dist/adapters/cli/runner-input.js.map +1 -1
  48. package/dist/adapters/cli/types.d.ts +20 -5
  49. package/dist/adapters/cli/types.d.ts.map +1 -1
  50. package/dist/bot-registry.d.ts +24 -0
  51. package/dist/bot-registry.d.ts.map +1 -1
  52. package/dist/bot-registry.js +110 -5
  53. package/dist/bot-registry.js.map +1 -1
  54. package/dist/cli/fleet-shutdown.d.ts +47 -0
  55. package/dist/cli/fleet-shutdown.d.ts.map +1 -0
  56. package/dist/cli/fleet-shutdown.js +387 -0
  57. package/dist/cli/fleet-shutdown.js.map +1 -0
  58. package/dist/cli/pm2-descriptor-guard.d.ts +19 -0
  59. package/dist/cli/pm2-descriptor-guard.d.ts.map +1 -0
  60. package/dist/cli/pm2-descriptor-guard.js +122 -0
  61. package/dist/cli/pm2-descriptor-guard.js.map +1 -0
  62. package/dist/cli/pm2-exact-start.d.ts +16 -0
  63. package/dist/cli/pm2-exact-start.d.ts.map +1 -0
  64. package/dist/cli/pm2-exact-start.js +63 -0
  65. package/dist/cli/pm2-exact-start.js.map +1 -0
  66. package/dist/cli/pm2-god-admission.d.ts +8 -0
  67. package/dist/cli/pm2-god-admission.d.ts.map +1 -0
  68. package/dist/cli/pm2-god-admission.js +25 -0
  69. package/dist/cli/pm2-god-admission.js.map +1 -0
  70. package/dist/cli/pm2-jlist.d.ts +13 -0
  71. package/dist/cli/pm2-jlist.d.ts.map +1 -0
  72. package/dist/cli/pm2-jlist.js +108 -0
  73. package/dist/cli/pm2-jlist.js.map +1 -0
  74. package/dist/cli/pm2-preflight.d.ts +10 -0
  75. package/dist/cli/pm2-preflight.d.ts.map +1 -0
  76. package/dist/cli/pm2-preflight.js +23 -0
  77. package/dist/cli/pm2-preflight.js.map +1 -0
  78. package/dist/cli/pm2-shutdown-capability.d.ts +27 -0
  79. package/dist/cli/pm2-shutdown-capability.d.ts.map +1 -0
  80. package/dist/cli/pm2-shutdown-capability.js +161 -0
  81. package/dist/cli/pm2-shutdown-capability.js.map +1 -0
  82. package/dist/cli/pm2-start-transaction.d.ts +55 -0
  83. package/dist/cli/pm2-start-transaction.d.ts.map +1 -0
  84. package/dist/cli/pm2-start-transaction.js +220 -0
  85. package/dist/cli/pm2-start-transaction.js.map +1 -0
  86. package/dist/cli/send-dispatch.d.ts +12 -0
  87. package/dist/cli/send-dispatch.d.ts.map +1 -1
  88. package/dist/cli/send-dispatch.js +31 -4
  89. package/dist/cli/send-dispatch.js.map +1 -1
  90. package/dist/cli/session-list-liveness.d.ts +1 -0
  91. package/dist/cli/session-list-liveness.d.ts.map +1 -1
  92. package/dist/cli/session-list-liveness.js +6 -0
  93. package/dist/cli/session-list-liveness.js.map +1 -1
  94. package/dist/cli/session-picker-layout.d.ts +26 -0
  95. package/dist/cli/session-picker-layout.d.ts.map +1 -0
  96. package/dist/cli/session-picker-layout.js +123 -0
  97. package/dist/cli/session-picker-layout.js.map +1 -0
  98. package/dist/cli/session-picker-viewport.d.ts +49 -0
  99. package/dist/cli/session-picker-viewport.d.ts.map +1 -0
  100. package/dist/cli/session-picker-viewport.js +46 -0
  101. package/dist/cli/session-picker-viewport.js.map +1 -0
  102. package/dist/cli/supervisor-shutdown-client.d.ts +31 -0
  103. package/dist/cli/supervisor-shutdown-client.d.ts.map +1 -0
  104. package/dist/cli/supervisor-shutdown-client.js +146 -0
  105. package/dist/cli/supervisor-shutdown-client.js.map +1 -0
  106. package/dist/cli/terminal-width.d.ts +48 -0
  107. package/dist/cli/terminal-width.d.ts.map +1 -0
  108. package/dist/cli/terminal-width.js +119 -0
  109. package/dist/cli/terminal-width.js.map +1 -0
  110. package/dist/cli/vc-agent.d.ts.map +1 -1
  111. package/dist/cli/vc-agent.js +1 -1
  112. package/dist/cli/vc-agent.js.map +1 -1
  113. package/dist/cli.d.ts.map +1 -1
  114. package/dist/cli.js +2269 -716
  115. package/dist/cli.js.map +1 -1
  116. package/dist/codex-app-runner.js +1630 -125
  117. package/dist/codex-app-runner.js.map +1 -1
  118. package/dist/core/ask-api.d.ts +8 -1
  119. package/dist/core/ask-api.d.ts.map +1 -1
  120. package/dist/core/ask-api.js +18 -0
  121. package/dist/core/ask-api.js.map +1 -1
  122. package/dist/core/ask-broker.d.ts +20 -0
  123. package/dist/core/ask-broker.d.ts.map +1 -1
  124. package/dist/core/ask-broker.js +467 -47
  125. package/dist/core/ask-broker.js.map +1 -1
  126. package/dist/core/ask-persist-store.d.ts +126 -0
  127. package/dist/core/ask-persist-store.d.ts.map +1 -0
  128. package/dist/core/ask-persist-store.js +188 -0
  129. package/dist/core/ask-persist-store.js.map +1 -0
  130. package/dist/core/ask-types.d.ts +80 -0
  131. package/dist/core/ask-types.d.ts.map +1 -1
  132. package/dist/core/ask-types.js +62 -0
  133. package/dist/core/ask-types.js.map +1 -1
  134. package/dist/core/cli-session-id-publisher.d.ts +20 -0
  135. package/dist/core/cli-session-id-publisher.d.ts.map +1 -0
  136. package/dist/core/cli-session-id-publisher.js +21 -0
  137. package/dist/core/cli-session-id-publisher.js.map +1 -0
  138. package/dist/core/command-handler.d.ts.map +1 -1
  139. package/dist/core/command-handler.js +427 -255
  140. package/dist/core/command-handler.js.map +1 -1
  141. package/dist/core/cost-calculator.d.ts +13 -0
  142. package/dist/core/cost-calculator.d.ts.map +1 -1
  143. package/dist/core/cost-calculator.js +385 -26
  144. package/dist/core/cost-calculator.js.map +1 -1
  145. package/dist/core/dashboard-ipc-server.d.ts +9 -0
  146. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  147. package/dist/core/dashboard-ipc-server.js +842 -288
  148. package/dist/core/dashboard-ipc-server.js.map +1 -1
  149. package/dist/core/explicit-session-backing-cleanup.d.ts +49 -0
  150. package/dist/core/explicit-session-backing-cleanup.d.ts.map +1 -0
  151. package/dist/core/explicit-session-backing-cleanup.js +76 -0
  152. package/dist/core/explicit-session-backing-cleanup.js.map +1 -0
  153. package/dist/core/idle-worker-sweeper.d.ts +20 -0
  154. package/dist/core/idle-worker-sweeper.d.ts.map +1 -1
  155. package/dist/core/idle-worker-sweeper.js +18 -0
  156. package/dist/core/idle-worker-sweeper.js.map +1 -1
  157. package/dist/core/inflight-input-tracker.d.ts +10 -0
  158. package/dist/core/inflight-input-tracker.d.ts.map +1 -1
  159. package/dist/core/inflight-input-tracker.js +7 -0
  160. package/dist/core/inflight-input-tracker.js.map +1 -1
  161. package/dist/core/managed-origin-attestation.d.ts +51 -0
  162. package/dist/core/managed-origin-attestation.d.ts.map +1 -0
  163. package/dist/core/managed-origin-attestation.js +208 -0
  164. package/dist/core/managed-origin-attestation.js.map +1 -0
  165. package/dist/core/managed-origin-capability.d.ts +62 -3
  166. package/dist/core/managed-origin-capability.d.ts.map +1 -1
  167. package/dist/core/managed-origin-capability.js +419 -9
  168. package/dist/core/managed-origin-capability.js.map +1 -1
  169. package/dist/core/pending-repo-journal.d.ts +6 -0
  170. package/dist/core/pending-repo-journal.d.ts.map +1 -0
  171. package/dist/core/pending-repo-journal.js +85 -0
  172. package/dist/core/pending-repo-journal.js.map +1 -0
  173. package/dist/core/persistent-backend.d.ts +6 -1
  174. package/dist/core/persistent-backend.d.ts.map +1 -1
  175. package/dist/core/persistent-backend.js +12 -6
  176. package/dist/core/persistent-backend.js.map +1 -1
  177. package/dist/core/process-start-identity.d.ts +3 -0
  178. package/dist/core/process-start-identity.d.ts.map +1 -0
  179. package/dist/core/process-start-identity.js +62 -0
  180. package/dist/core/process-start-identity.js.map +1 -0
  181. package/dist/core/raw-command-writer.d.ts +34 -0
  182. package/dist/core/raw-command-writer.d.ts.map +1 -0
  183. package/dist/core/raw-command-writer.js +48 -0
  184. package/dist/core/raw-command-writer.js.map +1 -0
  185. package/dist/core/reply-target.d.ts +85 -22
  186. package/dist/core/reply-target.d.ts.map +1 -1
  187. package/dist/core/reply-target.js +267 -32
  188. package/dist/core/reply-target.js.map +1 -1
  189. package/dist/core/resource-monitor/runtime.d.ts.map +1 -1
  190. package/dist/core/resource-monitor/runtime.js +4 -1
  191. package/dist/core/resource-monitor/runtime.js.map +1 -1
  192. package/dist/core/restart-report.d.ts +6 -1
  193. package/dist/core/restart-report.d.ts.map +1 -1
  194. package/dist/core/restart-report.js +22 -4
  195. package/dist/core/restart-report.js.map +1 -1
  196. package/dist/core/riff-shutdown-detach.d.ts +164 -0
  197. package/dist/core/riff-shutdown-detach.d.ts.map +1 -0
  198. package/dist/core/riff-shutdown-detach.js +787 -0
  199. package/dist/core/riff-shutdown-detach.js.map +1 -0
  200. package/dist/core/riff-worker-shutdown-readiness.d.ts +17 -0
  201. package/dist/core/riff-worker-shutdown-readiness.d.ts.map +1 -0
  202. package/dist/core/riff-worker-shutdown-readiness.js +21 -0
  203. package/dist/core/riff-worker-shutdown-readiness.js.map +1 -0
  204. package/dist/core/session-manager.d.ts +6 -6
  205. package/dist/core/session-manager.d.ts.map +1 -1
  206. package/dist/core/session-manager.js +1227 -594
  207. package/dist/core/session-manager.js.map +1 -1
  208. package/dist/core/session-marker.d.ts +1 -1
  209. package/dist/core/session-marker.d.ts.map +1 -1
  210. package/dist/core/session-marker.js +2 -2
  211. package/dist/core/session-marker.js.map +1 -1
  212. package/dist/core/session-mutation-guard.d.ts +17 -0
  213. package/dist/core/session-mutation-guard.d.ts.map +1 -0
  214. package/dist/core/session-mutation-guard.js +33 -0
  215. package/dist/core/session-mutation-guard.js.map +1 -0
  216. package/dist/core/shutdown-budgets.d.ts +27 -0
  217. package/dist/core/shutdown-budgets.d.ts.map +1 -0
  218. package/dist/core/shutdown-budgets.js +47 -0
  219. package/dist/core/shutdown-budgets.js.map +1 -0
  220. package/dist/core/supervisor-shutdown-ipc.d.ts +10 -0
  221. package/dist/core/supervisor-shutdown-ipc.d.ts.map +1 -0
  222. package/dist/core/supervisor-shutdown-ipc.js +10 -0
  223. package/dist/core/supervisor-shutdown-ipc.js.map +1 -0
  224. package/dist/core/supervisor-shutdown-protocol.d.ts +16 -0
  225. package/dist/core/supervisor-shutdown-protocol.d.ts.map +1 -0
  226. package/dist/core/supervisor-shutdown-protocol.js +16 -0
  227. package/dist/core/supervisor-shutdown-protocol.js.map +1 -0
  228. package/dist/core/trigger-final-suppression.d.ts +4 -0
  229. package/dist/core/trigger-final-suppression.d.ts.map +1 -1
  230. package/dist/core/trigger-final-suppression.js +6 -11
  231. package/dist/core/trigger-final-suppression.js.map +1 -1
  232. package/dist/core/trigger-session.d.ts +70 -0
  233. package/dist/core/trigger-session.d.ts.map +1 -1
  234. package/dist/core/trigger-session.js +923 -145
  235. package/dist/core/trigger-session.js.map +1 -1
  236. package/dist/core/types.d.ts +94 -1
  237. package/dist/core/types.d.ts.map +1 -1
  238. package/dist/core/types.js +9 -0
  239. package/dist/core/types.js.map +1 -1
  240. package/dist/core/worker-pool.d.ts +194 -13
  241. package/dist/core/worker-pool.d.ts.map +1 -1
  242. package/dist/core/worker-pool.js +2597 -547
  243. package/dist/core/worker-pool.js.map +1 -1
  244. package/dist/daemon.d.ts +76 -2
  245. package/dist/daemon.d.ts.map +1 -1
  246. package/dist/daemon.js +2255 -773
  247. package/dist/daemon.js.map +1 -1
  248. package/dist/dashboard/bot-payload.d.ts +20 -0
  249. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  250. package/dist/dashboard/bot-payload.js +24 -0
  251. package/dist/dashboard/bot-payload.js.map +1 -1
  252. package/dist/dashboard/feed-groups.d.ts +17 -0
  253. package/dist/dashboard/feed-groups.d.ts.map +1 -0
  254. package/dist/dashboard/feed-groups.js +75 -0
  255. package/dist/dashboard/feed-groups.js.map +1 -0
  256. package/dist/dashboard/session-card-model.d.ts +1 -1
  257. package/dist/dashboard/session-card-model.d.ts.map +1 -1
  258. package/dist/dashboard/session-card-model.js +8 -5
  259. package/dist/dashboard/session-card-model.js.map +1 -1
  260. package/dist/dashboard/web/bot-defaults-page.d.ts +4 -0
  261. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  262. package/dist/dashboard/web/bot-defaults-page.js +139 -46
  263. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  264. package/dist/dashboard/web/bot-defaults.d.ts +4 -0
  265. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  266. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  267. package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
  268. package/dist/dashboard/web/connectors-page.js +40 -3
  269. package/dist/dashboard/web/connectors-page.js.map +1 -1
  270. package/dist/dashboard/web/groups-page.d.ts.map +1 -1
  271. package/dist/dashboard/web/groups-page.js +95 -2
  272. package/dist/dashboard/web/groups-page.js.map +1 -1
  273. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  274. package/dist/dashboard/web/i18n.js +86 -40
  275. package/dist/dashboard/web/i18n.js.map +1 -1
  276. package/dist/dashboard/web/kanban-model.js +1 -1
  277. package/dist/dashboard/web/kanban-model.js.map +1 -1
  278. package/dist/dashboard/web/overview-page.d.ts.map +1 -1
  279. package/dist/dashboard/web/overview-page.js +3 -2
  280. package/dist/dashboard/web/overview-page.js.map +1 -1
  281. package/dist/dashboard/web/overview.d.ts +3 -0
  282. package/dist/dashboard/web/overview.d.ts.map +1 -1
  283. package/dist/dashboard/web/overview.js +2 -0
  284. package/dist/dashboard/web/overview.js.map +1 -1
  285. package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -1
  286. package/dist/dashboard/web/sessions-kanban.js +2 -0
  287. package/dist/dashboard/web/sessions-kanban.js.map +1 -1
  288. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  289. package/dist/dashboard/web/sessions-page.js +103 -2
  290. package/dist/dashboard/web/sessions-page.js.map +1 -1
  291. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  292. package/dist/dashboard/web/sessions.js +3 -2
  293. package/dist/dashboard/web/sessions.js.map +1 -1
  294. package/dist/dashboard/web/ui.d.ts +8 -0
  295. package/dist/dashboard/web/ui.d.ts.map +1 -1
  296. package/dist/dashboard/web/ui.js +15 -0
  297. package/dist/dashboard/web/ui.js.map +1 -1
  298. package/dist/dashboard-web/app.js +1 -1
  299. package/dist/dashboard-web/chunks/bot-defaults-page-GED4FEMS.js +10 -0
  300. package/dist/dashboard-web/chunks/chunk-6J5LS5AU.js +51 -0
  301. package/dist/dashboard-web/chunks/{chunk-ZU3UUKAR.js → chunk-HK7NIBJG.js} +1 -1
  302. package/dist/dashboard-web/chunks/{chunk-3UE7S77S.js → chunk-KRHWZEXU.js} +1 -1
  303. package/dist/dashboard-web/chunks/chunk-VBXJOJFH.js +1 -0
  304. package/dist/dashboard-web/chunks/connectors-page-EELM66G3.js +1 -0
  305. package/dist/dashboard-web/chunks/groups-page-WKUV6E42.js +8 -0
  306. package/dist/dashboard-web/chunks/{insights-page-T2ZX2RWL.js → insights-page-54UBPPOC.js} +1 -1
  307. package/dist/dashboard-web/chunks/{monitor-room-YNVBAGR6.js → monitor-room-PORHVKRH.js} +1 -1
  308. package/dist/dashboard-web/chunks/{monitoring-page-LHM55YWN.js → monitoring-page-XGA7AXNL.js} +1 -1
  309. package/dist/dashboard-web/chunks/{office-page-ATXVP7PW.js → office-page-AO3AFG45.js} +1 -1
  310. package/dist/dashboard-web/chunks/overview-page-F5BUTYR6.js +1 -0
  311. package/dist/dashboard-web/chunks/{roles-page-56VWM6CD.js → roles-page-M5GIASJU.js} +1 -1
  312. package/dist/dashboard-web/chunks/{schedules-page-S5K6U4EO.js → schedules-page-O232WQRR.js} +1 -1
  313. package/dist/dashboard-web/chunks/sessions-page-YFRPSTIL.js +6 -0
  314. package/dist/dashboard-web/chunks/{settings-page-QUZDQARR.js → settings-page-OJAZLZQT.js} +1 -1
  315. package/dist/dashboard-web/chunks/{skills-page-IFY7AEND.js → skills-page-EFZQPWV4.js} +1 -1
  316. package/dist/dashboard-web/chunks/{team-federation-page-C7FJQPFZ.js → team-federation-page-ZJVAP7HW.js} +1 -1
  317. package/dist/dashboard-web/chunks/{v3-page-2LMF3WWR.js → v3-page-GYWTRGO2.js} +1 -1
  318. package/dist/dashboard-web/chunks/{whiteboards-page-3XC6QRMY.js → whiteboards-page-MSDAG6P7.js} +1 -1
  319. package/dist/dashboard-web/style.css +255 -0
  320. package/dist/dashboard.js +172 -7
  321. package/dist/dashboard.js.map +1 -1
  322. package/dist/desktop/renderer/app.js +21 -0
  323. package/dist/desktop/renderer/app.js.map +1 -1
  324. package/dist/i18n/en.d.ts.map +1 -1
  325. package/dist/i18n/en.js +35 -9
  326. package/dist/i18n/en.js.map +1 -1
  327. package/dist/i18n/zh.d.ts.map +1 -1
  328. package/dist/i18n/zh.js +35 -9
  329. package/dist/i18n/zh.js.map +1 -1
  330. package/dist/im/lark/ask-card.d.ts +23 -0
  331. package/dist/im/lark/ask-card.d.ts.map +1 -1
  332. package/dist/im/lark/ask-card.js +94 -4
  333. package/dist/im/lark/ask-card.js.map +1 -1
  334. package/dist/im/lark/card-builder.d.ts +6 -1
  335. package/dist/im/lark/card-builder.d.ts.map +1 -1
  336. package/dist/im/lark/card-builder.js +112 -15
  337. package/dist/im/lark/card-builder.js.map +1 -1
  338. package/dist/im/lark/card-handler.d.ts +1 -1
  339. package/dist/im/lark/card-handler.d.ts.map +1 -1
  340. package/dist/im/lark/card-handler.js +496 -310
  341. package/dist/im/lark/card-handler.js.map +1 -1
  342. package/dist/im/lark/client.d.ts +7 -0
  343. package/dist/im/lark/client.d.ts.map +1 -1
  344. package/dist/im/lark/client.js +39 -26
  345. package/dist/im/lark/client.js.map +1 -1
  346. package/dist/im/lark/doc-comment.d.ts +7 -4
  347. package/dist/im/lark/doc-comment.d.ts.map +1 -1
  348. package/dist/im/lark/doc-comment.js +19 -6
  349. package/dist/im/lark/doc-comment.js.map +1 -1
  350. package/dist/im/lark/event-dispatcher.d.ts +16 -0
  351. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  352. package/dist/im/lark/event-dispatcher.js +88 -23
  353. package/dist/im/lark/event-dispatcher.js.map +1 -1
  354. package/dist/im/lark/forward-followup-content.d.ts.map +1 -1
  355. package/dist/im/lark/forward-followup-content.js +9 -1
  356. package/dist/im/lark/forward-followup-content.js.map +1 -1
  357. package/dist/im/lark/grant-command.d.ts.map +1 -1
  358. package/dist/im/lark/grant-command.js +7 -4
  359. package/dist/im/lark/grant-command.js.map +1 -1
  360. package/dist/im/lark/md-card.d.ts +11 -0
  361. package/dist/im/lark/md-card.d.ts.map +1 -1
  362. package/dist/im/lark/md-card.js +46 -0
  363. package/dist/im/lark/md-card.js.map +1 -1
  364. package/dist/im/lark/message-parser.d.ts +23 -2
  365. package/dist/im/lark/message-parser.d.ts.map +1 -1
  366. package/dist/im/lark/message-parser.js +58 -3
  367. package/dist/im/lark/message-parser.js.map +1 -1
  368. package/dist/im/lark/overview-card.d.ts.map +1 -1
  369. package/dist/im/lark/overview-card.js +2 -1
  370. package/dist/im/lark/overview-card.js.map +1 -1
  371. package/dist/services/async-trigger-state.d.ts +6 -1
  372. package/dist/services/async-trigger-state.d.ts.map +1 -1
  373. package/dist/services/async-trigger-state.js +21 -0
  374. package/dist/services/async-trigger-state.js.map +1 -1
  375. package/dist/services/async-trigger-store.d.ts +23 -1
  376. package/dist/services/async-trigger-store.d.ts.map +1 -1
  377. package/dist/services/async-trigger-store.js +96 -13
  378. package/dist/services/async-trigger-store.js.map +1 -1
  379. package/dist/services/bridge-fallback-gate.d.ts +40 -0
  380. package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
  381. package/dist/services/bridge-fallback-gate.js +124 -24
  382. package/dist/services/bridge-fallback-gate.js.map +1 -1
  383. package/dist/services/codex-app-runner-protocol.d.ts +8 -0
  384. package/dist/services/codex-app-runner-protocol.d.ts.map +1 -1
  385. package/dist/services/codex-app-runner-protocol.js +9 -2
  386. package/dist/services/codex-app-runner-protocol.js.map +1 -1
  387. package/dist/services/codex-bridge-queue.d.ts +1 -0
  388. package/dist/services/codex-bridge-queue.d.ts.map +1 -1
  389. package/dist/services/codex-bridge-queue.js +1 -0
  390. package/dist/services/codex-bridge-queue.js.map +1 -1
  391. package/dist/services/codex-service-tier.d.ts +2 -0
  392. package/dist/services/codex-service-tier.d.ts.map +1 -1
  393. package/dist/services/codex-service-tier.js +1 -0
  394. package/dist/services/codex-service-tier.js.map +1 -1
  395. package/dist/services/codex-transcript.d.ts +27 -0
  396. package/dist/services/codex-transcript.d.ts.map +1 -1
  397. package/dist/services/codex-transcript.js +340 -2
  398. package/dist/services/codex-transcript.js.map +1 -1
  399. package/dist/services/grant-policy.d.ts +3 -0
  400. package/dist/services/grant-policy.d.ts.map +1 -1
  401. package/dist/services/grant-policy.js +5 -0
  402. package/dist/services/grant-policy.js.map +1 -1
  403. package/dist/services/grant-prefs-store.d.ts +6 -3
  404. package/dist/services/grant-prefs-store.d.ts.map +1 -1
  405. package/dist/services/grant-prefs-store.js +42 -12
  406. package/dist/services/grant-prefs-store.js.map +1 -1
  407. package/dist/services/hook-runner.d.ts +20 -1
  408. package/dist/services/hook-runner.d.ts.map +1 -1
  409. package/dist/services/hook-runner.js +17 -13
  410. package/dist/services/hook-runner.js.map +1 -1
  411. package/dist/services/idempotency-store.d.ts +134 -0
  412. package/dist/services/idempotency-store.d.ts.map +1 -0
  413. package/dist/services/idempotency-store.js +299 -0
  414. package/dist/services/idempotency-store.js.map +1 -0
  415. package/dist/services/jsonl-cursor.d.ts +7 -3
  416. package/dist/services/jsonl-cursor.d.ts.map +1 -1
  417. package/dist/services/jsonl-cursor.js +55 -31
  418. package/dist/services/jsonl-cursor.js.map +1 -1
  419. package/dist/services/open-platform-rename.d.ts.map +1 -1
  420. package/dist/services/open-platform-rename.js +1 -108
  421. package/dist/services/open-platform-rename.js.map +1 -1
  422. package/dist/services/restart-intent-store.d.ts +22 -2
  423. package/dist/services/restart-intent-store.d.ts.map +1 -1
  424. package/dist/services/restart-intent-store.js +160 -18
  425. package/dist/services/restart-intent-store.js.map +1 -1
  426. package/dist/services/sandbox-store.d.ts +22 -0
  427. package/dist/services/sandbox-store.d.ts.map +1 -1
  428. package/dist/services/sandbox-store.js +37 -8
  429. package/dist/services/sandbox-store.js.map +1 -1
  430. package/dist/services/send-policy.d.ts +41 -33
  431. package/dist/services/send-policy.d.ts.map +1 -1
  432. package/dist/services/send-policy.js +39 -40
  433. package/dist/services/send-policy.js.map +1 -1
  434. package/dist/services/session-store.d.ts +66 -0
  435. package/dist/services/session-store.d.ts.map +1 -1
  436. package/dist/services/session-store.js +403 -67
  437. package/dist/services/session-store.js.map +1 -1
  438. package/dist/services/submit-notification.d.ts +3 -0
  439. package/dist/services/submit-notification.d.ts.map +1 -0
  440. package/dist/services/submit-notification.js +15 -0
  441. package/dist/services/submit-notification.js.map +1 -0
  442. package/dist/services/traex-transcript.d.ts +25 -2
  443. package/dist/services/traex-transcript.d.ts.map +1 -1
  444. package/dist/services/traex-transcript.js +133 -1
  445. package/dist/services/traex-transcript.js.map +1 -1
  446. package/dist/services/trigger-types.d.ts +13 -1
  447. package/dist/services/trigger-types.d.ts.map +1 -1
  448. package/dist/services/trigger-types.js +39 -0
  449. package/dist/services/trigger-types.js.map +1 -1
  450. package/dist/services/voice/index.d.ts +3 -2
  451. package/dist/services/voice/index.d.ts.map +1 -1
  452. package/dist/services/voice/index.js +5 -5
  453. package/dist/services/voice/index.js.map +1 -1
  454. package/dist/services/voice/openai.d.ts +2 -1
  455. package/dist/services/voice/openai.d.ts.map +1 -1
  456. package/dist/services/voice/openai.js +2 -1
  457. package/dist/services/voice/openai.js.map +1 -1
  458. package/dist/services/voice/sami.d.ts +5 -2
  459. package/dist/services/voice/sami.d.ts.map +1 -1
  460. package/dist/services/voice/sami.js +19 -4
  461. package/dist/services/voice/sami.js.map +1 -1
  462. package/dist/setup/bots-store.d.ts.map +1 -1
  463. package/dist/setup/bots-store.js +10 -4
  464. package/dist/setup/bots-store.js.map +1 -1
  465. package/dist/setup/lark-scopes.json +2 -0
  466. package/dist/setup/open-platform-automation.d.ts +9 -1
  467. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  468. package/dist/setup/open-platform-automation.js +44 -15
  469. package/dist/setup/open-platform-automation.js.map +1 -1
  470. package/dist/setup/open-platform-visibility.d.ts +42 -0
  471. package/dist/setup/open-platform-visibility.d.ts.map +1 -0
  472. package/dist/setup/open-platform-visibility.js +133 -0
  473. package/dist/setup/open-platform-visibility.js.map +1 -0
  474. package/dist/setup/verify-permissions.d.ts.map +1 -1
  475. package/dist/setup/verify-permissions.js +6 -0
  476. package/dist/setup/verify-permissions.js.map +1 -1
  477. package/dist/skills/definitions.js +2 -2
  478. package/dist/types.d.ts +290 -13
  479. package/dist/types.d.ts.map +1 -1
  480. package/dist/utils/bot-routing.d.ts +1 -0
  481. package/dist/utils/bot-routing.d.ts.map +1 -1
  482. package/dist/utils/bot-routing.js +1 -1
  483. package/dist/utils/bot-routing.js.map +1 -1
  484. package/dist/utils/child-env.d.ts +1 -1
  485. package/dist/utils/child-env.d.ts.map +1 -1
  486. package/dist/utils/child-env.js +9 -0
  487. package/dist/utils/child-env.js.map +1 -1
  488. package/dist/utils/codex-app-control.d.ts +438 -0
  489. package/dist/utils/codex-app-control.d.ts.map +1 -0
  490. package/dist/utils/codex-app-control.js +2336 -0
  491. package/dist/utils/codex-app-control.js.map +1 -0
  492. package/dist/utils/codex-app-dispatch-ledger.d.ts +78 -0
  493. package/dist/utils/codex-app-dispatch-ledger.d.ts.map +1 -0
  494. package/dist/utils/codex-app-dispatch-ledger.js +149 -0
  495. package/dist/utils/codex-app-dispatch-ledger.js.map +1 -0
  496. package/dist/utils/codex-app-turn-dispatch.d.ts +77 -0
  497. package/dist/utils/codex-app-turn-dispatch.d.ts.map +1 -0
  498. package/dist/utils/codex-app-turn-dispatch.js +141 -0
  499. package/dist/utils/codex-app-turn-dispatch.js.map +1 -0
  500. package/dist/utils/codex-app-turn-liveness.d.ts +125 -0
  501. package/dist/utils/codex-app-turn-liveness.d.ts.map +1 -0
  502. package/dist/utils/codex-app-turn-liveness.js +301 -0
  503. package/dist/utils/codex-app-turn-liveness.js.map +1 -0
  504. package/dist/utils/idle-detector.d.ts +12 -0
  505. package/dist/utils/idle-detector.d.ts.map +1 -1
  506. package/dist/utils/idle-detector.js +19 -0
  507. package/dist/utils/idle-detector.js.map +1 -1
  508. package/dist/utils/input-gate.d.ts +87 -0
  509. package/dist/utils/input-gate.d.ts.map +1 -1
  510. package/dist/utils/input-gate.js +86 -0
  511. package/dist/utils/input-gate.js.map +1 -1
  512. package/dist/utils/lark-upload.d.ts.map +1 -1
  513. package/dist/utils/lark-upload.js +52 -1
  514. package/dist/utils/lark-upload.js.map +1 -1
  515. package/dist/utils/pending-input-queue.d.ts +15 -0
  516. package/dist/utils/pending-input-queue.d.ts.map +1 -1
  517. package/dist/utils/pending-input-queue.js +5 -1
  518. package/dist/utils/pending-input-queue.js.map +1 -1
  519. package/dist/utils/user-token.d.ts.map +1 -1
  520. package/dist/utils/user-token.js +53 -2
  521. package/dist/utils/user-token.js.map +1 -1
  522. package/dist/worker-ipc-preload.d.ts +12 -0
  523. package/dist/worker-ipc-preload.d.ts.map +1 -0
  524. package/dist/worker-ipc-preload.js +44 -0
  525. package/dist/worker-ipc-preload.js.map +1 -0
  526. package/dist/worker.js +2604 -325
  527. package/dist/worker.js.map +1 -1
  528. package/dist/workflows/v3/session-relay-client.d.ts +1 -0
  529. package/dist/workflows/v3/session-relay-client.d.ts.map +1 -1
  530. package/dist/workflows/v3/session-relay-client.js +12 -3
  531. package/dist/workflows/v3/session-relay-client.js.map +1 -1
  532. package/package.json +1 -1
  533. package/dist/dashboard-web/chunks/bot-defaults-page-LTVOUDIS.js +0 -10
  534. package/dist/dashboard-web/chunks/chunk-DCS35UMD.js +0 -1
  535. package/dist/dashboard-web/chunks/chunk-MFQPCVHY.js +0 -51
  536. package/dist/dashboard-web/chunks/connectors-page-5KWDIMKC.js +0 -1
  537. package/dist/dashboard-web/chunks/groups-page-FHOKYXMW.js +0 -8
  538. package/dist/dashboard-web/chunks/overview-page-QYI3KBDD.js +0 -1
  539. package/dist/dashboard-web/chunks/sessions-page-WBP4N7D2.js +0 -6
@@ -0,0 +1,787 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import * as sessionStore from '../services/session-store.js';
3
+ import { logger } from '../utils/logger.js';
4
+ import { RIFF_ADMISSION_RESTORE_TIMEOUT_MS, RIFF_SHUTDOWN_BATCH_PERSIST_TIMEOUT_MS, RIFF_SHUTDOWN_DRAIN_TIMEOUT_MS, RIFF_SHUTDOWN_INITIAL_SNAPSHOT_TIMEOUT_MS, } from './shutdown-budgets.js';
5
+ /** The active registry can retain multiple aliases to one exact runtime object
6
+ * after transfer/restore. Process that object once, but refuse two distinct
7
+ * objects claiming the same durable session id: there is no unique generation
8
+ * that shutdown can safely fence or retire. */
9
+ export function collectUniqueDaemonShutdownSessions(candidates) {
10
+ const seenObjects = new Set();
11
+ const bySessionId = new Map();
12
+ const sessions = [];
13
+ for (const ds of candidates) {
14
+ if (seenObjects.has(ds))
15
+ continue;
16
+ seenObjects.add(ds);
17
+ const sessionId = ds.session.sessionId;
18
+ const existing = bySessionId.get(sessionId);
19
+ if (existing && existing !== ds) {
20
+ return {
21
+ ok: false,
22
+ sessionId,
23
+ error: `distinct daemon session generations share session id ${sessionId}`,
24
+ };
25
+ }
26
+ bySessionId.set(sessionId, ds);
27
+ sessions.push(ds);
28
+ }
29
+ return { ok: true, sessions };
30
+ }
31
+ function label(ds) {
32
+ return ds.session.sessionId.slice(0, 8);
33
+ }
34
+ function workerHasExited(worker) {
35
+ return (worker.exitCode !== null && worker.exitCode !== undefined)
36
+ || (worker.signalCode !== null && worker.signalCode !== undefined);
37
+ }
38
+ function send(worker, message) {
39
+ try {
40
+ worker.send(message);
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ /** Attach the exact-worker response/exit listeners before publishing a phase
48
+ * request. Results from another generation/session/request are inert. */
49
+ function requestPhase(ds, worker, requestId, phase, timeoutMs) {
50
+ return new Promise(resolve => {
51
+ let settled = false;
52
+ const finish = (result) => {
53
+ if (settled)
54
+ return;
55
+ settled = true;
56
+ clearTimeout(timer);
57
+ worker.removeListener('message', onMessage);
58
+ worker.removeListener('exit', onExit);
59
+ resolve(result);
60
+ };
61
+ const onMessage = (raw) => {
62
+ const msg = raw;
63
+ if (msg?.type !== 'riff_shutdown_result'
64
+ || msg.requestId !== requestId
65
+ || msg.phase !== phase)
66
+ return;
67
+ if (ds.worker !== worker) {
68
+ finish({ ok: false, taskId: msg.taskId, error: 'stale_worker_generation' });
69
+ return;
70
+ }
71
+ finish({
72
+ ok: msg.ok,
73
+ taskId: msg.taskId,
74
+ ...(msg.error ? { error: msg.error } : {}),
75
+ });
76
+ };
77
+ const onExit = () => finish({
78
+ ok: false,
79
+ taskId: null,
80
+ error: `worker_exited_during_shutdown_${phase}`,
81
+ });
82
+ const timer = setTimeout(() => finish({
83
+ ok: false,
84
+ taskId: null,
85
+ error: `riff_shutdown_${phase}_timeout`,
86
+ }), timeoutMs);
87
+ timer.unref?.();
88
+ worker.on('message', onMessage);
89
+ worker.once('exit', onExit);
90
+ const message = phase === 'prepare'
91
+ ? { type: 'riff_shutdown_prepare', requestId }
92
+ : { type: 'riff_shutdown_abort', requestId };
93
+ if (!send(worker, message)) {
94
+ finish({ ok: false, taskId: null, error: `riff_shutdown_${phase}_send_failed` });
95
+ }
96
+ });
97
+ }
98
+ function clearWorkerOwnership(ds, worker) {
99
+ if (ds.worker !== worker)
100
+ return;
101
+ ds.worker = null;
102
+ ds.workerPort = null;
103
+ ds.workerToken = null;
104
+ ds.workerViewToken = null;
105
+ ds.managedTurnOrigin = undefined;
106
+ ds.riffShutdownState = undefined;
107
+ }
108
+ function clearWorkerlessShutdownState(ds, requestId) {
109
+ if (ds.riffShutdownState?.requestId !== requestId)
110
+ return;
111
+ if (ds.worker)
112
+ return;
113
+ ds.riffShutdownState = undefined;
114
+ }
115
+ /** Daemon-owned accepted input has not crossed worker IPC yet. The bot-wide
116
+ * mutation lease blocks new admissions, but these older buffers must also be
117
+ * empty before a worker can be detached. */
118
+ function daemonInputBlocker(ds) {
119
+ const parts = [];
120
+ if (ds.pendingRepoCommitInFlight || ds.worktreeCreating)
121
+ parts.push('initial_start=1');
122
+ if (ds.pendingPrompt)
123
+ parts.push('prompt=1');
124
+ if (ds.pendingRawInput)
125
+ parts.push('raw=1');
126
+ if (ds.pendingFollowUpInput)
127
+ parts.push('raw_followup=1');
128
+ if ((ds.pendingFollowUps?.length ?? 0) > 0) {
129
+ parts.push(`followups=${ds.pendingFollowUps.length}`);
130
+ }
131
+ if (ds.session.queued)
132
+ parts.push('queued=1');
133
+ return parts.length > 0 ? parts.join(',') : null;
134
+ }
135
+ async function abortWorkerPreparation(ds, worker, requestId, timeoutMs, lineageVerified = false, exactTask) {
136
+ if (workerHasExited(worker)) {
137
+ if (ds.worker && ds.worker !== worker) {
138
+ return {
139
+ ok: false,
140
+ taskId: ds.riffShutdownState?.taskId ?? ds.session.riffParentTaskId ?? null,
141
+ error: 'new_worker_generation',
142
+ };
143
+ }
144
+ if (lineageVerified) {
145
+ if (ds.worker === worker)
146
+ clearWorkerOwnership(ds, worker);
147
+ else
148
+ clearWorkerlessShutdownState(ds, requestId);
149
+ return { ok: true, taskId: ds.session.riffParentTaskId ?? null };
150
+ }
151
+ // No backend remains to ACK admission restoration and the drained lineage
152
+ // was not durably recovered. Retain a daemon-side fence instead of claiming
153
+ // rollback success and permitting a stale-lineage replacement.
154
+ if (!ds.riffShutdownState || ds.riffShutdownState.requestId === requestId) {
155
+ ds.riffShutdownState = {
156
+ phase: 'prepared',
157
+ requestId,
158
+ taskId: ds.session.riffParentTaskId ?? null,
159
+ };
160
+ }
161
+ return {
162
+ ok: false,
163
+ taskId: ds.session.riffParentTaskId ?? null,
164
+ error: 'worker_exited_before_admission_restore',
165
+ };
166
+ }
167
+ if (ds.worker !== worker) {
168
+ return {
169
+ ok: false,
170
+ taskId: ds.riffShutdownState?.taskId ?? ds.session.riffParentTaskId ?? null,
171
+ error: 'new_worker_generation',
172
+ };
173
+ }
174
+ const result = await requestPhase(ds, worker, requestId, 'abort', timeoutMs);
175
+ if (result.ok && exactTask && result.taskId !== exactTask.taskId) {
176
+ return {
177
+ ok: false,
178
+ taskId: result.taskId,
179
+ error: `abort_task_lineage_mismatch:expected=${exactTask.taskId ?? 'none'},`
180
+ + `actual=${result.taskId ?? 'none'}`,
181
+ };
182
+ }
183
+ if (result.ok && ds.riffShutdownState?.requestId === requestId) {
184
+ ds.riffShutdownState = undefined;
185
+ }
186
+ return result;
187
+ }
188
+ function unfencedRefusal(ds, error, requestId) {
189
+ return {
190
+ ok: false,
191
+ fence: 'none',
192
+ ...(requestId ? { requestId } : {}),
193
+ taskId: ds.session.riffParentTaskId ?? null,
194
+ error,
195
+ };
196
+ }
197
+ /** Phase 1: fence one exact Riff generation and drain task-id materialization.
198
+ * Nothing exits or restores admission here. A failure after the prepare send
199
+ * returns an exact possibly-fenced handle so all peers can be restored in one
200
+ * concurrent fleet wave rather than serial drain+abort chains. */
201
+ export async function prepareRiffSessionForShutdown(ds, options = {}) {
202
+ const frozenBackend = ds.initConfig?.backendType ?? ds.session.backendType;
203
+ if (frozenBackend !== 'riff') {
204
+ return unfencedRefusal(ds, 'not_riff_backend');
205
+ }
206
+ if (ds.riffCloseState || ds.riffShutdownState) {
207
+ return unfencedRefusal(ds, ds.riffCloseState ? 'explicit_close_in_progress' : 'shutdown_detach_in_progress');
208
+ }
209
+ const daemonBlockerBeforePrepare = daemonInputBlocker(ds);
210
+ if (daemonBlockerBeforePrepare) {
211
+ return unfencedRefusal(ds, `daemon_inputs_not_drained:${daemonBlockerBeforePrepare}`);
212
+ }
213
+ const runtimeTaskIdAtPrepare = ds.session.riffParentTaskId ?? null;
214
+ let durableSnapshot = options.durableSnapshot;
215
+ if (!durableSnapshot) {
216
+ try {
217
+ [durableSnapshot] = sessionStore.getActiveRiffShutdownSnapshotsBatch([
218
+ ds.session.sessionId,
219
+ ]);
220
+ }
221
+ catch (err) {
222
+ return unfencedRefusal(ds, `durable_session_read_failed:${err instanceof Error ? err.message : String(err)}`);
223
+ }
224
+ }
225
+ if (!durableSnapshot || durableSnapshot.sessionId !== ds.session.sessionId) {
226
+ return unfencedRefusal(ds, 'durable_session_snapshot_mismatch');
227
+ }
228
+ const durableTaskIdAtPrepare = durableSnapshot.taskId;
229
+ const runtimeOwner = {
230
+ pid: ds.session.pid ?? null,
231
+ larkAppId: ds.session.larkAppId ?? null,
232
+ backendType: ds.session.backendType ?? null,
233
+ };
234
+ const durableOwnerAtPrepare = durableSnapshot.owner;
235
+ if (durableOwnerAtPrepare.pid !== runtimeOwner.pid
236
+ || durableOwnerAtPrepare.larkAppId !== runtimeOwner.larkAppId
237
+ || durableOwnerAtPrepare.backendType !== runtimeOwner.backendType) {
238
+ return unfencedRefusal(ds, `durable_session_owner_mismatch:current=${JSON.stringify(durableOwnerAtPrepare)},`
239
+ + `runtime=${JSON.stringify(runtimeOwner)}`);
240
+ }
241
+ const now = options.now ?? Date.now;
242
+ const abortReserveMs = options.abortTimeoutMs ?? RIFF_ADMISSION_RESTORE_TIMEOUT_MS;
243
+ let drainTimeoutMs = options.drainTimeoutMs ?? RIFF_SHUTDOWN_DRAIN_TIMEOUT_MS;
244
+ if (options.deadlineMs !== undefined) {
245
+ const availableDrainMs = options.deadlineMs
246
+ - now()
247
+ - RIFF_SHUTDOWN_BATCH_PERSIST_TIMEOUT_MS
248
+ - abortReserveMs;
249
+ if (availableDrainMs <= 0) {
250
+ return unfencedRefusal(ds, 'insufficient_abort_budget_before_fence');
251
+ }
252
+ drainTimeoutMs = Math.min(drainTimeoutMs, availableDrainMs);
253
+ }
254
+ const requestId = randomUUID();
255
+ const worker = ds.worker;
256
+ if (!worker || workerHasExited(worker)) {
257
+ // Retire a previously observed dead handle before installing the
258
+ // workerless fence. Any later non-null ds.worker is then unambiguously a
259
+ // new generation and cannot be blessed by this transaction.
260
+ if (worker)
261
+ clearWorkerOwnership(ds, worker);
262
+ // Workerless rows can still carry a newer runtime-only lineage after a
263
+ // failed ordinary riff_task_id save. Fence daemon admission now; phase 2
264
+ // performs an exact owner/lineage CAS and fresh disk verification.
265
+ ds.riffShutdownState = {
266
+ phase: 'prepared',
267
+ requestId,
268
+ taskId: ds.session.riffParentTaskId ?? null,
269
+ };
270
+ return {
271
+ ok: true,
272
+ fence: 'prepared',
273
+ requestId,
274
+ taskId: ds.session.riffParentTaskId ?? null,
275
+ runtimeTaskIdAtPrepare,
276
+ durableTaskIdAtPrepare,
277
+ durableOwnerAtPrepare,
278
+ lineageVerified: false,
279
+ worker: null,
280
+ };
281
+ }
282
+ ds.riffShutdownState = { phase: 'preparing', requestId };
283
+ const prepared = await requestPhase(ds, worker, requestId, 'prepare', drainTimeoutMs);
284
+ if (!prepared.ok) {
285
+ // This exact response proves the worker refused before installing a backend
286
+ // fence. Every other failure has ambiguous fence state and requires a
287
+ // positive admission-restored ACK.
288
+ const unfencedWorkerRefusal = prepared.error === 'explicit_close_in_progress'
289
+ || prepared.error === 'not_riff_backend'
290
+ || prepared.error === 'riff_shutdown_prepare_send_failed'
291
+ || prepared.error?.startsWith('worker_inputs_not_drained:') === true;
292
+ if (unfencedWorkerRefusal && ds.riffShutdownState?.requestId === requestId) {
293
+ ds.riffShutdownState = undefined;
294
+ }
295
+ if (unfencedWorkerRefusal) {
296
+ return {
297
+ ok: false,
298
+ fence: 'none',
299
+ requestId,
300
+ taskId: prepared.taskId,
301
+ error: prepared.error ?? 'riff_shutdown_prepare_failed',
302
+ };
303
+ }
304
+ return {
305
+ ok: false,
306
+ fence: 'possible',
307
+ requestId,
308
+ taskId: prepared.taskId,
309
+ error: prepared.error ?? 'riff_shutdown_prepare_failed',
310
+ worker,
311
+ };
312
+ }
313
+ if (ds.worker !== worker) {
314
+ return {
315
+ ok: false,
316
+ fence: 'possible',
317
+ requestId,
318
+ taskId: prepared.taskId,
319
+ error: 'stale_worker_generation',
320
+ worker,
321
+ };
322
+ }
323
+ ds.riffShutdownState = { phase: 'prepared', requestId, taskId: prepared.taskId };
324
+ // Worker events can release a queued-activation journal/tail independently
325
+ // of bot-turn admission. Re-sample after drain so commit cannot strand input.
326
+ const daemonBlockerAfterPrepare = daemonInputBlocker(ds);
327
+ if (daemonBlockerAfterPrepare) {
328
+ return {
329
+ ok: false,
330
+ fence: 'possible',
331
+ requestId,
332
+ taskId: prepared.taskId,
333
+ error: `daemon_inputs_not_drained:${daemonBlockerAfterPrepare}`,
334
+ worker,
335
+ expectedAbortTaskId: prepared.taskId,
336
+ };
337
+ }
338
+ return {
339
+ ok: true,
340
+ fence: 'prepared',
341
+ requestId,
342
+ taskId: prepared.taskId,
343
+ runtimeTaskIdAtPrepare,
344
+ durableTaskIdAtPrepare,
345
+ durableOwnerAtPrepare,
346
+ lineageVerified: false,
347
+ worker,
348
+ };
349
+ }
350
+ /** Take one fresh projection for the complete candidate set, then (and only
351
+ * then) publish prepare requests concurrently. */
352
+ export async function prepareRiffFleetForShutdown(candidates, options = {}) {
353
+ if (candidates.length === 0)
354
+ return [];
355
+ const now = options.now ?? Date.now;
356
+ const configuredSnapshotTimeout = options.snapshotTimeoutMs
357
+ ?? RIFF_SHUTDOWN_INITIAL_SNAPSHOT_TIMEOUT_MS;
358
+ const remaining = options.deadlineMs === undefined
359
+ ? configuredSnapshotTimeout
360
+ : Math.max(0, options.deadlineMs - now());
361
+ if (remaining <= 0) {
362
+ return candidates.map(ds => ({
363
+ ds,
364
+ result: unfencedRefusal(ds, 'shutdown_deadline_elapsed_before_initial_snapshot'),
365
+ }));
366
+ }
367
+ let snapshots;
368
+ try {
369
+ snapshots = sessionStore.getActiveRiffShutdownSnapshotsBatch(candidates.map(ds => ds.session.sessionId), { maxWaitMs: Math.min(configuredSnapshotTimeout, remaining) });
370
+ }
371
+ catch (error) {
372
+ const message = `initial_riff_snapshot_failed:${error instanceof Error
373
+ ? error.message
374
+ : String(error)}`;
375
+ return candidates.map(ds => ({ ds, result: unfencedRefusal(ds, message) }));
376
+ }
377
+ const snapshotsBySession = new Map(snapshots.map(snapshot => [snapshot.sessionId, snapshot]));
378
+ return Promise.all(candidates.map(async (ds) => ({
379
+ ds,
380
+ result: await prepareRiffSessionForShutdown(ds, {
381
+ ...options,
382
+ durableSnapshot: snapshotsBySession.get(ds.session.sessionId),
383
+ }),
384
+ })));
385
+ }
386
+ function validatePreparedRiffShutdownForPersistence(ds, prepared) {
387
+ if (ds.riffShutdownState?.requestId !== prepared.requestId
388
+ || ds.riffShutdownState.phase !== 'prepared') {
389
+ return {
390
+ ok: false,
391
+ requestId: prepared.requestId,
392
+ taskId: prepared.taskId,
393
+ error: 'shutdown_prepare_ownership_lost',
394
+ rollbackDisposition: 'retain_fence',
395
+ };
396
+ }
397
+ const daemonBlocker = daemonInputBlocker(ds);
398
+ if (daemonBlocker) {
399
+ return {
400
+ ok: false,
401
+ requestId: prepared.requestId,
402
+ taskId: prepared.taskId,
403
+ error: `daemon_inputs_not_drained:${daemonBlocker}`,
404
+ rollbackDisposition: 'abort_safe',
405
+ };
406
+ }
407
+ if (prepared.worker) {
408
+ if (ds.worker !== prepared.worker || workerHasExited(prepared.worker)) {
409
+ return {
410
+ ok: false,
411
+ requestId: prepared.requestId,
412
+ taskId: prepared.taskId,
413
+ error: 'stale_worker_generation',
414
+ rollbackDisposition: 'retain_fence',
415
+ };
416
+ }
417
+ }
418
+ else if (ds.worker) {
419
+ return {
420
+ ok: false,
421
+ requestId: prepared.requestId,
422
+ taskId: prepared.taskId,
423
+ error: 'new_worker_generation',
424
+ rollbackDisposition: 'retain_fence',
425
+ };
426
+ }
427
+ const runtimeOwner = {
428
+ pid: ds.session.pid ?? null,
429
+ larkAppId: ds.session.larkAppId ?? null,
430
+ backendType: ds.session.backendType ?? null,
431
+ };
432
+ if (runtimeOwner.pid !== prepared.durableOwnerAtPrepare.pid
433
+ || runtimeOwner.larkAppId !== prepared.durableOwnerAtPrepare.larkAppId
434
+ || runtimeOwner.backendType !== prepared.durableOwnerAtPrepare.backendType) {
435
+ return {
436
+ ok: false,
437
+ requestId: prepared.requestId,
438
+ taskId: prepared.taskId,
439
+ error: `runtime_owner_changed:${JSON.stringify(runtimeOwner)}`,
440
+ rollbackDisposition: 'retain_fence',
441
+ };
442
+ }
443
+ const runtimeTaskId = ds.session.riffParentTaskId ?? null;
444
+ const runtimeLineageExpected = prepared.worker
445
+ ? runtimeTaskId === prepared.runtimeTaskIdAtPrepare || runtimeTaskId === prepared.taskId
446
+ : runtimeTaskId === prepared.runtimeTaskIdAtPrepare;
447
+ if (!runtimeLineageExpected) {
448
+ return {
449
+ ok: false,
450
+ requestId: prepared.requestId,
451
+ taskId: prepared.taskId,
452
+ error: `runtime_lineage_changed:${runtimeTaskId ?? 'none'}`,
453
+ rollbackDisposition: 'retain_fence',
454
+ };
455
+ }
456
+ return { ok: true };
457
+ }
458
+ /** Phase 2 fleet transaction: validate every runtime generation, then compare
459
+ * and publish all durable lineage rows with one lock and one rename. */
460
+ export function persistPreparedRiffShutdownFleet(entries, options = {}) {
461
+ if (entries.length === 0)
462
+ return { ok: true };
463
+ const now = options.now ?? Date.now;
464
+ const validationFailures = entries
465
+ .map(({ ds, result }) => ({
466
+ sessionId: ds.session.sessionId,
467
+ failure: validatePreparedRiffShutdownForPersistence(ds, result),
468
+ }))
469
+ .filter((entry) => !entry.failure.ok);
470
+ if (validationFailures.length > 0) {
471
+ const retainFencedSessionIds = validationFailures
472
+ .filter(({ failure }) => failure.rollbackDisposition === 'retain_fence')
473
+ .map(({ sessionId }) => sessionId);
474
+ return {
475
+ ok: false,
476
+ taskId: null,
477
+ error: `Riff fleet persistence preflight failed: ${validationFailures
478
+ .map(({ sessionId, failure }) => `${sessionId}:${failure.error}`)
479
+ .join(';')}`,
480
+ rollbackDisposition: retainFencedSessionIds.length > 0 ? 'retain_fence' : 'abort_safe',
481
+ sessionIds: validationFailures.map(({ sessionId }) => sessionId),
482
+ retainFencedSessionIds,
483
+ };
484
+ }
485
+ const configuredPersistTimeout = options.persistTimeoutMs
486
+ ?? RIFF_SHUTDOWN_BATCH_PERSIST_TIMEOUT_MS;
487
+ const remaining = options.deadlineMs === undefined
488
+ ? configuredPersistTimeout
489
+ : Math.max(0, options.deadlineMs - now());
490
+ if (remaining <= 0) {
491
+ return {
492
+ ok: false,
493
+ taskId: null,
494
+ error: 'Riff fleet lineage batch failed (prewrite_io): shutdown deadline elapsed',
495
+ rollbackDisposition: 'abort_safe',
496
+ sessionIds: entries.map(({ ds }) => ds.session.sessionId),
497
+ retainFencedSessionIds: [],
498
+ };
499
+ }
500
+ try {
501
+ sessionStore.persistActiveRiffLineagesExactBatch(entries.map(({ ds, result }) => ({
502
+ sessionId: ds.session.sessionId,
503
+ taskId: result.durableTaskIdAtPrepare,
504
+ owner: result.durableOwnerAtPrepare,
505
+ targetTaskId: result.taskId,
506
+ expectedCurrentTaskIds: [result.durableTaskIdAtPrepare, result.taskId],
507
+ })), {
508
+ maxWaitMs: Math.min(configuredPersistTimeout, remaining),
509
+ });
510
+ }
511
+ catch (error) {
512
+ const batchError = error instanceof sessionStore.RiffLineageBatchError ? error : undefined;
513
+ const stage = batchError?.stage ?? 'prewrite_io';
514
+ const retainFencedSessionIds = stage === 'postrename_ambiguity'
515
+ ? entries.map(({ ds }) => ds.session.sessionId)
516
+ : stage === 'prewrite_ownership'
517
+ ? [...(batchError?.sessionIds ?? [])]
518
+ : [];
519
+ return {
520
+ ok: false,
521
+ taskId: null,
522
+ error: `Riff fleet lineage batch failed (${stage}): ${error instanceof Error
523
+ ? error.message
524
+ : String(error)}`,
525
+ rollbackDisposition: retainFencedSessionIds.length > 0 ? 'retain_fence' : 'abort_safe',
526
+ sessionIds: batchError?.sessionIds ?? entries.map(({ ds }) => ds.session.sessionId),
527
+ retainFencedSessionIds,
528
+ };
529
+ }
530
+ for (const { ds, result } of entries) {
531
+ ds.session.riffParentTaskId = result.taskId ?? undefined;
532
+ result.lineageVerified = true;
533
+ }
534
+ if (options.deadlineMs !== undefined && now() >= options.deadlineMs) {
535
+ const sessionIds = entries.map(({ ds }) => ds.session.sessionId);
536
+ return {
537
+ ok: false,
538
+ taskId: null,
539
+ error: 'shutdown_deadline_elapsed_after_batch_persist',
540
+ rollbackDisposition: 'retain_fence',
541
+ sessionIds,
542
+ retainFencedSessionIds: sessionIds,
543
+ };
544
+ }
545
+ const lost = entries
546
+ .filter(({ ds, result }) => !isPreparedRiffSessionCurrent(ds, result))
547
+ .map(({ ds }) => ds.session.sessionId);
548
+ if (lost.length > 0) {
549
+ return {
550
+ ok: false,
551
+ taskId: null,
552
+ error: `shutdown_prepare_ownership_lost_after_batch_persist:${lost.join(',')}`,
553
+ rollbackDisposition: 'retain_fence',
554
+ sessionIds: lost,
555
+ retainFencedSessionIds: lost,
556
+ };
557
+ }
558
+ return { ok: true };
559
+ }
560
+ /** Single-session compatibility path. Fleet shutdown uses the batch function
561
+ * above; this API remains for explicit focused operations and older callers. */
562
+ export function persistPreparedRiffShutdown(ds, prepared) {
563
+ const validation = validatePreparedRiffShutdownForPersistence(ds, prepared);
564
+ if (!validation.ok)
565
+ return validation;
566
+ try {
567
+ sessionStore.persistActiveRiffLineageExact(ds.session.sessionId, prepared.taskId, {
568
+ expectedCurrentTaskIds: [prepared.durableTaskIdAtPrepare, prepared.taskId],
569
+ expectedOwner: prepared.durableOwnerAtPrepare,
570
+ });
571
+ }
572
+ catch (err) {
573
+ return {
574
+ ok: false,
575
+ requestId: prepared.requestId,
576
+ taskId: prepared.taskId,
577
+ error: `lineage_persist_failed:${err instanceof Error ? err.message : String(err)}`,
578
+ rollbackDisposition: err instanceof sessionStore.RiffLineageOwnershipError
579
+ ? 'retain_fence'
580
+ : 'abort_safe',
581
+ };
582
+ }
583
+ let fresh;
584
+ try {
585
+ fresh = sessionStore.getSessionFresh(ds.session.sessionId);
586
+ }
587
+ catch (err) {
588
+ return {
589
+ ok: false,
590
+ requestId: prepared.requestId,
591
+ taskId: prepared.taskId,
592
+ error: `fresh_lineage_verification_failed:${err instanceof Error ? err.message : String(err)}`,
593
+ rollbackDisposition: 'retain_fence',
594
+ };
595
+ }
596
+ const freshTaskId = fresh?.riffParentTaskId ?? null;
597
+ const freshOwner = fresh
598
+ ? {
599
+ pid: fresh.pid ?? null,
600
+ larkAppId: fresh.larkAppId ?? null,
601
+ backendType: fresh.backendType ?? null,
602
+ }
603
+ : null;
604
+ const freshOwnerMatches = freshOwner !== null
605
+ && freshOwner.pid === prepared.durableOwnerAtPrepare.pid
606
+ && freshOwner.larkAppId === prepared.durableOwnerAtPrepare.larkAppId
607
+ && freshOwner.backendType === prepared.durableOwnerAtPrepare.backendType;
608
+ if (!fresh
609
+ || fresh.status !== 'active'
610
+ || freshTaskId !== prepared.taskId
611
+ || !freshOwnerMatches) {
612
+ return {
613
+ ok: false,
614
+ requestId: prepared.requestId,
615
+ taskId: prepared.taskId,
616
+ error: `fresh_lineage_verification_failed:status=${fresh?.status ?? 'missing'},`
617
+ + `task=${freshTaskId ?? 'none'},expected=${prepared.taskId ?? 'none'},`
618
+ + `owner=${JSON.stringify(freshOwner)},`
619
+ + `expectedOwner=${JSON.stringify(prepared.durableOwnerAtPrepare)}`,
620
+ rollbackDisposition: 'retain_fence',
621
+ };
622
+ }
623
+ ds.session.riffParentTaskId = prepared.taskId ?? undefined;
624
+ prepared.lineageVerified = true;
625
+ if (!isPreparedRiffSessionCurrent(ds, prepared)) {
626
+ return {
627
+ ok: false,
628
+ requestId: prepared.requestId,
629
+ taskId: prepared.taskId,
630
+ error: 'shutdown_prepare_ownership_lost_after_persist',
631
+ rollbackDisposition: 'retain_fence',
632
+ };
633
+ }
634
+ return { ok: true };
635
+ }
636
+ export function isPreparedRiffSessionCurrent(ds, prepared) {
637
+ if (ds.riffShutdownState?.requestId !== prepared.requestId
638
+ || ds.riffShutdownState.phase !== 'prepared')
639
+ return false;
640
+ if (prepared.worker) {
641
+ return ds.worker === prepared.worker && !workerHasExited(prepared.worker);
642
+ }
643
+ return ds.worker === null;
644
+ }
645
+ /** After verified lineage persistence, an exact prepared worker that exited
646
+ * and was cleared by worker-pool can be safely rolled back locally. A new
647
+ * worker generation or a different fence remains ownership ambiguity. */
648
+ export function canAbortVerifiedExitedRiffPreparation(ds, prepared) {
649
+ return prepared.lineageVerified
650
+ && !!prepared.worker
651
+ && workerHasExited(prepared.worker)
652
+ && ds.worker === null
653
+ && ds.riffShutdownState?.requestId === prepared.requestId;
654
+ }
655
+ /** Roll back one prepared participant. State clears only after the exact worker
656
+ * ACKs admission restoration; timeout/late ACK remains deliberately fail-closed. */
657
+ export async function abortPreparedRiffShutdown(ds, prepared, options = {}) {
658
+ if (ds.riffShutdownState?.requestId !== prepared.requestId) {
659
+ return { ok: false, taskId: prepared.taskId, error: 'shutdown_prepare_ownership_lost' };
660
+ }
661
+ if (!prepared.worker) {
662
+ if (ds.worker) {
663
+ return { ok: false, taskId: prepared.taskId, error: 'new_worker_generation' };
664
+ }
665
+ clearWorkerlessShutdownState(ds, prepared.requestId);
666
+ return { ok: true, taskId: prepared.taskId };
667
+ }
668
+ if (workerHasExited(prepared.worker)) {
669
+ return abortWorkerPreparation(ds, prepared.worker, prepared.requestId, options.abortTimeoutMs ?? RIFF_ADMISSION_RESTORE_TIMEOUT_MS, prepared.lineageVerified, { taskId: prepared.taskId });
670
+ }
671
+ return abortWorkerPreparation(ds, prepared.worker, prepared.requestId, options.abortTimeoutMs ?? RIFF_ADMISSION_RESTORE_TIMEOUT_MS, prepared.lineageVerified, { taskId: prepared.taskId });
672
+ }
673
+ async function abortPossiblyFencedRiffShutdown(ds, participant, timeoutMs) {
674
+ if (ds.riffShutdownState?.requestId !== participant.requestId) {
675
+ return {
676
+ ok: false,
677
+ taskId: participant.taskId,
678
+ error: 'shutdown_prepare_ownership_lost',
679
+ };
680
+ }
681
+ return abortWorkerPreparation(ds, participant.worker, participant.requestId, timeoutMs, false, Object.prototype.hasOwnProperty.call(participant, 'expectedAbortTaskId')
682
+ ? { taskId: participant.expectedAbortTaskId ?? null }
683
+ : undefined);
684
+ }
685
+ /** Restore every exact prepared/possibly-fenced generation concurrently. No
686
+ * participant can consume another's timeout budget. */
687
+ export async function abortRiffShutdownFleet(entries, options = {}) {
688
+ const now = options.now ?? Date.now;
689
+ const configuredTimeout = options.abortTimeoutMs ?? RIFF_ADMISSION_RESTORE_TIMEOUT_MS;
690
+ const remaining = options.deadlineMs === undefined
691
+ ? configuredTimeout
692
+ : Math.max(0, options.deadlineMs - now());
693
+ const timeoutMs = Math.min(configuredTimeout, remaining);
694
+ return Promise.all(entries.map(async ({ ds, result: participant }) => {
695
+ if (timeoutMs <= 0) {
696
+ return {
697
+ ds,
698
+ participant,
699
+ result: {
700
+ ok: false,
701
+ taskId: participant.taskId,
702
+ error: 'shutdown_deadline_elapsed_before_abort',
703
+ },
704
+ };
705
+ }
706
+ const result = participant.ok
707
+ ? await abortPreparedRiffShutdown(ds, participant, { abortTimeoutMs: timeoutMs })
708
+ : await abortPossiblyFencedRiffShutdown(ds, participant, timeoutMs);
709
+ return { ds, participant, result };
710
+ }));
711
+ }
712
+ /** Phase 3: synchronous, infallible-after-validation commit. The coordinator
713
+ * validates every participant first, then calls this without an intervening
714
+ * await, so one session can never refuse after a peer was detached. */
715
+ export function commitPreparedRiffShutdown(ds, prepared) {
716
+ if (!isPreparedRiffSessionCurrent(ds, prepared))
717
+ return false;
718
+ if (!prepared.worker) {
719
+ clearWorkerlessShutdownState(ds, prepared.requestId);
720
+ return true;
721
+ }
722
+ if (!send(prepared.worker, { type: 'riff_shutdown_commit', requestId: prepared.requestId })) {
723
+ // Lineage is already durably fresh-verified. Direct retirement is safe even
724
+ // if the final IPC channel closed between validation and send.
725
+ try {
726
+ prepared.worker.kill('SIGTERM');
727
+ }
728
+ catch { /* already exited */ }
729
+ }
730
+ clearWorkerOwnership(ds, prepared.worker);
731
+ return true;
732
+ }
733
+ /** Single-session compatibility wrapper. Daemon shutdown intentionally uses
734
+ * the explicit three-phase API above so a multi-Riff fleet cannot half-commit. */
735
+ export async function detachRiffWorkerForShutdown(ds, options = {}) {
736
+ const prepared = await prepareRiffSessionForShutdown(ds, options);
737
+ if (!prepared.ok) {
738
+ if (prepared.fence === 'none')
739
+ return prepared;
740
+ const [aborted] = await abortRiffShutdownFleet([{ ds, result: prepared }], options);
741
+ const abortSuffix = aborted.result.ok
742
+ ? ''
743
+ : `;admission_restore_failed:${aborted.result.error ?? 'unknown'}`;
744
+ logger.error(`[${label(ds)}] Riff shutdown drain failed (${prepared.error}${abortSuffix}); `
745
+ + (aborted.result.ok
746
+ ? 'worker retained with admission restored'
747
+ : 'worker retained and admission fence kept fail-closed'));
748
+ return {
749
+ ok: false,
750
+ requestId: prepared.requestId,
751
+ taskId: prepared.taskId,
752
+ error: prepared.error + abortSuffix,
753
+ };
754
+ }
755
+ const persisted = persistPreparedRiffShutdown(ds, prepared);
756
+ if (!persisted.ok) {
757
+ if (persisted.rollbackDisposition === 'retain_fence')
758
+ return persisted;
759
+ const aborted = await abortPreparedRiffShutdown(ds, prepared, options);
760
+ return {
761
+ ok: false,
762
+ requestId: prepared.requestId,
763
+ taskId: prepared.taskId,
764
+ error: persisted.error
765
+ + (aborted.ok ? '' : `;admission_restore_failed:${aborted.error ?? 'unknown'}`),
766
+ };
767
+ }
768
+ if (!commitPreparedRiffShutdown(ds, prepared)) {
769
+ return {
770
+ ok: false,
771
+ requestId: prepared.requestId,
772
+ taskId: prepared.taskId,
773
+ error: 'shutdown_prepare_ownership_lost_before_commit',
774
+ rollbackDisposition: 'retain_fence',
775
+ };
776
+ }
777
+ logger.info(`[${label(ds)}] Riff shutdown detach committed after durable lineage `
778
+ + `${prepared.taskId ?? 'none'}`);
779
+ return {
780
+ ok: true,
781
+ requestId: prepared.requestId,
782
+ taskId: prepared.taskId,
783
+ disposition: 'lineage_persisted',
784
+ ...(prepared.worker ? { worker: prepared.worker } : {}),
785
+ };
786
+ }
787
+ //# sourceMappingURL=riff-shutdown-detach.js.map