@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022248.91fa053

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 (864) hide show
  1. package/ARCHITECTURE.md +94 -91
  2. package/Dockerfile +5 -16
  3. package/README.md +7 -10
  4. package/bun.lock +0 -4
  5. package/docs/architecture/security.md +20 -20
  6. package/docs/stt-provider-onboarding.md +4 -5
  7. package/docs/trusted-contact-access.md +7 -7
  8. package/eslint-rules/cli-no-daemon-internals.js +4 -0
  9. package/eslint.config.mjs +7 -1
  10. package/knip.json +0 -1
  11. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
  12. package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
  13. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
  14. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
  15. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  16. package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
  17. package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
  18. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
  19. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
  21. package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
  22. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
  23. package/openapi.yaml +1073 -225
  24. package/package.json +1 -4
  25. package/scripts/test.sh +35 -13
  26. package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
  27. package/src/__tests__/acp-session.test.ts +4 -1
  28. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
  29. package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
  30. package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
  31. package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
  32. package/src/__tests__/app-source-watcher.test.ts +11 -0
  33. package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
  34. package/src/__tests__/assistant-attachments.test.ts +62 -4
  35. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
  36. package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
  37. package/src/__tests__/attachments-store.test.ts +3 -0
  38. package/src/__tests__/background-shell-bash.test.ts +34 -0
  39. package/src/__tests__/background-shell-host-bash.test.ts +12 -0
  40. package/src/__tests__/background-tool-registry.test.ts +97 -0
  41. package/src/__tests__/background-tool-routes.test.ts +72 -1
  42. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
  43. package/src/__tests__/btw-routes.test.ts +57 -3
  44. package/src/__tests__/call-controller.test.ts +474 -84
  45. package/src/__tests__/call-domain.test.ts +48 -1
  46. package/src/__tests__/call-pointer-messages.test.ts +57 -19
  47. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
  48. package/src/__tests__/call-routes-http.test.ts +15 -14
  49. package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
  50. package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
  51. package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
  52. package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
  53. package/src/__tests__/call-setup-flow.test.ts +311 -0
  54. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
  55. package/src/__tests__/channel-guardian.test.ts +4 -7
  56. package/src/__tests__/channel-readiness-service.test.ts +0 -6
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
  58. package/src/__tests__/channel-retry-sweep.test.ts +76 -64
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
  60. package/src/__tests__/clear-all-lexical.test.ts +90 -0
  61. package/src/__tests__/compactor-media-strip.test.ts +177 -0
  62. package/src/__tests__/config-loader-backfill.test.ts +5 -5
  63. package/src/__tests__/config-schema.test.ts +17 -0
  64. package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
  65. package/src/__tests__/contacts-relay-reads.test.ts +188 -23
  66. package/src/__tests__/contacts-tools.test.ts +42 -1
  67. package/src/__tests__/contacts-write.test.ts +181 -0
  68. package/src/__tests__/context-search-conversations-source.test.ts +220 -81
  69. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
  70. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  71. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  72. package/src/__tests__/conversation-agent-loop.test.ts +39 -0
  73. package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
  74. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
  75. package/src/__tests__/conversation-clear-safety.test.ts +0 -1
  76. package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
  77. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
  78. package/src/__tests__/conversation-disk-view.test.ts +1 -0
  79. package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
  80. package/src/__tests__/conversation-error.test.ts +0 -18
  81. package/src/__tests__/conversation-fork-crud.test.ts +67 -0
  82. package/src/__tests__/conversation-history-web-search.test.ts +7 -137
  83. package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
  84. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
  85. package/src/__tests__/conversation-process-callsite.test.ts +37 -0
  86. package/src/__tests__/conversation-queue.test.ts +149 -0
  87. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
  88. package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
  89. package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
  90. package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
  91. package/src/__tests__/conversation-skill-tools.test.ts +73 -0
  92. package/src/__tests__/conversation-wipe.test.ts +20 -5
  93. package/src/__tests__/credential-prompt-route.test.ts +69 -0
  94. package/src/__tests__/credential-security-invariants.test.ts +1 -3
  95. package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
  96. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
  97. package/src/__tests__/edit-propagation.test.ts +56 -2
  98. package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
  99. package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
  100. package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
  101. package/src/__tests__/guardian-question-mode.test.ts +57 -0
  102. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  103. package/src/__tests__/guardian-wait-controller.test.ts +619 -0
  104. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
  105. package/src/__tests__/heic-fixture.ts +55 -0
  106. package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
  107. package/src/__tests__/http-conversation-lineage.test.ts +6 -1
  108. package/src/__tests__/image-conversion.test.ts +170 -0
  109. package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
  110. package/src/__tests__/introduction-card-resolver.test.ts +354 -0
  111. package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
  112. package/src/__tests__/invite-routes-http.test.ts +246 -420
  113. package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
  114. package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
  115. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
  116. package/src/__tests__/list-messages-attachments.test.ts +159 -0
  117. package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
  118. package/src/__tests__/list-messages-queued.test.ts +25 -0
  119. package/src/__tests__/managed-store.test.ts +129 -1
  120. package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
  121. package/src/__tests__/media-stream-output.test.ts +350 -19
  122. package/src/__tests__/media-stream-server-integration.test.ts +943 -169
  123. package/src/__tests__/media-stream-stt-session.test.ts +498 -1
  124. package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
  125. package/src/__tests__/model-intents.test.ts +1 -1
  126. package/src/__tests__/mtime-cache.test.ts +19 -0
  127. package/src/__tests__/non-member-access-request.test.ts +349 -3
  128. package/src/__tests__/notification-decision-fallback.test.ts +104 -8
  129. package/src/__tests__/notification-decision-strategy.test.ts +57 -8
  130. package/src/__tests__/onboarding-template-contract.test.ts +27 -43
  131. package/src/__tests__/openai-provider.test.ts +33 -0
  132. package/src/__tests__/openai-responses-provider.test.ts +40 -0
  133. package/src/__tests__/persistence-layering-guard.test.ts +29 -20
  134. package/src/__tests__/persona-resolver.test.ts +56 -2
  135. package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
  136. package/src/__tests__/phone.test.ts +1 -15
  137. package/src/__tests__/plugin-bootstrap.test.ts +25 -196
  138. package/src/__tests__/plugin-disabled-state.test.ts +33 -0
  139. package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
  140. package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
  141. package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
  142. package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
  143. package/src/__tests__/plugin-pipeline.test.ts +63 -1
  144. package/src/__tests__/plugin-route-contribution.test.ts +62 -115
  145. package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
  146. package/src/__tests__/plugin-types.test.ts +0 -1
  147. package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
  148. package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
  149. package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
  150. package/src/__tests__/public-ingress-urls.test.ts +0 -48
  151. package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
  152. package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
  153. package/src/__tests__/resolve-trust-class.test.ts +28 -10
  154. package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
  155. package/src/__tests__/schedule-retry.test.ts +38 -14
  156. package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
  157. package/src/__tests__/schedule-routes.test.ts +14 -6
  158. package/src/__tests__/schedule-store.test.ts +3 -1
  159. package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
  160. package/src/__tests__/scheduler-recurrence.test.ts +57 -107
  161. package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
  162. package/src/__tests__/scheduler-wake.test.ts +13 -23
  163. package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
  164. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
  165. package/src/__tests__/shell-observability.test.ts +1 -0
  166. package/src/__tests__/skill-boundary-guard.test.ts +3 -4
  167. package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
  168. package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
  169. package/src/__tests__/skill-script-runner-host.test.ts +53 -0
  170. package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
  171. package/src/__tests__/skill-tool-factory.test.ts +73 -1
  172. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
  173. package/src/__tests__/slack-inbound-verification.test.ts +36 -0
  174. package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
  175. package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
  176. package/src/__tests__/stt-hints.test.ts +2 -256
  177. package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
  178. package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
  179. package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
  180. package/src/__tests__/subagent-persistence.test.ts +122 -0
  181. package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
  182. package/src/__tests__/subagent-terminal-message.test.ts +99 -0
  183. package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
  184. package/src/__tests__/system-prompt.test.ts +17 -118
  185. package/src/__tests__/task-scheduler.test.ts +68 -89
  186. package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
  187. package/src/__tests__/telephony-tts-guard.test.ts +538 -0
  188. package/src/__tests__/title-generate-hook.test.ts +16 -0
  189. package/src/__tests__/tool-approval-handler.test.ts +87 -1
  190. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
  191. package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
  192. package/src/__tests__/trust-context-guards.test.ts +21 -10
  193. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
  194. package/src/__tests__/twilio-provider.test.ts +17 -17
  195. package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
  196. package/src/__tests__/twilio-routes.test.ts +257 -387
  197. package/src/__tests__/twilio-validation.test.ts +1 -1
  198. package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
  199. package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
  200. package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
  201. package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
  202. package/src/__tests__/voice-quality.test.ts +2 -2
  203. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
  204. package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
  205. package/src/__tests__/voice-session-bridge.test.ts +1 -10
  206. package/src/__tests__/workspace-git-service.test.ts +1 -1
  207. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
  208. package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
  209. package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
  210. package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
  211. package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
  212. package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
  213. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
  214. package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
  215. package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
  216. package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
  217. package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
  218. package/src/acp/__tests__/session-manager.test.ts +6 -0
  219. package/src/acp/agent-process.test.ts +116 -0
  220. package/src/acp/agent-process.ts +71 -0
  221. package/src/acp/auto-install.ts +12 -8
  222. package/src/acp/failure-error.test.ts +109 -0
  223. package/src/acp/failure-error.ts +111 -0
  224. package/src/acp/prepare-agent-env.ts +0 -12
  225. package/src/acp/resolve-agent.test.ts +6 -45
  226. package/src/acp/resolve-agent.ts +2 -4
  227. package/src/acp/session-manager.test.ts +312 -0
  228. package/src/acp/session-manager.ts +102 -46
  229. package/src/agent/ax-tree-compaction.test.ts +4 -1
  230. package/src/agent/image-optimize.ts +17 -127
  231. package/src/agent/loop.ts +45 -192
  232. package/src/api/events/background-tool-completed.test.ts +51 -0
  233. package/src/api/events/background-tool-completed.ts +29 -0
  234. package/src/api/events/background-tool-started.test.ts +36 -0
  235. package/src/api/events/background-tool-started.ts +28 -0
  236. package/src/api/events/conversation-error.ts +0 -1
  237. package/src/api/events/open-panel.ts +33 -0
  238. package/src/api/events/subagent-status-changed.ts +4 -1
  239. package/src/api/index.ts +19 -0
  240. package/src/api/responses/conversation-message.ts +34 -0
  241. package/src/approvals/guardian-decision-primitive.ts +74 -24
  242. package/src/approvals/guardian-request-resolvers.ts +450 -122
  243. package/src/apps/app-store.ts +1 -0
  244. package/src/apps/shared-app-links-store.ts +1 -0
  245. package/src/avatar/identity-avatar.ts +3 -7
  246. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  247. package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
  248. package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
  249. package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
  250. package/src/calls/call-controller.ts +134 -48
  251. package/src/calls/call-domain.ts +18 -42
  252. package/src/calls/call-pointer-messages.ts +51 -67
  253. package/src/calls/call-setup-flow-types.ts +76 -0
  254. package/src/calls/call-setup-flow.ts +1743 -0
  255. package/src/calls/call-speech-output.ts +87 -23
  256. package/src/calls/call-store.ts +4 -0
  257. package/src/calls/call-transport.ts +22 -36
  258. package/src/calls/fish-audio-client.ts +3 -0
  259. package/src/calls/gateway-invite-reader.ts +98 -0
  260. package/src/calls/guardian-wait-controller.ts +451 -0
  261. package/src/calls/media-stream-audio-transcode.ts +82 -2
  262. package/src/calls/media-stream-output.ts +142 -36
  263. package/src/calls/media-stream-server.ts +297 -178
  264. package/src/calls/media-stream-stt-session.ts +393 -50
  265. package/src/calls/media-turn-detector.ts +4 -6
  266. package/src/calls/relay-access-wait.ts +3 -4
  267. package/src/calls/relay-setup-router.ts +22 -43
  268. package/src/calls/relay-verification.ts +17 -24
  269. package/src/calls/resolve-call-tts-provider.ts +96 -29
  270. package/src/calls/stt-hints.ts +24 -87
  271. package/src/calls/telephony-credential-preflight.ts +159 -0
  272. package/src/calls/telephony-tts-capability.ts +183 -0
  273. package/src/calls/tts-call-strategy.ts +18 -20
  274. package/src/calls/twilio-provider.ts +3 -2
  275. package/src/calls/twilio-routes.ts +47 -351
  276. package/src/calls/types.ts +5 -3
  277. package/src/calls/voice-ingress-preflight.ts +9 -0
  278. package/src/calls/voice-quality.ts +13 -18
  279. package/src/calls/voice-session-bridge.ts +25 -35
  280. package/src/channels/__tests__/types.test.ts +28 -0
  281. package/src/channels/channel-verification-sessions.ts +7 -2
  282. package/src/channels/config.ts +0 -42
  283. package/src/channels/slack-thread-store.ts +12 -0
  284. package/src/channels/types.ts +23 -0
  285. package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
  286. package/src/cli/commands/__tests__/schedules.test.ts +83 -34
  287. package/src/cli/commands/__tests__/status.test.ts +42 -2
  288. package/src/cli/commands/contacts.ts +2 -2
  289. package/src/cli/commands/credentials.ts +17 -0
  290. package/src/cli/commands/monitoring.ts +191 -0
  291. package/src/cli/commands/schedules-worker.ts +175 -0
  292. package/src/cli/commands/schedules.ts +169 -43
  293. package/src/cli/commands/status.ts +12 -1
  294. package/src/cli/commands/tools.ts +5 -1
  295. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
  296. package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
  297. package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
  298. package/src/cli/lib/search-plugins.ts +6 -0
  299. package/src/cli/lib/toggle-plugin.ts +21 -2
  300. package/src/cli/program.ts +3 -1
  301. package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
  302. package/src/config/acp-defaults.test.ts +0 -10
  303. package/src/config/acp-defaults.ts +0 -6
  304. package/src/config/bundled-skills/acp/SKILL.md +13 -45
  305. package/src/config/bundled-skills/acp/TOOLS.json +3 -3
  306. package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
  307. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
  308. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
  309. package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
  310. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  311. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
  312. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
  313. package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
  314. package/src/config/call-site-defaults.ts +0 -2
  315. package/src/config/feature-flag-registry.json +16 -8
  316. package/src/config/loader.ts +11 -0
  317. package/src/config/schema.ts +9 -1
  318. package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
  319. package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
  320. package/src/config/schemas/call-site-catalog.ts +0 -12
  321. package/src/config/schemas/calls.ts +8 -0
  322. package/src/config/schemas/elevenlabs.ts +1 -1
  323. package/src/config/schemas/llm.ts +0 -2
  324. package/src/config/schemas/memory-v2.ts +1 -1
  325. package/src/config/schemas/memory-v3.ts +82 -0
  326. package/src/config/schemas/monitoring.ts +61 -0
  327. package/src/config/schemas/schedules.ts +35 -0
  328. package/src/config/seed-inference-profiles.ts +2 -2
  329. package/src/config/skills-plugin-filter.test.ts +96 -0
  330. package/src/config/skills.ts +26 -0
  331. package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
  332. package/src/contacts/canonical-guardian-store.ts +5 -0
  333. package/src/contacts/contact-store.ts +81 -35
  334. package/src/contacts/contacts-write.ts +50 -25
  335. package/src/contacts/member-write-relay.ts +115 -31
  336. package/src/contacts/types.ts +0 -8
  337. package/src/context/compactor.ts +29 -15
  338. package/src/context/outbound-sanitize.ts +202 -0
  339. package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
  340. package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
  341. package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
  342. package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
  343. package/src/daemon/abort-watchdog.ts +7 -0
  344. package/src/daemon/app-source-watcher.ts +9 -0
  345. package/src/daemon/assistant-attachments.ts +42 -0
  346. package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
  347. package/src/daemon/conversation-agent-loop.ts +61 -68
  348. package/src/daemon/conversation-error.ts +1 -15
  349. package/src/daemon/conversation-history.ts +32 -236
  350. package/src/daemon/conversation-initial-prompt.ts +77 -0
  351. package/src/daemon/conversation-lifecycle.ts +25 -1
  352. package/src/daemon/conversation-messaging.ts +2 -2
  353. package/src/daemon/conversation-plugin-scope.ts +38 -0
  354. package/src/daemon/conversation-process.ts +50 -14
  355. package/src/daemon/conversation-runtime-assembly.ts +36 -6
  356. package/src/daemon/conversation-skill-tools.ts +19 -3
  357. package/src/daemon/conversation-store.ts +3 -3
  358. package/src/daemon/conversation-surfaces.ts +171 -0
  359. package/src/daemon/conversation-tool-setup.test.ts +95 -0
  360. package/src/daemon/conversation-tool-setup.ts +116 -1
  361. package/src/daemon/conversation-turn-finalize.ts +211 -0
  362. package/src/daemon/conversation.ts +92 -1
  363. package/src/daemon/disk-pressure-policy.ts +2 -1
  364. package/src/daemon/event-loop-watchdog.ts +22 -6
  365. package/src/daemon/external-plugins-bootstrap.ts +47 -134
  366. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  367. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
  368. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
  369. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
  370. package/src/daemon/handlers/config-a2a.ts +7 -14
  371. package/src/daemon/handlers/config-channels.ts +2 -10
  372. package/src/daemon/handlers/conversation-history.ts +3 -1
  373. package/src/daemon/handlers/conversations.ts +0 -52
  374. package/src/daemon/handlers/shared.ts +4 -24
  375. package/src/daemon/handlers/skills.ts +4 -1
  376. package/src/daemon/host-cu-proxy.ts +1 -1
  377. package/src/daemon/lifecycle.ts +59 -472
  378. package/src/daemon/message-protocol.ts +3 -3
  379. package/src/daemon/message-provenance.ts +12 -14
  380. package/src/daemon/message-types/background-tools.ts +28 -0
  381. package/src/daemon/message-types/contacts.ts +2 -10
  382. package/src/daemon/message-types/conversations.ts +10 -0
  383. package/src/daemon/message-types/integrations.ts +2 -0
  384. package/src/daemon/message-types/surfaces.ts +1 -0
  385. package/src/daemon/message-types/sync.ts +1 -0
  386. package/src/daemon/pointer-conversation-trust.ts +23 -9
  387. package/src/daemon/pointer-turn-runner.ts +174 -0
  388. package/src/daemon/providers-setup.ts +16 -0
  389. package/src/daemon/shutdown-handlers.ts +139 -47
  390. package/src/daemon/skill-memory-refresh.ts +2 -2
  391. package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
  392. package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
  393. package/src/daemon/tool-setup-types.ts +8 -0
  394. package/src/daemon/trust-context.ts +21 -6
  395. package/src/daemon/turn-latency-tracker.test.ts +93 -0
  396. package/src/daemon/turn-latency-tracker.ts +38 -0
  397. package/src/daemon/wake-conversation-ops.ts +10 -8
  398. package/src/documents/document-comments-store.test.ts +7 -1
  399. package/src/documents/document-comments-store.ts +8 -0
  400. package/src/documents/document-store.ts +15 -0
  401. package/src/export/__tests__/transcript-formatter.test.ts +11 -0
  402. package/src/export/transcript-formatter.ts +49 -67
  403. package/src/home/__tests__/feed-writer.test.ts +247 -1
  404. package/src/home/conversation-starter-checkpoints.ts +1 -0
  405. package/src/home/feed-writer.ts +61 -0
  406. package/src/home/job-handlers/conversation-starters.ts +1 -0
  407. package/src/hooks/hook-loader.ts +12 -0
  408. package/src/hooks/registry.ts +32 -4
  409. package/src/inbound/public-ingress-urls.ts +0 -17
  410. package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
  411. package/src/ipc/assistant-server.ts +28 -7
  412. package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
  413. package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
  414. package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
  415. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
  416. package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
  417. package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
  418. package/src/ipc/routes/db-proxy.ts +5 -2
  419. package/src/ipc/routes/invite-ipc-routes.ts +53 -39
  420. package/src/jobs/worker.ts +9 -2
  421. package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
  422. package/src/live-voice/live-voice-archive.ts +5 -0
  423. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
  424. package/src/messaging/providers/channel-transport.ts +6 -0
  425. package/src/messaging/providers/index.ts +3 -0
  426. package/src/messaging/providers/slack/api.test.ts +49 -1
  427. package/src/messaging/providers/slack/api.ts +110 -0
  428. package/src/messaging/providers/slack/send.test.ts +85 -0
  429. package/src/messaging/providers/slack/send.ts +100 -28
  430. package/src/messaging/providers/slack/transport.ts +7 -13
  431. package/src/messaging/providers/whatsapp/send.ts +29 -9
  432. package/src/monitoring/__tests__/control.test.ts +235 -0
  433. package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
  434. package/src/monitoring/control.ts +105 -0
  435. package/src/monitoring/resource-sampler.ts +258 -0
  436. package/src/monitoring/sample-ring-buffer.ts +108 -0
  437. package/src/monitoring/worker.ts +94 -0
  438. package/src/notifications/README.md +1 -1
  439. package/src/notifications/access-request-copy.ts +94 -23
  440. package/src/notifications/adapters/slack.ts +89 -21
  441. package/src/notifications/approval-card-builder.ts +33 -18
  442. package/src/notifications/approval-card-data.ts +48 -15
  443. package/src/notifications/broadcaster.ts +25 -16
  444. package/src/notifications/decision-engine.ts +131 -32
  445. package/src/notifications/guardian-question-mode.ts +58 -10
  446. package/src/permissions/approval-policy.ts +8 -1
  447. package/src/permissions/checker.ts +2 -0
  448. package/src/permissions/gateway-threshold-reader.ts +7 -6
  449. package/src/permissions/ipc-risk-types.ts +1 -0
  450. package/src/permissions/secret-prompter.ts +11 -3
  451. package/src/permissions/types.ts +2 -2
  452. package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
  453. package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
  454. package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
  455. package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
  456. package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
  457. package/src/persistence/a2a-invite-store.ts +205 -0
  458. package/src/persistence/attachments-store.ts +94 -10
  459. package/src/persistence/checkpoints.ts +45 -0
  460. package/src/persistence/conversation-crud.ts +453 -260
  461. package/src/persistence/conversation-display-order-migration.ts +8 -2
  462. package/src/persistence/conversation-group-migration.test.ts +8 -0
  463. package/src/persistence/conversation-group-migration.ts +9 -0
  464. package/src/persistence/conversation-queries.ts +244 -125
  465. package/src/persistence/conversation-row-batch-delete.ts +9 -5
  466. package/src/persistence/conversation-search-lexical.ts +49 -0
  467. package/src/persistence/db-async-query.ts +42 -0
  468. package/src/persistence/db-connection.ts +13 -0
  469. package/src/persistence/delivery-channels.ts +0 -82
  470. package/src/persistence/delivery-crud.ts +27 -6
  471. package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
  472. package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
  473. package/src/persistence/embeddings/embedding-identity.ts +17 -5
  474. package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
  475. package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
  476. package/src/persistence/embeddings/qdrant-client.ts +81 -5
  477. package/src/persistence/group-crud.ts +13 -1
  478. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
  479. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
  480. package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
  481. package/src/persistence/job-handlers/cleanup.ts +57 -9
  482. package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
  483. package/src/persistence/job-handlers/message-lexical.ts +251 -0
  484. package/src/persistence/jobs-store.ts +102 -8
  485. package/src/persistence/jobs-worker.ts +68 -28
  486. package/src/persistence/llm-request-log-store.ts +35 -19
  487. package/src/persistence/llm-usage-store.ts +11 -0
  488. package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
  489. package/src/persistence/memory-lifecycle-hooks.ts +55 -1
  490. package/src/persistence/migrations/028-call-session-mode.ts +1 -1
  491. package/src/persistence/migrations/116-messages-fts.ts +8 -1
  492. package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
  493. package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
  494. package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
  495. package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
  496. package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
  497. package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
  498. package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
  499. package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
  500. package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
  501. package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
  502. package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
  503. package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
  504. package/src/persistence/raw-query.ts +50 -11
  505. package/src/persistence/schema/a2a.ts +14 -0
  506. package/src/persistence/schema/contacts.ts +0 -62
  507. package/src/persistence/schema/conversation-groups.ts +12 -0
  508. package/src/persistence/schema/conversations.ts +2 -0
  509. package/src/persistence/schema/documents.ts +65 -0
  510. package/src/persistence/schema/guardian.ts +4 -0
  511. package/src/persistence/schema/index.ts +4 -0
  512. package/src/persistence/schema/memory-injection.ts +62 -0
  513. package/src/persistence/schema/workflows.ts +55 -0
  514. package/src/persistence/slow-query-log.ts +437 -0
  515. package/src/persistence/slow-sync-log.ts +204 -0
  516. package/src/persistence/steps.ts +16 -0
  517. package/src/persistence/subagent-store.ts +125 -0
  518. package/src/persistence/worker-control.ts +45 -238
  519. package/src/plugin-api/event-hub-facade.ts +172 -0
  520. package/src/plugin-api/index.ts +9 -1
  521. package/src/plugin-api/types.ts +40 -9
  522. package/src/plugins/defaults/default-plugin-names.ts +60 -0
  523. package/src/plugins/defaults/index.ts +19 -29
  524. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
  525. package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
  526. package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
  527. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
  528. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
  529. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
  530. package/src/plugins/defaults/memory/config.ts +11 -0
  531. package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
  532. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
  533. package/src/plugins/defaults/memory/embeddings.ts +77 -0
  534. package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
  535. package/src/plugins/defaults/memory/frontmatter.ts +50 -0
  536. package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
  537. package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
  538. package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
  539. package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
  540. package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
  541. package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
  542. package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
  543. package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
  544. package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
  545. package/src/plugins/defaults/memory/graph/tools.ts +1 -1
  546. package/src/plugins/defaults/memory/hooks/init.ts +31 -5
  547. package/src/plugins/defaults/memory/indexer.ts +2 -3
  548. package/src/plugins/defaults/memory/injectors.ts +2 -2
  549. package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
  550. package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
  551. package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
  552. package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
  553. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
  554. package/src/plugins/defaults/memory/job-handlers.ts +13 -12
  555. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
  556. package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
  557. package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
  558. package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
  559. package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
  560. package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
  561. package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
  562. package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
  563. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
  564. package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
  565. package/src/plugins/defaults/memory/search/semantic.ts +2 -2
  566. package/src/plugins/defaults/memory/startup.ts +244 -0
  567. package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
  568. package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
  569. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
  570. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
  571. package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
  572. package/src/plugins/defaults/memory/v2/activation.ts +2 -4
  573. package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
  574. package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
  575. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
  576. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
  577. package/src/plugins/defaults/memory/v2/migration.ts +2 -5
  578. package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
  579. package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
  580. package/src/plugins/defaults/memory/v2/router.ts +5 -5
  581. package/src/plugins/defaults/memory/v2/sim.ts +2 -4
  582. package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
  583. package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
  584. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
  585. package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
  586. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
  587. package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
  588. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
  589. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
  590. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
  591. package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
  592. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
  593. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
  594. package/src/plugins/defaults/memory/v3/card.ts +1 -4
  595. package/src/plugins/defaults/memory/v3/dense.ts +60 -25
  596. package/src/plugins/defaults/memory/v3/edge.ts +1 -1
  597. package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
  598. package/src/plugins/defaults/memory/v3/gate.ts +158 -0
  599. package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
  600. package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
  601. package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
  602. package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
  603. package/src/plugins/defaults/memory/v3/prune.ts +2 -2
  604. package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
  605. package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
  606. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
  607. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
  608. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
  609. package/src/plugins/defaults/turn-context/injectors.ts +1 -0
  610. package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
  611. package/src/plugins/injector-registry.ts +13 -2
  612. package/src/plugins/mtime-cache.ts +36 -47
  613. package/src/plugins/pipeline.ts +15 -1
  614. package/src/plugins/types.ts +14 -23
  615. package/src/prompts/__tests__/system-prompt.test.ts +170 -32
  616. package/src/prompts/persona-resolver.ts +13 -9
  617. package/src/prompts/system-prompt.ts +30 -9
  618. package/src/prompts/templates/BOOTSTRAP.md +16 -119
  619. package/src/prompts/templates/SOUL.md +43 -13
  620. package/src/prompts/templates/system-sections.ts +32 -27
  621. package/src/prompts/templates/users/default.md +19 -0
  622. package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
  623. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
  624. package/src/providers/model-intents.ts +2 -2
  625. package/src/providers/openai/chat-completions-provider.ts +14 -1
  626. package/src/providers/openai/responses-provider.ts +18 -0
  627. package/src/providers/placeholder-sentinels.ts +18 -8
  628. package/src/providers/retry.ts +1 -0
  629. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
  630. package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
  631. package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
  632. package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
  633. package/src/providers/speech-to-text/provider-catalog.ts +0 -89
  634. package/src/providers/speech-to-text/resolve.ts +55 -0
  635. package/src/providers/tool-progress-events.test.ts +50 -0
  636. package/src/providers/tool-progress-events.ts +99 -0
  637. package/src/providers/types.ts +1 -1
  638. package/src/runtime/AGENTS.md +5 -4
  639. package/src/runtime/__tests__/agent-wake.test.ts +158 -1
  640. package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
  641. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
  642. package/src/runtime/access-request-helper.ts +154 -3
  643. package/src/runtime/actor-trust-resolver.ts +7 -21
  644. package/src/runtime/agent-wake.ts +41 -1
  645. package/src/runtime/assistant-event.ts +86 -12
  646. package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
  647. package/src/runtime/channel-approval-types.ts +52 -2
  648. package/src/runtime/channel-approvals.ts +23 -8
  649. package/src/runtime/channel-invite-transport.ts +2 -2
  650. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  651. package/src/runtime/channel-readiness-service.ts +3 -5
  652. package/src/runtime/channel-retry-sweep.ts +18 -24
  653. package/src/runtime/channel-verification-service.ts +9 -11
  654. package/src/runtime/finalize-event-delivery.ts +30 -16
  655. package/src/runtime/guardian-action-service.ts +10 -11
  656. package/src/runtime/guardian-reply-router.ts +122 -21
  657. package/src/runtime/http-server.ts +44 -101
  658. package/src/runtime/introduction-policy.test.ts +214 -0
  659. package/src/runtime/introduction-policy.ts +284 -0
  660. package/src/runtime/invite-service.ts +104 -361
  661. package/src/runtime/local-actor-identity.test.ts +38 -0
  662. package/src/runtime/local-actor-identity.ts +14 -0
  663. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
  664. package/src/runtime/middleware/rate-limiter.ts +30 -0
  665. package/src/runtime/middleware/twilio-validation.ts +5 -7
  666. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
  667. package/src/runtime/migrations/origin-mode.ts +6 -6
  668. package/src/runtime/pre-first-message-gate.ts +1 -0
  669. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
  670. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
  671. package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
  672. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
  673. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
  674. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
  675. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
  676. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
  677. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
  678. package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
  679. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
  680. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
  681. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
  682. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
  683. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
  684. package/src/runtime/routes/acp-routes.ts +15 -3
  685. package/src/runtime/routes/app-management-routes.ts +4 -7
  686. package/src/runtime/routes/approval-routes.ts +4 -0
  687. package/src/runtime/routes/attachment-routes.ts +54 -3
  688. package/src/runtime/routes/avatar-routes.ts +0 -4
  689. package/src/runtime/routes/background-tool-routes.ts +34 -5
  690. package/src/runtime/routes/btw-routes.ts +32 -4
  691. package/src/runtime/routes/channel-route-shared.ts +18 -14
  692. package/src/runtime/routes/channel-verification-routes.ts +0 -3
  693. package/src/runtime/routes/contact-routes.ts +298 -117
  694. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  695. package/src/runtime/routes/conversation-management-routes.ts +74 -37
  696. package/src/runtime/routes/conversation-query-routes.ts +5 -2
  697. package/src/runtime/routes/conversation-routes.ts +222 -82
  698. package/src/runtime/routes/conversations-import-routes.ts +8 -1
  699. package/src/runtime/routes/credential-prompt-routes.ts +20 -5
  700. package/src/runtime/routes/debug-routes.ts +1 -0
  701. package/src/runtime/routes/documents-routes.ts +5 -2
  702. package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
  703. package/src/runtime/routes/global-search-routes.ts +2 -1
  704. package/src/runtime/routes/guardian-approval-interception.ts +51 -0
  705. package/src/runtime/routes/home-feed-routes.ts +60 -1
  706. package/src/runtime/routes/identity-routes.ts +4 -87
  707. package/src/runtime/routes/inbound-message-handler.ts +82 -41
  708. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
  709. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
  710. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
  711. package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
  712. package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
  713. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
  714. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
  715. package/src/runtime/routes/index.ts +6 -0
  716. package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
  717. package/src/runtime/routes/internal-twilio-routes.ts +0 -15
  718. package/src/runtime/routes/messages-lexical-routes.ts +75 -0
  719. package/src/runtime/routes/migration-routes.ts +69 -6
  720. package/src/runtime/routes/monitoring-routes.ts +237 -0
  721. package/src/runtime/routes/plugins-routes.ts +329 -8
  722. package/src/runtime/routes/schedule-routes.ts +49 -8
  723. package/src/runtime/routes/schedule-worker-routes.ts +210 -0
  724. package/src/runtime/routes/secret-routes.ts +1 -1
  725. package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
  726. package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
  727. package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
  728. package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
  729. package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
  730. package/src/runtime/services/analyze-conversation.ts +14 -4
  731. package/src/runtime/services/conversation-serializer.ts +5 -0
  732. package/src/runtime/slack-no-response.ts +47 -0
  733. package/src/runtime/slack-reply-session.test.ts +633 -0
  734. package/src/runtime/slack-reply-session.ts +382 -0
  735. package/src/runtime/slack-task-progress.ts +95 -0
  736. package/src/runtime/sync/resource-sync-events.ts +25 -0
  737. package/src/runtime/tool-grant-request-helper.ts +17 -1
  738. package/src/runtime/trust-class.test.ts +141 -0
  739. package/src/runtime/trust-class.ts +121 -0
  740. package/src/runtime/trust-verdict-consumer.ts +7 -6
  741. package/src/schedule/__tests__/run-script.test.ts +21 -0
  742. package/src/schedule/__tests__/worker-control.test.ts +241 -0
  743. package/src/schedule/run-script.ts +13 -6
  744. package/src/schedule/schedule-usage-store.ts +1 -0
  745. package/src/schedule/scheduler.ts +178 -127
  746. package/src/schedule/worker-control.ts +118 -0
  747. package/src/schedule/worker.ts +131 -0
  748. package/src/skills/__tests__/categories-cache.test.ts +38 -0
  749. package/src/skills/categories-cache.ts +40 -5
  750. package/src/skills/managed-store.ts +41 -6
  751. package/src/skills/validate-input.ts +47 -0
  752. package/src/stt/types.ts +5 -9
  753. package/src/subagent/manager.ts +267 -39
  754. package/src/subagent/types.ts +6 -2
  755. package/src/subagent/validate-allowlists.ts +65 -0
  756. package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
  757. package/src/telemetry/watchdog-direct-emit.ts +89 -0
  758. package/src/tools/acp/list-agents.test.ts +0 -6
  759. package/src/tools/background-tool-registry.ts +61 -0
  760. package/src/tools/document/document-comment-tool.test.ts +4 -0
  761. package/src/tools/host-terminal/host-shell.test.ts +397 -0
  762. package/src/tools/host-terminal/host-shell.ts +203 -14
  763. package/src/tools/skills/find-similar-skills.test.ts +152 -1
  764. package/src/tools/skills/find-similar-skills.ts +30 -4
  765. package/src/tools/skills/load.ts +36 -0
  766. package/src/tools/skills/scaffold-managed.ts +66 -34
  767. package/src/tools/skills/skill-script-runner.ts +17 -0
  768. package/src/tools/skills/skill-tool-factory.ts +5 -1
  769. package/src/tools/terminal/safe-env.ts +3 -0
  770. package/src/tools/terminal/shell.test.ts +177 -0
  771. package/src/tools/terminal/shell.ts +98 -4
  772. package/src/tools/tool-approval-handler.ts +106 -29
  773. package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
  774. package/src/tools/types.ts +29 -17
  775. package/src/tools/ui-surface/definitions.ts +3 -1
  776. package/src/tts/__tests__/provider-adapters.test.ts +37 -0
  777. package/src/tts/__tests__/provider-catalog.test.ts +21 -0
  778. package/src/tts/provider-catalog.ts +40 -9
  779. package/src/tts/providers/fish-audio-provider.ts +19 -10
  780. package/src/tts/types.ts +3 -4
  781. package/src/util/__tests__/process-tree.test.ts +10 -2
  782. package/src/util/__tests__/text-spacing.test.ts +53 -0
  783. package/src/util/cgroup-memory.ts +142 -0
  784. package/src/util/image-conversion.ts +281 -0
  785. package/src/util/phone.ts +1 -8
  786. package/src/util/platform.ts +33 -0
  787. package/src/util/process-tree.ts +10 -2
  788. package/src/util/text-spacing.ts +53 -0
  789. package/src/util/worker-process.ts +271 -0
  790. package/src/workflows/journal-store.ts +16 -1
  791. package/src/workflows/library.test.ts +35 -20
  792. package/src/workflows/library.ts +105 -66
  793. package/src/workspace/git-service.ts +1 -0
  794. package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
  795. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
  796. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
  797. package/src/workspace/migrations/118-seed-now-md.ts +64 -0
  798. package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
  799. package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
  800. package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
  801. package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
  802. package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
  803. package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
  804. package/src/workspace/migrations/registry.ts +12 -0
  805. package/drizzle/0000_dizzy_maggott.sql +0 -301
  806. package/drizzle/meta/0000_snapshot.json +0 -1933
  807. package/drizzle/meta/_journal.json +0 -13
  808. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
  809. package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
  810. package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
  811. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
  812. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
  813. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
  814. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
  815. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
  816. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
  817. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
  818. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
  819. package/src/__tests__/invite-redemption-service.test.ts +0 -1180
  820. package/src/__tests__/invite-service-ipc.test.ts +0 -350
  821. package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
  822. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
  823. package/src/__tests__/relay-server.test.ts +0 -6153
  824. package/src/__tests__/telephony-stt-routing.test.ts +0 -329
  825. package/src/__tests__/voice-invite-redemption.test.ts +0 -702
  826. package/src/calls/relay-server.ts +0 -2463
  827. package/src/calls/telephony-stt-routing.ts +0 -145
  828. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
  829. package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
  830. package/src/daemon/daemon-skill-host.ts +0 -262
  831. package/src/daemon/message-types/meet.ts +0 -143
  832. package/src/daemon/shutdown-registry.ts +0 -40
  833. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
  834. package/src/ipc/__tests__/skill-server.test.ts +0 -182
  835. package/src/ipc/skill-ipc-types.ts +0 -54
  836. package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
  837. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
  838. package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
  839. package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
  840. package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
  841. package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
  842. package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
  843. package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
  844. package/src/ipc/skill-routes/config.ts +0 -47
  845. package/src/ipc/skill-routes/events.ts +0 -147
  846. package/src/ipc/skill-routes/identity.ts +0 -21
  847. package/src/ipc/skill-routes/index.ts +0 -37
  848. package/src/ipc/skill-routes/log.ts +0 -40
  849. package/src/ipc/skill-routes/memory.ts +0 -92
  850. package/src/ipc/skill-routes/platform.ts +0 -39
  851. package/src/ipc/skill-routes/providers.ts +0 -162
  852. package/src/ipc/skill-routes/registries.ts +0 -338
  853. package/src/ipc/skill-server.ts +0 -831
  854. package/src/ipc/skill-socket-path.ts +0 -20
  855. package/src/jobs/register-job-handlers.ts +0 -74
  856. package/src/persistence/invite-store.ts +0 -481
  857. package/src/plugins/job-handler-registry.ts +0 -94
  858. package/src/providers/cache-control.ts +0 -26
  859. package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
  860. package/src/runtime/invite-redemption-service.ts +0 -828
  861. package/src/runtime/invite-redemption-templates.ts +0 -46
  862. package/src/runtime/runtime-mode.ts +0 -40
  863. package/src/runtime/slack-dm-text-delivery.ts +0 -177
  864. package/src/util/voice-code.ts +0 -31
