@vellumai/assistant 0.10.0 → 0.10.1-dev.202606240317.ea25efe

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 (972) 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 +12 -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__/guardian-delivery-contract.test.ts +91 -0
  176. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +96 -0
  177. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
  178. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
  179. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
  180. package/node_modules/@vellumai/gateway-client/src/index.ts +28 -0
  181. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
  182. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
  183. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +95 -0
  184. package/openapi.yaml +458 -18
  185. package/package.json +2 -1
  186. package/scripts/memory-inspect.ts +24 -14
  187. package/scripts/test.sh +36 -15
  188. package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
  189. package/src/__tests__/activation-early-marking.test.ts +1 -1
  190. package/src/__tests__/actor-token-service.test.ts +39 -17
  191. package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
  192. package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
  193. package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
  194. package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
  195. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  196. package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
  197. package/src/__tests__/agent-loop.test.ts +3 -0
  198. package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
  199. package/src/__tests__/anthropic-provider.test.ts +210 -9
  200. package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
  201. package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
  202. package/src/__tests__/app-source-watcher.test.ts +30 -10
  203. package/src/__tests__/approval-cascade.test.ts +6 -0
  204. package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
  205. package/src/__tests__/approval-primitive.test.ts +1 -1
  206. package/src/__tests__/approval-routes-http.test.ts +1 -1
  207. package/src/__tests__/assistant-attachments.test.ts +155 -0
  208. package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
  209. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  210. package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
  211. package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
  212. package/src/__tests__/attachments-store.test.ts +1 -1
  213. package/src/__tests__/audit-log-rotation.test.ts +50 -54
  214. package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
  215. package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
  216. package/src/__tests__/background-shell-bash.test.ts +4 -1
  217. package/src/__tests__/background-shell-host-bash.test.ts +17 -3
  218. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  219. package/src/__tests__/call-controller.test.ts +20 -1
  220. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  221. package/src/__tests__/call-domain.test.ts +1 -1
  222. package/src/__tests__/call-pointer-messages.test.ts +3 -4
  223. package/src/__tests__/call-recovery.test.ts +1 -1
  224. package/src/__tests__/call-routes-http.test.ts +1 -1
  225. package/src/__tests__/call-store.test.ts +1 -1
  226. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  227. package/src/__tests__/canonical-guardian-store.test.ts +24 -1
  228. package/src/__tests__/card-surface-data.test.ts +60 -0
  229. package/src/__tests__/channel-approval-routes.test.ts +73 -1119
  230. package/src/__tests__/channel-delivery-store.test.ts +1 -1
  231. package/src/__tests__/channel-guardian.test.ts +291 -641
  232. package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
  233. package/src/__tests__/channel-retry-sweep.test.ts +1 -1
  234. package/src/__tests__/compaction-events.test.ts +6 -0
  235. package/src/__tests__/compaction-trail-store.test.ts +6 -5
  236. package/src/__tests__/compaction.benchmark.test.ts +0 -1
  237. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  238. package/src/__tests__/config-loader-backfill.test.ts +188 -52
  239. package/src/__tests__/config-schema.test.ts +35 -0
  240. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
  241. package/src/__tests__/contact-store-user-file.test.ts +2 -2
  242. package/src/__tests__/contacts-relay-reads.test.ts +409 -0
  243. package/src/__tests__/contacts-tools.test.ts +4 -4
  244. package/src/__tests__/contacts-write.test.ts +1 -2
  245. package/src/__tests__/context-search-conversations-source.test.ts +1 -1
  246. package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
  247. package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
  248. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  249. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
  250. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
  251. package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
  252. package/src/__tests__/conversation-agent-loop.test.ts +7 -0
  253. package/src/__tests__/conversation-attachments.test.ts +2 -5
  254. package/src/__tests__/conversation-attention-store.test.ts +1 -1
  255. package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
  256. package/src/__tests__/conversation-clear-safety.test.ts +1 -1
  257. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  258. package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
  259. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
  260. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
  261. package/src/__tests__/conversation-disk-view.test.ts +1 -1
  262. package/src/__tests__/conversation-fork-crud.test.ts +10 -8
  263. package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
  264. package/src/__tests__/conversation-fork-route.test.ts +1 -1
  265. package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
  266. package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
  267. package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
  268. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  269. package/src/__tests__/conversation-lifecycle.test.ts +117 -0
  270. package/src/__tests__/conversation-list-source.test.ts +3 -3
  271. package/src/__tests__/conversation-process-callsite.test.ts +6 -14
  272. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  273. package/src/__tests__/conversation-queue.test.ts +95 -0
  274. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
  275. package/src/__tests__/conversation-routes-guardian-reply.test.ts +12 -0
  276. package/src/__tests__/conversation-routes-slash-commands.test.ts +12 -0
  277. package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
  278. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  279. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  280. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  281. package/src/__tests__/conversation-starter-routes.test.ts +5 -5
  282. package/src/__tests__/conversation-store.test.ts +1 -1
  283. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +4 -4
  284. package/src/__tests__/conversation-surfaces-task-progress.test.ts +352 -0
  285. package/src/__tests__/conversation-sync-tags.test.ts +1 -1
  286. package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
  287. package/src/__tests__/conversation-usage.test.ts +1 -1
  288. package/src/__tests__/conversation-wipe.test.ts +9 -8
  289. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  290. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  291. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  292. package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
  293. package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
  294. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  295. package/src/__tests__/db-acp-history.test.ts +2 -2
  296. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
  297. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
  298. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
  299. package/src/__tests__/db-migration-rollback.test.ts +129 -39
  300. package/src/__tests__/db-proxy-transaction.test.ts +1 -1
  301. package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
  302. package/src/__tests__/db-test-helpers.ts +36 -19
  303. package/src/__tests__/delete-propagation.test.ts +1 -1
  304. package/src/__tests__/deterministic-verification-control-plane.test.ts +28 -8
  305. package/src/__tests__/disk-pressure-guard.test.ts +41 -0
  306. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  307. package/src/__tests__/dm-backfill.test.ts +1 -1
  308. package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
  309. package/src/__tests__/dynamic-page-surface.test.ts +0 -94
  310. package/src/__tests__/edit-propagation.test.ts +1 -1
  311. package/src/__tests__/emit-signal-routing-intent.test.ts +93 -5
  312. package/src/__tests__/empty-response-hook.test.ts +42 -0
  313. package/src/__tests__/events-client-registration.test.ts +1 -1
  314. package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
  315. package/src/__tests__/followup-tools.test.ts +1 -1
  316. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  317. package/src/__tests__/guardian-action-sweep.test.ts +9 -2
  318. package/src/__tests__/guardian-binding-drift-heal.test.ts +76 -11
  319. package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
  320. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
  321. package/src/__tests__/guardian-dispatch.test.ts +96 -2
  322. package/src/__tests__/guardian-outbound-http.test.ts +20 -12
  323. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
  324. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  325. package/src/__tests__/guardian-routing-state.test.ts +1 -2
  326. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  327. package/src/__tests__/headless-browser-mode.test.ts +2 -2
  328. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  329. package/src/__tests__/heartbeat-service.test.ts +6 -0
  330. package/src/__tests__/helpers/channel-test-adapter.ts +92 -0
  331. package/src/__tests__/host-app-control-routes.test.ts +24 -30
  332. package/src/__tests__/host-bash-routes.test.ts +31 -41
  333. package/src/__tests__/host-browser-routes.test.ts +26 -32
  334. package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
  335. package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
  336. package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
  337. package/src/__tests__/http-conversation-lineage.test.ts +1 -1
  338. package/src/__tests__/http-user-message-parity.test.ts +165 -8
  339. package/src/__tests__/image-recovery-hook.test.ts +1 -1
  340. package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
  341. package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
  342. package/src/__tests__/inference-profile-reaper.test.ts +1 -1
  343. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  344. package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
  345. package/src/__tests__/injector-chain.test.ts +1 -1
  346. package/src/__tests__/injector-disk-pressure.test.ts +11 -6
  347. package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
  348. package/src/__tests__/invite-redemption-service.test.ts +244 -43
  349. package/src/__tests__/invite-routes-http.test.ts +35 -186
  350. package/src/__tests__/invite-service-ipc.test.ts +287 -0
  351. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
  352. package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
  353. package/src/__tests__/list-messages-attachments.test.ts +42 -1
  354. package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
  355. package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
  356. package/src/__tests__/list-messages-page-latest.test.ts +1 -1
  357. package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
  358. package/src/__tests__/llm-context-normalization.test.ts +105 -0
  359. package/src/__tests__/llm-context-route-provider.test.ts +69 -4
  360. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
  361. package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
  362. package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
  363. package/src/__tests__/llm-resolver.test.ts +205 -5
  364. package/src/__tests__/llm-usage-store.test.ts +65 -1
  365. package/src/__tests__/log-export-routes.test.ts +1 -1
  366. package/src/__tests__/log-export-workspace.test.ts +3 -3
  367. package/src/__tests__/media-stream-server-integration.test.ts +127 -0
  368. package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
  369. package/src/__tests__/memory-recall-log-store.test.ts +1 -1
  370. package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
  371. package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
  372. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  373. package/src/__tests__/mtime-cache.test.ts +375 -0
  374. package/src/__tests__/non-member-access-request.test.ts +190 -19
  375. package/src/__tests__/notification-broadcaster.test.ts +4 -0
  376. package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
  377. package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
  378. package/src/__tests__/notification-deep-link.test.ts +4 -0
  379. package/src/__tests__/notification-guardian-path.test.ts +20 -1
  380. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  381. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  382. package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
  383. package/src/__tests__/oauth-store.test.ts +1 -1
  384. package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
  385. package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
  386. package/src/__tests__/persist-unsendable-image.test.ts +1 -1
  387. package/src/__tests__/persona-resolver.test.ts +39 -1
  388. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  389. package/src/__tests__/playbook-execution.test.ts +1 -1
  390. package/src/__tests__/playbook-tools.test.ts +1 -1
  391. package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
  392. package/src/__tests__/plugin-bootstrap.test.ts +78 -0
  393. package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
  394. package/src/__tests__/provider-usage-tracking.test.ts +40 -1
  395. package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
  396. package/src/__tests__/reaction-persistence.test.ts +1 -1
  397. package/src/__tests__/registry.test.ts +3 -0
  398. package/src/__tests__/relay-server.test.ts +1026 -73
  399. package/src/__tests__/runtime-attachment-metadata.test.ts +9 -1
  400. package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
  401. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  402. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  403. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  404. package/src/__tests__/schedule-retry.test.ts +1 -1
  405. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
  406. package/src/__tests__/schedule-routes.test.ts +1 -1
  407. package/src/__tests__/schedule-store.test.ts +1 -1
  408. package/src/__tests__/schedule-tools.test.ts +1 -1
  409. package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
  410. package/src/__tests__/scheduler-recurrence.test.ts +1 -1
  411. package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
  412. package/src/__tests__/scheduler-wake.test.ts +2 -1
  413. package/src/__tests__/scoped-approval-grants.test.ts +1 -1
  414. package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
  415. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
  416. package/src/__tests__/secret-ingress-http.test.ts +12 -0
  417. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
  418. package/src/__tests__/send-endpoint-busy.test.ts +31 -9
  419. package/src/__tests__/sequence-store.test.ts +1 -1
  420. package/src/__tests__/server-history-render.test.ts +40 -1
  421. package/src/__tests__/settings-routes.test.ts +11 -10
  422. package/src/__tests__/skill-load-tool.test.ts +72 -0
  423. package/src/__tests__/skills.test.ts +44 -0
  424. package/src/__tests__/slack-inbound-verification.test.ts +48 -5
  425. package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
  426. package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
  427. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +102 -0
  428. package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
  429. package/src/__tests__/stt-hints.test.ts +44 -13
  430. package/src/__tests__/subagent-detail.test.ts +27 -0
  431. package/src/__tests__/subagent-disposal.test.ts +65 -0
  432. package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
  433. package/src/__tests__/subagent-tools.test.ts +1 -31
  434. package/src/__tests__/system-prompt.test.ts +1 -1
  435. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  436. package/src/__tests__/task-compiler.test.ts +1 -1
  437. package/src/__tests__/task-management-tools.test.ts +1 -1
  438. package/src/__tests__/task-memory-cleanup.test.ts +9 -6
  439. package/src/__tests__/task-scheduler.test.ts +1 -1
  440. package/src/__tests__/thread-backfill.test.ts +1 -1
  441. package/src/__tests__/tool-approval-handler.test.ts +1 -1
  442. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
  443. package/src/__tests__/tool-executor.test.ts +37 -1
  444. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
  445. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
  446. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
  447. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
  448. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  449. package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
  450. package/src/__tests__/turn-events-store.test.ts +1 -1
  451. package/src/__tests__/twilio-routes.test.ts +98 -3
  452. package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
  453. package/src/__tests__/usage-routes.test.ts +1 -1
  454. package/src/__tests__/user-plugin-loader.test.ts +34 -29
  455. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  456. package/src/__tests__/voice-invite-redemption.test.ts +134 -36
  457. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  458. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  459. package/src/__tests__/workspace-git-service.test.ts +114 -1
  460. package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
  461. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
  462. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  463. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
  464. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
  465. package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
  466. package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
  467. package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
  468. package/src/__tests__/workspace-tool-loader.test.ts +3 -0
  469. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
  470. package/src/a2a/__tests__/task-store.test.ts +1 -1
  471. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
  472. package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
  473. package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
  474. package/src/acp/__tests__/session-manager.test.ts +72 -1
  475. package/src/acp/index.ts +10 -0
  476. package/src/acp/session-manager.ts +35 -0
  477. package/src/agent/loop-exclusive-tool.test.ts +150 -0
  478. package/src/agent/loop.ts +101 -27
  479. package/src/api/constants/sse-replay.ts +41 -0
  480. package/src/api/events/ui-surface-show.ts +8 -3
  481. package/src/api/index.ts +7 -6
  482. package/src/api/responses/conversation-message.ts +4 -0
  483. package/src/api/responses/llm-request-log-entry.ts +25 -0
  484. package/src/api/responses/subagent-detail.ts +17 -0
  485. package/src/api/surfaces.ts +33 -0
  486. package/src/approvals/AGENTS.md +1 -2
  487. package/src/approvals/guardian-decision-primitive.ts +13 -210
  488. package/src/approvals/guardian-request-resolvers.ts +104 -58
  489. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  490. package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
  491. package/src/calls/__tests__/relay-setup-router.test.ts +349 -65
  492. package/src/calls/guardian-dispatch.ts +10 -8
  493. package/src/calls/inbound-trust-reader.ts +56 -0
  494. package/src/calls/media-stream-server.ts +21 -0
  495. package/src/calls/relay-server.ts +231 -72
  496. package/src/calls/relay-setup-router.ts +57 -13
  497. package/src/calls/relay-verification.ts +7 -7
  498. package/src/calls/stt-hints.ts +9 -12
  499. package/src/calls/twilio-routes.ts +13 -3
  500. package/src/cli/commands/__tests__/cache.test.ts +8 -1
  501. package/src/cli/commands/cache.ts +194 -181
  502. package/src/cli/commands/contacts.ts +6 -24
  503. package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
  504. package/src/cli/commands/db/__tests__/status.test.ts +7 -3
  505. package/src/cli/commands/db/status.ts +212 -33
  506. package/src/cli/commands/mcp.ts +252 -218
  507. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
  508. package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
  509. package/src/cli/commands/memory/index.ts +4 -0
  510. package/src/cli/commands/memory/memory-retrospective.ts +129 -0
  511. package/src/cli/commands/memory/memory-v3.ts +176 -4
  512. package/src/cli/commands/memory/worker.ts +175 -0
  513. package/src/cli/commands/plugins.ts +343 -14
  514. package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
  515. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
  516. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  517. package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
  518. package/src/cli/lib/install-from-github.ts +47 -6
  519. package/src/cli/lib/list-installed-plugins.ts +179 -1
  520. package/src/cli/lib/plugin-marketplace.ts +11 -0
  521. package/src/cli/lib/plugin-pin-history.ts +257 -0
  522. package/src/cli/lib/toggle-plugin.ts +146 -0
  523. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
  524. package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
  525. package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
  526. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
  527. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
  528. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
  529. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
  530. package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
  531. package/src/config/bundled-skills/contacts/SKILL.md +7 -12
  532. package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
  533. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  534. package/src/config/bundled-skills/workflows/SKILL.md +4 -3
  535. package/src/config/call-site-defaults.ts +11 -2
  536. package/src/config/feature-flag-registry.json +0 -8
  537. package/src/config/llm-resolver.ts +151 -14
  538. package/src/config/loader.ts +36 -5
  539. package/src/config/profile-dispatchability.ts +11 -0
  540. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  541. package/src/config/schemas/call-site-catalog.ts +7 -0
  542. package/src/config/schemas/llm.ts +2 -0
  543. package/src/config/schemas/memory-lifecycle.ts +17 -3
  544. package/src/config/schemas/memory-v3.ts +7 -0
  545. package/src/config/schemas/memory.ts +4 -0
  546. package/src/config/schemas/timeouts.ts +32 -0
  547. package/src/config/seed-inference-profiles.ts +147 -50
  548. package/src/config/skills.ts +27 -5
  549. package/src/config/sync-gated-profiles.ts +13 -1
  550. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
  551. package/src/contacts/contact-store.ts +21 -0
  552. package/src/contacts/contacts-write.ts +3 -0
  553. package/src/contacts/guardian-delivery-reader.ts +223 -0
  554. package/src/contacts/member-status.ts +9 -0
  555. package/src/credential-health/credential-health-service.ts +1 -5
  556. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  557. package/src/daemon/app-source-watcher.ts +31 -18
  558. package/src/daemon/assistant-attachments.ts +94 -4
  559. package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
  560. package/src/daemon/conversation-agent-loop.ts +18 -36
  561. package/src/daemon/conversation-process.ts +35 -16
  562. package/src/daemon/conversation-runtime-assembly.ts +91 -66
  563. package/src/daemon/conversation-surfaces.ts +273 -18
  564. package/src/daemon/conversation-tool-setup.ts +24 -64
  565. package/src/daemon/conversation.ts +149 -53
  566. package/src/daemon/disk-pressure-guard.ts +12 -2
  567. package/src/daemon/event-loop-watchdog.test.ts +85 -0
  568. package/src/daemon/event-loop-watchdog.ts +133 -0
  569. package/src/daemon/external-plugins-bootstrap.ts +26 -80
  570. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  571. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
  572. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
  573. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
  574. package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
  575. package/src/daemon/handlers/config-channels.ts +41 -27
  576. package/src/daemon/handlers/conversations.ts +84 -0
  577. package/src/daemon/handlers/shared.ts +7 -0
  578. package/src/daemon/lifecycle.ts +44 -5
  579. package/src/daemon/memory-v2-startup.test.ts +72 -0
  580. package/src/daemon/memory-v2-startup.ts +87 -19
  581. package/src/daemon/message-types/inbox.ts +0 -6
  582. package/src/daemon/message-types/messages.ts +0 -4
  583. package/src/daemon/message-types/surfaces.ts +12 -11
  584. package/src/daemon/server.ts +0 -4
  585. package/src/daemon/shutdown-handlers.ts +20 -0
  586. package/src/daemon/tool-setup-types.ts +7 -5
  587. package/src/daemon/trust-context.ts +6 -0
  588. package/src/daemon/wake-conversation-ops.ts +70 -0
  589. package/src/daemon/workspace-tools-watcher.ts +7 -3
  590. package/src/documents/document-comments-store.test.ts +1 -1
  591. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
  592. package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
  593. package/src/heartbeat/heartbeat-service.ts +3 -4
  594. package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
  595. package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
  596. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  597. package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
  598. package/src/ipc/assistant-server.ts +10 -2
  599. package/src/ipc/gateway-client.ts +2 -1
  600. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
  601. package/src/ipc/routes/invite-ipc-routes.ts +66 -0
  602. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
  603. package/src/memory/__tests__/activation-session-store.test.ts +1 -1
  604. package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
  605. package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
  606. package/src/memory/__tests__/conversation-queries.test.ts +1 -1
  607. package/src/memory/__tests__/db-async-query.test.ts +1 -1
  608. package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
  609. package/src/memory/__tests__/db-maintenance.test.ts +28 -36
  610. package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
  611. package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
  612. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
  613. package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
  614. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
  615. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
  616. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
  617. package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
  618. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
  619. package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
  620. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  621. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
  622. package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
  623. package/src/memory/__tests__/prompt-override.test.ts +192 -0
  624. package/src/memory/__tests__/table-relocation.test.ts +129 -0
  625. package/src/memory/conversation-crud.ts +461 -152
  626. package/src/memory/db-async-query.ts +89 -5
  627. package/src/memory/db-connection.ts +101 -18
  628. package/src/memory/db-init.ts +409 -234
  629. package/src/memory/db-maintenance.ts +43 -38
  630. package/src/memory/db-singleton.ts +45 -19
  631. package/src/memory/embedding-gemini.test.ts +3 -1
  632. package/src/memory/embedding-gemini.ts +18 -2
  633. package/src/memory/fork-message-copy.ts +170 -0
  634. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
  635. package/src/memory/graph/bootstrap.test.ts +6 -3
  636. package/src/memory/graph/retriever.test.ts +12 -12
  637. package/src/memory/graph/store.test.ts +15 -25
  638. package/src/memory/graph/store.ts +23 -14
  639. package/src/memory/graph/tool-handlers.ts +34 -5
  640. package/src/memory/graph/tools.ts +5 -2
  641. package/src/memory/indexer.ts +21 -9
  642. package/src/memory/job-handlers/cleanup.ts +10 -3
  643. package/src/memory/job-handlers/embedding.test.ts +4 -4
  644. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
  645. package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
  646. package/src/memory/jobs-store.ts +36 -24
  647. package/src/memory/llm-request-log-store.ts +51 -19
  648. package/src/memory/llm-usage-store.ts +79 -21
  649. package/src/memory/memory-retrospective-job.ts +27 -19
  650. package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
  651. package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
  652. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +13 -3
  653. package/src/memory/migrations/104-core-indexes.ts +1 -1
  654. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
  655. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
  656. package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
  657. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
  658. package/src/memory/migrations/136-drop-assistant-id-columns.ts +241 -219
  659. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
  660. package/src/memory/migrations/141-rename-verification-table.ts +45 -48
  661. package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
  662. package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
  663. package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
  664. package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
  665. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
  666. package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
  667. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
  668. package/src/memory/migrations/157-invite-contact-id.ts +73 -76
  669. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
  670. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
  671. package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
  672. package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
  673. package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
  674. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
  675. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
  676. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
  677. package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
  678. package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
  679. package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
  680. package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
  681. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
  682. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
  683. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
  684. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +135 -68
  685. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
  686. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
  687. package/src/memory/migrations/217-conversation-host-access.ts +13 -18
  688. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
  689. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
  690. package/src/memory/migrations/230-acp-session-history.ts +23 -28
  691. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
  692. package/src/memory/migrations/232-activation-state.ts +11 -16
  693. package/src/memory/migrations/233-document-conversations.ts +20 -25
  694. package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
  695. package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
  696. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
  697. package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
  698. package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
  699. package/src/memory/migrations/242-message-bookmarks.ts +17 -22
  700. package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
  701. package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
  702. package/src/memory/migrations/251-a2a-tasks.ts +27 -32
  703. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
  704. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
  705. package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
  706. package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
  707. package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
  708. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
  709. package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
  710. package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
  711. package/src/memory/migrations/270-schedule-description.ts +7 -12
  712. package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
  713. package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
  714. package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
  715. package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
  716. package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
  717. package/src/memory/migrations/__tests__/014-backfill-inbox-thread-state.test.ts +108 -0
  718. package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
  719. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -0
  720. package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
  721. package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
  722. package/src/memory/migrations/helpers/relocation.ts +227 -0
  723. package/src/memory/migrations/registry.ts +63 -0
  724. package/src/memory/migrations/run-migrations.ts +187 -16
  725. package/src/memory/migrations/schema-introspection.ts +14 -0
  726. package/src/memory/migrations/validate-migration-state.ts +50 -145
  727. package/src/memory/prompt-override.ts +129 -0
  728. package/src/memory/raw-query.ts +47 -2
  729. package/src/memory/skill-loaded-events-store.test.ts +1 -1
  730. package/src/memory/task-memory-cleanup.ts +62 -41
  731. package/src/memory/tool-executed-events-store.test.ts +1 -1
  732. package/src/memory/turn-trace-store.test.ts +1 -1
  733. package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
  734. package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
  735. package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
  736. package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  737. package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  738. package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
  739. package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
  740. package/src/memory/v2/cli-command-store.ts +75 -38
  741. package/src/memory/v2/prompts/consolidation.ts +13 -82
  742. package/src/memory/v2/prompts/router.ts +21 -93
  743. package/src/memory/v2/skill-store.ts +68 -31
  744. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
  745. package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
  746. package/src/memory/v3-eval/eval-packets.ts +197 -12
  747. package/src/memory/v3-eval/eval-tally.ts +234 -0
  748. package/src/memory/worker-control.ts +118 -0
  749. package/src/memory/worker-process.ts +72 -0
  750. package/src/messaging/provider.ts +10 -0
  751. package/src/messaging/providers/gmail/adapter.ts +1 -0
  752. package/src/messaging/providers/gmail/client.ts +13 -0
  753. package/src/messaging/providers/index.ts +1 -1
  754. package/src/messaging/providers/slack/send.test.ts +87 -39
  755. package/src/messaging/providers/slack/send.ts +84 -105
  756. package/src/notifications/README.md +9 -5
  757. package/src/notifications/__tests__/broadcaster.test.ts +16 -8
  758. package/src/notifications/__tests__/connected-channels.test.ts +114 -0
  759. package/src/notifications/__tests__/decision-engine.test.ts +78 -9
  760. package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
  761. package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
  762. package/src/notifications/adapters/slack.ts +12 -10
  763. package/src/notifications/approval-card-builder.ts +81 -20
  764. package/src/notifications/approval-card-data.ts +8 -5
  765. package/src/notifications/broadcaster.ts +8 -1
  766. package/src/notifications/canonical-delivery-recorder.ts +7 -5
  767. package/src/notifications/conversation-candidates.ts +24 -59
  768. package/src/notifications/copy-composer.ts +48 -68
  769. package/src/notifications/decision-engine.ts +15 -7
  770. package/src/notifications/destination-resolver.ts +68 -24
  771. package/src/notifications/deterministic-checks.ts +19 -16
  772. package/src/notifications/emit-signal.ts +68 -15
  773. package/src/notifications/trusted-contact-payloads.ts +70 -0
  774. package/src/oauth/byo-connection.test.ts +9 -0
  775. package/src/oauth/connection-resolver.test.ts +174 -6
  776. package/src/oauth/connection-resolver.ts +132 -5
  777. package/src/oauth/oauth-store.ts +16 -3
  778. package/src/oauth/scope-utils.ts +39 -0
  779. package/src/permissions/question-prompter.test.ts +1 -1
  780. package/src/permissions/question-prompter.ts +7 -4
  781. package/src/plugin-api/index.ts +9 -4
  782. package/src/plugin-api/model-profiles.test.ts +123 -0
  783. package/src/plugin-api/model-profiles.ts +5 -1
  784. package/src/plugin-api/vision-support.test.ts +173 -0
  785. package/src/plugin-api/vision-support.ts +113 -0
  786. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +90 -0
  787. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
  788. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
  789. package/src/plugins/defaults/advisor/consult.ts +65 -6
  790. package/src/plugins/defaults/advisor/context-pack.ts +288 -0
  791. package/src/plugins/defaults/advisor/steering.ts +14 -2
  792. package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
  793. package/src/plugins/defaults/compaction/window-manager.ts +45 -64
  794. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
  795. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +441 -0
  796. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +57 -0
  797. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +61 -0
  798. package/src/plugins/defaults/image-fallback/package.json +14 -0
  799. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +108 -0
  800. package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
  801. package/src/plugins/defaults/image-fallback/src/image-persist.ts +56 -0
  802. package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
  803. package/src/plugins/defaults/index.ts +27 -0
  804. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
  805. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  806. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +134 -5
  807. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
  808. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
  809. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +246 -19
  810. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
  811. package/src/plugins/external-plugin-loader.ts +47 -6
  812. package/src/plugins/mtime-cache.ts +772 -0
  813. package/src/plugins/pipeline.ts +7 -2
  814. package/src/plugins/registry.ts +16 -5
  815. package/src/plugins/user-loader.ts +22 -76
  816. package/src/prompts/persona-resolver.ts +29 -11
  817. package/src/prompts/system-prompt.ts +1 -1
  818. package/src/prompts/templates/system-sections.ts +4 -4
  819. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  820. package/src/providers/anthropic/client.ts +290 -185
  821. package/src/providers/call-site-routing.ts +14 -0
  822. package/src/providers/gemini/client.ts +43 -0
  823. package/src/providers/inference/adapter-factory.ts +6 -0
  824. package/src/providers/inference/connections.ts +6 -1
  825. package/src/providers/model-catalog.ts +53 -0
  826. package/src/providers/openai/responses-provider.ts +5 -0
  827. package/src/providers/openrouter/client.ts +5 -0
  828. package/src/providers/platform-proxy/constants.ts +5 -0
  829. package/src/providers/provider-send-message.ts +4 -0
  830. package/src/providers/ratelimit.ts +13 -0
  831. package/src/providers/retry.ts +14 -0
  832. package/src/providers/together/client.ts +35 -0
  833. package/src/providers/types.ts +25 -0
  834. package/src/providers/usage-tracking.ts +11 -0
  835. package/src/runtime/AGENTS.md +9 -1
  836. package/src/runtime/__tests__/agent-wake.test.ts +259 -4
  837. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
  838. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +64 -0
  839. package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
  840. package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
  841. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +670 -0
  842. package/src/runtime/access-request-helper.ts +19 -39
  843. package/src/runtime/actor-trust-resolver.ts +8 -16
  844. package/src/runtime/agent-wake.ts +183 -60
  845. package/src/runtime/anchored-guardian.test.ts +156 -0
  846. package/src/runtime/anchored-guardian.ts +135 -0
  847. package/src/runtime/assistant-stream-state.ts +9 -2
  848. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
  849. package/src/runtime/auth/require-bound-guardian.ts +21 -11
  850. package/src/runtime/channel-reply-delivery.ts +6 -3
  851. package/src/runtime/channel-verification-service.ts +24 -0
  852. package/src/runtime/guardian-decision-types.ts +3 -22
  853. package/src/runtime/guardian-vellum-migration.ts +66 -7
  854. package/src/runtime/http-server.ts +1 -15
  855. package/src/runtime/invite-redemption-service.ts +155 -6
  856. package/src/runtime/invite-service.ts +113 -62
  857. package/src/runtime/local-actor-identity.ts +76 -11
  858. package/src/runtime/local-principal-trust.ts +52 -0
  859. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
  860. package/src/runtime/pending-interactions.ts +11 -1
  861. package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
  862. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
  863. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
  864. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
  865. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
  866. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
  867. package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
  868. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  869. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
  870. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
  871. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
  872. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
  873. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
  874. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
  875. package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
  876. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
  877. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
  878. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +163 -0
  879. package/src/runtime/routes/acp-routes-list.test.ts +4 -0
  880. package/src/runtime/routes/acp-routes.test.ts +5 -6
  881. package/src/runtime/routes/attachment-routes.ts +21 -17
  882. package/src/runtime/routes/browser-routes.ts +19 -1
  883. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
  884. package/src/runtime/routes/channel-verification-routes.ts +13 -2
  885. package/src/runtime/routes/contact-routes.ts +275 -164
  886. package/src/runtime/routes/conversation-query-routes.ts +15 -5
  887. package/src/runtime/routes/conversation-routes.ts +80 -66
  888. package/src/runtime/routes/conversation-starter-routes.ts +7 -8
  889. package/src/runtime/routes/events-routes.ts +2 -2
  890. package/src/runtime/routes/guardian-approval-interception.ts +13 -274
  891. package/src/runtime/routes/host-app-control-routes.ts +5 -4
  892. package/src/runtime/routes/host-bash-routes.ts +5 -4
  893. package/src/runtime/routes/host-browser-routes.ts +9 -11
  894. package/src/runtime/routes/host-cu-routes.ts +5 -4
  895. package/src/runtime/routes/host-file-routes.ts +5 -4
  896. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  897. package/src/runtime/routes/http-adapter.ts +1 -1
  898. package/src/runtime/routes/inbound-message-handler.ts +21 -16
  899. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +376 -0
  900. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +86 -64
  901. package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
  902. package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
  903. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
  904. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
  905. package/src/runtime/routes/llm-context-normalization.ts +71 -0
  906. package/src/runtime/routes/log-export-routes.ts +2 -2
  907. package/src/runtime/routes/mcp-auth-routes.ts +38 -15
  908. package/src/runtime/routes/memory-eval-routes.ts +92 -0
  909. package/src/runtime/routes/memory-item-routes.test.ts +12 -11
  910. package/src/runtime/routes/migration-routes.ts +51 -40
  911. package/src/runtime/routes/plugins-routes.ts +164 -8
  912. package/src/runtime/routes/schedule-routes.ts +1 -0
  913. package/src/runtime/routes/subagents-routes.ts +5 -0
  914. package/src/runtime/routes/surface-action-routes.ts +39 -51
  915. package/src/runtime/routes/usage-routes.ts +3 -0
  916. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  917. package/src/runtime/slack-block-formatting.ts +46 -48
  918. package/src/runtime/trust-verdict-consumer.ts +210 -0
  919. package/src/schedule/scheduler.ts +6 -9
  920. package/src/signals/user-message.ts +16 -0
  921. package/src/subagent/manager.ts +9 -0
  922. package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
  923. package/src/tools/ask-question/ask-question-tool.test.ts +89 -52
  924. package/src/tools/ask-question/ask-question-tool.ts +27 -73
  925. package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
  926. package/src/tools/browser/browser-execution.ts +16 -4
  927. package/src/tools/document/document-comment-tool.test.ts +1 -1
  928. package/src/tools/executor.ts +15 -3
  929. package/src/tools/host-terminal/host-shell.ts +28 -9
  930. package/src/tools/memory/register.test.ts +32 -0
  931. package/src/tools/skills/load.ts +43 -2
  932. package/src/tools/subagent/spawn.ts +4 -10
  933. package/src/tools/terminal/shell.ts +16 -5
  934. package/src/tools/tool-defaults.ts +2 -0
  935. package/src/tools/types.ts +18 -2
  936. package/src/tools/ui-surface/definitions.ts +0 -43
  937. package/src/util/fs-watcher-error.ts +36 -0
  938. package/src/util/log-redact.ts +2 -4
  939. package/src/util/logs-db-path.ts +22 -0
  940. package/src/util/memory-db-path.ts +23 -0
  941. package/src/util/platform.ts +5 -0
  942. package/src/watcher/providers/gmail.ts +7 -2
  943. package/src/workflows/engine-integration.test.ts +1 -1
  944. package/src/workflows/engine.test.ts +1 -1
  945. package/src/workflows/engine.ts +22 -0
  946. package/src/workflows/fanout-load.test.ts +1 -1
  947. package/src/workflows/journal-store.test.ts +1 -1
  948. package/src/workflows/leaf-runner.test.ts +40 -1
  949. package/src/workflows/leaf-runner.ts +26 -1
  950. package/src/workspace/git-service.ts +144 -29
  951. package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
  952. package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
  953. package/src/workspace/migrations/registry.ts +4 -0
  954. package/src/workspace/migrations/runner.ts +32 -2
  955. package/src/__tests__/access-request-decision.test.ts +0 -375
  956. package/src/__tests__/guardian-grant-minting.test.ts +0 -607
  957. package/src/__tests__/plugin-source-watcher.test.ts +0 -302
  958. package/src/api/events/turn-profile-auto-routed.ts +0 -28
  959. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
  960. package/src/daemon/plugin-source-watcher.ts +0 -278
  961. package/src/daemon/switch-inference-profile-tool.ts +0 -62
  962. package/src/memory/guardian-approvals.ts +0 -361
  963. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
  964. package/src/memory/migrations/038-actor-token-records.ts +0 -45
  965. package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
  966. package/src/memory/migrations/103-complex-migrations.ts +0 -23
  967. package/src/memory/migrations/113-late-migrations.ts +0 -30
  968. package/src/memory/migrations/index.ts +0 -301
  969. package/src/runtime/routes/access-request-decision.ts +0 -297
  970. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
  971. package/src/runtime/routes/channel-guardian-routes.ts +0 -19
  972. package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
