botmux 3.2.1 → 3.4.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 (277) hide show
  1. package/dist/adapters/backend/sandbox.d.ts +47 -0
  2. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  3. package/dist/adapters/backend/sandbox.js +137 -0
  4. package/dist/adapters/backend/sandbox.js.map +1 -1
  5. package/dist/adapters/cli/pi.d.ts.map +1 -1
  6. package/dist/adapters/cli/pi.js +4 -0
  7. package/dist/adapters/cli/pi.js.map +1 -1
  8. package/dist/adapters/cli/read-isolation.d.ts +72 -3
  9. package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
  10. package/dist/adapters/cli/read-isolation.js +143 -6
  11. package/dist/adapters/cli/read-isolation.js.map +1 -1
  12. package/dist/adapters/cli/registry.d.ts.map +1 -1
  13. package/dist/adapters/cli/registry.js +8 -2
  14. package/dist/adapters/cli/registry.js.map +1 -1
  15. package/dist/adapters/cli/types.d.ts +8 -1
  16. package/dist/adapters/cli/types.d.ts.map +1 -1
  17. package/dist/cli/deferred-topic-send.d.ts +37 -0
  18. package/dist/cli/deferred-topic-send.d.ts.map +1 -0
  19. package/dist/cli/deferred-topic-send.js +69 -0
  20. package/dist/cli/deferred-topic-send.js.map +1 -0
  21. package/dist/cli/pm2-command.d.ts.map +1 -1
  22. package/dist/cli/pm2-command.js +6 -0
  23. package/dist/cli/pm2-command.js.map +1 -1
  24. package/dist/cli.d.ts.map +1 -1
  25. package/dist/cli.js +173 -34
  26. package/dist/cli.js.map +1 -1
  27. package/dist/core/command-handler.d.ts.map +1 -1
  28. package/dist/core/command-handler.js +17 -12
  29. package/dist/core/command-handler.js.map +1 -1
  30. package/dist/core/dashboard-ipc-server.d.ts +4 -1
  31. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  32. package/dist/core/dashboard-ipc-server.js +99 -8
  33. package/dist/core/dashboard-ipc-server.js.map +1 -1
  34. package/dist/core/deferred-schedule-settlement.d.ts +20 -0
  35. package/dist/core/deferred-schedule-settlement.d.ts.map +1 -0
  36. package/dist/core/deferred-schedule-settlement.js +18 -0
  37. package/dist/core/deferred-schedule-settlement.js.map +1 -0
  38. package/dist/core/deferred-topic-binding.d.ts +19 -0
  39. package/dist/core/deferred-topic-binding.d.ts.map +1 -0
  40. package/dist/core/deferred-topic-binding.js +55 -0
  41. package/dist/core/deferred-topic-binding.js.map +1 -0
  42. package/dist/core/device-isolation-activation.d.ts +56 -0
  43. package/dist/core/device-isolation-activation.d.ts.map +1 -0
  44. package/dist/core/device-isolation-activation.js +110 -0
  45. package/dist/core/device-isolation-activation.js.map +1 -0
  46. package/dist/core/device-isolation-daemon.d.ts +84 -0
  47. package/dist/core/device-isolation-daemon.d.ts.map +1 -0
  48. package/dist/core/device-isolation-daemon.js +591 -0
  49. package/dist/core/device-isolation-daemon.js.map +1 -0
  50. package/dist/core/scheduler.d.ts +26 -20
  51. package/dist/core/scheduler.d.ts.map +1 -1
  52. package/dist/core/scheduler.js +114 -56
  53. package/dist/core/scheduler.js.map +1 -1
  54. package/dist/core/session-discovery.d.ts.map +1 -1
  55. package/dist/core/session-discovery.js +47 -15
  56. package/dist/core/session-discovery.js.map +1 -1
  57. package/dist/core/session-manager.d.ts +17 -1
  58. package/dist/core/session-manager.d.ts.map +1 -1
  59. package/dist/core/session-manager.js +178 -84
  60. package/dist/core/session-manager.js.map +1 -1
  61. package/dist/core/types.d.ts +13 -0
  62. package/dist/core/types.d.ts.map +1 -1
  63. package/dist/core/types.js +10 -0
  64. package/dist/core/types.js.map +1 -1
  65. package/dist/core/worker-pool.d.ts +7 -0
  66. package/dist/core/worker-pool.d.ts.map +1 -1
  67. package/dist/core/worker-pool.js +86 -1
  68. package/dist/core/worker-pool.js.map +1 -1
  69. package/dist/daemon.d.ts.map +1 -1
  70. package/dist/daemon.js +95 -5
  71. package/dist/daemon.js.map +1 -1
  72. package/dist/dashboard/schedule-card-model.d.ts +12 -3
  73. package/dist/dashboard/schedule-card-model.d.ts.map +1 -1
  74. package/dist/dashboard/schedule-card-model.js +32 -8
  75. package/dist/dashboard/schedule-card-model.js.map +1 -1
  76. package/dist/dashboard/web/dashboard-components.d.ts +7 -0
  77. package/dist/dashboard/web/dashboard-components.d.ts.map +1 -1
  78. package/dist/dashboard/web/dashboard-components.js +11 -2
  79. package/dist/dashboard/web/dashboard-components.js.map +1 -1
  80. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  81. package/dist/dashboard/web/i18n.js +30 -6
  82. package/dist/dashboard/web/i18n.js.map +1 -1
  83. package/dist/dashboard/web/schedules-page.d.ts +2 -0
  84. package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
  85. package/dist/dashboard/web/schedules-page.js +74 -27
  86. package/dist/dashboard/web/schedules-page.js.map +1 -1
  87. package/dist/dashboard-web/app.js +1 -1
  88. package/dist/dashboard-web/chunks/{bot-defaults-page-O37SAQD5.js → bot-defaults-page-B5AY4B2J.js} +1 -1
  89. package/dist/dashboard-web/chunks/{chunk-6QHMLMIM.js → chunk-CUV65BIQ.js} +3 -3
  90. package/dist/dashboard-web/chunks/{chunk-O2DPQL7C.js → chunk-JNRSPKLS.js} +1 -1
  91. package/dist/dashboard-web/chunks/{chunk-FYALHCPG.js → chunk-P6GO5KT4.js} +1 -1
  92. package/dist/dashboard-web/chunks/chunk-QFMH6ITB.js +1 -0
  93. package/dist/dashboard-web/chunks/{chunk-B42PCL5P.js → chunk-UBOLHQCK.js} +1 -1
  94. package/dist/dashboard-web/chunks/{connectors-page-DZBQ42MH.js → connectors-page-KTC2QWNW.js} +1 -1
  95. package/dist/dashboard-web/chunks/{groups-page-3IEGRZKQ.js → groups-page-B3EKGOLY.js} +1 -1
  96. package/dist/dashboard-web/chunks/{insights-page-X3ADRON3.js → insights-page-X6RXNCWX.js} +1 -1
  97. package/dist/dashboard-web/chunks/{monitor-room-IV36RGQY.js → monitor-room-LLRA5LQW.js} +1 -1
  98. package/dist/dashboard-web/chunks/{monitoring-page-ADFKVON4.js → monitoring-page-7MT5FEOS.js} +1 -1
  99. package/dist/dashboard-web/chunks/{office-page-CALAOWNS.js → office-page-KD46D5TD.js} +1 -1
  100. package/dist/dashboard-web/chunks/{overview-page-SLMGLK3M.js → overview-page-JUWNH32O.js} +1 -1
  101. package/dist/dashboard-web/chunks/{roles-page-L7JJ4FFV.js → roles-page-P6F7NLOI.js} +1 -1
  102. package/dist/dashboard-web/chunks/schedules-page-XIHWZST4.js +1 -0
  103. package/dist/dashboard-web/chunks/{sessions-page-OKJ5YWUZ.js → sessions-page-2VECQ27T.js} +1 -1
  104. package/dist/dashboard-web/chunks/{settings-page-P6MI2ZUE.js → settings-page-HMIUE2JA.js} +1 -1
  105. package/dist/dashboard-web/chunks/{skills-page-FT7BVZ6X.js → skills-page-A46KVWBL.js} +1 -1
  106. package/dist/dashboard-web/chunks/{team-federation-page-DEYCPUFB.js → team-federation-page-SDUC56DF.js} +1 -1
  107. package/dist/dashboard-web/chunks/{v3-page-4IOWREZG.js → v3-page-J5JOTUSQ.js} +1 -1
  108. package/dist/dashboard-web/chunks/{whiteboards-page-2VMBETZH.js → whiteboards-page-U7LSOAWI.js} +1 -1
  109. package/dist/dashboard-web/style.css +34 -4
  110. package/dist/dashboard.js +16 -1
  111. package/dist/dashboard.js.map +1 -1
  112. package/dist/desktop/main/auto-start.d.ts +2 -0
  113. package/dist/desktop/main/auto-start.d.ts.map +1 -1
  114. package/dist/desktop/main/auto-start.js +10 -6
  115. package/dist/desktop/main/auto-start.js.map +1 -1
  116. package/dist/desktop/main/bundled-runtime.d.ts +12 -0
  117. package/dist/desktop/main/bundled-runtime.d.ts.map +1 -0
  118. package/dist/desktop/main/bundled-runtime.js +30 -0
  119. package/dist/desktop/main/bundled-runtime.js.map +1 -0
  120. package/dist/desktop/main/device-status.d.ts +15 -0
  121. package/dist/desktop/main/device-status.d.ts.map +1 -0
  122. package/dist/desktop/main/device-status.js +94 -0
  123. package/dist/desktop/main/device-status.js.map +1 -0
  124. package/dist/desktop/main/external-runtime.d.ts +9 -0
  125. package/dist/desktop/main/external-runtime.d.ts.map +1 -1
  126. package/dist/desktop/main/external-runtime.js +88 -18
  127. package/dist/desktop/main/external-runtime.js.map +1 -1
  128. package/dist/desktop/main/ipc.d.ts.map +1 -1
  129. package/dist/desktop/main/ipc.js +1 -0
  130. package/dist/desktop/main/ipc.js.map +1 -1
  131. package/dist/desktop/main/node-command.d.ts +21 -0
  132. package/dist/desktop/main/node-command.d.ts.map +1 -1
  133. package/dist/desktop/main/node-command.js +41 -0
  134. package/dist/desktop/main/node-command.js.map +1 -1
  135. package/dist/desktop/main/pm2-apps.d.ts +4 -2
  136. package/dist/desktop/main/pm2-apps.d.ts.map +1 -1
  137. package/dist/desktop/main/pm2-apps.js +11 -3
  138. package/dist/desktop/main/pm2-apps.js.map +1 -1
  139. package/dist/desktop/main/runtime-service.d.ts +21 -5
  140. package/dist/desktop/main/runtime-service.d.ts.map +1 -1
  141. package/dist/desktop/main/runtime-service.js +94 -10
  142. package/dist/desktop/main/runtime-service.js.map +1 -1
  143. package/dist/desktop/main/runtime-source.d.ts +2 -0
  144. package/dist/desktop/main/runtime-source.d.ts.map +1 -1
  145. package/dist/desktop/main/runtime-source.js +12 -6
  146. package/dist/desktop/main/runtime-source.js.map +1 -1
  147. package/dist/desktop/main/tray.d.ts +1 -0
  148. package/dist/desktop/main/tray.d.ts.map +1 -1
  149. package/dist/desktop/main/tray.js +3 -3
  150. package/dist/desktop/main/tray.js.map +1 -1
  151. package/dist/desktop/main.js +28 -8
  152. package/dist/desktop/main.js.map +1 -1
  153. package/dist/desktop/preload.js +3 -0
  154. package/dist/desktop/preload.js.map +1 -1
  155. package/dist/desktop/renderer/app.d.ts +2 -1
  156. package/dist/desktop/renderer/app.d.ts.map +1 -1
  157. package/dist/desktop/renderer/app.js +6 -1
  158. package/dist/desktop/renderer/app.js.map +1 -1
  159. package/dist/desktop/renderer/runtime-state.d.ts.map +1 -1
  160. package/dist/desktop/renderer/runtime-state.js +2 -0
  161. package/dist/desktop/renderer/runtime-state.js.map +1 -1
  162. package/dist/desktop/shared/shell-path-probes.d.ts +24 -0
  163. package/dist/desktop/shared/shell-path-probes.d.ts.map +1 -0
  164. package/dist/desktop/shared/shell-path-probes.js +38 -0
  165. package/dist/desktop/shared/shell-path-probes.js.map +1 -0
  166. package/dist/desktop/shared/types.d.ts +21 -1
  167. package/dist/desktop/shared/types.d.ts.map +1 -1
  168. package/dist/desktop/smoke.d.ts +1 -0
  169. package/dist/desktop/smoke.d.ts.map +1 -1
  170. package/dist/desktop/smoke.js +20 -5
  171. package/dist/desktop/smoke.js.map +1 -1
  172. package/dist/i18n/en.d.ts.map +1 -1
  173. package/dist/i18n/en.js +16 -7
  174. package/dist/i18n/en.js.map +1 -1
  175. package/dist/i18n/zh.d.ts.map +1 -1
  176. package/dist/i18n/zh.js +16 -7
  177. package/dist/i18n/zh.js.map +1 -1
  178. package/dist/im/lark/card-handler.d.ts.map +1 -1
  179. package/dist/im/lark/card-handler.js +3 -0
  180. package/dist/im/lark/card-handler.js.map +1 -1
  181. package/dist/im/lark/event-dispatcher.d.ts +1 -0
  182. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  183. package/dist/im/lark/event-dispatcher.js +1 -1
  184. package/dist/im/lark/event-dispatcher.js.map +1 -1
  185. package/dist/im/lark/schedules-card.d.ts +2 -2
  186. package/dist/im/lark/schedules-card.d.ts.map +1 -1
  187. package/dist/im/lark/schedules-card.js +50 -34
  188. package/dist/im/lark/schedules-card.js.map +1 -1
  189. package/dist/index-daemon.js +13 -1
  190. package/dist/index-daemon.js.map +1 -1
  191. package/dist/platform/bind.d.ts +4 -1
  192. package/dist/platform/bind.d.ts.map +1 -1
  193. package/dist/platform/bind.js +10 -1
  194. package/dist/platform/bind.js.map +1 -1
  195. package/dist/platform/binding.d.ts.map +1 -1
  196. package/dist/platform/binding.js +15 -9
  197. package/dist/platform/binding.js.map +1 -1
  198. package/dist/platform/device-command.d.ts +35 -0
  199. package/dist/platform/device-command.d.ts.map +1 -0
  200. package/dist/platform/device-command.js +187 -0
  201. package/dist/platform/device-command.js.map +1 -0
  202. package/dist/platform/device-enroll.d.ts +156 -0
  203. package/dist/platform/device-enroll.d.ts.map +1 -0
  204. package/dist/platform/device-enroll.js +781 -0
  205. package/dist/platform/device-enroll.js.map +1 -0
  206. package/dist/platform/device-isolation-activation-client.d.ts +28 -0
  207. package/dist/platform/device-isolation-activation-client.d.ts.map +1 -0
  208. package/dist/platform/device-isolation-activation-client.js +279 -0
  209. package/dist/platform/device-isolation-activation-client.js.map +1 -0
  210. package/dist/platform/device-isolation.d.ts +35 -0
  211. package/dist/platform/device-isolation.d.ts.map +1 -0
  212. package/dist/platform/device-isolation.js +90 -0
  213. package/dist/platform/device-isolation.js.map +1 -0
  214. package/dist/platform/device-paths.d.ts +9 -0
  215. package/dist/platform/device-paths.d.ts.map +1 -0
  216. package/dist/platform/device-paths.js +14 -0
  217. package/dist/platform/device-paths.js.map +1 -0
  218. package/dist/platform/device.d.ts +77 -0
  219. package/dist/platform/device.d.ts.map +1 -0
  220. package/dist/platform/device.js +212 -0
  221. package/dist/platform/device.js.map +1 -0
  222. package/dist/platform/host-command-context.d.ts +15 -0
  223. package/dist/platform/host-command-context.d.ts.map +1 -0
  224. package/dist/platform/host-command-context.js +26 -0
  225. package/dist/platform/host-command-context.js.map +1 -0
  226. package/dist/platform/secure-host-file.d.ts +12 -0
  227. package/dist/platform/secure-host-file.d.ts.map +1 -0
  228. package/dist/platform/secure-host-file.js +182 -0
  229. package/dist/platform/secure-host-file.js.map +1 -0
  230. package/dist/services/schedule-store.d.ts +6 -2
  231. package/dist/services/schedule-store.d.ts.map +1 -1
  232. package/dist/services/schedule-store.js +19 -4
  233. package/dist/services/schedule-store.js.map +1 -1
  234. package/dist/skills/definitions.d.ts.map +1 -1
  235. package/dist/skills/definitions.js +4 -5
  236. package/dist/skills/definitions.js.map +1 -1
  237. package/dist/types.d.ts +45 -8
  238. package/dist/types.d.ts.map +1 -1
  239. package/dist/utils/atomic-write.d.ts +13 -0
  240. package/dist/utils/atomic-write.d.ts.map +1 -1
  241. package/dist/utils/atomic-write.js +89 -9
  242. package/dist/utils/atomic-write.js.map +1 -1
  243. package/dist/utils/child-env.d.ts +40 -1
  244. package/dist/utils/child-env.d.ts.map +1 -1
  245. package/dist/utils/child-env.js +45 -0
  246. package/dist/utils/child-env.js.map +1 -1
  247. package/dist/utils/pending-input-queue.d.ts +10 -0
  248. package/dist/utils/pending-input-queue.d.ts.map +1 -1
  249. package/dist/utils/pending-input-queue.js +15 -0
  250. package/dist/utils/pending-input-queue.js.map +1 -1
  251. package/dist/worker.js +391 -28
  252. package/dist/worker.js.map +1 -1
  253. package/dist/workflows/events/payloads.d.ts +4 -4
  254. package/dist/workflows/events/schema.d.ts +16 -16
  255. package/dist/workflows/hostExecutors/botmux-schedule.d.ts +3 -1
  256. package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -1
  257. package/dist/workflows/hostExecutors/botmux-schedule.js +14 -3
  258. package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -1
  259. package/dist/workflows/v3/architect.js +1 -1
  260. package/dist/workflows/v3/architect.js.map +1 -1
  261. package/dist/workflows/v3/contract.d.ts +8 -0
  262. package/dist/workflows/v3/contract.d.ts.map +1 -1
  263. package/dist/workflows/v3/contract.js.map +1 -1
  264. package/dist/workflows/v3/daemon-run.d.ts.map +1 -1
  265. package/dist/workflows/v3/daemon-run.js +2 -0
  266. package/dist/workflows/v3/daemon-run.js.map +1 -1
  267. package/dist/workflows/v3/ephemeral-pool.d.ts.map +1 -1
  268. package/dist/workflows/v3/ephemeral-pool.js +10 -2
  269. package/dist/workflows/v3/ephemeral-pool.js.map +1 -1
  270. package/dist/workflows/v3/run-envelope.d.ts +24 -24
  271. package/dist/workflows/v3/runtime.d.ts +5 -0
  272. package/dist/workflows/v3/runtime.d.ts.map +1 -1
  273. package/dist/workflows/v3/runtime.js +1 -0
  274. package/dist/workflows/v3/runtime.js.map +1 -1
  275. package/package.json +6 -3
  276. package/dist/dashboard-web/chunks/chunk-I35DXGM4.js +0 -1
  277. package/dist/dashboard-web/chunks/schedules-page-Z3672POL.js +0 -1