@@ -2,9 +2,9 @@
2
2
  * Tests for the inbound admission-floor enforcement in `routeSetup`.
3
3
  *
4
4
  * `routeSetup` reads several module-level singletons (config, trust resolver,
5
- * pending verification session, invite store, contact store). Those I/O
5
+ * pending verification session, gateway voice-invite reader). Those I/O
6
6
  * collaborators are mocked so the tables below can drive trust class, member
7
- * status, pending challenge, active invites, and the bound invite contact
7
+ * status, pending challenge, and the gateway's active-voice-invite view
8
8
  * directly — no database is touched.
9
9
  *
10
10
  * The admission floor is exercised through the REAL, pure `enforceAdmissionPolicy`:
@@ -60,21 +60,17 @@ mock.module("../../runtime/channel-verification-service.js", () => ({
60
60
  getPendingSession: () => pendingChallenge,
61
61
  }));
62
62
 
63
- // Controllable active voice invites.
64
- let activeInvites: Array<{
65
- contactId: string;
66
- friendName: string | null;
63
+ // Controllable gateway active-voice-invite view. The real reader fails soft
64
+ // to `null` on ANY gateway failure by contract, so `null` covers both "no
65
+ // invite" and "gateway unreachable / IPC error".
66
+ let activeVoiceInvite: {
67
+ inviteId: string;
68
+ inviteeName: string | null;
67
69
  guardianName: string | null;
68
- expiresAt?: number;
69
- }> = [];
70
- mock.module("../../persistence/invite-store.js", () => ({
71
- findActiveVoiceInvites: () => activeInvites,
72
- }));
73
-
74
- // Controllable bound contact for invite-redemption name resolution.
75
- let boundContact: { displayName?: string | null } | null = null;
76
- mock.module("../../contacts/contact-store.js", () => ({
77
- getContact: () => boundContact,
70
+ codeDigits: number;
71
+ } | null = null;
72
+ mock.module("../gateway-invite-reader.js", () => ({
73
+ getActiveVoiceInvite: async () => activeVoiceInvite,
78
74
  }));
79
75
 
80
76
  const { routeSetup } = await import("../relay-setup-router.js");
@@ -91,10 +87,6 @@ function makeChannel(overrides: Partial<ContactChannel> = {}): ContactChannel {
91
87
  address: "+12025550142",
92
88
  isPrimary: true,
93
89
  externalChatId: null,
94
- inviteId: null,
95
- lastSeenAt: null,
96
- interactionCount: 0,
97
- lastInteraction: null,
98
90
  updatedAt: null,
99
91
  createdAt: 0,
100
92
  ...overrides,
@@ -109,8 +101,6 @@ function makeContact(
109
101
  displayName: "Test Caller",
110
102
  notes: null,
111
103
  role: "contact",
112
- lastInteraction: null,
113
- interactionCount: 0,
114
104
  createdAt: 0,
115
105
  updatedAt: 0,
116
106
  contactType: "human",
@@ -170,8 +160,7 @@ function route(
170
160
 
171
161
  beforeEach(() => {
172
162
  pendingChallenge = null;
173
- activeInvites = [];
174
- boundContact = null;
163
+ activeVoiceInvite = null;
175
164
  resolveActorTrustMock.mockClear();
176
165
  });
177
166
 
@@ -231,9 +220,9 @@ describe("routeSetup — admission floor table", () => {
231
220
 
232
221
  for (const { policy, admits, denies } of cases) {
233
222
  for (const trustClass of denies) {
234
- test(`${policy} denies ${trustClass}`, () => {
223
+ test(`${policy} denies ${trustClass}`, async () => {
235
224
  setTrust(trustClass);
236
- const { outcome } = route(policy);
225
+ const { outcome } = await route(policy);
237
226
  expect(outcome.action).toBe("deny");
238
227
  if (outcome.action === "deny") {
239
228
  expect(outcome.logReason).toBe(
@@ -243,9 +232,9 @@ describe("routeSetup — admission floor table", () => {
243
232
  });
244
233
  }
245
234
  for (const trustClass of admits) {
246
- test(`${policy} admits ${trustClass}`, () => {
235
+ test(`${policy} admits ${trustClass}`, async () => {
247
236
  setTrust(trustClass);
248
- const { outcome } = route(policy);
237
+ const { outcome } = await route(policy);
249
238
  expect(outcome.action).not.toBe("deny");
250
239
  });
251
240
  }
@@ -257,17 +246,17 @@ describe("routeSetup — admission floor table", () => {
257
246
  // ---------------------------------------------------------------------------
258
247
 
259
248
  describe("routeSetup — blocked / revoked", () => {
260
- test("blocked caller is denied (pre-floor ACL check)", () => {
249
+ test("blocked caller is denied (pre-floor ACL check)", async () => {
261
250
  nextTrust = makeTrust("unknown", { status: "blocked" });
262
- const { outcome } = route("strangers");
251
+ const { outcome } = await route("strangers");
263
252
  expect(outcome.action).toBe("deny");
264
253
  });
265
254
 
266
- test("revoked member is denied under permissive floor", () => {
255
+ test("revoked member is denied under permissive floor", async () => {
267
256
  // Revoked → resolver classifies as unknown; the floor mock denies on
268
257
  // memberStatus regardless of the permissive policy.
269
258
  nextTrust = makeTrust("unknown", { status: "revoked" });
270
- const { outcome } = route("strangers");
259
+ const { outcome } = await route("strangers");
271
260
  expect(outcome.action).toBe("deny");
272
261
  });
273
262
  });
@@ -277,33 +266,33 @@ describe("routeSetup — blocked / revoked", () => {
277
266
  // ---------------------------------------------------------------------------
278
267
 
279
268
  describe("routeSetup — no policy preserves current behavior", () => {
280
- test("unknown caller → name_capture", () => {
269
+ test("unknown caller → name_capture", async () => {
281
270
  nextTrust = makeTrust("unknown");
282
- expect(route(null).outcome.action).toBe("name_capture");
283
- expect(route(undefined).outcome.action).toBe("name_capture");
271
+ expect((await route(null)).outcome.action).toBe("name_capture");
272
+ expect((await route(undefined)).outcome.action).toBe("name_capture");
284
273
  });
285
274
 
286
- test("unverified known caller → unverified_caller", () => {
275
+ test("unverified known caller → unverified_caller", async () => {
287
276
  nextTrust = makeTrust("unverified_contact", { status: "unverified" });
288
- expect(route(null).outcome.action).toBe("unverified_caller");
277
+ expect((await route(null)).outcome.action).toBe("unverified_caller");
289
278
  });
290
279
 
291
- test("trusted contact → normal_call", () => {
280
+ test("trusted contact → normal_call", async () => {
292
281
  nextTrust = makeTrust("trusted_contact", { status: "active" });
293
- expect(route(null).outcome.action).toBe("normal_call");
282
+ expect((await route(null)).outcome.action).toBe("normal_call");
294
283
  });
295
284
 
296
- test("guardian → normal_call", () => {
285
+ test("guardian → normal_call", async () => {
297
286
  nextTrust = makeTrust("guardian", { status: "active", role: "guardian" });
298
- expect(route(null).outcome.action).toBe("normal_call");
287
+ expect((await route(null)).outcome.action).toBe("normal_call");
299
288
  });
300
289
 
301
- test("member policy deny still denies", () => {
290
+ test("member policy deny still denies", async () => {
302
291
  nextTrust = makeTrust("trusted_contact", {
303
292
  status: "active",
304
293
  policy: "deny",
305
294
  });
306
- expect(route(null).outcome.action).toBe("deny");
295
+ expect((await route(null)).outcome.action).toBe("deny");
307
296
  });
308
297
  });
309
298
 
@@ -315,39 +304,39 @@ describe("routeSetup — no policy preserves current behavior", () => {
315
304
  // and connect directly. With a null policy the legacy identity flows persist.
316
305
 
317
306
  describe("routeSetup — permissive floor admits to normal_call", () => {
318
- test("any_contact admits an unverified_contact to normal_call (not unverified_caller)", () => {
307
+ test("any_contact admits an unverified_contact to normal_call (not unverified_caller)", async () => {
319
308
  nextTrust = makeTrust("unverified_contact", { status: "unverified" });
320
- const { outcome } = route("any_contact");
309
+ const { outcome } = await route("any_contact");
321
310
  expect(outcome.action).toBe("normal_call");
322
311
  });
323
312
 
324
- test("strangers admits an unknown caller to normal_call (not name_capture)", () => {
313
+ test("strangers admits an unknown caller to normal_call (not name_capture)", async () => {
325
314
  nextTrust = makeTrust("unknown");
326
- const { outcome } = route("strangers");
315
+ const { outcome } = await route("strangers");
327
316
  expect(outcome.action).toBe("normal_call");
328
317
  });
329
318
 
330
- test("strangers admits an unverified_contact to normal_call", () => {
319
+ test("strangers admits an unverified_contact to normal_call", async () => {
331
320
  nextTrust = makeTrust("unverified_contact", { status: "unverified" });
332
- const { outcome } = route("strangers");
321
+ const { outcome } = await route("strangers");
333
322
  expect(outcome.action).toBe("normal_call");
334
323
  });
335
324
 
336
- test("null policy preserves legacy name_capture for unknown caller", () => {
325
+ test("null policy preserves legacy name_capture for unknown caller", async () => {
337
326
  nextTrust = makeTrust("unknown");
338
- expect(route(null).outcome.action).toBe("name_capture");
327
+ expect((await route(null)).outcome.action).toBe("name_capture");
339
328
  });
340
329
 
341
- test("null policy preserves legacy unverified_caller for unverified caller", () => {
330
+ test("null policy preserves legacy unverified_caller for unverified caller", async () => {
342
331
  nextTrust = makeTrust("unverified_contact", { status: "unverified" });
343
- expect(route(null).outcome.action).toBe("unverified_caller");
332
+ expect((await route(null)).outcome.action).toBe("unverified_caller");
344
333
  });
345
334
 
346
- test("trusted_contacts (default) still denies unknown and unverified", () => {
335
+ test("trusted_contacts (default) still denies unknown and unverified", async () => {
347
336
  nextTrust = makeTrust("unknown");
348
- expect(route("trusted_contacts").outcome.action).toBe("deny");
337
+ expect((await route("trusted_contacts")).outcome.action).toBe("deny");
349
338
  nextTrust = makeTrust("unverified_contact", { status: "unverified" });
350
- expect(route("trusted_contacts").outcome.action).toBe("deny");
339
+ expect((await route("trusted_contacts")).outcome.action).toBe("deny");
351
340
  });
352
341
  });
353
342
 
@@ -356,33 +345,68 @@ describe("routeSetup — permissive floor admits to normal_call", () => {
356
345
  // ---------------------------------------------------------------------------
357
346
 
358
347
  describe("routeSetup — floor bypasses", () => {
359
- test("active voice invite bypasses the floor (no_one policy)", () => {
348
+ test("active voice invite bypasses the floor (no_one policy)", async () => {
360
349
  nextTrust = makeTrust("unknown");
361
- activeInvites = [
362
- {
363
- contactId: "contact-123",
364
- friendName: "Friend",
365
- guardianName: "Guardian",
366
- },
367
- ];
368
- boundContact = { displayName: "Friend Name" };
369
- const { outcome } = route("no_one");
350
+ activeVoiceInvite = {
351
+ inviteId: "inv-123",
352
+ inviteeName: "Friend Name",
353
+ guardianName: "Guardian",
354
+ codeDigits: 6,
355
+ };
356
+ const { outcome } = await route("no_one");
370
357
  expect(outcome.action).toBe("invite_redemption");
371
358
  if (outcome.action === "invite_redemption") {
372
359
  expect(outcome.inviteeName).toBe("Friend Name");
373
360
  }
374
361
  });
375
362
 
376
- test("pending verification challenge bypasses the floor (no_one policy)", () => {
363
+ test("pending verification challenge bypasses the floor (no_one policy)", async () => {
377
364
  // A pending challenge for a known member routes to verification regardless
378
365
  // of the floor.
379
366
  nextTrust = makeTrust("trusted_contact", { status: "active" });
380
367
  pendingChallenge = { id: "vs_1" };
381
- const { outcome } = route("no_one");
368
+ const { outcome } = await route("no_one");
382
369
  expect(outcome.action).toBe("verification");
383
370
  });
384
371
  });
385
372
 
373
+ // ---------------------------------------------------------------------------
374
+ // Fail-soft detection: the gateway reader resolves `null` on any gateway
375
+ // failure, so an unknown caller falls to the legacy identity flows instead of
376
+ // invite_redemption — detection never blocks setup on a gateway blip.
377
+ // ---------------------------------------------------------------------------
378
+
379
+ describe("routeSetup — fail-soft voice-invite detection", () => {
380
+ test("null gateway invite view (no invite / gateway error) → name_capture, not invite_redemption", async () => {
381
+ nextTrust = makeTrust("unknown");
382
+ activeVoiceInvite = null;
383
+ const { outcome } = await route(null);
384
+ expect(outcome.action).toBe("name_capture");
385
+ });
386
+
387
+ test("null gateway invite view for an unverified member → unverified_caller, not invite_redemption", async () => {
388
+ nextTrust = makeTrust("unverified_contact", { status: "unverified" });
389
+ activeVoiceInvite = null;
390
+ const { outcome } = await route(null);
391
+ expect(outcome.action).toBe("unverified_caller");
392
+ });
393
+
394
+ test("null inviteeName from the gateway keeps the neutral-greeting contract", async () => {
395
+ nextTrust = makeTrust("unknown");
396
+ activeVoiceInvite = {
397
+ inviteId: "inv-124",
398
+ inviteeName: null,
399
+ guardianName: null,
400
+ codeDigits: 6,
401
+ };
402
+ const { outcome } = await route(null);
403
+ expect(outcome.action).toBe("invite_redemption");
404
+ if (outcome.action === "invite_redemption") {
405
+ expect(outcome.inviteeName).toBeNull();
406
+ }
407
+ });
408
+ });
409
+
386
410
  // ---------------------------------------------------------------------------
387
411
  // Caller-trust source: gateway verdict first, local fallback
388
412
  // ---------------------------------------------------------------------------
@@ -414,8 +438,8 @@ function makeMemberVerdict(
414
438
  }
415
439
 
416
440
  describe("routeSetup — caller-trust source", () => {
417
- test("present verdict builds trust from the verdict (no local resolve)", () => {
418
- const { resolved, outcome } = route(
441
+ test("present verdict builds trust from the verdict (no local resolve)", async () => {
442
+ const { resolved, outcome } = await route(
419
443
  null,
420
444
  makeMemberVerdict("guardian", { status: "active" }),
421
445
  );
@@ -425,31 +449,31 @@ describe("routeSetup — caller-trust source", () => {
425
449
  expect(outcome.action).toBe("normal_call");
426
450
  });
427
451
 
428
- test("resolutionFailed verdict falls back to local resolveActorTrust", () => {
452
+ test("resolutionFailed verdict falls back to local resolveActorTrust", async () => {
429
453
  nextTrust = makeTrust("guardian", { status: "active", role: "guardian" });
430
- const { resolved } = route(null, makeVerdict({ resolutionFailed: true }));
454
+ const { resolved } = await route(null, makeVerdict({ resolutionFailed: true }));
431
455
 
432
456
  expect(resolveActorTrustMock).toHaveBeenCalledTimes(1);
433
457
  expect(resolved.actorTrust.trustClass).toBe("guardian");
434
458
  });
435
459
 
436
- test("null verdict falls back to local resolveActorTrust", () => {
460
+ test("null verdict falls back to local resolveActorTrust", async () => {
437
461
  nextTrust = makeTrust("trusted_contact", { status: "active" });
438
- const { resolved } = route(null, null);
462
+ const { resolved } = await route(null, null);
439
463
 
440
464
  expect(resolveActorTrustMock).toHaveBeenCalledTimes(1);
441
465
  expect(resolved.actorTrust.trustClass).toBe("trusted_contact");
442
466
  });
443
467
 
444
- test("absent verdict falls back to local resolveActorTrust", () => {
468
+ test("absent verdict falls back to local resolveActorTrust", async () => {
445
469
  nextTrust = makeTrust("guardian", { status: "active", role: "guardian" });
446
- route(null);
470
+ await route(null);
447
471
 
448
472
  expect(resolveActorTrustMock).toHaveBeenCalledTimes(1);
449
473
  });
450
474
 
451
- test("admission floor still applies on the verdict path (guardian_only denies trusted_contact)", () => {
452
- const { outcome } = route(
475
+ test("admission floor still applies on the verdict path (guardian_only denies trusted_contact)", async () => {
476
+ const { outcome } = await route(
453
477
  "guardian_only",
454
478
  makeMemberVerdict("trusted_contact", { status: "active" }),
455
479
  );
@@ -458,9 +482,9 @@ describe("routeSetup — caller-trust source", () => {
458
482
  expect(outcome.action).toBe("deny");
459
483
  });
460
484
 
461
- test("admission floor still applies on the fallback path (guardian_only denies trusted_contact)", () => {
485
+ test("admission floor still applies on the fallback path (guardian_only denies trusted_contact)", async () => {
462
486
  nextTrust = makeTrust("trusted_contact", { status: "active" });
463
- const { outcome } = route(
487
+ const { outcome } = await route(
464
488
  "guardian_only",
465
489
  makeVerdict({ resolutionFailed: true }),
466
490
  );
@@ -477,8 +501,8 @@ describe("routeSetup — caller-trust source", () => {
477
501
  // ---------------------------------------------------------------------------
478
502
 
479
503
  describe("routeSetup — verdict path enforces member ACL", () => {
480
- test("blocked member via verdict is denied (not normal_call) under permissive floor", () => {
481
- const { outcome } = route(
504
+ test("blocked member via verdict is denied (not normal_call) under permissive floor", async () => {
505
+ const { outcome } = await route(
482
506
  "strangers",
483
507
  makeMemberVerdict("unknown", { status: "blocked" }),
484
508
  );
@@ -487,8 +511,8 @@ describe("routeSetup — verdict path enforces member ACL", () => {
487
511
  expect(outcome.action).toBe("deny");
488
512
  });
489
513
 
490
- test("revoked member via verdict is denied under permissive floor", () => {
491
- const { outcome } = route(
514
+ test("revoked member via verdict is denied under permissive floor", async () => {
515
+ const { outcome } = await route(
492
516
  "strangers",
493
517
  makeMemberVerdict("unknown", { status: "revoked" }),
494
518
  );
@@ -497,8 +521,8 @@ describe("routeSetup — verdict path enforces member ACL", () => {
497
521
  expect(outcome.action).toBe("deny");
498
522
  });
499
523
 
500
- test("policy deny member via verdict is denied (not normal_call)", () => {
501
- const { outcome } = route(
524
+ test("policy deny member via verdict is denied (not normal_call)", async () => {
525
+ const { outcome } = await route(
502
526
  null,
503
527
  makeMemberVerdict("trusted_contact", {
504
528
  status: "active",
@@ -510,8 +534,8 @@ describe("routeSetup — verdict path enforces member ACL", () => {
510
534
  expect(outcome.action).toBe("deny");
511
535
  });
512
536
 
513
- test("policy escalate member via verdict is denied (live call can't await approval)", () => {
514
- const { outcome } = route(
537
+ test("policy escalate member via verdict is denied (live call can't await approval)", async () => {
538
+ const { outcome } = await route(
515
539
  null,
516
540
  makeMemberVerdict("trusted_contact", {
517
541
  status: "active",
@@ -523,8 +547,8 @@ describe("routeSetup — verdict path enforces member ACL", () => {
523
547
  expect(outcome.action).toBe("deny");
524
548
  });
525
549
 
526
- test("trusted/active member via verdict still admits to normal_call", () => {
527
- const { outcome } = route(
550
+ test("trusted/active member via verdict still admits to normal_call", async () => {
551
+ const { outcome } = await route(
528
552
  null,
529
553
  makeMemberVerdict("trusted_contact", {
530
554
  status: "active",
@@ -536,8 +560,8 @@ describe("routeSetup — verdict path enforces member ACL", () => {
536
560
  expect(outcome.action).toBe("normal_call");
537
561
  });
538
562
 
539
- test("guardian via verdict still admits to normal_call", () => {
540
- const { outcome } = route(
563
+ test("guardian via verdict still admits to normal_call", async () => {
564
+ const { outcome } = await route(
541
565
  null,
542
566
  makeMemberVerdict("guardian", { status: "active" }),
543
567
  );
@@ -555,9 +579,9 @@ describe("routeSetup — verdict path enforces member ACL", () => {
555
579
  // ---------------------------------------------------------------------------
556
580
 
557
581
  describe("routeSetup — unresolvable member verdict falls back to local", () => {
558
- test("member identity with missing status falls back to local resolveActorTrust", () => {
582
+ test("member identity with missing status falls back to local resolveActorTrust", async () => {
559
583
  nextTrust = makeTrust("trusted_contact", { status: "active" });
560
- const { resolved } = route(
584
+ const { resolved } = await route(
561
585
  null,
562
586
  makeVerdict({
563
587
  trustClass: "trusted_contact",
@@ -572,9 +596,9 @@ describe("routeSetup — unresolvable member verdict falls back to local", () =>
572
596
  expect(resolved.actorTrust.trustClass).toBe("trusted_contact");
573
597
  });
574
598
 
575
- test("member identity with unknown status falls back to local resolveActorTrust", () => {
599
+ test("member identity with unknown status falls back to local resolveActorTrust", async () => {
576
600
  nextTrust = makeTrust("trusted_contact", { status: "active" });
577
- route(
601
+ await route(
578
602
  null,
579
603
  makeVerdict({
580
604
  trustClass: "trusted_contact",
@@ -588,9 +612,9 @@ describe("routeSetup — unresolvable member verdict falls back to local", () =>
588
612
  expect(resolveActorTrustMock).toHaveBeenCalledTimes(1);
589
613
  });
590
614
 
591
- test("member identity with unknown policy falls back to local resolveActorTrust", () => {
615
+ test("member identity with unknown policy falls back to local resolveActorTrust", async () => {
592
616
  nextTrust = makeTrust("trusted_contact", { status: "active" });
593
- route(
617
+ await route(
594
618
  null,
595
619
  makeVerdict({
596
620
  trustClass: "trusted_contact",
@@ -604,15 +628,15 @@ describe("routeSetup — unresolvable member verdict falls back to local", () =>
604
628
  expect(resolveActorTrustMock).toHaveBeenCalledTimes(1);
605
629
  });
606
630
 
607
- test("real stranger verdict (no member identity) still takes the verdict path", () => {
608
- const { resolved } = route(null, makeVerdict({ trustClass: "unknown" }));
631
+ test("real stranger verdict (no member identity) still takes the verdict path", async () => {
632
+ const { resolved } = await route(null, makeVerdict({ trustClass: "unknown" }));
609
633
 
610
634
  expect(resolveActorTrustMock).not.toHaveBeenCalled();
611
635
  expect(resolved.actorTrust.trustClass).toBe("unknown");
612
636
  });
613
637
 
614
- test("valid member verdict (good status+policy) still takes the verdict path", () => {
615
- const { outcome } = route(
638
+ test("valid member verdict (good status+policy) still takes the verdict path", async () => {
639
+ const { outcome } = await route(
616
640
  null,
617
641
  makeMemberVerdict("trusted_contact", {
618
642
  status: "active",