@@ -61,6 +61,36 @@ mock.module("../runtime/gateway-client.js", () => ({
61
61
  },
62
62
  }));
63
63
 
64
+ // Guardian identity for the access request resolves via the gateway delivery
65
+ // reader, not the local contacts DB. Seed it per-test via seedGatewayGuardian.
66
+ interface GatewayGuardian {
67
+ channelType: string;
68
+ contactId: string;
69
+ principalId?: string | null;
70
+ displayName?: string | null;
71
+ address: string;
72
+ externalChatId?: string | null;
73
+ status: string;
74
+ verifiedAt?: number | null;
75
+ }
76
+ let gatewayGuardians: GatewayGuardian[] = [];
77
+ mock.module("../contacts/guardian-delivery-reader.js", () => ({
78
+ getGuardianDelivery: async () => gatewayGuardians,
79
+ guardianForChannel: (list: GatewayGuardian[], channelType: string) =>
80
+ list.find((g) => g.channelType === channelType && g.status === "active"),
81
+ }));
82
+
83
+ function seedGatewayGuardian(g: Partial<GatewayGuardian> & {
84
+ channelType: string;
85
+ address: string;
86
+ }): void {
87
+ gatewayGuardians.push({
88
+ contactId: `c-${g.channelType}`,
89
+ status: "active",
90
+ ...g,
91
+ });
92
+ }
93
+
64
94
  import {
65
95
  listCanonicalGuardianDeliveries,
66
96
  listCanonicalGuardianRequests,
@@ -71,7 +101,7 @@ import { notifyGuardianOfAccessRequest } from "../runtime/access-request-helper.
71
101
  import { handleChannelInbound } from "./helpers/channel-test-adapter.js";
72
102
  import { createGuardianBinding } from "./helpers/create-guardian-binding.js";
73
103
 
74
- initializeDb();
104
+ await initializeDb();
75
105
 
76
106
  // ---------------------------------------------------------------------------
77
107
  // Helpers
@@ -86,7 +116,6 @@ const TEST_BEARER_TOKEN = "test-token";
86
116
  */
87
117
  function resetState(): string {
88
118
  const db = getDb();
89
- db.run("DELETE FROM channel_guardian_approval_requests");
90
119
  db.run("DELETE FROM channel_inbound_events");
91
120
  db.run("DELETE FROM conversations");
92
121
  db.run("DELETE FROM notification_events");
@@ -96,6 +125,7 @@ function resetState(): string {
96
125
  db.run("DELETE FROM contacts");
97
126
  emitSignalCalls.length = 0;
98
127
  deliverReplyCalls.length = 0;
128
+ gatewayGuardians = [];
99
129
  mockEmitResult = {
100
130
  signalId: "mock-signal-id",
101
131
  deduplicated: false,
@@ -103,8 +133,15 @@ function resetState(): string {
103
133
  reason: "mock",
104
134
  deliveryResults: [],
105
135
  };
106
- // Seed the vellum anchor binding (gateway does this at startup in production)
136
+ // Seed the vellum anchor binding in the gateway list (gateway does this at
137
+ // startup in production). The DB write mirrors it for any local INFO reads.
107
138
  const principalId = `vellum-principal-${crypto.randomUUID()}`;
139
+ seedGatewayGuardian({
140
+ channelType: "vellum",
141
+ address: principalId,
142
+ principalId,
143
+ displayName: principalId,
144
+ });
108
145
  createGuardianBinding({
109
146
  channel: "vellum",
110
147
  guardianExternalUserId: principalId,
@@ -173,6 +210,12 @@ describe("non-member access request notification", () => {
173
210
 
174
211
  test("guardian is notified when a non-member messages and a guardian binding exists", async () => {
175
212
  // Set up a guardian binding for this channel using the anchor principal
213
+ seedGatewayGuardian({
214
+ channelType: "telegram",
215
+ address: "guardian-user-789",
216
+ externalChatId: "guardian-chat-789",
217
+ principalId: anchorPrincipalId,
218
+ });
176
219
  createGuardianBinding({
177
220
  channel: "telegram",
178
221
  guardianExternalUserId: "guardian-user-789",
@@ -218,6 +261,12 @@ describe("non-member access request notification", () => {
218
261
  });
219
262
 
220
263
  test("no duplicate approval requests for repeated messages from same non-member", async () => {
264
+ seedGatewayGuardian({
265
+ channelType: "telegram",
266
+ address: "guardian-user-789",
267
+ externalChatId: "guardian-chat-789",
268
+ principalId: anchorPrincipalId,
269
+ });
221
270
  createGuardianBinding({
222
271
  channel: "telegram",
223
272
  guardianExternalUserId: "guardian-user-789",
@@ -290,6 +339,12 @@ describe("non-member access request notification", () => {
290
339
  // Only a voice guardian binding exists — no Telegram binding.
291
340
  // Since cross-channel fallback was removed, the access request resolves
292
341
  // to the assistant's vellum anchor identity instead.
342
+ seedGatewayGuardian({
343
+ channelType: "phone",
344
+ address: "guardian-voice-user",
345
+ externalChatId: "guardian-voice-chat",
346
+ principalId: anchorPrincipalId,
347
+ });
293
348
  createGuardianBinding({
294
349
  channel: "phone",
295
350
  guardianExternalUserId: "guardian-voice-user",
@@ -352,8 +407,8 @@ describe("access-request-helper unit tests", () => {
352
407
  anchorPrincipalId = resetState();
353
408
  });
354
409
 
355
- test("notifyGuardianOfAccessRequest returns no_sender_id when actorExternalId is absent", () => {
356
- const result = notifyGuardianOfAccessRequest({
410
+ test("notifyGuardianOfAccessRequest returns no_sender_id when actorExternalId is absent", async () => {
411
+ const result = await notifyGuardianOfAccessRequest({
357
412
  canonicalAssistantId: "self",
358
413
  sourceChannel: "telegram",
359
414
  conversationExternalId: "chat-123",
@@ -373,8 +428,8 @@ describe("access-request-helper unit tests", () => {
373
428
  expect(pending.length).toBe(0);
374
429
  });
375
430
 
376
- test("notifyGuardianOfAccessRequest creates request with self-healed principal when no binding exists", () => {
377
- const result = notifyGuardianOfAccessRequest({
431
+ test("notifyGuardianOfAccessRequest creates request with self-healed principal when no binding exists", async () => {
432
+ const result = await notifyGuardianOfAccessRequest({
378
433
  canonicalAssistantId: "self",
379
434
  sourceChannel: "telegram",
380
435
  conversationExternalId: "chat-123",
@@ -401,8 +456,14 @@ describe("access-request-helper unit tests", () => {
401
456
  expect(emitSignalCalls.length).toBe(1);
402
457
  });
403
458
 
404
- test("notifyGuardianOfAccessRequest falls back to assistant-anchored vellum identity when source-channel binding is missing", () => {
459
+ test("notifyGuardianOfAccessRequest falls back to assistant-anchored vellum identity when source-channel binding is missing", async () => {
405
460
  // Only voice binding exists
461
+ seedGatewayGuardian({
462
+ channelType: "phone",
463
+ address: "guardian-voice",
464
+ externalChatId: "voice-chat",
465
+ principalId: "test-principal-id",
466
+ });
406
467
  createGuardianBinding({
407
468
  channel: "phone",
408
469
  guardianExternalUserId: "guardian-voice",
@@ -411,7 +472,7 @@ describe("access-request-helper unit tests", () => {
411
472
  verifiedVia: "test",
412
473
  });
413
474
 
414
- const result = notifyGuardianOfAccessRequest({
475
+ const result = await notifyGuardianOfAccessRequest({
415
476
  canonicalAssistantId: "self",
416
477
  sourceChannel: "telegram",
417
478
  conversationExternalId: "tg-chat",
@@ -436,8 +497,20 @@ describe("access-request-helper unit tests", () => {
436
497
  expect(payload.guardianBindingChannel).toBe("vellum");
437
498
  });
438
499
 
439
- test("notifyGuardianOfAccessRequest prefers source-channel binding over vellum anchor", () => {
500
+ test("notifyGuardianOfAccessRequest prefers source-channel binding over vellum anchor", async () => {
440
501
  // Both Telegram and voice bindings exist with the anchor principal
502
+ seedGatewayGuardian({
503
+ channelType: "telegram",
504
+ address: "guardian-tg",
505
+ externalChatId: "tg-chat",
506
+ principalId: anchorPrincipalId,
507
+ });
508
+ seedGatewayGuardian({
509
+ channelType: "phone",
510
+ address: "guardian-voice",
511
+ externalChatId: "voice-chat",
512
+ principalId: anchorPrincipalId,
513
+ });
441
514
  createGuardianBinding({
442
515
  channel: "telegram",
443
516
  guardianExternalUserId: "guardian-tg",
@@ -453,7 +526,7 @@ describe("access-request-helper unit tests", () => {
453
526
  verifiedVia: "test",
454
527
  });
455
528
 
456
- const result = notifyGuardianOfAccessRequest({
529
+ const result = await notifyGuardianOfAccessRequest({
457
530
  canonicalAssistantId: "self",
458
531
  sourceChannel: "telegram",
459
532
  conversationExternalId: "chat-123",
@@ -478,8 +551,100 @@ describe("access-request-helper unit tests", () => {
478
551
  expect(payload.guardianBindingChannel).toBe("telegram");
479
552
  });
480
553
 
481
- test("notifyGuardianOfAccessRequest for voice channel includes actorDisplayName in contextPayload", () => {
482
- const result = notifyGuardianOfAccessRequest({
554
+ test("notifyGuardianOfAccessRequest falls back to local source-channel binding when gateway delivery is empty", async () => {
555
+ // Gateway delivery read yields nothing (restart/timeout/malformed IPC).
556
+ gatewayGuardians = [];
557
+ // Local dual-written mirror still has the vellum anchor + telegram binding.
558
+ createGuardianBinding({
559
+ channel: "telegram",
560
+ guardianExternalUserId: "guardian-tg",
561
+ guardianDeliveryChatId: "tg-chat",
562
+ guardianPrincipalId: anchorPrincipalId,
563
+ verifiedVia: "test",
564
+ });
565
+
566
+ const result = await notifyGuardianOfAccessRequest({
567
+ canonicalAssistantId: "self",
568
+ sourceChannel: "telegram",
569
+ conversationExternalId: "chat-123",
570
+ actorExternalId: "unknown-user",
571
+ });
572
+
573
+ expect(result.notified).toBe(true);
574
+
575
+ const pending = listCanonicalGuardianRequests({
576
+ status: "pending",
577
+ requesterExternalUserId: "unknown-user",
578
+ kind: "access_request",
579
+ });
580
+ expect(pending.length).toBe(1);
581
+ // Request is decidable: local read supplied the principal + source binding.
582
+ expect(pending[0].guardianPrincipalId).toBe(anchorPrincipalId);
583
+ expect(pending[0].guardianExternalUserId).toBe("guardian-tg");
584
+
585
+ const payload = emitSignalCalls[0].contextPayload as Record<
586
+ string,
587
+ unknown
588
+ >;
589
+ expect(payload.guardianBindingChannel).toBe("telegram");
590
+ });
591
+
592
+ test("notifyGuardianOfAccessRequest falls back to local vellum anchor when gateway delivery is empty", async () => {
593
+ // Gateway empty; only the local vellum anchor from resetState remains.
594
+ gatewayGuardians = [];
595
+
596
+ const result = await notifyGuardianOfAccessRequest({
597
+ canonicalAssistantId: "self",
598
+ sourceChannel: "telegram",
599
+ conversationExternalId: "chat-123",
600
+ actorExternalId: "unknown-user",
601
+ });
602
+
603
+ expect(result.notified).toBe(true);
604
+
605
+ const pending = listCanonicalGuardianRequests({
606
+ status: "pending",
607
+ requesterExternalUserId: "unknown-user",
608
+ kind: "access_request",
609
+ });
610
+ expect(pending.length).toBe(1);
611
+ // Decidable via the local vellum anchor principal.
612
+ expect(pending[0].guardianPrincipalId).toBe(anchorPrincipalId);
613
+
614
+ const payload = emitSignalCalls[0].contextPayload as Record<
615
+ string,
616
+ unknown
617
+ >;
618
+ expect(payload.guardianBindingChannel).toBe("vellum");
619
+ });
620
+
621
+ test("notifyGuardianOfAccessRequest does not create a decisionable request when both gateway and local reads are empty", async () => {
622
+ // Genuinely unbound assistant: gateway empty AND no local binding. Prior
623
+ // behavior rejects creation of a decisionable request without a principal.
624
+ gatewayGuardians = [];
625
+ const db = getDb();
626
+ db.run("DELETE FROM contact_channels");
627
+ db.run("DELETE FROM contacts");
628
+
629
+ await expect(
630
+ notifyGuardianOfAccessRequest({
631
+ canonicalAssistantId: "self",
632
+ sourceChannel: "telegram",
633
+ conversationExternalId: "chat-123",
634
+ actorExternalId: "unknown-user",
635
+ }),
636
+ ).rejects.toThrow();
637
+
638
+ const pending = listCanonicalGuardianRequests({
639
+ status: "pending",
640
+ requesterExternalUserId: "unknown-user",
641
+ kind: "access_request",
642
+ });
643
+ expect(pending.length).toBe(0);
644
+ });
645
+
646
+ test("notifyGuardianOfAccessRequest for voice channel includes actorDisplayName in contextPayload", async () => {
647
+ const result = await notifyGuardianOfAccessRequest({
483
648
  canonicalAssistantId: "self",
484
649
  sourceChannel: "phone",
485
650
  conversationExternalId: "+15559998888",
@@ -509,8 +674,8 @@ describe("access-request-helper unit tests", () => {
509
674
  expect(pending.length).toBe(1);
510
675
  });
511
676
 
512
- test("notifyGuardianOfAccessRequest includes requestCode in contextPayload", () => {
513
- const result = notifyGuardianOfAccessRequest({
677
+ test("notifyGuardianOfAccessRequest includes requestCode in contextPayload", async () => {
678
+ const result = await notifyGuardianOfAccessRequest({
514
679
  canonicalAssistantId: "self",
515
680
  sourceChannel: "telegram",
516
681
  conversationExternalId: "chat-123",
@@ -530,8 +695,8 @@ describe("access-request-helper unit tests", () => {
530
695
  expect((payload.requestCode as string).length).toBe(6);
531
696
  });
532
697
 
533
- test("notifyGuardianOfAccessRequest includes previousMemberStatus in contextPayload", () => {
534
- const result = notifyGuardianOfAccessRequest({
698
+ test("notifyGuardianOfAccessRequest includes previousMemberStatus in contextPayload", async () => {
699
+ const result = await notifyGuardianOfAccessRequest({
535
700
  canonicalAssistantId: "self",
536
701
  sourceChannel: "telegram",
537
702
  conversationExternalId: "chat-123",
@@ -571,7 +736,7 @@ describe("access-request-helper unit tests", () => {
571
736
  ],
572
737
  };
573
738
 
574
- const result = notifyGuardianOfAccessRequest({
739
+ const result = await notifyGuardianOfAccessRequest({
575
740
  canonicalAssistantId: "self",
576
741
  sourceChannel: "phone",
577
742
  conversationExternalId: "+15556667777",
@@ -604,6 +769,12 @@ describe("access-request-helper unit tests", () => {
604
769
  // Set up a telegram guardian binding with the anchor principal so
605
770
  // guardianResolutionSource resolves to "source-channel-contact" and
606
771
  // sameChannelOnly is true.
772
+ seedGatewayGuardian({
773
+ channelType: "telegram",
774
+ address: "guardian-user-456",
775
+ externalChatId: "guardian-chat-456",
776
+ principalId: anchorPrincipalId,
777
+ });
607
778
  createGuardianBinding({
608
779
  channel: "telegram",
609
780
  guardianExternalUserId: "guardian-user-456",
@@ -626,7 +797,7 @@ describe("access-request-helper unit tests", () => {
626
797
  ],
627
798
  };
628
799
 
629
- const result = notifyGuardianOfAccessRequest({
800
+ const result = await notifyGuardianOfAccessRequest({
630
801
  canonicalAssistantId: "self",
631
802
  sourceChannel: "telegram",
632
803
  conversationExternalId: "chat-123",
@@ -24,6 +24,10 @@ mock.module("../util/logger.js", () => ({
24
24
  }),
25
25
  }));
26
26
 
27
+ mock.module("../contacts/guardian-delivery-reader.js", () => ({
28
+ getGuardianDelivery: async () => null,
29
+ }));
30
+
27
31
  // Mock destination-resolver to return a destination for every requested channel.
28
32
  // External channels (telegram, slack) include bindingContext.
29
33
  mock.module("../notifications/destination-resolver.js", () => ({
@@ -0,0 +1,203 @@
1
+ /**
2
+ * DB-backed tests for guardian-context enrichment of notification conversation
3
+ * candidates.
4
+ *
5
+ * `buildConversationCandidates` counts each candidate's pending guardian
6
+ * requests through the canonical store's conversation-scope query, which
7
+ * matches both a request's source conversation and any conversation its card
8
+ * was delivered to. These tests lock that wiring — in particular that a
9
+ * request delivered to a conversation different from its synthetic source is
10
+ * still counted for the conversation that shows the card.
11
+ */
12
+
13
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
14
+
15
+ mock.module("../util/logger.js", () => ({
16
+ getLogger: () =>
17
+ new Proxy({} as Record<string, unknown>, {
18
+ get: () => () => {},
19
+ }),
20
+ }));
21
+
22
+ import {
23
+ createCanonicalGuardianDelivery,
24
+ createCanonicalGuardianRequest,
25
+ resolveCanonicalGuardianRequest,
26
+ } from "../memory/canonical-guardian-store.js";
27
+ import { getDb } from "../memory/db-connection.js";
28
+ import { initializeDb } from "../memory/db-init.js";
29
+ import { conversations } from "../memory/schema.js";
30
+ import { recordGuardianRequestDeliveries } from "../notifications/canonical-delivery-recorder.js";
31
+ import { buildConversationCandidates } from "../notifications/conversation-candidates.js";
32
+ import { createDecision } from "../notifications/decisions-store.js";
33
+ import { createDelivery } from "../notifications/deliveries-store.js";
34
+ import { createEvent } from "../notifications/events-store.js";
35
+ import type { NotificationChannel } from "../notifications/types.js";
36
+
37
+ await initializeDb();
38
+
39
+ const TEST_PRINCIPAL = "test-principal-id";
40
+ const CHANNEL = "vellum" as NotificationChannel;
41
+
42
+ function resetTables(): void {
43
+ const db = getDb();
44
+ db.run("DELETE FROM canonical_guardian_deliveries");
45
+ db.run("DELETE FROM canonical_guardian_requests");
46
+ db.run("DELETE FROM notification_deliveries");
47
+ db.run("DELETE FROM notification_decisions");
48
+ db.run("DELETE FROM notification_events");
49
+ db.run("DELETE FROM conversations");
50
+ }
51
+
52
+ /**
53
+ * Seed a conversation the candidate builder will surface: a "sent" notification
54
+ * delivery wired event -> decision -> delivery -> conversation on `channel`.
55
+ */
56
+ function seedCandidateConversation(
57
+ conversationId: string,
58
+ channel: NotificationChannel = CHANNEL,
59
+ ): void {
60
+ const db = getDb();
61
+ const now = Date.now();
62
+ db.insert(conversations)
63
+ .values({
64
+ id: conversationId,
65
+ title: "Test thread",
66
+ createdAt: now,
67
+ updatedAt: now,
68
+ })
69
+ .run();
70
+
71
+ const eventId = `evt-${conversationId}`;
72
+ const decisionId = `dec-${conversationId}`;
73
+ createEvent({
74
+ id: eventId,
75
+ sourceEventName: "schedule.notify",
76
+ sourceChannel: channel,
77
+ sourceContextId: conversationId,
78
+ attentionHints: {
79
+ requiresAction: false,
80
+ urgency: "low",
81
+ isAsyncBackground: false,
82
+ visibleInSourceNow: false,
83
+ },
84
+ payload: {},
85
+ });
86
+ createDecision({
87
+ id: decisionId,
88
+ notificationEventId: eventId,
89
+ shouldNotify: true,
90
+ selectedChannels: [channel],
91
+ reasoningSummary: "test",
92
+ confidence: 1,
93
+ fallbackUsed: false,
94
+ });
95
+ createDelivery({
96
+ id: `del-${conversationId}`,
97
+ notificationDecisionId: decisionId,
98
+ channel,
99
+ destination: "dest",
100
+ status: "sent",
101
+ attempt: 1,
102
+ sentAt: now,
103
+ conversationId,
104
+ });
105
+ }
106
+
107
+ function candidateFor(
108
+ conversationId: string,
109
+ channel: NotificationChannel = CHANNEL,
110
+ ) {
111
+ const set = buildConversationCandidates([channel]);
112
+ return set[channel]?.find((c) => c.conversationId === conversationId);
113
+ }
114
+
115
+ describe("buildConversationCandidates guardian enrichment", () => {
116
+ beforeEach(() => {
117
+ resetTables();
118
+ });
119
+
120
+ test("counts pending requests via both source and delivery conversation scope", () => {
121
+ const convId = "conv-guardian";
122
+ seedCandidateConversation(convId);
123
+
124
+ // (1) pending request whose SOURCE conversation is the candidate.
125
+ createCanonicalGuardianRequest({
126
+ kind: "tool_approval",
127
+ sourceType: "channel",
128
+ conversationId: convId,
129
+ guardianPrincipalId: TEST_PRINCIPAL,
130
+ });
131
+
132
+ // (2) pending request with a synthetic source id whose card was DELIVERED
133
+ // to the candidate conversation (a different conversation than its source).
134
+ const delivered = createCanonicalGuardianRequest({
135
+ kind: "access_request",
136
+ sourceType: "channel",
137
+ conversationId: "access-req-xyz",
138
+ guardianPrincipalId: TEST_PRINCIPAL,
139
+ });
140
+ createCanonicalGuardianDelivery({
141
+ requestId: delivered.id,
142
+ destinationChannel: CHANNEL,
143
+ destinationConversationId: convId,
144
+ });
145
+
146
+ expect(
147
+ candidateFor(convId)?.guardianContext?.pendingUnresolvedRequestCount,
148
+ ).toBe(2);
149
+ });
150
+
151
+ test("omits guardian context when the conversation's only request is resolved", () => {
152
+ const convId = "conv-resolved";
153
+ seedCandidateConversation(convId);
154
+
155
+ const req = createCanonicalGuardianRequest({
156
+ kind: "tool_approval",
157
+ sourceType: "channel",
158
+ conversationId: convId,
159
+ guardianPrincipalId: TEST_PRINCIPAL,
160
+ });
161
+ resolveCanonicalGuardianRequest(req.id, "pending", { status: "approved" });
162
+
163
+ // The conversation still surfaces as a candidate (it had a delivery), but
164
+ // with no guardian context since nothing is pending.
165
+ const candidate = candidateFor(convId);
166
+ expect(candidate).toBeDefined();
167
+ expect(candidate?.guardianContext).toBeUndefined();
168
+ });
169
+
170
+ test("counts a Slack channel card recorded through the real recorder", () => {
171
+ const SLACK = "slack" as NotificationChannel;
172
+ const convId = "conv-slack-card";
173
+ seedCandidateConversation(convId, SLACK);
174
+
175
+ // Channel-only access request: a synthetic source conversation, card
176
+ // delivered to a Slack chat. The recorder records the card's internal
177
+ // conversation, so the Slack candidate counts it.
178
+ const req = createCanonicalGuardianRequest({
179
+ kind: "access_request",
180
+ sourceType: "channel",
181
+ sourceChannel: "slack",
182
+ conversationId: "access-req-synthetic",
183
+ guardianPrincipalId: TEST_PRINCIPAL,
184
+ });
185
+ recordGuardianRequestDeliveries({
186
+ requestId: req.id,
187
+ deliveryResults: [
188
+ {
189
+ channel: "slack",
190
+ destination: "slack-chat-1",
191
+ status: "sent",
192
+ conversationId: convId,
193
+ messageId: "ts-1",
194
+ },
195
+ ],
196
+ });
197
+
198
+ expect(
199
+ candidateFor(convId, SLACK)?.guardianContext
200
+ ?.pendingUnresolvedRequestCount,
201
+ ).toBe(1);
202
+ });
203
+ });
@@ -36,17 +36,36 @@ mock.module("../prompts/system-prompt.js", () => ({
36
36
  buildCoreIdentityContext: () => null,
37
37
  }));
38
38
 
39
- // ── Guardian contact mock ────────────────────────────────────────────
39
+ // ── Guardian binding + contact notes mocks ───────────────────────────
40
40
 
41
- let mockGuardianResult: {
42
- contact: { notes: string | null };
43
- channels: Record<string, unknown>[];
44
- } | null = null;
41
+ // Guardian binding (ACL) is resolved via the gateway pull; notes (INFO) are
42
+ // joined locally by contactId. Tests drive both via mutable slots.
43
+ let guardianDeliveryFixture: Array<{ contactId: string }> = [];
44
+ let contactInfoFixture: Record<string, { notes: string | null } | null> = {};
45
+
46
+ mock.module("../contacts/guardian-delivery-reader.js", () => ({
47
+ getGuardianDelivery: async () => guardianDeliveryFixture,
48
+ anyGuardian: (list: Array<{ contactId: string }>) => list[0],
49
+ }));
45
50
 
46
51
  mock.module("../contacts/contact-store.js", () => ({
47
- listGuardianChannels: () => mockGuardianResult,
52
+ findContactInfoById: (contactId: string) =>
53
+ contactInfoFixture[contactId] ?? null,
48
54
  }));
49
55
 
56
+ const GUARDIAN_CONTACT_ID = "guardian-contact-1";
57
+
58
+ /** Bind a guardian with the given notes (or no guardian when notes is null). */
59
+ function setGuardian(notes: string | null | undefined): void {
60
+ if (notes === undefined) {
61
+ guardianDeliveryFixture = [];
62
+ contactInfoFixture = {};
63
+ return;
64
+ }
65
+ guardianDeliveryFixture = [{ contactId: GUARDIAN_CONTACT_ID }];
66
+ contactInfoFixture = { [GUARDIAN_CONTACT_ID]: { notes } };
67
+ }
68
+
50
69
  // ── Provider mock with system prompt capture ──────────────────────────
51
70
 
52
71
  let configuredProvider: {
@@ -134,15 +153,12 @@ describe("recipient context in notification decision engine", () => {
134
153
  beforeEach(() => {
135
154
  configuredProvider = null;
136
155
  extractedToolUse = null;
137
- mockGuardianResult = null;
156
+ setGuardian(undefined);
138
157
  capturedSystemPrompt = undefined;
139
158
  });
140
159
 
141
160
  test("guardian contact notes appear in system prompt as <recipient-context>", async () => {
142
- mockGuardianResult = {
143
- contact: { notes: "Prefers formal tone. Address as Dr. Smith." },
144
- channels: [{ type: "vellum" }],
145
- };
161
+ setGuardian("Prefers formal tone. Address as Dr. Smith.");
146
162
  setupLLMProvider();
147
163
 
148
164
  const signal = makeSignal();
@@ -157,7 +173,7 @@ describe("recipient context in notification decision engine", () => {
157
173
  });
158
174
 
159
175
  test("recipient-context is omitted when no guardian exists", async () => {
160
- mockGuardianResult = null;
176
+ setGuardian(undefined);
161
177
  setupLLMProvider();
162
178
 
163
179
  const signal = makeSignal();
@@ -169,10 +185,7 @@ describe("recipient context in notification decision engine", () => {
169
185
  });
170
186
 
171
187
  test("recipient-context is omitted when guardian notes are null", async () => {
172
- mockGuardianResult = {
173
- contact: { notes: null },
174
- channels: [{ type: "vellum" }],
175
- };
188
+ setGuardian(null);
176
189
  setupLLMProvider();
177
190
 
178
191
  const signal = makeSignal();
@@ -184,10 +197,7 @@ describe("recipient context in notification decision engine", () => {
184
197
  });
185
198
 
186
199
  test("recipient-context is omitted when guardian notes are empty string", async () => {
187
- mockGuardianResult = {
188
- contact: { notes: "" },
189
- channels: [{ type: "vellum" }],
190
- };
200
+ setGuardian("");
191
201
  setupLLMProvider();
192
202
 
193
203
  const signal = makeSignal();
@@ -199,10 +209,7 @@ describe("recipient context in notification decision engine", () => {
199
209
  });
200
210
 
201
211
  test("large guardian notes are truncated to prevent oversized prompts", async () => {
202
- mockGuardianResult = {
203
- contact: { notes: "N".repeat(3000) },
204
- channels: [{ type: "vellum" }],
205
- };
212
+ setGuardian("N".repeat(3000));
206
213
  setupLLMProvider();
207
214
 
208
215
  const signal = makeSignal();
@@ -226,10 +233,7 @@ describe("recipient context in notification decision engine", () => {
226
233
  });
227
234
 
228
235
  test("fallback path works correctly without recipient context", async () => {
229
- mockGuardianResult = {
230
- contact: { notes: "Prefers formal tone." },
231
- channels: [{ type: "vellum" }],
232
- };
236
+ setGuardian("Prefers formal tone.");
233
237
  // null provider forces fallback path
234
238
  configuredProvider = null;
235
239
 
@@ -247,10 +251,7 @@ describe("recipient context in notification decision engine", () => {
247
251
  });
248
252
 
249
253
  test("recipient-context appears after user-preferences in prompt", async () => {
250
- mockGuardianResult = {
251
- contact: { notes: "Prefers brief updates." },
252
- channels: [{ type: "vellum" }],
253
- };
254
+ setGuardian("Prefers brief updates.");
254
255
  setupLLMProvider();
255
256
 
256
257
  const signal = makeSignal();