@vellumai/assistant 0.10.0 → 0.10.1-staging.1

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 (824) hide show
  1. package/ARCHITECTURE.md +36 -37
  2. package/bun.lock +3 -0
  3. package/docs/workflows.md +12 -7
  4. package/eslint-rules/cli-no-daemon-internals.js +6 -0
  5. package/node_modules/@slack/types/LICENSE +23 -0
  6. package/node_modules/@slack/types/README.md +32 -0
  7. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
  8. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
  9. package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
  10. package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
  11. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
  12. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
  13. package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
  14. package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
  15. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
  16. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
  17. package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
  18. package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
  19. package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
  20. package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
  21. package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
  22. package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
  23. package/node_modules/@slack/types/dist/calls.d.ts +26 -0
  24. package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
  25. package/node_modules/@slack/types/dist/calls.js +6 -0
  26. package/node_modules/@slack/types/dist/calls.js.map +1 -0
  27. package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
  28. package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
  29. package/node_modules/@slack/types/dist/chunk.js +3 -0
  30. package/node_modules/@slack/types/dist/chunk.js.map +1 -0
  31. package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
  32. package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
  33. package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
  34. package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
  35. package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
  36. package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
  37. package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
  38. package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
  39. package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
  40. package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
  41. package/node_modules/@slack/types/dist/dialog.js +3 -0
  42. package/node_modules/@slack/types/dist/dialog.js.map +1 -0
  43. package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
  44. package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
  45. package/node_modules/@slack/types/dist/events/app.js +3 -0
  46. package/node_modules/@slack/types/dist/events/app.js.map +1 -0
  47. package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
  48. package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
  49. package/node_modules/@slack/types/dist/events/assistant.js +3 -0
  50. package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
  51. package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
  52. package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
  53. package/node_modules/@slack/types/dist/events/call.js +3 -0
  54. package/node_modules/@slack/types/dist/events/call.js.map +1 -0
  55. package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
  56. package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
  57. package/node_modules/@slack/types/dist/events/channel.js +3 -0
  58. package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
  59. package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
  60. package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
  61. package/node_modules/@slack/types/dist/events/dnd.js +3 -0
  62. package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
  63. package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
  64. package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
  65. package/node_modules/@slack/types/dist/events/email.js +3 -0
  66. package/node_modules/@slack/types/dist/events/email.js.map +1 -0
  67. package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
  68. package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
  69. package/node_modules/@slack/types/dist/events/emoji.js +3 -0
  70. package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
  71. package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
  72. package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
  73. package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
  74. package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
  75. package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
  76. package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
  77. package/node_modules/@slack/types/dist/events/file.js +4 -0
  78. package/node_modules/@slack/types/dist/events/file.js.map +1 -0
  79. package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
  80. package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
  81. package/node_modules/@slack/types/dist/events/function.js +3 -0
  82. package/node_modules/@slack/types/dist/events/function.js.map +1 -0
  83. package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
  84. package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
  85. package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
  86. package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
  87. package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
  88. package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
  89. package/node_modules/@slack/types/dist/events/group.js +3 -0
  90. package/node_modules/@slack/types/dist/events/group.js.map +1 -0
  91. package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
  92. package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
  93. package/node_modules/@slack/types/dist/events/im.js +3 -0
  94. package/node_modules/@slack/types/dist/events/im.js.map +1 -0
  95. package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
  96. package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
  97. package/node_modules/@slack/types/dist/events/index.js +43 -0
  98. package/node_modules/@slack/types/dist/events/index.js.map +1 -0
  99. package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
  100. package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
  101. package/node_modules/@slack/types/dist/events/invite.js +3 -0
  102. package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
  103. package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
  104. package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
  105. package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
  106. package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
  107. package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
  108. package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
  109. package/node_modules/@slack/types/dist/events/member.js +3 -0
  110. package/node_modules/@slack/types/dist/events/member.js.map +1 -0
  111. package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
  112. package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
  113. package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
  114. package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
  115. package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
  116. package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
  117. package/node_modules/@slack/types/dist/events/message.js +3 -0
  118. package/node_modules/@slack/types/dist/events/message.js.map +1 -0
  119. package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
  120. package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
  121. package/node_modules/@slack/types/dist/events/pin.js +3 -0
  122. package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
  123. package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
  124. package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
  125. package/node_modules/@slack/types/dist/events/reaction.js +3 -0
  126. package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
  127. package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
  128. package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
  129. package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
  130. package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
  131. package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
  132. package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
  133. package/node_modules/@slack/types/dist/events/star.js +3 -0
  134. package/node_modules/@slack/types/dist/events/star.js.map +1 -0
  135. package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
  136. package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
  137. package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
  138. package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
  139. package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
  140. package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
  141. package/node_modules/@slack/types/dist/events/subteam.js +3 -0
  142. package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
  143. package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
  144. package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
  145. package/node_modules/@slack/types/dist/events/team.js +3 -0
  146. package/node_modules/@slack/types/dist/events/team.js.map +1 -0
  147. package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
  148. package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
  149. package/node_modules/@slack/types/dist/events/token.js +3 -0
  150. package/node_modules/@slack/types/dist/events/token.js.map +1 -0
  151. package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
  152. package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
  153. package/node_modules/@slack/types/dist/events/user.js +3 -0
  154. package/node_modules/@slack/types/dist/events/user.js.map +1 -0
  155. package/node_modules/@slack/types/dist/index.d.ts +12 -0
  156. package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
  157. package/node_modules/@slack/types/dist/index.js +28 -0
  158. package/node_modules/@slack/types/dist/index.js.map +1 -0
  159. package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
  160. package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
  161. package/node_modules/@slack/types/dist/message-attachments.js +3 -0
  162. package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
  163. package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
  164. package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
  165. package/node_modules/@slack/types/dist/message-metadata.js +27 -0
  166. package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
  167. package/node_modules/@slack/types/dist/views.d.ts +71 -0
  168. package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
  169. package/node_modules/@slack/types/dist/views.js +3 -0
  170. package/node_modules/@slack/types/dist/views.js.map +1 -0
  171. package/node_modules/@slack/types/package.json +47 -0
  172. package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
  173. package/node_modules/@vellumai/gateway-client/package.json +1 -0
  174. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
  175. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +65 -0
  176. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
  177. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
  178. package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
  179. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
  180. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
  181. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +78 -0
  182. package/openapi.yaml +345 -18
  183. package/package.json +2 -1
  184. package/scripts/memory-inspect.ts +24 -14
  185. package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
  186. package/src/__tests__/activation-early-marking.test.ts +1 -1
  187. package/src/__tests__/actor-token-service.test.ts +3 -3
  188. package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
  189. package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
  190. package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
  191. package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
  192. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  193. package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
  194. package/src/__tests__/agent-loop.test.ts +3 -0
  195. package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
  196. package/src/__tests__/anthropic-provider.test.ts +143 -9
  197. package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
  198. package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
  199. package/src/__tests__/app-source-watcher.test.ts +30 -10
  200. package/src/__tests__/approval-cascade.test.ts +6 -0
  201. package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
  202. package/src/__tests__/approval-primitive.test.ts +1 -1
  203. package/src/__tests__/approval-routes-http.test.ts +1 -1
  204. package/src/__tests__/assistant-attachments.test.ts +155 -0
  205. package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
  206. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  207. package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
  208. package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
  209. package/src/__tests__/attachments-store.test.ts +1 -1
  210. package/src/__tests__/audit-log-rotation.test.ts +50 -54
  211. package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
  212. package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
  213. package/src/__tests__/background-shell-bash.test.ts +4 -1
  214. package/src/__tests__/background-shell-host-bash.test.ts +17 -3
  215. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  216. package/src/__tests__/call-controller.test.ts +1 -1
  217. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  218. package/src/__tests__/call-domain.test.ts +1 -1
  219. package/src/__tests__/call-pointer-messages.test.ts +3 -4
  220. package/src/__tests__/call-recovery.test.ts +1 -1
  221. package/src/__tests__/call-routes-http.test.ts +1 -1
  222. package/src/__tests__/call-store.test.ts +1 -1
  223. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  224. package/src/__tests__/canonical-guardian-store.test.ts +24 -1
  225. package/src/__tests__/channel-approval-routes.test.ts +73 -1119
  226. package/src/__tests__/channel-delivery-store.test.ts +1 -1
  227. package/src/__tests__/channel-guardian.test.ts +265 -641
  228. package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
  229. package/src/__tests__/channel-retry-sweep.test.ts +1 -1
  230. package/src/__tests__/compaction-events.test.ts +6 -0
  231. package/src/__tests__/compaction-trail-store.test.ts +6 -5
  232. package/src/__tests__/compaction.benchmark.test.ts +0 -1
  233. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  234. package/src/__tests__/config-loader-backfill.test.ts +183 -51
  235. package/src/__tests__/config-schema.test.ts +34 -0
  236. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
  237. package/src/__tests__/contact-store-user-file.test.ts +2 -2
  238. package/src/__tests__/contacts-relay-reads.test.ts +409 -0
  239. package/src/__tests__/contacts-tools.test.ts +4 -4
  240. package/src/__tests__/contacts-write.test.ts +1 -2
  241. package/src/__tests__/context-search-conversations-source.test.ts +1 -1
  242. package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
  243. package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
  244. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  245. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
  246. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
  247. package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
  248. package/src/__tests__/conversation-agent-loop.test.ts +3 -0
  249. package/src/__tests__/conversation-attachments.test.ts +2 -5
  250. package/src/__tests__/conversation-attention-store.test.ts +1 -1
  251. package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
  252. package/src/__tests__/conversation-clear-safety.test.ts +1 -1
  253. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  254. package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
  255. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
  256. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
  257. package/src/__tests__/conversation-disk-view.test.ts +1 -1
  258. package/src/__tests__/conversation-fork-crud.test.ts +10 -8
  259. package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
  260. package/src/__tests__/conversation-fork-route.test.ts +1 -1
  261. package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
  262. package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
  263. package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
  264. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  265. package/src/__tests__/conversation-lifecycle.test.ts +117 -0
  266. package/src/__tests__/conversation-list-source.test.ts +3 -3
  267. package/src/__tests__/conversation-process-callsite.test.ts +6 -14
  268. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  269. package/src/__tests__/conversation-queue.test.ts +6 -0
  270. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
  271. package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
  272. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  273. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  274. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  275. package/src/__tests__/conversation-starter-routes.test.ts +5 -5
  276. package/src/__tests__/conversation-store.test.ts +1 -1
  277. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -1
  278. package/src/__tests__/conversation-sync-tags.test.ts +1 -1
  279. package/src/__tests__/conversation-usage.test.ts +1 -1
  280. package/src/__tests__/conversation-wipe.test.ts +9 -8
  281. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  282. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  283. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  284. package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
  285. package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
  286. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  287. package/src/__tests__/db-acp-history.test.ts +2 -2
  288. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
  289. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
  290. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
  291. package/src/__tests__/db-migration-rollback.test.ts +129 -39
  292. package/src/__tests__/db-proxy-transaction.test.ts +1 -1
  293. package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
  294. package/src/__tests__/db-test-helpers.ts +36 -19
  295. package/src/__tests__/delete-propagation.test.ts +1 -1
  296. package/src/__tests__/deterministic-verification-control-plane.test.ts +26 -8
  297. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  298. package/src/__tests__/dm-backfill.test.ts +1 -1
  299. package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
  300. package/src/__tests__/edit-propagation.test.ts +1 -1
  301. package/src/__tests__/emit-signal-routing-intent.test.ts +83 -0
  302. package/src/__tests__/empty-response-hook.test.ts +42 -0
  303. package/src/__tests__/events-client-registration.test.ts +1 -1
  304. package/src/__tests__/followup-tools.test.ts +1 -1
  305. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  306. package/src/__tests__/guardian-action-sweep.test.ts +9 -2
  307. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  308. package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
  309. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
  310. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  311. package/src/__tests__/guardian-outbound-http.test.ts +7 -12
  312. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
  313. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  314. package/src/__tests__/guardian-routing-state.test.ts +1 -2
  315. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  316. package/src/__tests__/headless-browser-mode.test.ts +2 -2
  317. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  318. package/src/__tests__/heartbeat-service.test.ts +6 -0
  319. package/src/__tests__/helpers/channel-test-adapter.ts +98 -0
  320. package/src/__tests__/http-conversation-lineage.test.ts +1 -1
  321. package/src/__tests__/image-recovery-hook.test.ts +1 -1
  322. package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
  323. package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
  324. package/src/__tests__/inference-profile-reaper.test.ts +1 -1
  325. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  326. package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
  327. package/src/__tests__/injector-chain.test.ts +1 -1
  328. package/src/__tests__/injector-disk-pressure.test.ts +11 -6
  329. package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
  330. package/src/__tests__/invite-redemption-service.test.ts +244 -43
  331. package/src/__tests__/invite-routes-http.test.ts +35 -186
  332. package/src/__tests__/invite-service-ipc.test.ts +287 -0
  333. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
  334. package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
  335. package/src/__tests__/list-messages-attachments.test.ts +42 -1
  336. package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
  337. package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
  338. package/src/__tests__/list-messages-page-latest.test.ts +1 -1
  339. package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
  340. package/src/__tests__/llm-context-route-provider.test.ts +69 -4
  341. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
  342. package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
  343. package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
  344. package/src/__tests__/llm-usage-store.test.ts +40 -1
  345. package/src/__tests__/log-export-routes.test.ts +1 -1
  346. package/src/__tests__/log-export-workspace.test.ts +3 -3
  347. package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
  348. package/src/__tests__/memory-recall-log-store.test.ts +1 -1
  349. package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
  350. package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
  351. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  352. package/src/__tests__/mtime-cache.test.ts +375 -0
  353. package/src/__tests__/non-member-access-request.test.ts +1 -2
  354. package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
  355. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  356. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  357. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  358. package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
  359. package/src/__tests__/oauth-store.test.ts +1 -1
  360. package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
  361. package/src/__tests__/persist-unsendable-image.test.ts +1 -1
  362. package/src/__tests__/persona-resolver.test.ts +39 -1
  363. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  364. package/src/__tests__/playbook-execution.test.ts +1 -1
  365. package/src/__tests__/playbook-tools.test.ts +1 -1
  366. package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
  367. package/src/__tests__/plugin-bootstrap.test.ts +78 -0
  368. package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
  369. package/src/__tests__/provider-usage-tracking.test.ts +1 -1
  370. package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
  371. package/src/__tests__/reaction-persistence.test.ts +1 -1
  372. package/src/__tests__/relay-server.test.ts +357 -56
  373. package/src/__tests__/runtime-attachment-metadata.test.ts +10 -1
  374. package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
  375. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  376. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  377. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  378. package/src/__tests__/schedule-retry.test.ts +1 -1
  379. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
  380. package/src/__tests__/schedule-routes.test.ts +1 -1
  381. package/src/__tests__/schedule-store.test.ts +1 -1
  382. package/src/__tests__/schedule-tools.test.ts +1 -1
  383. package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
  384. package/src/__tests__/scheduler-recurrence.test.ts +1 -1
  385. package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
  386. package/src/__tests__/scheduler-wake.test.ts +2 -1
  387. package/src/__tests__/scoped-approval-grants.test.ts +1 -1
  388. package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
  389. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
  390. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
  391. package/src/__tests__/send-endpoint-busy.test.ts +1 -1
  392. package/src/__tests__/sequence-store.test.ts +1 -1
  393. package/src/__tests__/server-history-render.test.ts +40 -1
  394. package/src/__tests__/settings-routes.test.ts +11 -10
  395. package/src/__tests__/skill-load-tool.test.ts +72 -0
  396. package/src/__tests__/slack-inbound-verification.test.ts +1 -3
  397. package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
  398. package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
  399. package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
  400. package/src/__tests__/subagent-tools.test.ts +1 -31
  401. package/src/__tests__/system-prompt.test.ts +1 -1
  402. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  403. package/src/__tests__/task-compiler.test.ts +1 -1
  404. package/src/__tests__/task-management-tools.test.ts +1 -1
  405. package/src/__tests__/task-memory-cleanup.test.ts +9 -6
  406. package/src/__tests__/task-scheduler.test.ts +1 -1
  407. package/src/__tests__/thread-backfill.test.ts +1 -1
  408. package/src/__tests__/tool-approval-handler.test.ts +1 -1
  409. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
  410. package/src/__tests__/tool-executor.test.ts +32 -1
  411. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
  412. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
  413. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
  414. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
  415. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  416. package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
  417. package/src/__tests__/turn-events-store.test.ts +1 -1
  418. package/src/__tests__/twilio-routes.test.ts +2 -3
  419. package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
  420. package/src/__tests__/usage-routes.test.ts +1 -1
  421. package/src/__tests__/user-plugin-loader.test.ts +34 -29
  422. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  423. package/src/__tests__/voice-invite-redemption.test.ts +134 -36
  424. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  425. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  426. package/src/__tests__/workspace-git-service.test.ts +114 -1
  427. package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
  428. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
  429. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  430. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
  431. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
  432. package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
  433. package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
  434. package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
  435. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
  436. package/src/a2a/__tests__/task-store.test.ts +1 -1
  437. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
  438. package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
  439. package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
  440. package/src/acp/__tests__/session-manager.test.ts +72 -1
  441. package/src/acp/index.ts +10 -0
  442. package/src/acp/session-manager.ts +35 -0
  443. package/src/agent/loop.ts +45 -27
  444. package/src/api/index.ts +0 -6
  445. package/src/approvals/AGENTS.md +1 -2
  446. package/src/approvals/guardian-decision-primitive.ts +13 -210
  447. package/src/approvals/guardian-request-resolvers.ts +104 -58
  448. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  449. package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
  450. package/src/calls/__tests__/relay-setup-router.test.ts +88 -62
  451. package/src/calls/inbound-trust-reader.ts +40 -0
  452. package/src/calls/relay-server.ts +65 -23
  453. package/src/calls/relay-setup-router.ts +20 -6
  454. package/src/calls/relay-verification.ts +7 -7
  455. package/src/cli/commands/contacts.ts +6 -24
  456. package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
  457. package/src/cli/commands/db/__tests__/status.test.ts +7 -3
  458. package/src/cli/commands/db/status.ts +212 -33
  459. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
  460. package/src/cli/commands/memory/index.ts +2 -0
  461. package/src/cli/commands/memory/memory-retrospective.ts +129 -0
  462. package/src/cli/commands/memory/memory-v3.ts +176 -4
  463. package/src/cli/commands/plugins.ts +268 -11
  464. package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
  465. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  466. package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
  467. package/src/cli/lib/install-from-github.ts +47 -6
  468. package/src/cli/lib/plugin-marketplace.ts +11 -0
  469. package/src/cli/lib/plugin-pin-history.ts +257 -0
  470. package/src/cli/lib/toggle-plugin.ts +146 -0
  471. package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
  472. package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
  473. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
  474. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
  475. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
  476. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
  477. package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
  478. package/src/config/bundled-skills/contacts/SKILL.md +7 -12
  479. package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
  480. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  481. package/src/config/bundled-skills/workflows/SKILL.md +4 -3
  482. package/src/config/call-site-defaults.ts +11 -2
  483. package/src/config/feature-flag-registry.json +0 -8
  484. package/src/config/profile-dispatchability.ts +11 -0
  485. package/src/config/schemas/call-site-catalog.ts +7 -0
  486. package/src/config/schemas/llm.ts +2 -0
  487. package/src/config/schemas/memory-lifecycle.ts +5 -3
  488. package/src/config/schemas/timeouts.ts +24 -0
  489. package/src/config/seed-inference-profiles.ts +133 -45
  490. package/src/config/sync-gated-profiles.ts +13 -1
  491. package/src/contacts/contact-store.ts +21 -0
  492. package/src/contacts/member-status.ts +9 -0
  493. package/src/credential-health/credential-health-service.ts +1 -5
  494. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  495. package/src/daemon/app-source-watcher.ts +31 -18
  496. package/src/daemon/assistant-attachments.ts +94 -4
  497. package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
  498. package/src/daemon/conversation-agent-loop.ts +9 -36
  499. package/src/daemon/conversation-runtime-assembly.ts +91 -66
  500. package/src/daemon/conversation-tool-setup.ts +20 -63
  501. package/src/daemon/conversation.ts +144 -52
  502. package/src/daemon/event-loop-watchdog.test.ts +85 -0
  503. package/src/daemon/event-loop-watchdog.ts +133 -0
  504. package/src/daemon/external-plugins-bootstrap.ts +26 -80
  505. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  506. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
  507. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
  508. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
  509. package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
  510. package/src/daemon/handlers/config-channels.ts +32 -18
  511. package/src/daemon/handlers/conversations.ts +7 -0
  512. package/src/daemon/handlers/shared.ts +7 -0
  513. package/src/daemon/lifecycle.ts +16 -3
  514. package/src/daemon/message-types/inbox.ts +0 -6
  515. package/src/daemon/message-types/messages.ts +0 -4
  516. package/src/daemon/message-types/surfaces.ts +18 -8
  517. package/src/daemon/server.ts +0 -4
  518. package/src/daemon/tool-setup-types.ts +0 -7
  519. package/src/daemon/trust-context.ts +6 -0
  520. package/src/daemon/wake-conversation-ops.ts +70 -0
  521. package/src/daemon/workspace-tools-watcher.ts +7 -3
  522. package/src/documents/document-comments-store.test.ts +1 -1
  523. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
  524. package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
  525. package/src/heartbeat/heartbeat-service.ts +3 -4
  526. package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
  527. package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
  528. package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
  529. package/src/ipc/assistant-server.ts +8 -0
  530. package/src/ipc/gateway-client.ts +2 -1
  531. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
  532. package/src/ipc/routes/invite-ipc-routes.ts +66 -0
  533. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
  534. package/src/memory/__tests__/activation-session-store.test.ts +1 -1
  535. package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
  536. package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
  537. package/src/memory/__tests__/conversation-queries.test.ts +1 -1
  538. package/src/memory/__tests__/db-async-query.test.ts +1 -1
  539. package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
  540. package/src/memory/__tests__/db-maintenance.test.ts +28 -36
  541. package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
  542. package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
  543. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
  544. package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
  545. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
  546. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
  547. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
  548. package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
  549. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
  550. package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
  551. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  552. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
  553. package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
  554. package/src/memory/__tests__/table-relocation.test.ts +129 -0
  555. package/src/memory/conversation-crud.ts +461 -152
  556. package/src/memory/db-async-query.ts +89 -5
  557. package/src/memory/db-connection.ts +101 -18
  558. package/src/memory/db-init.ts +409 -234
  559. package/src/memory/db-maintenance.ts +43 -38
  560. package/src/memory/db-singleton.ts +45 -19
  561. package/src/memory/fork-message-copy.ts +170 -0
  562. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
  563. package/src/memory/graph/bootstrap.test.ts +6 -3
  564. package/src/memory/graph/retriever.test.ts +12 -12
  565. package/src/memory/graph/store.test.ts +15 -25
  566. package/src/memory/graph/store.ts +23 -14
  567. package/src/memory/graph/tool-handlers.ts +34 -5
  568. package/src/memory/graph/tools.ts +5 -2
  569. package/src/memory/indexer.ts +21 -9
  570. package/src/memory/job-handlers/cleanup.ts +10 -3
  571. package/src/memory/job-handlers/embedding.test.ts +4 -4
  572. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
  573. package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
  574. package/src/memory/jobs-store.ts +36 -24
  575. package/src/memory/llm-request-log-store.ts +51 -19
  576. package/src/memory/llm-usage-store.ts +31 -1
  577. package/src/memory/memory-retrospective-job.ts +27 -19
  578. package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
  579. package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
  580. package/src/memory/migrations/104-core-indexes.ts +1 -1
  581. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
  582. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
  583. package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
  584. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
  585. package/src/memory/migrations/136-drop-assistant-id-columns.ts +227 -230
  586. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
  587. package/src/memory/migrations/141-rename-verification-table.ts +45 -48
  588. package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
  589. package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
  590. package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
  591. package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
  592. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
  593. package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
  594. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
  595. package/src/memory/migrations/157-invite-contact-id.ts +73 -76
  596. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
  597. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
  598. package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
  599. package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
  600. package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
  601. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
  602. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
  603. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
  604. package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
  605. package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
  606. package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
  607. package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
  608. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
  609. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
  610. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
  611. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +50 -57
  612. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
  613. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
  614. package/src/memory/migrations/217-conversation-host-access.ts +13 -18
  615. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
  616. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
  617. package/src/memory/migrations/230-acp-session-history.ts +23 -28
  618. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
  619. package/src/memory/migrations/232-activation-state.ts +11 -16
  620. package/src/memory/migrations/233-document-conversations.ts +20 -25
  621. package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
  622. package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
  623. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
  624. package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
  625. package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
  626. package/src/memory/migrations/242-message-bookmarks.ts +17 -22
  627. package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
  628. package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
  629. package/src/memory/migrations/251-a2a-tasks.ts +27 -32
  630. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
  631. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
  632. package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
  633. package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
  634. package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
  635. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
  636. package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
  637. package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
  638. package/src/memory/migrations/270-schedule-description.ts +7 -12
  639. package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
  640. package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
  641. package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
  642. package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
  643. package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
  644. package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
  645. package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
  646. package/src/memory/migrations/helpers/relocation.ts +227 -0
  647. package/src/memory/migrations/registry.ts +63 -0
  648. package/src/memory/migrations/run-migrations.ts +187 -16
  649. package/src/memory/migrations/validate-migration-state.ts +50 -145
  650. package/src/memory/raw-query.ts +47 -2
  651. package/src/memory/skill-loaded-events-store.test.ts +1 -1
  652. package/src/memory/task-memory-cleanup.ts +62 -41
  653. package/src/memory/tool-executed-events-store.test.ts +1 -1
  654. package/src/memory/turn-trace-store.test.ts +1 -1
  655. package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
  656. package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
  657. package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  658. package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  659. package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
  660. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
  661. package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
  662. package/src/memory/v3-eval/eval-packets.ts +197 -12
  663. package/src/memory/v3-eval/eval-tally.ts +234 -0
  664. package/src/messaging/provider.ts +10 -0
  665. package/src/messaging/providers/gmail/adapter.ts +1 -0
  666. package/src/messaging/providers/gmail/client.ts +14 -0
  667. package/src/messaging/providers/index.ts +1 -1
  668. package/src/messaging/providers/slack/send.test.ts +87 -39
  669. package/src/messaging/providers/slack/send.ts +84 -105
  670. package/src/notifications/README.md +9 -5
  671. package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
  672. package/src/notifications/adapters/slack.ts +12 -10
  673. package/src/notifications/approval-card-builder.ts +81 -20
  674. package/src/notifications/approval-card-data.ts +8 -5
  675. package/src/notifications/canonical-delivery-recorder.ts +7 -5
  676. package/src/notifications/conversation-candidates.ts +24 -59
  677. package/src/notifications/copy-composer.ts +48 -68
  678. package/src/notifications/deterministic-checks.ts +19 -16
  679. package/src/notifications/emit-signal.ts +29 -1
  680. package/src/notifications/trusted-contact-payloads.ts +70 -0
  681. package/src/oauth/byo-connection.test.ts +9 -0
  682. package/src/oauth/connection-resolver.test.ts +146 -6
  683. package/src/oauth/connection-resolver.ts +132 -5
  684. package/src/oauth/oauth-store.ts +16 -3
  685. package/src/oauth/scope-utils.ts +21 -0
  686. package/src/plugin-api/index.ts +9 -4
  687. package/src/plugin-api/model-profiles.test.ts +123 -0
  688. package/src/plugin-api/model-profiles.ts +5 -1
  689. package/src/plugin-api/vision-support.test.ts +149 -0
  690. package/src/plugin-api/vision-support.ts +78 -0
  691. package/src/plugins/defaults/compaction/window-manager.ts +45 -64
  692. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
  693. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +302 -0
  694. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +103 -0
  695. package/src/plugins/defaults/image-fallback/package.json +14 -0
  696. package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
  697. package/src/plugins/defaults/image-fallback/src/image-persist.ts +59 -0
  698. package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
  699. package/src/plugins/defaults/index.ts +23 -0
  700. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
  701. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  702. package/src/plugins/external-plugin-loader.ts +47 -6
  703. package/src/plugins/mtime-cache.ts +772 -0
  704. package/src/plugins/pipeline.ts +7 -2
  705. package/src/plugins/registry.ts +16 -5
  706. package/src/plugins/user-loader.ts +22 -76
  707. package/src/prompts/persona-resolver.ts +29 -11
  708. package/src/prompts/system-prompt.ts +1 -1
  709. package/src/prompts/templates/system-sections.ts +4 -4
  710. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  711. package/src/providers/anthropic/client.ts +254 -185
  712. package/src/providers/call-site-routing.ts +10 -0
  713. package/src/providers/gemini/client.ts +43 -0
  714. package/src/providers/inference/adapter-factory.ts +6 -0
  715. package/src/providers/inference/connections.ts +6 -1
  716. package/src/providers/model-catalog.ts +37 -0
  717. package/src/providers/platform-proxy/constants.ts +5 -0
  718. package/src/providers/ratelimit.ts +9 -0
  719. package/src/providers/retry.ts +10 -0
  720. package/src/providers/together/client.ts +35 -0
  721. package/src/providers/types.ts +16 -0
  722. package/src/providers/usage-tracking.ts +7 -0
  723. package/src/runtime/AGENTS.md +9 -1
  724. package/src/runtime/__tests__/agent-wake.test.ts +259 -4
  725. package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
  726. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +417 -0
  727. package/src/runtime/actor-trust-resolver.ts +8 -16
  728. package/src/runtime/agent-wake.ts +183 -60
  729. package/src/runtime/channel-reply-delivery.ts +6 -3
  730. package/src/runtime/guardian-decision-types.ts +3 -22
  731. package/src/runtime/http-server.ts +1 -15
  732. package/src/runtime/invite-redemption-service.ts +155 -6
  733. package/src/runtime/invite-service.ts +113 -62
  734. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
  735. package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
  736. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
  737. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
  738. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
  739. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
  740. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
  741. package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
  742. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  743. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
  744. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
  745. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
  746. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
  747. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
  748. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
  749. package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
  750. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
  751. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
  752. package/src/runtime/routes/acp-routes-list.test.ts +4 -0
  753. package/src/runtime/routes/acp-routes.test.ts +5 -6
  754. package/src/runtime/routes/attachment-routes.ts +21 -17
  755. package/src/runtime/routes/browser-routes.ts +19 -1
  756. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
  757. package/src/runtime/routes/channel-verification-routes.ts +12 -1
  758. package/src/runtime/routes/contact-routes.ts +275 -164
  759. package/src/runtime/routes/conversation-query-routes.ts +15 -5
  760. package/src/runtime/routes/conversation-routes.ts +24 -3
  761. package/src/runtime/routes/conversation-starter-routes.ts +7 -8
  762. package/src/runtime/routes/guardian-approval-interception.ts +13 -274
  763. package/src/runtime/routes/inbound-message-handler.ts +20 -15
  764. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +285 -0
  765. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +45 -34
  766. package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
  767. package/src/runtime/routes/log-export-routes.ts +2 -2
  768. package/src/runtime/routes/memory-eval-routes.ts +92 -0
  769. package/src/runtime/routes/memory-item-routes.test.ts +12 -11
  770. package/src/runtime/routes/migration-routes.ts +51 -40
  771. package/src/runtime/routes/plugins-routes.ts +164 -8
  772. package/src/runtime/routes/schedule-routes.ts +1 -0
  773. package/src/runtime/routes/usage-routes.ts +3 -0
  774. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  775. package/src/runtime/slack-block-formatting.ts +46 -48
  776. package/src/runtime/trust-verdict-consumer.ts +172 -0
  777. package/src/schedule/scheduler.ts +6 -9
  778. package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
  779. package/src/tools/ask-question/ask-question-tool.test.ts +60 -52
  780. package/src/tools/ask-question/ask-question-tool.ts +14 -73
  781. package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
  782. package/src/tools/browser/browser-execution.ts +16 -4
  783. package/src/tools/document/document-comment-tool.test.ts +1 -1
  784. package/src/tools/executor.ts +15 -3
  785. package/src/tools/host-terminal/host-shell.ts +28 -9
  786. package/src/tools/memory/register.test.ts +32 -0
  787. package/src/tools/skills/load.ts +43 -2
  788. package/src/tools/subagent/spawn.ts +4 -10
  789. package/src/tools/terminal/shell.ts +16 -5
  790. package/src/tools/types.ts +1 -0
  791. package/src/util/fs-watcher-error.ts +36 -0
  792. package/src/util/logs-db-path.ts +22 -0
  793. package/src/util/memory-db-path.ts +23 -0
  794. package/src/watcher/providers/gmail.ts +7 -2
  795. package/src/workflows/engine-integration.test.ts +1 -1
  796. package/src/workflows/engine.test.ts +1 -1
  797. package/src/workflows/engine.ts +22 -0
  798. package/src/workflows/fanout-load.test.ts +1 -1
  799. package/src/workflows/journal-store.test.ts +1 -1
  800. package/src/workflows/leaf-runner.test.ts +40 -1
  801. package/src/workflows/leaf-runner.ts +26 -1
  802. package/src/workspace/git-service.ts +144 -29
  803. package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
  804. package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
  805. package/src/workspace/migrations/registry.ts +4 -0
  806. package/src/workspace/migrations/runner.ts +32 -2
  807. package/src/__tests__/access-request-decision.test.ts +0 -375
  808. package/src/__tests__/guardian-grant-minting.test.ts +0 -607
  809. package/src/__tests__/plugin-source-watcher.test.ts +0 -302
  810. package/src/api/events/turn-profile-auto-routed.ts +0 -28
  811. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
  812. package/src/daemon/plugin-source-watcher.ts +0 -278
  813. package/src/daemon/switch-inference-profile-tool.ts +0 -62
  814. package/src/memory/guardian-approvals.ts +0 -361
  815. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
  816. package/src/memory/migrations/038-actor-token-records.ts +0 -45
  817. package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
  818. package/src/memory/migrations/103-complex-migrations.ts +0 -23
  819. package/src/memory/migrations/113-late-migrations.ts +0 -30
  820. package/src/memory/migrations/index.ts +0 -301
  821. package/src/runtime/routes/access-request-decision.ts +0 -297
  822. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
  823. package/src/runtime/routes/channel-guardian-routes.ts +0 -19
  824. package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
