@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -160,6 +160,14 @@ mock.module("node:fs", () => {
160
160
  };
161
161
  });
162
162
 
163
+ // Capture broadcastMessage calls
164
+ const broadcastedMessages: Array<{ type: string; [k: string]: unknown }> = [];
165
+ mock.module("../runtime/assistant-event-hub.js", () => ({
166
+ broadcastMessage: (msg: unknown) => {
167
+ broadcastedMessages.push(msg as { type: string; [k: string]: unknown });
168
+ },
169
+ }));
170
+
163
171
  // ─── Imports (after mocks) ──────────────────────────────────────────────────
164
172
 
165
173
  import {
@@ -168,38 +176,13 @@ import {
168
176
  handleRecordingStatusCore,
169
177
  handleRecordingStop,
170
178
  } from "../daemon/handlers/recording.js";
171
- import type { HandlerContext } from "../daemon/handlers/shared.js";
172
179
  import type { RecordingStatus } from "../daemon/message-types/computer-use.js";
173
- import { DebouncerMap } from "../util/debounce.js";
174
180
 
175
181
  // ─── Test helpers ───────────────────────────────────────────────────────────
176
182
 
177
- function createCtx(): {
178
- ctx: HandlerContext;
179
- sent: Array<{ type: string; [k: string]: unknown }>;
180
- } {
181
- const sent: Array<{ type: string; [k: string]: unknown }> = [];
182
-
183
- const ctx: HandlerContext = {
184
- sharedRequestTimestamps: [],
185
- debounceTimers: new DebouncerMap({ defaultDelayMs: 200 }),
186
- suppressConfigReload: false,
187
- setSuppressConfigReload: noop,
188
- updateConfigFingerprint: noop,
189
- send: (msg) => {
190
- sent.push(msg as { type: string; [k: string]: unknown });
191
- },
192
- broadcast: (msg) => {
193
- sent.push(msg as { type: string; [k: string]: unknown });
194
- },
195
- clearAllConversations: () => 0,
196
- getOrCreateConversation: () => {
197
- throw new Error("not implemented");
198
- },
199
- touchConversation: noop,
200
- };
201
-
202
- return { ctx, sent };
183
+ function createSent(): Array<{ type: string; [k: string]: unknown }> {
184
+ broadcastedMessages.length = 0;
185
+ return broadcastedMessages;
203
186
  }
204
187
 
205
188
  // ─── Tests ──────────────────────────────────────────────────────────────────
@@ -216,10 +199,10 @@ describe("handleRecordingStart", () => {
216
199
  });
217
200
 
218
201
  test("sends recording_start event and returns a UUID", () => {
219
- const { ctx, sent } = createCtx();
202
+ const sent = createSent();
220
203
  const conversationId = "conv-1";
221
204
 
222
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
205
+ const recordingId = handleRecordingStart(conversationId, undefined);
223
206
 
224
207
  expect(recordingId).not.toBeNull();
225
208
  // UUID v4 format
@@ -234,21 +217,21 @@ describe("handleRecordingStart", () => {
234
217
  });
235
218
 
236
219
  test("passes recording options through", () => {
237
- const { ctx, sent } = createCtx();
220
+ const sent = createSent();
238
221
  const options = { captureScope: "window" as const, includeAudio: true };
239
222
 
240
- handleRecordingStart("conv-2", options, ctx);
223
+ handleRecordingStart("conv-2", options);
241
224
 
242
225
  expect(sent[0].options).toEqual(options);
243
226
  });
244
227
 
245
228
  test("returns null when recording already active and sends no messages", () => {
246
- const { ctx, sent } = createCtx();
229
+ const sent = createSent();
247
230
 
248
- const id1 = handleRecordingStart("conv-3", undefined, ctx);
231
+ const id1 = handleRecordingStart("conv-3", undefined);
249
232
  expect(id1).toBeTruthy();
250
233
 
251
- const id2 = handleRecordingStart("conv-3", undefined, ctx);
234
+ const id2 = handleRecordingStart("conv-3", undefined);
252
235
 
253
236
  // Should return null (callers handle messaging)
254
237
  expect(id2).toBeNull();
@@ -259,13 +242,13 @@ describe("handleRecordingStart", () => {
259
242
  });
260
243
 
261
244
  test("returns null when a different conversation already has an active recording (global guard)", () => {
262
- const { ctx, sent } = createCtx();
245
+ const sent = createSent();
263
246
 
264
- const id1 = handleRecordingStart("conv-global-a", undefined, ctx);
247
+ const id1 = handleRecordingStart("conv-global-a", undefined);
265
248
  expect(id1).toBeTruthy();
266
249
 
267
250
  // A second start from a different conversation should be rejected
268
- const id2 = handleRecordingStart("conv-global-b", undefined, ctx);
251
+ const id2 = handleRecordingStart("conv-global-b", undefined);
269
252
  expect(id2).toBeNull();
270
253
 
271
254
  // Only the first call sends recording_start
@@ -287,15 +270,15 @@ describe("handleRecordingStop", () => {
287
270
  });
288
271
 
289
272
  test("sends recording_stop for an active recording", () => {
290
- const { ctx, sent } = createCtx();
273
+ const sent = createSent();
291
274
  const conversationId = "conv-stop-1";
292
275
 
293
276
  // Start a recording first
294
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
277
+ const recordingId = handleRecordingStart(conversationId, undefined);
295
278
  expect(recordingId).not.toBeNull();
296
279
  sent.length = 0; // Clear the start message
297
280
 
298
- const result = handleRecordingStop(conversationId, ctx);
281
+ const result = handleRecordingStop(conversationId);
299
282
 
300
283
  expect(result).toBe(recordingId!);
301
284
  expect(sent).toHaveLength(1);
@@ -304,27 +287,27 @@ describe("handleRecordingStop", () => {
304
287
  });
305
288
 
306
289
  test("returns undefined when no active recording exists", () => {
307
- const { ctx } = createCtx();
290
+ createSent();
308
291
 
309
- const result = handleRecordingStop("conv-no-recording", ctx);
292
+ const result = handleRecordingStop("conv-no-recording");
310
293
 
311
294
  expect(result).toBeUndefined();
312
295
  });
313
296
 
314
297
  test("resolves to globally active recording from a different conversation", () => {
315
- const { ctx, sent } = createCtx();
298
+ const sent = createSent();
316
299
  const convA = "conv-owner";
317
300
  const convB = "conv-stopper";
318
301
 
319
302
  // Bind socket to conv-A (the owning conversation)
320
303
 
321
304
  // Start a recording on conv-A
322
- const recordingId = handleRecordingStart(convA, undefined, ctx);
305
+ const recordingId = handleRecordingStart(convA, undefined);
323
306
  expect(recordingId).not.toBeNull();
324
307
  sent.length = 0;
325
308
 
326
309
  // Stop from conv-B — should resolve to the globally active recording on conv-A
327
- const result = handleRecordingStop(convB, ctx);
310
+ const result = handleRecordingStop(convB);
328
311
 
329
312
  expect(result).toBe(recordingId!);
330
313
  expect(sent).toHaveLength(1);
@@ -333,13 +316,13 @@ describe("handleRecordingStop", () => {
333
316
  });
334
317
 
335
318
  test("returns recordingId when stopped via broadcast", () => {
336
- const { ctx } = createCtx();
319
+ createSent();
337
320
  const conversationId = "conv-broadcast-stop";
338
321
 
339
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
322
+ const recordingId = handleRecordingStart(conversationId, undefined);
340
323
  expect(recordingId).not.toBeNull();
341
324
 
342
- const result = handleRecordingStop(conversationId, ctx);
325
+ const result = handleRecordingStop(conversationId);
343
326
 
344
327
  // Broadcast-based stop always returns the recordingId
345
328
  expect(result).toBe(recordingId!);
@@ -358,10 +341,10 @@ describe("handleRecordingStatusCore", () => {
358
341
  });
359
342
 
360
343
  test("handles started status without errors", async () => {
361
- const { ctx } = createCtx();
344
+ createSent();
362
345
  const conversationId = "conv-status-1";
363
346
 
364
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
347
+ const recordingId = handleRecordingStart(conversationId, undefined);
365
348
  expect(recordingId).not.toBeNull();
366
349
 
367
350
  const statusMsg: RecordingStatus = {
@@ -371,16 +354,16 @@ describe("handleRecordingStatusCore", () => {
371
354
  };
372
355
 
373
356
  // Should not throw
374
- await handleRecordingStatusCore(statusMsg, ctx);
357
+ await handleRecordingStatusCore(statusMsg);
375
358
  });
376
359
 
377
360
  test("handles stopped status with file — creates attachment and notifies client", async () => {
378
- const { ctx, sent } = createCtx();
361
+ const sent = createSent();
379
362
  const conversationId = "conv-status-stopped";
380
363
 
381
364
  // Bind socket
382
365
 
383
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
366
+ const recordingId = handleRecordingStart(conversationId, undefined);
384
367
  expect(recordingId).not.toBeNull();
385
368
  sent.length = 0;
386
369
 
@@ -399,7 +382,7 @@ describe("handleRecordingStatusCore", () => {
399
382
  durationMs: 5000,
400
383
  };
401
384
 
402
- await handleRecordingStatusCore(statusMsg, ctx);
385
+ await handleRecordingStatusCore(statusMsg);
403
386
 
404
387
  // Should have sent assistant_text_delta and message_complete
405
388
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
@@ -424,10 +407,10 @@ describe("handleRecordingStatusCore", () => {
424
407
  });
425
408
 
426
409
  test("handles stopped status and creates assistant message when none exists", async () => {
427
- const { ctx, sent } = createCtx();
410
+ const sent = createSent();
428
411
  const conversationId = "conv-status-no-msg";
429
412
 
430
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
413
+ const recordingId = handleRecordingStart(conversationId, undefined);
431
414
  expect(recordingId).not.toBeNull();
432
415
  sent.length = 0;
433
416
 
@@ -441,7 +424,7 @@ describe("handleRecordingStatusCore", () => {
441
424
  durationMs: 3000,
442
425
  };
443
426
 
444
- await handleRecordingStatusCore(statusMsg, ctx);
427
+ await handleRecordingStatusCore(statusMsg);
445
428
 
446
429
  // An assistant message should have been created via addMessage mock
447
430
  expect(mockMessages.length).toBeGreaterThanOrEqual(1);
@@ -450,12 +433,12 @@ describe("handleRecordingStatusCore", () => {
450
433
  });
451
434
 
452
435
  test("handles stopped status when file does not exist — notifies client", async () => {
453
- const { ctx, sent } = createCtx();
436
+ const sent = createSent();
454
437
  const conversationId = "conv-status-no-file";
455
438
 
456
439
  mockFileExists = false;
457
440
 
458
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
441
+ const recordingId = handleRecordingStart(conversationId, undefined);
459
442
  expect(recordingId).not.toBeNull();
460
443
  sent.length = 0;
461
444
 
@@ -468,7 +451,7 @@ describe("handleRecordingStatusCore", () => {
468
451
  };
469
452
 
470
453
  // Should not throw — the handler logs the error and notifies the client
471
- await handleRecordingStatusCore(statusMsg, ctx);
454
+ await handleRecordingStatusCore(statusMsg);
472
455
 
473
456
  // No attachment should have been created
474
457
  expect(mockAttachments.length).toBe(0);
@@ -484,13 +467,13 @@ describe("handleRecordingStatusCore", () => {
484
467
  });
485
468
 
486
469
  test("handles stopped status with zero-length file — treated as failure", async () => {
487
- const { ctx, sent } = createCtx();
470
+ const sent = createSent();
488
471
  const conversationId = "conv-status-zero-file";
489
472
 
490
473
  mockFileExists = true;
491
474
  mockFileSize = 0;
492
475
 
493
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
476
+ const recordingId = handleRecordingStart(conversationId, undefined);
494
477
  expect(recordingId).not.toBeNull();
495
478
  sent.length = 0;
496
479
 
@@ -502,7 +485,7 @@ describe("handleRecordingStatusCore", () => {
502
485
  durationMs: 2000,
503
486
  };
504
487
 
505
- await handleRecordingStatusCore(statusMsg, ctx);
488
+ await handleRecordingStatusCore(statusMsg);
506
489
 
507
490
  // No attachment should have been created for a zero-length file
508
491
  expect(mockAttachments.length).toBe(0);
@@ -525,13 +508,13 @@ describe("handleRecordingStatusCore", () => {
525
508
  });
526
509
 
527
510
  test("successful finalization — attachment created and success message sent", async () => {
528
- const { ctx, sent } = createCtx();
511
+ const sent = createSent();
529
512
  const conversationId = "conv-status-success";
530
513
 
531
514
  mockFileExists = true;
532
515
  mockFileSize = 4096;
533
516
 
534
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
517
+ const recordingId = handleRecordingStart(conversationId, undefined);
535
518
  expect(recordingId).not.toBeNull();
536
519
  sent.length = 0;
537
520
 
@@ -543,7 +526,7 @@ describe("handleRecordingStatusCore", () => {
543
526
  durationMs: 5000,
544
527
  };
545
528
 
546
- await handleRecordingStatusCore(statusMsg, ctx);
529
+ await handleRecordingStatusCore(statusMsg);
547
530
 
548
531
  // Attachment should have been created
549
532
  expect(mockAttachments.length).toBe(1);
@@ -562,13 +545,13 @@ describe("handleRecordingStatusCore", () => {
562
545
  });
563
546
 
564
547
  test("rejects file path outside allowed directory", async () => {
565
- const { ctx, sent } = createCtx();
548
+ const sent = createSent();
566
549
  const conversationId = "conv-status-outside-dir";
567
550
 
568
551
  mockFileExists = true;
569
552
  mockFileSize = 4096;
570
553
 
571
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
554
+ const recordingId = handleRecordingStart(conversationId, undefined);
572
555
  expect(recordingId).not.toBeNull();
573
556
  sent.length = 0;
574
557
 
@@ -580,7 +563,7 @@ describe("handleRecordingStatusCore", () => {
580
563
  durationMs: 5000,
581
564
  };
582
565
 
583
- await handleRecordingStatusCore(statusMsg, ctx);
566
+ await handleRecordingStatusCore(statusMsg);
584
567
 
585
568
  // No attachment should have been created — path is outside allowlist
586
569
  expect(mockAttachments.length).toBe(0);
@@ -598,10 +581,10 @@ describe("handleRecordingStatusCore", () => {
598
581
  });
599
582
 
600
583
  test("failed finalization — failure status sent and no success message", async () => {
601
- const { ctx, sent } = createCtx();
584
+ const sent = createSent();
602
585
  const conversationId = "conv-status-fail-final";
603
586
 
604
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
587
+ const recordingId = handleRecordingStart(conversationId, undefined);
605
588
  expect(recordingId).not.toBeNull();
606
589
  sent.length = 0;
607
590
 
@@ -613,7 +596,7 @@ describe("handleRecordingStatusCore", () => {
613
596
  error: "Video writer finished with non-completed status 3",
614
597
  };
615
598
 
616
- await handleRecordingStatusCore(statusMsg, ctx);
599
+ await handleRecordingStatusCore(statusMsg);
617
600
 
618
601
  // No attachment should have been created
619
602
  expect(mockAttachments.length).toBe(0);
@@ -632,10 +615,10 @@ describe("handleRecordingStatusCore", () => {
632
615
  });
633
616
 
634
617
  test("handles failed status and notifies client", async () => {
635
- const { ctx, sent } = createCtx();
618
+ const sent = createSent();
636
619
  const conversationId = "conv-status-failed";
637
620
 
638
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
621
+ const recordingId = handleRecordingStart(conversationId, undefined);
639
622
  expect(recordingId).not.toBeNull();
640
623
  sent.length = 0;
641
624
 
@@ -646,7 +629,7 @@ describe("handleRecordingStatusCore", () => {
646
629
  error: "Permission denied",
647
630
  };
648
631
 
649
- await handleRecordingStatusCore(statusMsg, ctx);
632
+ await handleRecordingStatusCore(statusMsg);
650
633
 
651
634
  // Should send error notification
652
635
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
@@ -659,10 +642,10 @@ describe("handleRecordingStatusCore", () => {
659
642
  });
660
643
 
661
644
  test("handles failed status with no error message", async () => {
662
- const { ctx, sent } = createCtx();
645
+ const sent = createSent();
663
646
  const conversationId = "conv-status-failed-no-err";
664
647
 
665
- const recordingId = handleRecordingStart(conversationId, undefined, ctx);
648
+ const recordingId = handleRecordingStart(conversationId, undefined);
666
649
  expect(recordingId).not.toBeNull();
667
650
  sent.length = 0;
668
651
 
@@ -672,7 +655,7 @@ describe("handleRecordingStatusCore", () => {
672
655
  status: "failed",
673
656
  };
674
657
 
675
- await handleRecordingStatusCore(statusMsg, ctx);
658
+ await handleRecordingStatusCore(statusMsg);
676
659
 
677
660
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
678
661
  expect(textDeltas.length).toBeGreaterThanOrEqual(1);
@@ -680,7 +663,7 @@ describe("handleRecordingStatusCore", () => {
680
663
  });
681
664
 
682
665
  test("handles status with attachToConversationId fallback", async () => {
683
- const { ctx, sent } = createCtx();
666
+ const sent = createSent();
684
667
  const conversationId = "conv-fallback";
685
668
 
686
669
  // Send a recording_status directly with attachToConversationId
@@ -694,7 +677,7 @@ describe("handleRecordingStatusCore", () => {
694
677
  };
695
678
 
696
679
  // Should not throw — uses attachToConversationId as fallback
697
- await handleRecordingStatusCore(statusMsg, ctx);
680
+ await handleRecordingStatusCore(statusMsg);
698
681
 
699
682
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
700
683
  expect(textDeltas.length).toBeGreaterThanOrEqual(1);
@@ -117,6 +117,7 @@ function buildContext(
117
117
  traceEvents.push({ event, body, options });
118
118
  },
119
119
  } as unknown as HistoryConversationContext["traceEmitter"],
120
+ sendToClient: () => {},
120
121
  messages,
121
122
  processing: false,
122
123
  abortController: null,
@@ -139,7 +140,7 @@ describe("regenerate fire-and-forget error path", () => {
139
140
  },
140
141
  });
141
142
 
142
- await regenerate(session, () => {}, "req-123");
143
+ await regenerate(session, "req-123");
143
144
 
144
145
  // Give the fire-and-forget .catch() a tick to run.
145
146
  await new Promise((resolve) => setImmediate(resolve));
@@ -167,7 +168,7 @@ describe("regenerate fire-and-forget error path", () => {
167
168
  },
168
169
  });
169
170
 
170
- await regenerate(session, () => {});
171
+ await regenerate(session);
171
172
 
172
173
  await new Promise((resolve) => setImmediate(resolve));
173
174
 
@@ -185,7 +186,7 @@ describe("regenerate fire-and-forget error path", () => {
185
186
  runAgentLoop: async () => {},
186
187
  });
187
188
 
188
- await regenerate(session, () => {}, "req-ok");
189
+ await regenerate(session, "req-ok");
189
190
 
190
191
  await new Promise((resolve) => setImmediate(resolve));
191
192
 
@@ -215,10 +215,7 @@ import {
215
215
  } from "../calls/relay-server.js";
216
216
  import { setVoiceBridgeDeps } from "../calls/voice-session-bridge.js";
217
217
  import { upsertContact } from "../contacts/contact-store.js";
218
- import {
219
- createGuardianBinding,
220
- upsertContactChannel,
221
- } from "../contacts/contacts-write.js";
218
+ import { upsertContactChannel } from "../contacts/contacts-write.js";
222
219
  import {
223
220
  listCanonicalGuardianRequests,
224
221
  resolveCanonicalGuardianRequest,
@@ -238,6 +235,7 @@ import {
238
235
  getGuardianBinding,
239
236
  } from "../runtime/channel-verification-service.js";
240
237
  import { generateVoiceCode, hashVoiceCode } from "../util/voice-code.js";
238
+ import { createGuardianBinding } from "./helpers/create-guardian-binding.js";
241
239
 
242
240
  initializeDb();
243
241
 
@@ -1419,9 +1417,11 @@ describe("relay-server", () => {
1419
1417
  expect(relay.isVerificationSessionActive()).toBe(false);
1420
1418
  expect(relay.getConnectionState()).toBe("connected");
1421
1419
 
1422
- // Guardian binding should have been created
1420
+ // Guardian binding is NOT created by the assistant — the gateway owns
1421
+ // binding creation for inbound voice verification. The assistant only
1422
+ // transitions to connected state and starts the normal call flow.
1423
1423
  const binding = getGuardianBinding("self", "phone");
1424
- expect(binding).not.toBeNull();
1424
+ expect(binding).toBeNull();
1425
1425
 
1426
1426
  // Orchestrator greeting should have fired
1427
1427
  const textMessages = ws.sentMessages
@@ -1490,9 +1490,9 @@ describe("relay-server", () => {
1490
1490
  expect(relay.isVerificationSessionActive()).toBe(false);
1491
1491
  expect(relay.getConnectionState()).toBe("connected");
1492
1492
 
1493
- // Binding created
1493
+ // Binding is NOT created by the assistant — gateway owns this.
1494
1494
  const binding = getGuardianBinding("self", "phone");
1495
- expect(binding).not.toBeNull();
1495
+ expect(binding).toBeNull();
1496
1496
 
1497
1497
  // Greeting should have started
1498
1498
  const textMessages = ws.sentMessages
@@ -1746,18 +1746,23 @@ describe("relay-server", () => {
1746
1746
 
1747
1747
  await new Promise((resolve) => setTimeout(resolve, 10));
1748
1748
 
1749
+ // The gateway creates the guardian binding before the ConversationRelay
1750
+ // WebSocket is established, so resolveActorTrust() would find it in
1751
+ // production. Without a gateway in this test, trust reflects the
1752
+ // resolved state without a binding.
1749
1753
  const postVerify = (
1750
1754
  relay.getController() as unknown as {
1751
1755
  trustContext?: {
1752
1756
  sourceChannel?: string;
1753
1757
  trustClass?: string;
1754
- guardianExternalUserId?: string;
1755
1758
  };
1756
1759
  }
1757
1760
  )?.trustContext;
1758
1761
  expect(postVerify?.sourceChannel).toBe("phone");
1759
- expect(postVerify?.trustClass).toBe("guardian");
1760
- expect(postVerify?.guardianExternalUserId).toBe(session.fromNumber);
1762
+ // Trust class is 'unknown' because the gateway creates the binding
1763
+ // before the relay is established. Without a gateway in this test,
1764
+ // resolveActorTrust finds no guardian binding.
1765
+ expect(postVerify?.trustClass).toBe("unknown");
1761
1766
 
1762
1767
  relay.destroy();
1763
1768
  });
@@ -4034,9 +4039,9 @@ describe("relay-server", () => {
4034
4039
  expect(relay.isVerificationSessionActive()).toBe(false);
4035
4040
  expect(relay.getConnectionState()).toBe("connected");
4036
4041
 
4037
- // Guardian binding should have been created
4042
+ // Guardian binding is NOT created by the assistant — gateway owns this.
4038
4043
  const binding = getGuardianBinding("self", "phone");
4039
- expect(binding).not.toBeNull();
4044
+ expect(binding).toBeNull();
4040
4045
 
4041
4046
  // Normal greeting should fire (from mockSendMessage), not the handoff copy
4042
4047
  const textMessages = ws.sentMessages
@@ -54,8 +54,6 @@ const mockConfig = {
54
54
  rateLimit: { maxRequestsPerMinute: 0 },
55
55
  secretDetection: {
56
56
  enabled: false,
57
- action: "warn" as const,
58
- entropyThreshold: 4.0,
59
57
  },
60
58
  };
61
59
 
@@ -136,10 +134,6 @@ mock.module("../tools/shared/filesystem/path-policy.js", () => ({
136
134
  hostPolicy: () => ({ ok: false }),
137
135
  }));
138
136
 
139
- mock.module("../tools/terminal/sandbox.js", () => ({
140
- wrapCommand: () => ({ command: "", sandboxed: false }),
141
- }));
142
-
143
137
  import { PermissionPrompter } from "../permissions/prompter.js";
144
138
  import { ToolExecutor } from "../tools/executor.js";
145
139
  import type { ToolContext as TC } from "../tools/types.js";
@@ -231,7 +225,11 @@ describe("requireFreshApproval: non-interactive guardian denial", () => {
231
225
  const result = await executor.execute(
232
226
  "bash",
233
227
  { command: "echo hello" },
234
- makeContext({ isInteractive: false, trustClass: "guardian", requireFreshApproval: true }),
228
+ makeContext({
229
+ isInteractive: false,
230
+ trustClass: "guardian",
231
+ requireFreshApproval: true,
232
+ }),
235
233
  );
236
234
 
237
235
  expect(result.isError).toBe(true);
@@ -283,7 +281,11 @@ describe("requireFreshApproval: non-interactive guardian denial", () => {
283
281
  const result = await executor.execute(
284
282
  "gmail_send_draft",
285
283
  { draft_id: "draft-123", confidence: 0.99 },
286
- makeContext({ isInteractive: false, trustClass: "guardian", requireFreshApproval: true }),
284
+ makeContext({
285
+ isInteractive: false,
286
+ trustClass: "guardian",
287
+ requireFreshApproval: true,
288
+ }),
287
289
  );
288
290
 
289
291
  expect(result.isError).toBe(true);
@@ -318,12 +320,9 @@ describe("requireFreshApproval: persistent decisions disabled", () => {
318
320
  checkResultOverride = undefined;
319
321
  scopeOptionsOverride = undefined;
320
322
  riskOverride = "high";
321
-
322
323
  });
323
324
 
324
- afterEach(() => {
325
-
326
- });
325
+ afterEach(() => {});
327
326
 
328
327
  test("manage_secure_command_tool prompt does not offer persistent decisions", async () => {
329
328
  checkResultOverride = { decision: "allow", reason: "Matched trust rule" };
@@ -372,8 +371,6 @@ describe("requireFreshApproval: persistent decisions disabled", () => {
372
371
  expect(promptEvent).toBeDefined();
373
372
  expect(promptEvent!.persistentDecisionsAllowed).toBe(false);
374
373
  });
375
-
376
-
377
374
  });
378
375
 
379
376
  // ---------------------------------------------------------------------------
@@ -386,12 +383,9 @@ describe("requireFreshApproval: grant-consumed does not skip permission check",
386
383
  checkResultOverride = undefined;
387
384
  scopeOptionsOverride = undefined;
388
385
  riskOverride = "high";
389
-
390
386
  });
391
387
 
392
- afterEach(() => {
393
-
394
- });
388
+ afterEach(() => {});
395
389
 
396
390
  test("manage_secure_command_tool is prompted even when executor sets requireFreshApproval and grantConsumed would normally short-circuit", async () => {
397
391
  // This test verifies the code path in executor.ts where the
@@ -441,12 +435,9 @@ describe("requireFreshApproval: context flag propagation", () => {
441
435
  checkResultOverride = undefined;
442
436
  scopeOptionsOverride = undefined;
443
437
  riskOverride = "high";
444
-
445
438
  });
446
439
 
447
- afterEach(() => {
448
-
449
- });
440
+ afterEach(() => {});
450
441
 
451
442
  test("manage_secure_command_tool sets both forcePromptSideEffects and requireFreshApproval", async () => {
452
443
  checkResultOverride = { decision: "allow", reason: "Matched trust rule" };
@@ -34,9 +34,9 @@ mock.module("../config/loader.js", () => ({
34
34
  mock.module("../daemon/process-message.js", () => ({
35
35
  resolveTurnChannel: () => "whatsapp",
36
36
  resolveTurnInterface: () => "whatsapp",
37
- makePendingInteractionRegistrar: () => () => {},
38
37
  prepareConversationForMessage: async () => ({}),
39
38
  processMessage: async () => ({ messageId: `mock-msg-${Date.now()}` }),
39
+ processMessageInBackground: async () => ({ messageId: "mock-bg" }),
40
40
  }));
41
41
 
42
42
  mock.module("../daemon/approval-generators.js", () => ({
@@ -72,7 +72,7 @@ async function publishAndReadFrame(
72
72
  abortSignal: ac.signal,
73
73
  });
74
74
 
75
- const event = buildAssistantEvent("self", message, conversationId);
75
+ const event = buildAssistantEvent(message, conversationId);
76
76
  await assistantEventHub.publish(event);
77
77
 
78
78
  const reader = stream.getReader();
@@ -322,7 +322,7 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
322
322
 
323
323
  // ── Envelope integrity ───────────────────────────────────────────────────
324
324
 
325
- test("SSE envelope preserves assistantId and conversationId across all event types", async () => {
325
+ test("SSE envelope preserves conversationId across all event types", async () => {
326
326
  const conversationKey = "parity-envelope-check";
327
327
  const { conversationId } = getOrCreateConversation(conversationKey);
328
328
 
@@ -338,7 +338,7 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
338
338
  type: "assistant_text_delta" as const,
339
339
  text: "envelope test",
340
340
  };
341
- const published = buildAssistantEvent("self", msg, conversationId);
341
+ const published = buildAssistantEvent(msg, conversationId);
342
342
  await assistantEventHub.publish(published);
343
343
 
344
344
  const reader = stream.getReader();
@@ -358,7 +358,6 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
358
358
 
359
359
  // Envelope fields
360
360
  expect(received.id).toBe(published.id);
361
- expect(received.assistantId).toBe("self");
362
361
  expect(received.conversationId).toBe(conversationId);
363
362
  expect(received.emittedAt).toBe(published.emittedAt);
364
363
  // SSE frame fields