@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2

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 (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -38,7 +38,6 @@ mock.module("../runtime/assistant-event-hub.js", () => ({
38
38
 
39
39
  const {
40
40
  DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT,
41
- DISK_PRESSURE_MIN_FREE_FLOOR_MB,
42
41
  DISK_PRESSURE_OVERRIDE_CONFIRMATION,
43
42
  DISK_PRESSURE_THRESHOLD_PERCENT,
44
43
  DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT,
@@ -343,44 +342,4 @@ describe("disk pressure guard", () => {
343
342
  setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT - 1);
344
343
  expect(evaluateDiskPressureNow().state).toBe("ok");
345
344
  });
346
-
347
- test("stays ok at a critical usage percentage while ample free space remains", () => {
348
- // 99% used of a large volume still leaves gigabytes free — above the floor.
349
- const totalMb = 1_000_000;
350
- const usedMb = Math.round(totalMb * 0.99); // freeMb ~= 10_000 MiB
351
- setDiskUsage(usedMb, totalMb);
352
- expect(diskSample!.freeMb).toBeGreaterThanOrEqual(
353
- DISK_PRESSURE_MIN_FREE_FLOOR_MB,
354
- );
355
-
356
- const status = evaluateDiskPressureNow();
357
-
358
- expect(status.state).toBe("ok");
359
- expect(status.locked).toBe(false);
360
- expect(status.effectivelyLocked).toBe(false);
361
- });
362
-
363
- test("stays ok at a warning usage percentage while ample free space remains", () => {
364
- const totalMb = 1_000_000;
365
- const usedMb = Math.round(totalMb * 0.85); // 85% used, freeMb ~= 150_000 MiB
366
- setDiskUsage(usedMb, totalMb);
367
-
368
- const status = evaluateDiskPressureNow();
369
-
370
- expect(status.state).toBe("ok");
371
- });
372
-
373
- test("locks at a critical usage percentage once free space drops below the floor", () => {
374
- // High percentage AND little absolute headroom: floor does not apply.
375
- const totalMb = 100_000;
376
- const freeMb = DISK_PRESSURE_MIN_FREE_FLOOR_MB - 1;
377
- setDiskUsage(totalMb - freeMb, totalMb);
378
- expect(diskSample!.freeMb).toBeLessThan(DISK_PRESSURE_MIN_FREE_FLOOR_MB);
379
-
380
- const status = evaluateDiskPressureNow();
381
-
382
- expect(status.state).toBe("critical");
383
- expect(status.locked).toBe(true);
384
- expect(status.effectivelyLocked).toBe(true);
385
- });
386
345
  });
@@ -30,8 +30,6 @@ const addMessageCalls: Array<{
30
30
  }> = [];
31
31
 
32
32
  mock.module("../memory/conversation-crud.js", () => ({
33
- setConversationProcessingStartedAt: () => {},
34
- isConversationProcessing: () => false,
35
33
  addMessage: async (
36
34
  conversationId: string,
37
35
  role: string,
@@ -19,19 +19,14 @@ mock.module("../channels/config.js", () => ({
19
19
  getDeliverableChannels: () => ["vellum", "telegram"],
20
20
  }));
21
21
 
22
- // Guardian connectivity is resolved from the gateway pull. No active guardian
23
- // binding ⇒ binding-based channels (telegram) are not reported connected.
24
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
25
- getGuardianDelivery: async () => [],
26
- guardianForChannel: () => undefined,
27
- }));
28
-
29
- // connectivity falls back to the local contacts read on a per-channel gateway
30
- // no-match; no local binding ⇒ telegram stays disconnected.
31
22
  mock.module("../contacts/contact-store.js", () => ({
32
- findGuardianForChannel: () => null,
23
+ findGuardianForChannel: (_channelType: string, _assistantId: string) => null,
33
24
  }));
34
25
 
26
+ // Note: stale mock for channel-guardian-store.js removed — the barrel was
27
+ // deleted and none of the functions it mocked (getActiveBinding) existed in
28
+ // the barrel.
29
+
35
30
  mock.module("../notifications/adapters/macos.js", () => ({
36
31
  VellumAdapter: class {
37
32
  constructor(_broadcastFn: unknown) {}
@@ -29,13 +29,7 @@ mock.module("../config/env.js", () => ({
29
29
  }));
30
30
 
31
31
  mock.module("../runtime/local-actor-identity.js", () => ({
32
- findLocalGuardianPrincipalIdFromStore: () => fakeGuardianPrincipalId,
33
- resolveActorPrincipalIdForLocalGuardianSync: (
34
- rawHeader: string | undefined,
35
- ) => {
36
- if (rawHeader !== "dev-bypass" || !fakeHttpAuthDisabled) return rawHeader;
37
- return fakeGuardianPrincipalId;
38
- },
32
+ findLocalGuardianPrincipalId: () => fakeGuardianPrincipalId,
39
33
  }));
40
34
 
41
35
  mock.module("../util/logger.js", () => ({
@@ -225,11 +225,10 @@ describe("exploration-drift post-tool-use hook — long-dig trigger", () => {
225
225
  expect(ctx.toolResponse.content).toBe(BASE_CONTENT);
226
226
  });
227
227
 
228
- test("counts code_search, file_read, and file_list as exploration tools", async () => {
229
- const explorationNames = ["code_search", "file_read", "file_list"];
228
+ test("counts file_read and file_list as exploration tools", async () => {
230
229
  const messages: Message[] = [];
231
230
  for (let i = 0; i < EXPLORATION_NUDGE_THRESHOLD - 1; i++) {
232
- const name = explorationNames[i % explorationNames.length];
231
+ const name = i % 2 === 0 ? "file_read" : "file_list";
233
232
  const id = `${name}-${i}`;
234
233
  messages.push(toolUseTurn(id, name, { path: `/tmp/file-${i}` }));
235
234
  messages.push(toolResultTurn(id));
@@ -51,8 +51,6 @@ const createdConversations: Array<{
51
51
  let conversationIdCounter = 0;
52
52
 
53
53
  mock.module("../memory/conversation-crud.js", () => ({
54
- setConversationProcessingStartedAt: () => {},
55
- isConversationProcessing: () => false,
56
54
  setConversationOriginChannelIfUnset: () => {},
57
55
  updateConversationContextWindow: () => {},
58
56
  deleteMessageById: () => {},
@@ -7,16 +7,6 @@ mock.module("../util/logger.js", () => ({
7
7
  }),
8
8
  }));
9
9
 
10
- import type { GuardianDelivery } from "@vellumai/gateway-client";
11
-
12
- let mockGuardians: GuardianDelivery[] | null = [];
13
-
14
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
15
- getGuardianDelivery: async () => mockGuardians,
16
- guardianForChannel: (list: GuardianDelivery[], channelType: string) =>
17
- list.find((g) => g.channelType === channelType && g.status === "active"),
18
- }));
19
-
20
10
  import { findGuardianForChannel } from "../contacts/contact-store.js";
21
11
  import { getDb } from "../memory/db-connection.js";
22
12
  import { initializeDb } from "../memory/db-init.js";
@@ -31,24 +21,12 @@ function resetTables(): void {
31
21
  db.run("DELETE FROM contacts");
32
22
  }
33
23
 
34
- /** Gateway delivery mirroring the local guardian binding's principal. */
35
- function gatewayGuardian(principalId: string): GuardianDelivery {
36
- return {
37
- channelType: "vellum",
38
- contactId: "guardian-contact",
39
- principalId,
40
- address: principalId,
41
- status: "active",
42
- };
43
- }
44
-
45
24
  describe("healGuardianBindingDrift", () => {
46
25
  beforeEach(() => {
47
26
  resetTables();
48
- mockGuardians = [];
49
27
  });
50
28
 
51
- test("heals drift when both principals have vellum-principal- prefix", async () => {
29
+ test("heals drift when both principals have vellum-principal- prefix", () => {
52
30
  // Simulate DB reset: new guardian binding with a different UUID
53
31
  createGuardianBinding({
54
32
  channel: "vellum",
@@ -57,10 +35,9 @@ describe("healGuardianBindingDrift", () => {
57
35
  guardianPrincipalId: "vellum-principal-new-uuid",
58
36
  verifiedVia: "startup-migration",
59
37
  });
60
- mockGuardians = [gatewayGuardian("vellum-principal-new-uuid")];
61
38
 
62
39
  // Client arrives with the old JWT principal
63
- const healed = await healGuardianBindingDrift("vellum-principal-old-uuid");
40
+ const healed = healGuardianBindingDrift("vellum-principal-old-uuid");
64
41
  expect(healed).toBe(true);
65
42
 
66
43
  // Guardian binding now matches the old JWT
@@ -70,31 +47,7 @@ describe("healGuardianBindingDrift", () => {
70
47
  expect(guardian!.channel.address).toBe("vellum-principal-old-uuid");
71
48
  });
72
49
 
73
- test("repairs the stale local mirror even when the gateway already matches the JWT", async () => {
74
- // Gateway binding already matches the incoming JWT principal, but the
75
- // local mirror is stale — the gateway-source-of-truth drift mode. The
76
- // /v1/messages trust path still reads the local mirror in this plan, so
77
- // a stale row must be repaired or the actor stays classified `unknown`.
78
- createGuardianBinding({
79
- channel: "vellum",
80
- guardianExternalUserId: "vellum-principal-stale-local",
81
- guardianDeliveryChatId: "local",
82
- guardianPrincipalId: "vellum-principal-stale-local",
83
- verifiedVia: "startup-migration",
84
- });
85
- mockGuardians = [gatewayGuardian("vellum-principal-jwt")];
86
-
87
- const healed = await healGuardianBindingDrift("vellum-principal-jwt");
88
- expect(healed).toBe(true);
89
-
90
- // Local mirror now matches the JWT, so a subsequent local trust
91
- // resolution classifies the actor as guardian rather than unknown.
92
- const guardian = findGuardianForChannel("vellum");
93
- expect(guardian!.contact.principalId).toBe("vellum-principal-jwt");
94
- expect(guardian!.channel.address).toBe("vellum-principal-jwt");
95
- });
96
-
97
- test("no-op when principals already match", async () => {
50
+ test("no-op when principals already match", () => {
98
51
  createGuardianBinding({
99
52
  channel: "vellum",
100
53
  guardianExternalUserId: "vellum-principal-same",
@@ -102,13 +55,12 @@ describe("healGuardianBindingDrift", () => {
102
55
  guardianPrincipalId: "vellum-principal-same",
103
56
  verifiedVia: "startup-migration",
104
57
  });
105
- mockGuardians = [gatewayGuardian("vellum-principal-same")];
106
58
 
107
- const healed = await healGuardianBindingDrift("vellum-principal-same");
59
+ const healed = healGuardianBindingDrift("vellum-principal-same");
108
60
  expect(healed).toBe(false);
109
61
  });
110
62
 
111
- test("refuses to heal when incoming principal lacks vellum-principal- prefix", async () => {
63
+ test("refuses to heal when incoming principal lacks vellum-principal- prefix", () => {
112
64
  createGuardianBinding({
113
65
  channel: "vellum",
114
66
  guardianExternalUserId: "vellum-principal-aaa",
@@ -116,10 +68,9 @@ describe("healGuardianBindingDrift", () => {
116
68
  guardianPrincipalId: "vellum-principal-aaa",
117
69
  verifiedVia: "startup-migration",
118
70
  });
119
- mockGuardians = [gatewayGuardian("vellum-principal-aaa")];
120
71
 
121
72
  // External/platform principal — should NOT be adopted
122
- const healed = await healGuardianBindingDrift("platform-user-12345");
73
+ const healed = healGuardianBindingDrift("platform-user-12345");
123
74
  expect(healed).toBe(false);
124
75
 
125
76
  // Guardian unchanged
@@ -127,7 +78,7 @@ describe("healGuardianBindingDrift", () => {
127
78
  expect(guardian!.contact.principalId).toBe("vellum-principal-aaa");
128
79
  });
129
80
 
130
- test("refuses to heal when stored principal lacks vellum-principal- prefix", async () => {
81
+ test("refuses to heal when stored principal lacks vellum-principal- prefix", () => {
131
82
  createGuardianBinding({
132
83
  channel: "vellum",
133
84
  guardianExternalUserId: "verified-phone-guardian",
@@ -135,33 +86,17 @@ describe("healGuardianBindingDrift", () => {
135
86
  guardianPrincipalId: "verified-phone-guardian",
136
87
  verifiedVia: "challenge",
137
88
  });
138
- mockGuardians = [gatewayGuardian("verified-phone-guardian")];
139
89
 
140
90
  // Even with a vellum-principal- incoming, don't overwrite a real binding
141
- const healed = await healGuardianBindingDrift("vellum-principal-attacker");
91
+ const healed = healGuardianBindingDrift("vellum-principal-attacker");
142
92
  expect(healed).toBe(false);
143
93
 
144
94
  const guardian = findGuardianForChannel("vellum");
145
95
  expect(guardian!.contact.principalId).toBe("verified-phone-guardian");
146
96
  });
147
97
 
148
- test("returns false when gateway reports no guardian binding", async () => {
149
- mockGuardians = [];
150
- const healed = await healGuardianBindingDrift("vellum-principal-orphan");
151
- expect(healed).toBe(false);
152
- });
153
-
154
- test("returns false when the gateway is unreachable (null list)", async () => {
155
- createGuardianBinding({
156
- channel: "vellum",
157
- guardianExternalUserId: "vellum-principal-aaa",
158
- guardianDeliveryChatId: "local",
159
- guardianPrincipalId: "vellum-principal-aaa",
160
- verifiedVia: "startup-migration",
161
- });
162
- mockGuardians = null;
163
-
164
- const healed = await healGuardianBindingDrift("vellum-principal-old-uuid");
98
+ test("returns false when no guardian binding exists", () => {
99
+ const healed = healGuardianBindingDrift("vellum-principal-orphan");
165
100
  expect(healed).toBe(false);
166
101
  });
167
102
  });
@@ -24,11 +24,6 @@ mock.module("../config/loader.js", () => ({
24
24
  }),
25
25
  }));
26
26
 
27
- // The pending_question request principal is resolved via the SAME local source
28
- // the Vellum actor uses — findGuardianForChannel("vellum")?.contact.principalId
29
- // — so the stamped principal always equals the submitting actor principal. The
30
- // real contacts DB is seeded in resetTables(); tests model drift / missing
31
- // guardian by reseeding or clearing that local binding directly.
32
27
  const emitCalls: unknown[] = [];
33
28
  let conversationCreatedFromMock: ConversationCreatedInfo | null = null;
34
29
  let mockEmitResult: {
@@ -159,18 +154,11 @@ describe("guardian-dispatch", () => {
159
154
  "SELECT * FROM canonical_guardian_requests WHERE call_session_id = ?",
160
155
  )
161
156
  .get(session.id) as
162
- | {
163
- id: string;
164
- status: string;
165
- question_text: string;
166
- guardian_principal_id: string | null;
167
- }
157
+ | { id: string; status: string; question_text: string }
168
158
  | undefined;
169
159
  expect(request).toBeDefined();
170
160
  expect(request!.status).toBe("pending");
171
161
  expect(request!.question_text).toBe("What is the gate code?");
172
- // principalId comes from the local guardian binding (same source the actor submits)
173
- expect(request!.guardian_principal_id).toBe("test-principal-id");
174
162
 
175
163
  const vellumDelivery = raw
176
164
  .query(
@@ -187,88 +175,6 @@ describe("guardian-dispatch", () => {
187
175
  expect(typeof signalParams.onConversationCreated).toBe("function");
188
176
  });
189
177
 
190
- test("stamps the request principal from the local source the actor submits, not the (possibly drifted) gateway binding", async () => {
191
- // Simulate gateway/local binding drift: the local guardian binding (the
192
- // source the actor submit path reads) carries a different principal than
193
- // the gateway would. The request must be stamped with that local value so
194
- // a later actor submission matches (no identity_mismatch under drift).
195
- const db = getDb();
196
- db.run("DELETE FROM contact_channels");
197
- db.run("DELETE FROM contacts");
198
- createGuardianBinding({
199
- channel: "vellum",
200
- guardianExternalUserId: "local-actor-principal",
201
- guardianDeliveryChatId: "local",
202
- guardianPrincipalId: "local-actor-principal",
203
- verifiedVia: "bootstrap",
204
- });
205
-
206
- const convId = "conv-dispatch-drift";
207
- ensureConversation(convId);
208
-
209
- const session = createCallSession({
210
- conversationId: convId,
211
- provider: "twilio",
212
- fromNumber: "+15550001111",
213
- toNumber: "+15550002222",
214
- });
215
- const pq = createPendingQuestion(session.id, "Drifted bindings?");
216
-
217
- await dispatchGuardianQuestion({
218
- callSessionId: session.id,
219
- conversationId: convId,
220
- assistantId: "self",
221
- pendingQuestion: pq,
222
- });
223
-
224
- const raw = (db as unknown as { $client: import("bun:sqlite").Database })
225
- .$client;
226
- const request = raw
227
- .query(
228
- "SELECT * FROM canonical_guardian_requests WHERE call_session_id = ?",
229
- )
230
- .get(session.id) as
231
- | { guardian_principal_id: string | null }
232
- | undefined;
233
- expect(request).toBeDefined();
234
- expect(request!.guardian_principal_id).toBe("local-actor-principal");
235
- });
236
-
237
- test("skips dispatch when no local guardian binding exists (no principal to stamp)", async () => {
238
- const db = getDb();
239
- db.run("DELETE FROM contact_channels");
240
- db.run("DELETE FROM contacts");
241
-
242
- const convId = "conv-dispatch-no-principal";
243
- ensureConversation(convId);
244
-
245
- const session = createCallSession({
246
- conversationId: convId,
247
- provider: "twilio",
248
- fromNumber: "+15550001111",
249
- toNumber: "+15550002222",
250
- });
251
- const pq = createPendingQuestion(session.id, "No principal available");
252
-
253
- await dispatchGuardianQuestion({
254
- callSessionId: session.id,
255
- conversationId: convId,
256
- assistantId: "self",
257
- pendingQuestion: pq,
258
- });
259
-
260
- // No request is created and the pipeline is never invoked.
261
- const raw = (db as unknown as { $client: import("bun:sqlite").Database })
262
- .$client;
263
- const request = raw
264
- .query(
265
- "SELECT * FROM canonical_guardian_requests WHERE call_session_id = ?",
266
- )
267
- .get(session.id) as { id: string } | null;
268
- expect(request).toBeNull();
269
- expect(emitCalls).toHaveLength(0);
270
- });
271
-
272
178
  test("creates a telegram guardian delivery with binding metadata when pipeline sends telegram", async () => {
273
179
  const convId = "conv-dispatch-2";
274
180
  ensureConversation(convId);
@@ -84,19 +84,6 @@ globalThis.fetch = (async (
84
84
  return originalFetch(input, init as never);
85
85
  }) as unknown as typeof fetch;
86
86
 
87
- // Guardian-delivery reader mock — the inbound challenge guard reads guardian
88
- // existence from the gateway. These tests seed no binding, so report an empty
89
- // list (not bound) rather than a null that would fail closed as already-bound.
90
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
91
- getGuardianDelivery: async () => [],
92
- getGuardianDeliveryFresh: async () => [],
93
- guardianForChannel: (
94
- list: Array<{ channelType: string; status: string }>,
95
- channelType: string,
96
- ) =>
97
- list.find((g) => g.channelType === channelType && g.status === "active"),
98
- }));
99
-
100
87
  // ---------------------------------------------------------------------------
101
88
  // Now import modules under test (after mocks are in place)
102
89
  // ---------------------------------------------------------------------------
@@ -70,8 +70,6 @@ mock.module("../schedule/recurrence-engine.js", () => ({
70
70
 
71
71
  const createdConversations: Array<{ conversationType: string }> = [];
72
72
  mock.module("../memory/conversation-crud.js", () => ({
73
- setConversationProcessingStartedAt: () => {},
74
- isConversationProcessing: () => false,
75
73
  getConversation: () => null,
76
74
  getMessages: () => [],
77
75
  createConversation: (opts: { conversationType: string }) => {
@@ -137,8 +137,6 @@ const mockStoredMessages: Array<{
137
137
  }> = [];
138
138
 
139
139
  mock.module("../memory/conversation-crud.js", () => ({
140
- setConversationProcessingStartedAt: () => {},
141
- isConversationProcessing: () => false,
142
140
  setConversationOriginChannelIfUnset: () => {},
143
141
  updateConversationContextWindow: () => {},
144
142
  deleteMessageById: () => {},
@@ -138,11 +138,16 @@ function stampTrustVerdict(body: Record<string, unknown>): void {
138
138
  const channelType = String(body.sourceChannel ?? "");
139
139
  const actorExternalId =
140
140
  typeof body.actorExternalId === "string" ? body.actorExternalId : undefined;
141
+ const externalChatId =
142
+ typeof body.conversationExternalId === "string"
143
+ ? body.conversationExternalId
144
+ : undefined;
141
145
  if (!channelType) return;
142
146
 
143
147
  const verdict = resolveLocalTrustVerdict({
144
148
  channelType,
145
149
  actorExternalId,
150
+ externalChatId,
146
151
  });
147
152
  body.sourceMetadata = { ...(meta ?? {}), trustVerdict: verdict };
148
153
  }
@@ -151,14 +156,15 @@ function stampTrustVerdict(body: Record<string, unknown>): void {
151
156
  export function resolveLocalTrustVerdict(input: {
152
157
  channelType: string;
153
158
  actorExternalId?: string;
159
+ externalChatId?: string;
154
160
  }): TrustVerdict {
155
161
  const canonicalSenderId = input.actorExternalId ?? null;
156
162
 
157
- // Match the gateway's address-only member resolution (no externalChatId).
158
163
  const member = input.actorExternalId
159
164
  ? findContactChannel({
160
165
  channelType: input.channelType,
161
166
  address: input.actorExternalId,
167
+ externalChatId: input.externalChatId,
162
168
  })
163
169
  : null;
164
170
  const guardian = findGuardianForChannel(input.channelType);
@@ -62,7 +62,7 @@ afterAll(() => {
62
62
 
63
63
  const handleHostAppControlResult = ROUTES.find(
64
64
  (r) => r.endpoint === "host-app-control-result",
65
- )!.handler as (args: Record<string, unknown>) => Promise<unknown>;
65
+ )!.handler;
66
66
 
67
67
  // ── Tests ────────────────────────────────────────────────────────────
68
68
 
@@ -395,7 +395,7 @@ describe("handleHostAppControlResult — same-actor guard", () => {
395
395
  ).toThrow(BadRequestError);
396
396
  });
397
397
 
398
- test("targeted + missing header: interaction is NOT consumed (still pending)", async () => {
398
+ test("targeted + missing header: interaction is NOT consumed (still pending)", () => {
399
399
  const requestId = "ac-req-targeted-no-header-stays";
400
400
  pending.set(requestId, {
401
401
  conversationId: "conv-1",
@@ -404,11 +404,13 @@ describe("handleHostAppControlResult — same-actor guard", () => {
404
404
  targetActorPrincipalId: "user-1",
405
405
  });
406
406
 
407
- await handleHostAppControlResult({
408
- body: { requestId, state: "running" },
409
- }).catch(() => {
407
+ try {
408
+ handleHostAppControlResult({
409
+ body: { requestId, state: "running" },
410
+ });
411
+ } catch {
410
412
  // expected
411
- });
413
+ }
412
414
 
413
415
  expect(pending.has(requestId)).toBe(true);
414
416
  });
@@ -435,7 +437,7 @@ describe("handleHostAppControlResult — same-actor guard", () => {
435
437
  ).toThrow(ForbiddenError);
436
438
  });
437
439
 
438
- test("targeted + wrong client id: interaction is NOT consumed", async () => {
440
+ test("targeted + wrong client id: interaction is NOT consumed", () => {
439
441
  const requestId = "ac-req-targeted-wrong-client-stays";
440
442
  pending.set(requestId, {
441
443
  conversationId: "conv-1",
@@ -444,15 +446,17 @@ describe("handleHostAppControlResult — same-actor guard", () => {
444
446
  targetActorPrincipalId: "user-1",
445
447
  });
446
448
 
447
- await handleHostAppControlResult({
448
- body: { requestId, state: "running" },
449
- headers: {
450
- "x-vellum-client-id": "client-B",
451
- "x-vellum-actor-principal-id": "user-1",
452
- },
453
- }).catch(() => {
449
+ try {
450
+ handleHostAppControlResult({
451
+ body: { requestId, state: "running" },
452
+ headers: {
453
+ "x-vellum-client-id": "client-B",
454
+ "x-vellum-actor-principal-id": "user-1",
455
+ },
456
+ });
457
+ } catch {
454
458
  // expected
455
- });
459
+ }
456
460
 
457
461
  expect(pending.has(requestId)).toBe(true);
458
462
  });
@@ -479,7 +483,7 @@ describe("handleHostAppControlResult — same-actor guard", () => {
479
483
  ).toThrow(ForbiddenError);
480
484
  });
481
485
 
482
- test("targeted + wrong actor principal: interaction is NOT consumed", async () => {
486
+ test("targeted + wrong actor principal: interaction is NOT consumed", () => {
483
487
  const requestId = "ac-req-targeted-wrong-actor-stays";
484
488
  pending.set(requestId, {
485
489
  conversationId: "conv-1",
@@ -488,15 +492,17 @@ describe("handleHostAppControlResult — same-actor guard", () => {
488
492
  targetActorPrincipalId: "user-1",
489
493
  });
490
494
 
491
- await handleHostAppControlResult({
492
- body: { requestId, state: "running" },
493
- headers: {
494
- "x-vellum-client-id": "client-A",
495
- "x-vellum-actor-principal-id": "user-2",
496
- },
497
- }).catch(() => {
495
+ try {
496
+ handleHostAppControlResult({
497
+ body: { requestId, state: "running" },
498
+ headers: {
499
+ "x-vellum-client-id": "client-A",
500
+ "x-vellum-actor-principal-id": "user-2",
501
+ },
502
+ });
503
+ } catch {
498
504
  // expected
499
- });
505
+ }
500
506
 
501
507
  expect(pending.has(requestId)).toBe(true);
502
508
  });