@@ -18,7 +18,7 @@ import { config } from '../config.js';
18
18
  import * as sessionStore from '../services/session-store.js';
19
19
  import { persistStreamCardState, rememberLastCliInput } from './session-manager.js';
20
20
  import { fallbackTurnId, isSubstituteTurn } from './reply-target.js';
21
- import { updateMessage, deleteMessage, sendEphemeralCard, sendUserMessage, addReaction, removeReaction, MessageWithdrawnError } from '../im/lark/client.js';
21
+ import { updateMessage, deleteMessage, sendEphemeralCard, sendUserMessage, addReaction, removeReaction, getMessageChatId, MessageWithdrawnError } from '../im/lark/client.js';
22
22
  import { buildStreamingCard, buildPrivateSnapshotCard, buildSessionCard, buildTuiPromptCard, buildTuiPromptResolvedCard, buildRelayedFrozenCard, getCliDisplayName } from '../im/lark/card-builder.js';
23
23
  import { loadFrozenCards, saveFrozenCards } from '../services/frozen-card-store.js';
24
24
  import { hashUrlForLog, cancelRiffTaskById } from '../adapters/backend/riff-backend.js';
@@ -77,6 +77,8 @@ import { neutralizeLarkAtTags } from '../services/send-policy.js';
77
77
  import { recordVcMeetingListenerMessage } from '../services/vc-meeting-listener-message-store.js';