@@ -2,14 +2,12 @@
2
2
  * Tests for `db-maintenance.ts` (orchestration) and the underlying
3
3
  * `db-async-query.ts` abstraction.
4
4
  *
5
- * The contract this PR locks in:
6
- * 1. `runDbMaintenance` runs `VACUUM` through the async abstraction
7
- * when the `sqlite3` CLI is available, that means a subprocess
8
- * and the daemon's main event loop keeps ticking. (The structural
9
- * anti-block assertion lives in
10
- * `db-async-query.test.ts`; here we focus on orchestration.)
11
- * 2. The subprocess actually shrinks the on-disk page count when
12
- * there's reclaimable space.
5
+ * The contract this locks in:
6
+ * 1. `runDbMaintenance` runs `PRAGMA optimize` through the async
7
+ * abstraction and then truncates the WAL on the daemon connection.
8
+ * It intentionally does NOT run a full VACUUM (which in WAL mode
9
+ * inflates the WAL to ~the DB size and needs ~2x the DB size free).
10
+ * 2. The truncating checkpoint shrinks the WAL file once it has grown.
13
11
  * 3. `maybeRunDbMaintenance` is genuinely async — callers can `await`
14
12
  * it and observe completion.
15
13
  * 4. The 24 h interval guard short-circuits a recent re-run.
@@ -17,7 +15,7 @@
17
15
  * The per-file temp workspace is set up by `test-preload.ts`; tests just
18
16
  * dynamic-import the DB modules so they resolve paths under that temp dir.
19
17
  */
20
- import { Database } from "bun:sqlite";
18
+ import { existsSync, statSync } from "node:fs";
21
19
  import { beforeEach, describe, expect, test } from "bun:test";
22
20
 
23
21
  const { getSqlite } = await import("../db-connection.js");
@@ -28,7 +26,7 @@ const { maybeRunDbMaintenance } = await import("../db-maintenance.js");
28
26
  const { getLastUserMessageTimestamp } = await import("../conversation-crud.js");
29
27
  const { getDbPath } = await import("../../util/platform.js");
30
28
 
31
- initializeDb();
29
+ await initializeDb();
32
30
 
33
31
  const MAINTENANCE_CHECKPOINT_KEY = "db_maintenance:last_run";
34
32
  const QUIET_PERIOD_MS = 3 * 60 * 60 * 1000;
@@ -56,8 +54,9 @@ function insertMessage(role: "user" | "assistant", createdAt: number): void {
56
54
  .run(`msg-${createdAt}-${role}`, convId, role, "[]", createdAt);
57
55
  }
58
56
 
59
- /** Inflate the test DB with bloat that VACUUM can reclaim. */
60
- function inflateAndDelete(byteTarget: number): void {
57
+ /** Pile writes into the WAL (without checkpointing) so a truncating
58
+ * checkpoint has measurable work to do. */
59
+ function inflateWal(byteTarget: number): void {
61
60
  const sqlite = getSqlite();
62
61
  sqlite.exec(
63
62
  "CREATE TABLE IF NOT EXISTS bloat (id INTEGER PRIMARY KEY, payload BLOB)",
@@ -72,11 +71,10 @@ function inflateAndDelete(byteTarget: number): void {
72
71
  for (let i = 0; i < rowsTarget; i++) {
73
72
  insert.run(payload);
74
73
  }
74
+ // Commit, but do not checkpoint — the frames stay in the WAL, leaving it at
75
+ // its high-water mark (a PASSIVE auto-checkpoint resets the WAL for reuse but
76
+ // never shrinks the file). Maintenance is what should truncate it.
75
77
  sqlite.exec("COMMIT");
76
- sqlite.exec("DELETE FROM bloat");
77
- sqlite.exec("DROP TABLE bloat");
78
- // Force the WAL onto the main DB file so the bloat is visible on disk.
79
- sqlite.exec("PRAGMA wal_checkpoint(TRUNCATE)");
80
78
  }
81
79
 
82
80
  describe("maybeRunDbMaintenance", () => {
@@ -106,36 +104,30 @@ describe("maybeRunDbMaintenance", () => {
106
104
  expect(getMemoryCheckpoint(MAINTENANCE_CHECKPOINT_KEY)).toBe(String(now));
107
105
  });
108
106
 
109
- test("VACUUM reclaims pages on a bloated DB", async () => {
107
+ test("truncates a bloated WAL", async () => {
110
108
  const sqlite = getSqlite();
111
109
  sqlite.exec("DROP TABLE IF EXISTS bloat");
112
110
  sqlite.exec("PRAGMA wal_checkpoint(TRUNCATE)");
113
111
 
114
- inflateAndDelete(8 * 1024 * 1024);
115
-
116
- const dbPath = getDbPath();
117
- // Read page_count from a fresh connection so we observe post-write
118
- // ground truth without snapshot caching on the main test connection.
119
- const readPageCount = (): number => {
120
- const probe = new Database(dbPath, { readonly: true });
121
- try {
122
- return (
123
- probe.query("PRAGMA page_count").get() as { page_count: number }
124
- ).page_count;
125
- } finally {
126
- probe.close();
127
- }
128
- };
129
- const pagesBefore = readPageCount();
112
+ const walPath = `${getDbPath()}-wal`;
113
+ const walSize = (): number =>
114
+ existsSync(walPath) ? statSync(walPath).size : 0;
115
+
116
+ inflateWal(4 * 1024 * 1024);
117
+ // Sanity: the writes really did grow the WAL on disk.
118
+ expect(walSize()).toBeGreaterThan(1024 * 1024);
130
119
 
131
120
  await maybeRunDbMaintenance();
132
121
 
133
- const pagesAfter = readPageCount();
134
- expect(pagesAfter).toBeLessThan(pagesBefore);
122
+ // Maintenance truncates the WAL back down (no VACUUM, so the data is folded
123
+ // into the main file rather than rebuilt).
124
+ expect(walSize()).toBeLessThan(64 * 1024);
125
+
126
+ sqlite.exec("DROP TABLE IF EXISTS bloat");
135
127
  }, 60_000);
136
128
 
137
129
  test("defers maintenance while the last user message is within the quiet period", async () => {
138
- /** VACUUM must not fire while the user is active, so a recent user
130
+ /** Maintenance must not fire while the user is active, so a recent user
139
131
  * message keeps maintenance deferred. */
140
132
  // GIVEN the user sent a message one minute ago (well within the quiet period)
141
133
  const now = Date.now();
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Tests for the dedicated memory database connection.
3
+ *
4
+ * What this locks in:
5
+ * 1. Opening the memory connection creates `assistant-memory.db` on disk and
6
+ * runs it in WAL mode (its own `-wal`, independent of the main DB) — the
7
+ * regression that lets a high-churn table (the `memory_jobs` queue) bloat
8
+ * the *main* WAL is exactly what this split exists to prevent.
9
+ * 2. The main connection no longer ATTACHes the memory file: there is no
10
+ * `memory` schema on its `database_list`.
11
+ * 3. `memory_jobs` lives in the dedicated memory connection, not in the main
12
+ * connection — proving the physical split.
13
+ * 4. `runAsyncSqlite({ dbPath })` targets the given file via the sqlite3
14
+ * CLI backend, leaving the main DB untouched.
15
+ */
16
+ import { existsSync } from "node:fs";
17
+ import { tmpdir } from "node:os";
18
+ import { join } from "node:path";
19
+ import { describe, expect, test } from "bun:test";
20
+
21
+ import { removeTestDbFiles } from "../../__tests__/assert-not-live-db.js";
22
+
23
+ const { getSqlite, getMemorySqlite } = await import("../db-connection.js");
24
+ const { initializeDb } = await import("../db-init.js");
25
+ const { runAsyncSqlite } = await import("../db-async-query.js");
26
+ const { getMemoryDbPath } = await import("../../util/memory-db-path.js");
27
+ const { findSqlite3 } = await import("../../util/sqlite3-runtime.js");
28
+
29
+ await initializeDb();
30
+
31
+ const sqlite3Available = findSqlite3() !== undefined;
32
+
33
+ describe("memory database connection", () => {
34
+ test("opens the memory file and creates it on disk in WAL mode", () => {
35
+ const memory = getMemorySqlite();
36
+ expect(memory).not.toBeNull();
37
+ expect(existsSync(getMemoryDbPath())).toBe(true);
38
+
39
+ const mode = memory!
40
+ .query<{ journal_mode: string }, []>("PRAGMA journal_mode")
41
+ .get();
42
+ expect(mode?.journal_mode).toBe("wal");
43
+ });
44
+
45
+ test("the main connection does not attach the memory file", () => {
46
+ const attached = getSqlite()
47
+ .query<{ name: string }, []>("PRAGMA database_list")
48
+ .all();
49
+ expect(attached.some((e) => e.name === "memory")).toBe(false);
50
+ });
51
+
52
+ test("memory_jobs lives in the memory connection, not main", () => {
53
+ const inMemory = getMemorySqlite()!
54
+ .query<
55
+ { name: string },
56
+ []
57
+ >(`SELECT name FROM sqlite_master WHERE type='table' AND name='memory_jobs'`)
58
+ .get();
59
+ expect(inMemory?.name).toBe("memory_jobs");
60
+
61
+ const inMain = getSqlite()
62
+ .query<
63
+ { name: string },
64
+ []
65
+ >(`SELECT name FROM main.sqlite_master WHERE name='memory_jobs'`)
66
+ .get();
67
+ expect(inMain).toBeNull();
68
+ });
69
+
70
+ test.if(sqlite3Available)(
71
+ "runAsyncSqlite({ dbPath }) targets the given file, not the main DB",
72
+ async () => {
73
+ const targetPath = join(
74
+ tmpdir(),
75
+ `vellum-async-memory-dbpath-${Date.now()}.db`,
76
+ );
77
+ try {
78
+ const result = await runAsyncSqlite(
79
+ "CREATE TABLE dbpath_probe (x INTEGER); INSERT INTO dbpath_probe VALUES (42); SELECT changes();",
80
+ { dbPath: targetPath, forceBackend: "sqlite3-cli" },
81
+ );
82
+ expect(result.ok).toBe(true);
83
+ expect(result.backend).toBe("sqlite3-cli");
84
+
85
+ // The target file got the table…
86
+ const { Database } = await import("bun:sqlite");
87
+ const probe = new Database(targetPath, { readonly: true });
88
+ try {
89
+ const row = probe
90
+ .query<
91
+ { name: string },
92
+ []
93
+ >("SELECT name FROM sqlite_master WHERE name = 'dbpath_probe'")
94
+ .get();
95
+ expect(row?.name).toBe("dbpath_probe");
96
+ } finally {
97
+ probe.close();
98
+ }
99
+
100
+ // …and the main DB did not.
101
+ const inMain = getSqlite()
102
+ .query<
103
+ { name: string },
104
+ []
105
+ >("SELECT name FROM main.sqlite_master WHERE name = 'dbpath_probe'")
106
+ .get();
107
+ expect(inMain).toBeNull();
108
+ } finally {
109
+ removeTestDbFiles(targetPath);
110
+ }
111
+ },
112
+ );
113
+ });
@@ -18,7 +18,7 @@ import { getDb } from "../db-connection.js";
18
18
  import { initializeDb } from "../db-init.js";
19
19
  import { conversations } from "../schema.js";
20
20
 
21
- initializeDb();
21
+ await initializeDb();
22
22
 
23
23
  function resetTables(): void {
24
24
  const db = getDb();
@@ -18,7 +18,7 @@ import { initializeDb } from "../db-init.js";
18
18
  import { MEMORY_RETROSPECTIVE_SOURCE } from "../memory-retrospective-constants.js";
19
19
  import { conversations } from "../schema.js";
20
20
 
21
- initializeDb();
21
+ await initializeDb();
22
22
 
23
23
  function resetTables(): void {
24
24
  const db = getDb();
@@ -0,0 +1,232 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ import { makeMockLogger } from "../../__tests__/helpers/mock-logger.js";
4
+
5
+ mock.module("../../util/logger.js", () => ({
6
+ getLogger: () => makeMockLogger(),
7
+ }));
8
+
9
+ mock.module("../../config/loader.js", () => ({
10
+ getConfig: () => ({
11
+ ui: {},
12
+ model: "test",
13
+ provider: "test",
14
+ memory: { enabled: false },
15
+ rateLimit: { maxRequestsPerMinute: 0 },
16
+ secretDetection: { enabled: false },
17
+ }),
18
+ }));
19
+
20
+ import {
21
+ addMessage,
22
+ createConversation,
23
+ getMessages,
24
+ } from "../conversation-crud.js";
25
+ import { getDb, getSqlite } from "../db-connection.js";
26
+ import { initializeDb } from "../db-init.js";
27
+ import {
28
+ buildForkCopyScript,
29
+ copyForkMessagesViaSubprocess,
30
+ type ForkIdPair,
31
+ } from "../fork-message-copy.js";
32
+ import { messages as messagesTable } from "../schema.js";
33
+
34
+ await initializeDb();
35
+
36
+ function resetTables(): void {
37
+ const db = getDb();
38
+ db.run("DELETE FROM messages");
39
+ db.run("DELETE FROM conversations");
40
+ }
41
+
42
+ /** Mirror of the production `cloneForkMessageMetadata` semantics. */
43
+ function expectedClonedMetadata(
44
+ sourceMetadata: string | null,
45
+ sourceMessageId: string,
46
+ ): unknown {
47
+ const parsed = sourceMetadata == null ? null : JSON.parse(sourceMetadata);
48
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
49
+ const record = parsed as Record<string, unknown>;
50
+ const existing = record.forkSourceMessageId;
51
+ return {
52
+ ...record,
53
+ forkSourceMessageId:
54
+ typeof existing === "string" ? existing : sourceMessageId,
55
+ };
56
+ }
57
+ return { forkSourceMessageId: sourceMessageId };
58
+ }
59
+
60
+ /** Build an in-JS old→new id map for a source conversation's messages. */
61
+ function idPairsFor(sourceConversationId: string): ForkIdPair[] {
62
+ return getMessages(sourceConversationId).map((m) => ({
63
+ oldId: m.id,
64
+ newId: crypto.randomUUID(),
65
+ }));
66
+ }
67
+
68
+ describe("copyForkMessagesViaSubprocess", () => {
69
+ beforeEach(() => {
70
+ resetTables();
71
+ });
72
+
73
+ test("copies rows with cloneForkMessageMetadata parity and a fresh id", async () => {
74
+ const source = createConversation("source");
75
+ await addMessage(source.id, "user", "draft a plan", {
76
+ metadata: { branch: 1, source: "user" },
77
+ skipIndexing: true,
78
+ });
79
+ await addMessage(source.id, "assistant", "here is a pass", {
80
+ metadata: { automated: true },
81
+ skipIndexing: true,
82
+ });
83
+ // Already-stamped metadata must be preserved, not overwritten.
84
+ await addMessage(source.id, "user", "carry this", {
85
+ metadata: { forkSourceMessageId: "pre-existing", note: "x" },
86
+ skipIndexing: true,
87
+ });
88
+ // Null metadata must become a fresh provenance-only object.
89
+ await addMessage(source.id, "user", "no metadata", {
90
+ skipIndexing: true,
91
+ });
92
+
93
+ const fork = createConversation({
94
+ title: "fork",
95
+ conversationType: "background",
96
+ });
97
+ const sourceMessages = getMessages(source.id);
98
+ const idPairs = sourceMessages.map((m) => ({
99
+ oldId: m.id,
100
+ newId: crypto.randomUUID(),
101
+ }));
102
+
103
+ const result = await copyForkMessagesViaSubprocess({
104
+ forkConversationId: fork.id,
105
+ idPairs,
106
+ forceInProcess: true,
107
+ });
108
+ expect(result.ok).toBe(true);
109
+
110
+ const forkMessages = getMessages(fork.id);
111
+ expect(forkMessages).toHaveLength(sourceMessages.length);
112
+ expect(forkMessages.map((m) => m.role)).toEqual(
113
+ sourceMessages.map((m) => m.role),
114
+ );
115
+ expect(forkMessages.map((m) => m.content)).toEqual(
116
+ sourceMessages.map((m) => m.content),
117
+ );
118
+ expect(forkMessages.map((m) => m.createdAt)).toEqual(
119
+ sourceMessages.map((m) => m.createdAt),
120
+ );
121
+ expect(
122
+ forkMessages.map((m) => (m.metadata ? JSON.parse(m.metadata) : null)),
123
+ ).toEqual(
124
+ sourceMessages.map((m) => expectedClonedMetadata(m.metadata, m.id)),
125
+ );
126
+ // Fresh ids, and assigned exactly per the supplied map.
127
+ const byOld = new Map(idPairs.map((p) => [p.oldId, p.newId]));
128
+ for (const src of sourceMessages) {
129
+ const expectedNewId = byOld.get(src.id);
130
+ expect(forkMessages.some((f) => f.id === expectedNewId)).toBe(true);
131
+ }
132
+ });
133
+
134
+ test("does not copy client_message_id onto fork rows", async () => {
135
+ const source = createConversation("source");
136
+ const db = getDb();
137
+ const createdAt = Date.now();
138
+ db.run(
139
+ `INSERT INTO messages (id, conversation_id, role, content, created_at, client_message_id)
140
+ VALUES ('msg-with-client-id', '${source.id}', 'user', 'hi', ${createdAt}, 'client-123')`,
141
+ );
142
+
143
+ const fork = createConversation({
144
+ title: "fork",
145
+ conversationType: "background",
146
+ });
147
+ await copyForkMessagesViaSubprocess({
148
+ forkConversationId: fork.id,
149
+ idPairs: [{ oldId: "msg-with-client-id", newId: crypto.randomUUID() }],
150
+ forceInProcess: true,
151
+ });
152
+
153
+ const forkRow = db
154
+ .select()
155
+ .from(messagesTable)
156
+ .all()
157
+ .find((r) => r.conversationId === fork.id);
158
+ expect(forkRow).toBeDefined();
159
+ expect(forkRow?.clientMessageId ?? null).toBeNull();
160
+ });
161
+
162
+ test("copies across batch boundaries", async () => {
163
+ const source = createConversation("source");
164
+ for (let i = 0; i < 5; i++) {
165
+ await addMessage(source.id, "user", `m${i}`, { skipIndexing: true });
166
+ }
167
+ const fork = createConversation({
168
+ title: "fork",
169
+ conversationType: "background",
170
+ });
171
+ const idPairs = idPairsFor(source.id);
172
+
173
+ const result = await copyForkMessagesViaSubprocess({
174
+ forkConversationId: fork.id,
175
+ idPairs,
176
+ batchSize: 2,
177
+ forceInProcess: true,
178
+ });
179
+ expect(result.ok).toBe(true);
180
+ expect(getMessages(fork.id)).toHaveLength(5);
181
+ });
182
+
183
+ test("no-op for an empty id map", async () => {
184
+ const result = await copyForkMessagesViaSubprocess({
185
+ forkConversationId: crypto.randomUUID(),
186
+ idPairs: [],
187
+ forceInProcess: true,
188
+ });
189
+ expect(result.ok).toBe(true);
190
+ expect(result.elapsedMs).toBe(0);
191
+ });
192
+
193
+ test("does not leave the staging temp table on the connection", async () => {
194
+ const source = createConversation("source");
195
+ await addMessage(source.id, "user", "hi", { skipIndexing: true });
196
+ const fork = createConversation({
197
+ title: "fork",
198
+ conversationType: "background",
199
+ });
200
+ await copyForkMessagesViaSubprocess({
201
+ forkConversationId: fork.id,
202
+ idPairs: idPairsFor(source.id),
203
+ forceInProcess: true,
204
+ });
205
+ const tempTable = getSqlite()
206
+ .query(
207
+ "SELECT name FROM sqlite_temp_master WHERE type='table' AND name='_fork_id_map'",
208
+ )
209
+ .get();
210
+ expect(tempTable).toBeNull();
211
+ });
212
+ });
213
+
214
+ describe("buildForkCopyScript", () => {
215
+ test("rejects an unsafe fork id", () => {
216
+ expect(() =>
217
+ buildForkCopyScript({
218
+ forkConversationId: "abc'); DROP TABLE messages;--",
219
+ idPairs: [],
220
+ }),
221
+ ).toThrow(/unsafe id/);
222
+ });
223
+
224
+ test("rejects an unsafe message id", () => {
225
+ expect(() =>
226
+ buildForkCopyScript({
227
+ forkConversationId: crypto.randomUUID(),
228
+ idPairs: [{ oldId: "ok", newId: "bad'id" }],
229
+ }),
230
+ ).toThrow(/unsafe id/);
231
+ });
232
+ });
@@ -71,6 +71,8 @@ mock.module("../qdrant-circuit-breaker.js", () => ({
71
71
  mock.module("../raw-query.js", () => ({
72
72
  rawAll: () => [],
73
73
  rawChanges: () => 0,
74
+ rawMemoryAll: () => [],
75
+ rawMemoryChanges: () => 0,
74
76
  }));
75
77
 
76
78
  // Drizzle-shaped no-op db. Tracks inserts/updates so tests can observe
@@ -111,6 +113,7 @@ function makeStubDb() {
111
113
  const stubDb = makeStubDb();
112
114
  mock.module("../db-connection.js", () => ({
113
115
  getDb: () => stubDb,
116
+ getMemoryDb: () => stubDb,
114
117
  }));
115
118
 
116
119
  // Now load the real modules under test.
@@ -67,7 +67,7 @@ const tmpWorkspace = mkdtempSync(
67
67
  const previousWorkspaceEnv = process.env.VELLUM_WORKSPACE_DIR;
68
68
  process.env.VELLUM_WORKSPACE_DIR = tmpWorkspace;
69
69
 
70
- import { getDb } from "../db-connection.js";
70
+ import { getMemoryDb } from "../db-connection.js";
71
71
  import { initializeDb } from "../db-init.js";
72
72
  import { enqueueMemoryJob } from "../jobs-store.js";
73
73
  import { runMemoryJobsOnce } from "../jobs-worker.js";
@@ -75,8 +75,8 @@ import { _resetQdrantBreaker } from "../qdrant-circuit-breaker.js";
75
75
  import { memoryJobs } from "../schema.js";
76
76
 
77
77
  describe("graph_trigger_embed under memory v2", () => {
78
- beforeAll(() => {
79
- initializeDb();
78
+ beforeAll(async () => {
79
+ await initializeDb();
80
80
  });
81
81
 
82
82
  afterAll(() => {
@@ -89,7 +89,7 @@ describe("graph_trigger_embed under memory v2", () => {
89
89
  });
90
90
 
91
91
  beforeEach(() => {
92
- getDb().run("DELETE FROM memory_jobs");
92
+ getMemoryDb()!.run("DELETE FROM memory_jobs");
93
93
  triggerHandlerCalls = 0;
94
94
  _resetQdrantBreaker();
95
95
  });
@@ -103,7 +103,7 @@ describe("graph_trigger_embed under memory v2", () => {
103
103
 
104
104
  expect(triggerHandlerCalls).toBe(1);
105
105
 
106
- const rows = getDb()
106
+ const rows = getMemoryDb()!
107
107
  .select()
108
108
  .from(memoryJobs)
109
109
  .where(eq(memoryJobs.id, jobId))
@@ -59,7 +59,7 @@ afterAll(() => {
59
59
  rmSync(tmpWorkspace, { recursive: true, force: true });
60
60
  });
61
61
 
62
- const { getDb } = await import("../db-connection.js");
62
+ const { getMemoryDb } = await import("../db-connection.js");
63
63
  const { initializeDb } = await import("../db-init.js");
64
64
  const { resetTestTables } = await import("../raw-query.js");
65
65
  const { memoryJobs } = await import("../schema.js");
@@ -107,7 +107,7 @@ function removeBuffer(): void {
107
107
  }
108
108
 
109
109
  function countPendingJobs(type: string): number {
110
- return getDb()
110
+ return getMemoryDb()!
111
111
  .select()
112
112
  .from(memoryJobs)
113
113
  .where(eq(memoryJobs.type, type))
@@ -115,7 +115,7 @@ function countPendingJobs(type: string): number {
115
115
  }
116
116
 
117
117
  function consolidationJobPayloads(): Record<string, unknown>[] {
118
- return getDb()
118
+ return getMemoryDb()!
119
119
  .select({ payload: memoryJobs.payload })
120
120
  .from(memoryJobs)
121
121
  .where(eq(memoryJobs.type, "memory_v2_consolidate"))
@@ -126,12 +126,14 @@ function consolidationJobPayloads(): Record<string, unknown>[] {
126
126
  // Initialize the DB once for the file; clear per-test tables in beforeEach
127
127
  // rather than tearing down the singleton, which is slow because it re-runs
128
128
  // every migration on the next access.
129
- initializeDb();
129
+ await initializeDb();
130
130
 
131
131
  beforeEach(() => {
132
132
  // Clear job + checkpoint state so each test starts from zero rows. Other
133
- // tables stay intact — the worker only inspects these two.
134
- resetTestTables("memory_jobs", "memory_checkpoints");
133
+ // tables stay intact — the worker only inspects these two. memory_jobs lives
134
+ // in the dedicated memory connection; memory_checkpoints in main.
135
+ getMemoryDb()!.run("DELETE FROM memory_jobs");
136
+ resetTestTables("memory_checkpoints");
135
137
  });
136
138
 
137
139
  // ---------------------------------------------------------------------------
@@ -161,7 +161,7 @@ mock.module("../conversation-crud.js", () => ({
161
161
  title: "Source conversation",
162
162
  };
163
163
  },
164
- forkConversation: (params: {
164
+ forkConversationForRetrospective: async (params: {
165
165
  conversationId: string;
166
166
  throughMessageId?: string;
167
167
  source: string;
@@ -497,6 +497,28 @@ describe("memoryRetrospectiveJob", () => {
497
497
  expect(instructionText).not.toContain("(none)");
498
498
  });
499
499
 
500
+ test("subsequent run: <already_remembered> flattens a prior batched (array) remember call", async () => {
501
+ priorRetroId = "prior-retro-conv-1";
502
+ priorRetroMessages = [
503
+ {
504
+ role: "assistant",
505
+ content: JSON.stringify([
506
+ {
507
+ type: "tool_use",
508
+ name: "remember",
509
+ input: { content: ["Bob switched teams", "Launch slipped to Q3"] },
510
+ },
511
+ ]),
512
+ },
513
+ ];
514
+ await memoryRetrospectiveJob(makeJob(), stubConfig);
515
+
516
+ const instructionText = persistedInstructionText();
517
+ expect(instructionText).toContain("- Bob switched teams");
518
+ expect(instructionText).toContain("- Launch slipped to Q3");
519
+ expect(instructionText).not.toContain("(none)");
520
+ });
521
+
500
522
  test("malformed prior-retrospective messages are skipped, run still proceeds", async () => {
501
523
  priorRetroId = "prior-retro-conv-1";
502
524
  priorRetroMessages = [
@@ -685,39 +707,12 @@ describe("memoryRetrospectiveJob", () => {
685
707
  expect(wakeCalls[0]!.opts.toolGateMode).toBe("execution");
686
708
  });
687
709
 
688
- // -------------------------------------------------------------------------
689
- // Source background-turn parity (isNonInteractive)
690
- // -------------------------------------------------------------------------
691
-
692
- test("background source wake runs non-interactive (reproduces <background_turn>)", async () => {
693
- conversationOverrides["src-conv-1"] = {
694
- source: "heartbeat",
695
- forkParentMessageId: null,
696
- title: "Heartbeat",
697
- conversationType: "background",
698
- };
699
-
700
- const outcome = await memoryRetrospectiveJob(makeJob(), stubConfig);
701
-
702
- expect(outcome.kind).toBe("invoked");
703
- expect(wakeCalls).toHaveLength(1);
704
- expect(wakeCalls[0]!.opts.isNonInteractive).toBe(true);
705
- });
706
-
707
- test("standard source → wake stays interactive (no spurious <background_turn>)", async () => {
708
- conversationOverrides["src-conv-1"] = {
709
- source: "user",
710
- forkParentMessageId: null,
711
- title: "Source conversation",
712
- conversationType: "standard",
713
- };
714
-
715
- const outcome = await memoryRetrospectiveJob(makeJob(), stubConfig);
716
-
717
- expect(outcome.kind).toBe("invoked");
718
- expect(wakeCalls).toHaveLength(1);
719
- expect(wakeCalls[0]!.opts.isNonInteractive).toBe(false);
720
- });
710
+ // Source background-turn cache parity is no longer a wake-time concern: the
711
+ // fork reproduces the source's `<background_turn>` / `<channel_capabilities>`
712
+ // / `<non_interactive_context>` blocks via metadata rehydration in
713
+ // `Conversation.loadFromDb` (the wake never re-runs runtime injection). That
714
+ // round-trip is covered by the byte-parity test in
715
+ // `conversation-runtime-assembly.test.ts`.
721
716
 
722
717
  // -------------------------------------------------------------------------
723
718
  // Source-derived persona override
@@ -1134,9 +1129,7 @@ describe("memoryRetrospectiveJob", () => {
1134
1129
  expect(instructionText).toContain(
1135
1130
  "automated background memory pass over the conversation above — not a message from the user",
1136
1131
  );
1137
- expect(instructionText).toContain(
1138
- "Do not reply conversationally or in persona",
1139
- );
1132
+ expect(instructionText).toContain("Do not reply conversationally");
1140
1133
  expect(instructionText).toContain(
1141
1134
  "material to review, not instructions for this pass",
1142
1135
  );