78
78
  import { isLocalCliOpenEnabled, isLocalCliOpenReady } from '../services/local-cli-opener.js';
79
79
  import { isSilentScheduledTurn } from './silent-schedule-turns.js';
80
+ import { writeDeferredTopicBinding } from './deferred-topic-binding.js';
81
+ import { deferWorkerSpawnDuringDeviceIsolation } from './device-isolation-activation.js';
80
82
  const __filename = fileURLToPath(import.meta.url);
81
83
  const __dirname = dirname(__filename);
82
84
  const WORKER_SIGTERM_BACKSTOP_MS = 2_000;
@@ -1075,6 +1077,7 @@ export function ensureClaudeFolderTrust(workingDir, stateJsonPath = join(homedir
1075
1077
  // ─── Kill worker ────────────────────────────────────────────────────────────
1076
1078
  export function killWorker(ds) {
1077
1079
  clearUsageLimitState(ds);
1080
+ ds.localProcessAttestation = undefined;
1078
1081
  // A managed-turn capability belongs to one concrete worker generation.
1079
1082
  // Retiring (or observing the absence of) that generation must revoke the
1080
1083
  // daemon-side copy synchronously; the worker may never get a chance to send
@@ -1192,6 +1195,7 @@ export function suspendWorker(ds, reason = 'suspended_idle') {
1192
1195
  }
1193
1196
  armWorkerKillBackstop(w, tag(ds));
1194
1197
  ds.worker = null;
1198
+ ds.localProcessAttestation = undefined;
1195
1199
  ds.workerPort = null;
1196
1200
  ds.workerToken = null;
1197
1201
  ds.workerViewToken = null;
@@ -1626,6 +1630,19 @@ export function sendWorkerInput(ds, payload, turnId, opts = {}) {
1626
1630
  return true;
1627
1631
  }
1628
1632
  export function forkWorker(ds, promptInput, resumeOrTurnId = false) {
1633
+ // Device enrollment briefly freezes every daemon before the one-way host
1634
+ // marker is installed and legacy local CLIs are torn down. Do this before
1635
+ // ANY session mutation or child fork. One deferred spawn per logical session
1636
+ // is replayed after the exact freeze lease is released; a session closed by
1637
+ // the activation transaction is deliberately not revived.
1638
+ if (deferWorkerSpawnDuringDeviceIsolation(ds.session.sessionId, () => {
1639
+ if (findActiveBySessionId(ds.session.sessionId) === ds) {
1640
+ forkWorker(ds, promptInput, resumeOrTurnId);
1641
+ }
1642
+ })) {
1643
+ logger.info(`[${tag(ds)}] worker spawn deferred during device credential activation`);
1644
+ return;
1645
+ }
1629
1646
  const cb = requireCallbacks();
1630
1647
  const bot = getBot(ds.larkAppId);
1631
1648
  const botCfg = bot.config;
@@ -1644,6 +1661,7 @@ export function forkWorker(ds, promptInput, resumeOrTurnId = false) {
1644
1661
  // worker.js lives in the same directory as daemon.js (src/)
1645
1662
  const workerPath = join(__dirname, '..', 'worker.js');
1646
1663
  const t = tag(ds);
1664
+ ds.localProcessAttestation = undefined;
1647
1665
  let resume = false;
1648
1666
  let initTurnId;
1649
1667
  let initDispatchAttempt;
@@ -1877,6 +1895,7 @@ export function forkWorker(ds, promptInput, resumeOrTurnId = false) {
1877
1895
  backendConfig: botCfg.riff,
1878
1896
  riffParentTaskId: ds.session.riffParentTaskId,
1879
1897
  riffRepoDirs: ds.session.riffRepoDirs,
1898
+ deferredScheduleRun: ds.session.deferredScheduleRun,
1880
1899
  prompt,
1881
1900
  ...(promptCodexAppInput ? { promptCodexAppInput } : {}),
1882
1901
  resume,
@@ -2043,6 +2062,24 @@ function setupWorkerHandlers(ds, worker, startupState = { ready: false, failureN
2043
2062
  worker.on('message', async (msg) => {
2044
2063
  const effectiveCliId = sessionCliId(ds, botCfg);
2045
2064
  switch (msg.type) {
2065
+ case 'local_process_attestation': {
2066
+ // This message arrives over the private parent<->worker IPC channel;
2067
+ // unlike .botmux-cli-pids it cannot be forged or deleted by the CLI.
2068
+ // Bind it to the daemon's current worker generation so a late message
2069
+ // from a replaced worker never attests the replacement process.
2070
+ if (ds.worker !== worker)
2071
+ break;
2072
+ ds.localProcessAttestation = {
2073
+ backendType: msg.backendType,
2074
+ credentialIsolated: msg.credentialIsolated,
2075
+ ...(msg.cliPid !== undefined ? { cliPid: msg.cliPid } : {}),
2076
+ ...(msg.cliProcStart !== undefined ? { cliProcStart: msg.cliProcStart } : {}),
2077
+ ...(ds.workerGeneration !== undefined
2078
+ ? { workerGeneration: ds.workerGeneration }
2079
+ : {}),
2080
+ };
2081
+ break;
2082
+ }
2046
2083
  case 'ready': {
2047
2084
  startupState.ready = true;
2048
2085
  ds.workerPort = msg.port;
@@ -2335,6 +2372,11 @@ function setupWorkerHandlers(ds, worker, startupState = { ready: false, failureN
2335
2372
  recordUsageForDaemonSession(ds);
2336
2373
  void finishTurnReactions(ds);
2337
2374
  }
2375
+ if (ds.lastScreenStatus === 'idle'
2376
+ && msg.turnId
2377
+ && ds.session.deferredScheduleRun?.turnId === msg.turnId) {
2378
+ void cb.onDeferredScheduleTurnSettled?.(ds, { turnId: msg.turnId, source: 'idle' });
2379
+ }
2338
2380
  // If every over-cap process was busy, the earlier check deliberately
2339
2381
  // left them alone. Re-check on the first idle edge so capacity is
2340
2382
  // reclaimed immediately instead of waiting for the 60s backstop.
@@ -2667,6 +2709,43 @@ function setupWorkerHandlers(ds, worker, startupState = { ready: false, failureN
2667
2709
  sessionStore.updateSession(ds.session);
2668
2710
  break;
2669
2711
  }
2712
+ case 'deferred_topic_materialized': {
2713
+ if (ds.worker !== worker || msg.sessionId !== ds.session.sessionId) {
2714
+ logger.warn(`[${t}] Dropped deferred topic binding from stale/wrong worker`);
2715
+ break;
2716
+ }
2717
+ // Local backends claim through the host-visible sidecar directly. Only
2718
+ // Riff needs the terminal-output relay, and terminal text is agent-
2719
+ // controlled, so never let a fabricated local line create a binding.
2720
+ if ((ds.initConfig?.backendType ?? ds.session.backendType) !== 'riff') {
2721
+ logger.warn(`[${t}] Dropped deferred topic relay from non-Riff backend`);
2722
+ break;
2723
+ }
2724
+ const run = ds.session.deferredScheduleRun;
2725
+ if (!run || msg.turnId !== run.turnId || !msg.rootMessageId.startsWith('om_')) {
2726
+ logger.warn(`[${t}] Dropped deferred topic binding with mismatched run identity`);
2727
+ break;
2728
+ }
2729
+ // Defense in depth for the remote stdout relay: prove the claimed
2730
+ // message actually exists in this run's target chat before persisting
2731
+ // the host-side binding. This fences fabricated/cross-chat message ids.
2732
+ const claimedChatId = await getMessageChatId(ds.larkAppId, msg.rootMessageId);
2733
+ if (claimedChatId !== ds.chatId) {
2734
+ logger.warn(`[${t}] Dropped deferred topic binding outside target chat`);
2735
+ break;
2736
+ }
2737
+ writeDeferredTopicBinding(config.session.dataDir, {
2738
+ sessionId: ds.session.sessionId,
2739
+ turnId: run.turnId,
2740
+ chatId: ds.chatId,
2741
+ larkAppId: ds.larkAppId,
2742
+ routingAnchor: run.routingAnchor,
2743
+ rootMessageId: msg.rootMessageId,
2744
+ createdAt: new Date().toISOString(),
2745
+ });
2746
+ logger.info(`[${t}] Deferred topic root recorded ${msg.rootMessageId.substring(0, 12)}`);
2747
+ break;
2748
+ }
2670
2749
  case 'bridge_source_session': {
2671
2750
  if (msg.bridge !== 'hermes')
2672
2751
  break;
@@ -2728,6 +2807,12 @@ function setupWorkerHandlers(ds, worker, startupState = { ready: false, failureN
2728
2807
  // never let a projection/store failure crash the worker IPC loop.
2729
2808
  logger.error(`[${t}] Failed to persist turn_terminal for ${msg.turnId.substring(0, 8)}: ${err.message}`);
2730
2809
  }
2810
+ try {
2811
+ await cb.onDeferredScheduleTurnSettled?.(ds, { turnId: msg.turnId, source: 'terminal' });
2812
+ }
2813
+ catch (err) {
2814
+ logger.error(`[${t}] Failed to settle deferred schedule turn ${msg.turnId.substring(0, 8)}: ${err.message}`);
2815
+ }
2731
2816
  break;
2732
2817
  }
2733
2818
  case 'receiver_reset_ready': {