@vellumai/assistant 0.10.12 → 0.11.0-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (809) hide show
  1. package/AGENTS.md +1 -1
  2. package/ARCHITECTURE.md +4 -5
  3. package/README.md +1 -1
  4. package/docs/architecture/memory.md +60 -23
  5. package/docs/error-handling.md +3 -3
  6. package/docs/guardian-request-flow.md +112 -0
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
  13. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
  14. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
  15. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
  16. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
  17. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
  19. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  23. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  24. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  25. package/node_modules/@vellumai/gateway-client/package.json +1 -1
  26. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
  27. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
  28. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  29. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  30. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  31. package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  32. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  33. package/openapi.yaml +264 -14
  34. package/package.json +2 -2
  35. package/src/__tests__/acp-session.test.ts +3 -3
  36. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
  37. package/src/__tests__/anthropic-provider.test.ts +40 -0
  38. package/src/__tests__/app-conversation-ids-backfill.test.ts +33 -2
  39. package/src/__tests__/app-conversation-ids.test.ts +204 -0
  40. package/src/__tests__/approval-cascade.test.ts +5 -5
  41. package/src/__tests__/approval-routes-http.test.ts +3 -3
  42. package/src/__tests__/ask-question-resolver.test.ts +207 -0
  43. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  44. package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
  45. package/src/__tests__/assistant-event-hub.test.ts +13 -11
  46. package/src/__tests__/assistant-event.test.ts +12 -9
  47. package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
  48. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
  49. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
  50. package/src/__tests__/assistant-stream-state.test.ts +17 -7
  51. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  52. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  53. package/src/__tests__/call-conversation-messages.test.ts +134 -18
  54. package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
  55. package/src/__tests__/channel-approvals.test.ts +0 -27
  56. package/src/__tests__/channel-guardian.test.ts +85 -512
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
  58. package/src/__tests__/channel-retry-sweep.test.ts +88 -1
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
  60. package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
  61. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
  62. package/src/__tests__/compaction-events.test.ts +8 -8
  63. package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
  64. package/src/__tests__/config-model-image-provider.test.ts +20 -0
  65. package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
  66. package/src/__tests__/config-schema.test.ts +14 -2
  67. package/src/__tests__/config-set-platform-guard.test.ts +11 -12
  68. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  69. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
  70. package/src/__tests__/context-search-memory-source.test.ts +1 -1
  71. package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
  72. package/src/__tests__/context-token-estimator.test.ts +54 -1
  73. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
  74. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
  75. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  76. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
  77. package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
  78. package/src/__tests__/conversation-agent-loop.test.ts +39 -30
  79. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  80. package/src/__tests__/conversation-evictor.test.ts +49 -0
  81. package/src/__tests__/conversation-fork-crud.test.ts +1 -1
  82. package/src/__tests__/conversation-group-tools.test.ts +279 -0
  83. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  84. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  85. package/src/__tests__/conversation-lineage.test.ts +235 -0
  86. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
  87. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  88. package/src/__tests__/conversation-queue.test.ts +81 -81
  89. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
  90. package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
  91. package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
  92. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
  93. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  94. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  95. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  96. package/src/__tests__/conversation-summarize-route.test.ts +9 -0
  97. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
  98. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  99. package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
  100. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  101. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  102. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  103. package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
  104. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
  105. package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
  106. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  107. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  108. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  109. package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
  110. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
  111. package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
  112. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  113. package/src/__tests__/daemon-assistant-events.test.ts +14 -15
  114. package/src/__tests__/db-test-helpers.ts +13 -27
  115. package/src/__tests__/disk-pressure-routes.test.ts +12 -3
  116. package/src/__tests__/document-tool-security.test.ts +95 -0
  117. package/src/__tests__/drain-kick-guard.test.ts +232 -0
  118. package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
  119. package/src/__tests__/emit-event-signal.test.ts +5 -6
  120. package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
  121. package/src/__tests__/events-tail-route.test.ts +6 -4
  122. package/src/__tests__/feature-flag-test-helpers.ts +10 -20
  123. package/src/__tests__/file-edit-tool.test.ts +24 -4
  124. package/src/__tests__/file-list-tool.test.ts +2 -1
  125. package/src/__tests__/file-read-tool.test.ts +62 -10
  126. package/src/__tests__/file-write-tool.test.ts +24 -5
  127. package/src/__tests__/followup-tools.test.ts +58 -0
  128. package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
  129. package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
  130. package/src/__tests__/guardian-question-mode.test.ts +42 -3
  131. package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
  132. package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
  133. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  134. package/src/__tests__/heartbeat-service.test.ts +1 -0
  135. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  136. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  137. package/src/__tests__/host-file-edit-tool.test.ts +3 -3
  138. package/src/__tests__/host-file-read-tool.test.ts +2 -2
  139. package/src/__tests__/host-file-write-tool.test.ts +7 -3
  140. package/src/__tests__/host-shell-tool.test.ts +17 -5
  141. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  142. package/src/__tests__/image-credentials.test.ts +65 -8
  143. package/src/__tests__/injection-block.test.ts +4 -4
  144. package/src/__tests__/injector-chain.test.ts +1 -1
  145. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  146. package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
  147. package/src/__tests__/injector-v3-suppression.test.ts +6 -4
  148. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
  149. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  150. package/src/__tests__/llm-usage-store.test.ts +67 -4
  151. package/src/__tests__/log-redact.test.ts +18 -0
  152. package/src/__tests__/managed-profile-guard.test.ts +27 -0
  153. package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
  154. package/src/__tests__/media-generate-image.test.ts +62 -11
  155. package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
  156. package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
  157. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  158. package/src/__tests__/notification-decision-strategy.test.ts +115 -11
  159. package/src/__tests__/notification-deep-link.test.ts +12 -12
  160. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  161. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  162. package/src/__tests__/path-policy.test.ts +315 -0
  163. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  164. package/src/__tests__/persistence-layering-guard.test.ts +2 -2
  165. package/src/__tests__/pkb-autoinject.test.ts +1 -1
  166. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
  167. package/src/__tests__/platform-callback-registration.test.ts +10 -10
  168. package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
  169. package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
  170. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
  171. package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
  172. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  173. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
  174. package/src/__tests__/require-fresh-approval.test.ts +38 -38
  175. package/src/__tests__/resolve-app-id.test.ts +32 -0
  176. package/src/__tests__/run-due-schedules.test.ts +72 -1
  177. package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
  178. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  179. package/src/__tests__/schedule-routes.test.ts +44 -5
  180. package/src/__tests__/schedule-store.test.ts +3 -3
  181. package/src/__tests__/schedule-tools.test.ts +176 -0
  182. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  183. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  184. package/src/__tests__/secret-response-routing.test.ts +3 -3
  185. package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
  186. package/src/__tests__/secret-scanner.test.ts +36 -0
  187. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  188. package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
  189. package/src/__tests__/starter-task-flow.test.ts +26 -3
  190. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  191. package/src/__tests__/subagent-disposal.test.ts +40 -11
  192. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  193. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  194. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  195. package/src/__tests__/subagent-manager-notify.test.ts +73 -14
  196. package/src/__tests__/subagent-notify-parent.test.ts +48 -4
  197. package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
  198. package/src/__tests__/subagent-tools.test.ts +64 -0
  199. package/src/__tests__/sync-message-contract.test.ts +3 -3
  200. package/src/__tests__/terminal-tools.test.ts +12 -3
  201. package/src/__tests__/test-preload.ts +9 -0
  202. package/src/__tests__/tool-approval-handler.test.ts +587 -43
  203. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
  204. package/src/__tests__/tool-executor.test.ts +116 -0
  205. package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
  206. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
  207. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  208. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  209. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  210. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
  211. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  212. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  213. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  214. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  215. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
  216. package/src/__tests__/workspace-policy.test.ts +482 -2
  217. package/src/acp/__tests__/client-handler.test.ts +3 -3
  218. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  219. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  220. package/src/acp/client-handler.ts +3 -3
  221. package/src/acp/session-manager.ts +8 -8
  222. package/src/api/events/subagent-event.ts +2 -2
  223. package/src/api/responses/memory-v2-activation-log.ts +2 -2
  224. package/src/api/responses/subagent-detail.ts +13 -0
  225. package/src/approvals/AGENTS.md +2 -0
  226. package/src/approvals/guardian-request-resolvers.ts +118 -24
  227. package/src/apps/app-store.ts +95 -4
  228. package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
  229. package/src/calls/__tests__/voice-session-bridge.test.ts +229 -7
  230. package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
  231. package/src/calls/call-controller.ts +27 -27
  232. package/src/calls/call-conversation-messages.ts +58 -18
  233. package/src/calls/voice-control-protocol.ts +56 -0
  234. package/src/calls/voice-session-bridge.ts +178 -65
  235. package/src/calls/voice-triage-escalate.ts +2 -3
  236. package/src/channels/config.ts +8 -0
  237. package/src/channels/types.ts +1 -0
  238. package/src/cli/commands/config.ts +49 -13
  239. package/src/cli/commands/memory/index.help.ts +4 -2
  240. package/src/cli/commands/memory/memory-retrospective.ts +5 -0
  241. package/src/cli/commands/webhooks.help.ts +9 -4
  242. package/src/cli/lib/bundled-marketplace.json +12 -0
  243. package/src/cli.ts +2 -109
  244. package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
  245. package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
  246. package/src/config/assistant-feature-flags.ts +1 -1
  247. package/src/config/bundled-skills/conversation-groups/SKILL.md +29 -0
  248. package/src/config/bundled-skills/conversation-groups/TOOLS.json +58 -0
  249. package/src/config/bundled-skills/conversation-groups/tools/group-create.ts +12 -0
  250. package/src/config/bundled-skills/conversation-groups/tools/group-list.ts +12 -0
  251. package/src/config/bundled-skills/conversation-groups/tools/move-to-group.ts +12 -0
  252. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
  253. package/src/config/bundled-skills/schedule/SKILL.md +2 -0
  254. package/src/config/feature-flag-cache.ts +6 -16
  255. package/src/config/feature-flag-registry.json +14 -38
  256. package/src/config/loader.ts +7 -1
  257. package/src/config/memory-tier.ts +15 -10
  258. package/src/config/memory-v3-gate.test.ts +278 -1
  259. package/src/config/memory-v3-gate.ts +88 -26
  260. package/src/config/raw-config-utils.ts +1 -1
  261. package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
  262. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  263. package/src/config/schemas/live-voice.ts +33 -7
  264. package/src/config/schemas/llm.ts +1 -0
  265. package/src/config/schemas/memory-retrospective.ts +13 -0
  266. package/src/config/schemas/memory-substrate.ts +183 -0
  267. package/src/config/schemas/memory-v2.ts +3 -2
  268. package/src/config/schemas/memory-v3.ts +11 -4
  269. package/src/config/schemas/memory.ts +35 -1
  270. package/src/config/schemas/services.ts +10 -2
  271. package/src/config/substrate-twin-shadowing.ts +195 -0
  272. package/src/config/webhook-routing.ts +67 -0
  273. package/src/context/compactor.ts +10 -3
  274. package/src/context/token-estimator.ts +21 -0
  275. package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
  276. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  277. package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
  278. package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
  279. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  280. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  281. package/src/daemon/channel-ui-capability.ts +70 -1
  282. package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
  283. package/src/daemon/conversation-agent-loop.ts +12 -5
  284. package/src/daemon/conversation-evictor.ts +26 -4
  285. package/src/daemon/conversation-launch.ts +11 -14
  286. package/src/daemon/conversation-lineage.ts +76 -0
  287. package/src/daemon/conversation-messaging.ts +14 -14
  288. package/src/daemon/conversation-notifiers.ts +2 -2
  289. package/src/daemon/conversation-process.ts +133 -21
  290. package/src/daemon/conversation-queue-manager.ts +7 -7
  291. package/src/daemon/conversation-runtime-assembly.ts +16 -0
  292. package/src/daemon/conversation-store.ts +11 -3
  293. package/src/daemon/conversation-surfaces.ts +8 -14
  294. package/src/daemon/conversation-tool-setup.ts +13 -7
  295. package/src/daemon/conversation-usage.ts +12 -11
  296. package/src/daemon/conversation.ts +38 -15
  297. package/src/daemon/disk-pressure-guard.ts +5 -12
  298. package/src/daemon/embedding-reconcile.ts +14 -9
  299. package/src/daemon/handlers/config-channels.ts +40 -134
  300. package/src/daemon/handlers/config-model.ts +15 -7
  301. package/src/daemon/handlers/conversations.ts +4 -2
  302. package/src/daemon/handlers/shared.ts +29 -0
  303. package/src/daemon/host-proxy-base.ts +4 -4
  304. package/src/daemon/lifecycle.ts +13 -0
  305. package/src/daemon/message-protocol.ts +8 -144
  306. package/src/daemon/message-types/computer-use.ts +0 -12
  307. package/src/daemon/message-types/conversations.ts +9 -345
  308. package/src/daemon/message-types/host-app-control.ts +0 -9
  309. package/src/daemon/message-types/host-browser.ts +0 -7
  310. package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
  311. package/src/daemon/message-types/messages.ts +0 -48
  312. package/src/daemon/message-types/notifications.ts +0 -7
  313. package/src/daemon/message-types/skills.ts +0 -5
  314. package/src/daemon/message-types/surfaces.ts +0 -9
  315. package/src/daemon/message-types/sync.ts +0 -2
  316. package/src/daemon/process-message.ts +5 -5
  317. package/src/daemon/skill-memory-refresh.ts +5 -5
  318. package/src/daemon/tool-side-effects.ts +32 -16
  319. package/src/daemon/trust-context.ts +1 -1
  320. package/src/daemon/wake-conversation-ops.ts +4 -4
  321. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
  322. package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
  323. package/src/heartbeat/heartbeat-run-store.ts +81 -4
  324. package/src/heartbeat/heartbeat-service.ts +32 -1
  325. package/src/home/__tests__/feed-writer.test.ts +7 -7
  326. package/src/home/__tests__/home-content-refresh.test.ts +3 -0
  327. package/src/home/__tests__/suggested-prompts.test.ts +1 -0
  328. package/src/home/feed-writer.ts +6 -13
  329. package/src/home/home-content-refresh.ts +6 -9
  330. package/src/home/relationship-state-writer.ts +5 -12
  331. package/src/home/suggested-prompts-cache.ts +6 -19
  332. package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
  333. package/src/ipc/events-publish-client.ts +44 -0
  334. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  335. package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
  336. package/src/ipc/routes/events-ipc-routes.ts +11 -31
  337. package/src/live-voice/__tests__/front-decision.test.ts +4 -176
  338. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
  339. package/src/live-voice/__tests__/live-voice-continuation-fork-hydration.test.ts +286 -0
  340. package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
  341. package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
  342. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
  343. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
  344. package/src/live-voice/__tests__/live-voice-vad.test.ts +1154 -636
  345. package/src/live-voice/front-decision.ts +5 -155
  346. package/src/live-voice/live-voice-metrics.ts +4 -1
  347. package/src/live-voice/live-voice-session.ts +1288 -439
  348. package/src/live-voice/progress-phrases.ts +17 -0
  349. package/src/live-voice/protocol.ts +15 -0
  350. package/src/media/app-icon-generator.ts +15 -8
  351. package/src/media/avatar-router.ts +9 -5
  352. package/src/media/image-credentials.ts +42 -10
  353. package/src/media/image-service.ts +1 -13
  354. package/src/media/types.ts +26 -3
  355. package/src/notifications/AGENTS.md +2 -0
  356. package/src/notifications/__tests__/broadcaster.test.ts +95 -0
  357. package/src/notifications/adapters/macos.ts +3 -3
  358. package/src/notifications/broadcaster.ts +57 -0
  359. package/src/notifications/copy-composer.ts +0 -15
  360. package/src/notifications/decision-engine.ts +21 -22
  361. package/src/notifications/guardian-question-mode.ts +57 -2
  362. package/src/notifications/home-feed-side-effect.ts +4 -0
  363. package/src/notifications/signal.ts +6 -4
  364. package/src/notifications/trusted-contact-payloads.ts +3 -4
  365. package/src/notifications/vellum-card-affinity.ts +39 -0
  366. package/src/oauth/AGENTS.md +1 -1
  367. package/src/permissions/channel-permission-query.test.ts +69 -0
  368. package/src/permissions/channel-permission-query.ts +73 -1
  369. package/src/permissions/checker.test.ts +298 -15
  370. package/src/permissions/checker.ts +102 -36
  371. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  372. package/src/permissions/confirmation-guardian-request.ts +2 -2
  373. package/src/permissions/gateway-threshold-reader.test.ts +224 -17
  374. package/src/permissions/gateway-threshold-reader.ts +82 -10
  375. package/src/permissions/ipc-risk-types.ts +8 -0
  376. package/src/permissions/prompter.ts +5 -5
  377. package/src/permissions/question-guardian-request.test.ts +222 -0
  378. package/src/permissions/question-guardian-request.ts +179 -0
  379. package/src/permissions/question-prompter.test.ts +8 -8
  380. package/src/permissions/question-prompter.ts +18 -0
  381. package/src/permissions/secret-prompter.ts +2 -4
  382. package/src/permissions/workspace-policy.ts +269 -34
  383. package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
  384. package/src/persistence/__tests__/message-content-file.test.ts +58 -3
  385. package/src/persistence/conversation-crud.ts +93 -0
  386. package/src/persistence/conversation-key-store.ts +63 -0
  387. package/src/persistence/conversation-parent.ts +27 -0
  388. package/src/persistence/db-async-query.ts +1 -1
  389. package/src/persistence/db-singleton.ts +14 -27
  390. package/src/persistence/delivery-crud.ts +45 -0
  391. package/src/persistence/embeddings/embedding-backend.ts +2 -1
  392. package/src/persistence/embeddings/embedding-identity.ts +7 -3
  393. package/src/persistence/job-utils.ts +32 -27
  394. package/src/persistence/jobs-store.ts +92 -3
  395. package/src/persistence/lifecycle-quiesce.ts +80 -0
  396. package/src/persistence/llm-usage-store.ts +45 -8
  397. package/src/persistence/message-content-file.ts +4 -4
  398. package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
  399. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
  400. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
  401. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
  402. package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
  403. package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
  404. package/src/persistence/migrations/354-backfill-app-conversation-lineage.ts +41 -0
  405. package/src/persistence/schema/infrastructure.ts +11 -0
  406. package/src/persistence/steps.ts +9 -1
  407. package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
  408. package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
  409. package/src/plugin-api/conversation-turn.ts +4 -4
  410. package/src/plugin-api/event-hub-facade.ts +15 -6
  411. package/src/plugin-api/index.ts +10 -4
  412. package/src/plugin-api/publish-event.ts +36 -0
  413. package/src/plugins/AGENTS.md +2 -0
  414. package/src/plugins/defaults/compaction/window-manager.ts +9 -0
  415. package/src/plugins/defaults/index.ts +9 -13
  416. package/src/plugins/defaults/memory/AGENTS.md +775 -0
  417. package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
  418. package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
  419. package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
  420. package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
  421. package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
  422. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
  423. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
  424. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
  425. package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
  426. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
  427. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
  428. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
  429. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  430. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
  431. package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
  432. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
  433. package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
  434. package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
  435. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
  436. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
  437. package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
  438. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
  439. package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
  440. package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
  441. package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
  442. package/src/plugins/defaults/memory/graph/store.ts +1 -0
  443. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
  444. package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
  445. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
  446. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
  447. package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
  448. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
  449. package/src/plugins/defaults/memory/indexer.ts +146 -89
  450. package/src/plugins/defaults/memory/injectors.ts +86 -41
  451. package/src/plugins/defaults/memory/job-handlers.ts +130 -39
  452. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
  453. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
  454. package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
  455. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
  456. package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
  457. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
  458. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
  459. package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
  460. package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
  461. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
  462. package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
  463. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
  464. package/src/plugins/defaults/memory/startup.ts +58 -21
  465. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
  466. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
  467. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
  468. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
  469. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
  470. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
  471. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
  472. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
  473. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
  474. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
  475. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
  476. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
  477. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
  478. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
  479. package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
  480. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
  481. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
  482. package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
  483. package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
  484. package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
  485. package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
  486. package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
  487. package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
  488. package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
  489. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
  490. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
  491. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
  492. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
  493. package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
  494. package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
  495. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
  496. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
  497. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
  498. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
  499. package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
  500. package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
  501. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
  502. package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
  503. package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
  504. package/src/plugins/defaults/memory/tools.test.ts +1 -1
  505. package/src/plugins/defaults/memory/tools.ts +1 -1
  506. package/src/plugins/defaults/memory/v1/README.md +5 -0
  507. package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
  508. package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
  509. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
  510. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
  511. package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
  512. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
  513. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
  514. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
  515. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
  516. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
  517. package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
  518. package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
  519. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
  520. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
  521. package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
  522. package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
  523. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
  524. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
  525. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
  526. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
  527. package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
  528. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
  529. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
  530. package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
  531. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
  532. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
  533. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
  534. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
  535. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
  536. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
  537. package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
  538. package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
  539. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
  540. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
  541. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
  542. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
  543. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
  544. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
  545. package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
  546. package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
  547. package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
  548. package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
  549. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
  550. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
  551. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
  552. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  553. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  554. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
  555. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
  556. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
  557. package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
  558. package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
  559. package/src/plugins/defaults/memory/v2/activation.ts +30 -163
  560. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
  561. package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
  562. package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
  563. package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
  564. package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
  565. package/src/plugins/defaults/memory/v2/injection.ts +36 -26
  566. package/src/plugins/defaults/memory/v2/migration.ts +2 -2
  567. package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
  568. package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
  569. package/src/plugins/defaults/memory/v2/router.ts +38 -15
  570. package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
  571. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
  572. package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
  573. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
  574. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
  575. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
  576. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
  577. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
  578. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
  579. package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
  580. package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
  581. package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
  582. package/src/plugins/defaults/memory/v3/card.ts +25 -9
  583. package/src/plugins/defaults/memory/v3/edge.ts +52 -18
  584. package/src/plugins/defaults/memory/v3/gate.ts +4 -4
  585. package/src/plugins/defaults/memory/v3/injector.ts +10 -3
  586. package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
  587. package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
  588. package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
  589. package/src/plugins/defaults/memory/v3/prune.ts +40 -16
  590. package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
  591. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
  592. package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
  593. package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
  594. package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
  595. package/src/plugins/defaults/memory/v3/types.ts +4 -1
  596. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
  597. package/src/plugins/defaults/memory/validation.ts +1 -1
  598. package/src/plugins/defaults/memory/worker.ts +2 -1
  599. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
  600. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
  601. package/src/plugins/types.ts +2 -2
  602. package/src/prompts/sections.ts +4 -16
  603. package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
  604. package/src/providers/anthropic/client.ts +15 -6
  605. package/src/providers/content-block-schema.ts +26 -0
  606. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
  607. package/src/providers/inference/adapter-factory.ts +6 -0
  608. package/src/providers/inference/connections.ts +30 -14
  609. package/src/providers/model-catalog.ts +77 -0
  610. package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
  611. package/src/providers/openai/chat-completions-provider.ts +65 -17
  612. package/src/providers/openai/input-audio.ts +76 -0
  613. package/src/providers/openrouter/client.ts +0 -2
  614. package/src/providers/platform-proxy/constants.ts +4 -0
  615. package/src/providers/poolside/client.ts +42 -0
  616. package/src/providers/registry.ts +40 -8
  617. package/src/providers/retry.ts +2 -0
  618. package/src/providers/types.ts +39 -1
  619. package/src/providers/vercel-ai-gateway/client.ts +0 -2
  620. package/src/runtime/AGENTS.md +7 -5
  621. package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
  622. package/src/runtime/__tests__/question-resolution.test.ts +111 -0
  623. package/src/runtime/access-request-helper.ts +7 -15
  624. package/src/runtime/assistant-event-hub.ts +43 -31
  625. package/src/runtime/assistant-event-publish-options.ts +31 -0
  626. package/src/runtime/assistant-event.ts +19 -30
  627. package/src/runtime/assistant-stream-state.ts +4 -4
  628. package/src/runtime/channel-approvals.ts +0 -25
  629. package/src/runtime/channel-readiness-service.ts +99 -40
  630. package/src/runtime/channel-retry-sweep.ts +38 -15
  631. package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
  632. package/src/runtime/guardian-reply-router.ts +108 -0
  633. package/src/runtime/http-server.ts +8 -0
  634. package/src/runtime/http-types.ts +2 -2
  635. package/src/runtime/process-role.ts +42 -0
  636. package/src/runtime/question-request-guardian-bridge.ts +184 -0
  637. package/src/runtime/question-resolution.ts +153 -0
  638. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
  639. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
  640. package/src/runtime/routes/__tests__/subagents-routes.test.ts +250 -0
  641. package/src/runtime/routes/__tests__/webhook-routes.test.ts +201 -0
  642. package/src/runtime/routes/acp-routes.ts +2 -2
  643. package/src/runtime/routes/bookmark-routes.ts +3 -15
  644. package/src/runtime/routes/canned-message-complete.ts +2 -2
  645. package/src/runtime/routes/consolidation-routes.ts +8 -2
  646. package/src/runtime/routes/conversation-list-routes.ts +3 -19
  647. package/src/runtime/routes/conversation-management-routes.ts +1 -5
  648. package/src/runtime/routes/conversation-query-routes.ts +52 -8
  649. package/src/runtime/routes/conversation-routes.ts +36 -22
  650. package/src/runtime/routes/credential-request-routes.ts +0 -1
  651. package/src/runtime/routes/filing-routes.ts +7 -7
  652. package/src/runtime/routes/global-search-routes.ts +1 -1
  653. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  654. package/src/runtime/routes/image-generation-routes.ts +12 -9
  655. package/src/runtime/routes/inbound-message-handler.ts +17 -0
  656. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
  657. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
  658. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
  659. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
  660. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
  661. package/src/runtime/routes/index.ts +2 -0
  662. package/src/runtime/routes/lifecycle-routes.ts +199 -0
  663. package/src/runtime/routes/platform-routes.ts +3 -8
  664. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  665. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  666. package/src/runtime/routes/question-routes.ts +34 -87
  667. package/src/runtime/routes/secret-routes.ts +11 -1
  668. package/src/runtime/routes/settings-routes.ts +8 -18
  669. package/src/runtime/routes/subagents-routes.ts +35 -8
  670. package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
  671. package/src/runtime/routes/webhook-routes.ts +89 -30
  672. package/src/runtime/routes/workspace-routes.test.ts +7 -4
  673. package/src/runtime/slack-reply-session.test.ts +12 -12
  674. package/src/runtime/slack-reply-session.ts +17 -17
  675. package/src/runtime/sync/sync-publisher.test.ts +7 -5
  676. package/src/runtime/tool-grant-request-helper.ts +4 -0
  677. package/src/schedule/schedule-store.ts +70 -0
  678. package/src/schedule/scheduler.ts +27 -0
  679. package/src/security/AGENTS.md +1 -1
  680. package/src/security/credential-key.ts +17 -0
  681. package/src/security/secret-ingress.ts +14 -105
  682. package/src/security/secret-patterns.ts +8 -139
  683. package/src/security/secret-scanner.ts +8 -3
  684. package/src/security/store-path-override.ts +6 -16
  685. package/src/sequence/store.ts +8 -0
  686. package/src/signals/emit-event.ts +5 -10
  687. package/src/signals/event-stream.ts +20 -10
  688. package/src/subagent/manager.ts +76 -25
  689. package/src/subagent/notify.ts +8 -0
  690. package/src/subagent/types.ts +13 -3
  691. package/src/telegram/__tests__/webhook-health.test.ts +442 -0
  692. package/src/telegram/webhook-health.ts +478 -0
  693. package/src/telemetry/AGENTS.md +6 -0
  694. package/src/telemetry/memory-corpus-size.test.ts +129 -0
  695. package/src/telemetry/memory-corpus-size.ts +184 -0
  696. package/src/telemetry/memory-tier-reporter.test.ts +67 -2
  697. package/src/telemetry/memory-tier-reporter.ts +30 -3
  698. package/src/tools/__tests__/conversation-group-tool-input-schemas.test.ts +61 -0
  699. package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
  700. package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
  701. package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
  702. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
  703. package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
  704. package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
  705. package/src/tools/acp/abort.ts +21 -1
  706. package/src/tools/acp/context.ts +5 -5
  707. package/src/tools/acp/spawn.test.ts +15 -5
  708. package/src/tools/acp/spawn.ts +26 -3
  709. package/src/tools/acp/status.ts +20 -1
  710. package/src/tools/acp/steer.test.ts +20 -0
  711. package/src/tools/acp/steer.ts +23 -2
  712. package/src/tools/apps/resolve-app-id.ts +15 -3
  713. package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
  714. package/src/tools/ask-question/ask-question-tool.ts +68 -92
  715. package/src/tools/browser/browser-screencast.ts +6 -6
  716. package/src/tools/calls/call-end.ts +24 -3
  717. package/src/tools/calls/call-start.ts +35 -11
  718. package/src/tools/calls/call-status.ts +20 -1
  719. package/src/tools/conversation-groups/group_create.ts +63 -0
  720. package/src/tools/conversation-groups/group_list.ts +20 -0
  721. package/src/tools/conversation-groups/group_shared.ts +52 -0
  722. package/src/tools/conversation-groups/move_to_group.ts +106 -0
  723. package/src/tools/document/document-comment-tool.test.ts +49 -0
  724. package/src/tools/document/document-comment-tool.ts +45 -6
  725. package/src/tools/document/document-tool.ts +142 -24
  726. package/src/tools/executor.ts +27 -13
  727. package/src/tools/filesystem/edit.ts +62 -60
  728. package/src/tools/filesystem/list.ts +36 -29
  729. package/src/tools/filesystem/read.ts +56 -39
  730. package/src/tools/filesystem/write.ts +44 -38
  731. package/src/tools/followups/followup_create.ts +41 -12
  732. package/src/tools/followups/followup_list.ts +34 -6
  733. package/src/tools/followups/followup_resolve.ts +26 -4
  734. package/src/tools/host-filesystem/edit.ts +50 -60
  735. package/src/tools/host-filesystem/read.ts +45 -39
  736. package/src/tools/host-filesystem/write.ts +31 -36
  737. package/src/tools/host-terminal/host-shell.ts +76 -62
  738. package/src/tools/policy-context.ts +27 -10
  739. package/src/tools/schedule/create.ts +76 -33
  740. package/src/tools/schedule/delete.ts +21 -2
  741. package/src/tools/schedule/list.ts +25 -3
  742. package/src/tools/schedule/update.ts +105 -48
  743. package/src/tools/shared/filesystem/path-policy.ts +246 -40
  744. package/src/tools/shared/zod-tool-schema.ts +117 -0
  745. package/src/tools/subagent/abort.ts +12 -4
  746. package/src/tools/subagent/consult-deadline.ts +9 -3
  747. package/src/tools/subagent/message.ts +21 -5
  748. package/src/tools/subagent/notify-parent.ts +44 -23
  749. package/src/tools/subagent/read.ts +15 -4
  750. package/src/tools/subagent/resolve.ts +26 -4
  751. package/src/tools/subagent/spawn.ts +37 -13
  752. package/src/tools/subagent/status.ts +12 -4
  753. package/src/tools/system/request-permission.ts +35 -26
  754. package/src/tools/terminal/shell.ts +68 -55
  755. package/src/tools/tool-approval-handler.ts +327 -53
  756. package/src/tools/tool-input-schemas.ts +85 -0
  757. package/src/tools/tool-types.ts +7 -0
  758. package/src/tools/types.ts +8 -0
  759. package/src/tools/workflows/manage-workflows.ts +30 -2
  760. package/src/tools/workflows/run-workflow.test.ts +54 -2
  761. package/src/tools/workflows/run-workflow.ts +32 -4
  762. package/src/util/fs-symlinks.ts +30 -0
  763. package/src/util/log-redact.ts +7 -3
  764. package/src/util/platform.ts +15 -0
  765. package/src/vellum-assistant-namespace.d.ts +80 -0
  766. package/src/watcher/watcher-store.ts +8 -0
  767. package/src/workflows/leaf-runner.test.ts +104 -2
  768. package/src/workflows/leaf-runner.ts +31 -6
  769. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
  770. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
  771. package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
  772. package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
  773. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
  774. package/src/workspace/migrations/registry.ts +4 -0
  775. package/tsconfig.plugin-api.json +1 -1
  776. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  777. package/src/__tests__/secret-patterns.test.ts +0 -27
  778. package/src/config/__tests__/proc-to-skills.test.ts +0 -21
  779. package/src/config/memory-tier.test.ts +0 -44
  780. package/src/daemon/message-types/acp.ts +0 -20
  781. package/src/daemon/message-types/apps.ts +0 -11
  782. package/src/daemon/message-types/background-tools.ts +0 -14
  783. package/src/daemon/message-types/bookmarks.ts +0 -13
  784. package/src/daemon/message-types/contacts.ts +0 -13
  785. package/src/daemon/message-types/document-comments.ts +0 -14
  786. package/src/daemon/message-types/documents.ts +0 -13
  787. package/src/daemon/message-types/home.ts +0 -15
  788. package/src/daemon/message-types/host-bash.ts +0 -12
  789. package/src/daemon/message-types/host-cu.ts +0 -10
  790. package/src/daemon/message-types/host-file.ts +0 -12
  791. package/src/daemon/message-types/host-transfer.ts +0 -12
  792. package/src/daemon/message-types/integrations.ts +0 -90
  793. package/src/daemon/message-types/memory.ts +0 -10
  794. package/src/daemon/message-types/schedules.ts +0 -14
  795. package/src/daemon/message-types/settings.ts +0 -17
  796. package/src/daemon/message-types/subagents.ts +0 -63
  797. package/src/daemon/message-types/upgrades.ts +0 -14
  798. package/src/daemon/message-types/workflows.ts +0 -25
  799. package/src/daemon/message-types/workspace.ts +0 -137
  800. package/src/live-voice/ack-phrases.ts +0 -58
  801. package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
  802. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
  803. package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
  804. package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
  805. package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
  806. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
  807. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
  808. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
  809. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
@@ -33,7 +33,7 @@ mock.module("../../daemon/conversation-store.js", () => ({
33
33
 
34
34
  // Conversation-CRUD doubles for the teardown transcript-hygiene pass. The
35
35
  // real module is spread so every other export keeps its production behavior;
36
- // only the three functions the hygiene pass (and discard) touch are recorded.
36
+ // only the functions the hygiene pass (and discard) touch are recorded.
37
37
  import * as realConversationCrud from "../../persistence/conversation-crud.js";
38
38
 
39
39
  let getMessageByIdImpl: (
@@ -65,10 +65,14 @@ mock.module("../../persistence/conversation-crud.js", () => ({
65
65
  crudLog.deletes.push(messageId);
66
66
  return { segmentIds: [], deletedSummaryIds: [] };
67
67
  },
68
+ // The echo path advances the snapshot anchor for a real-user turn; the
69
+ // fake conversation has no row in SQLite, so stub the write out.
70
+ recordConversationPersistedSeq: () => {},
68
71
  }));
69
72
 
70
73
  import { setConfig } from "../../__tests__/helpers/set-config.js";
71
74
  import { ABORT_WATCHDOG_MS } from "../../daemon/abort-watchdog.js";
75
+ import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
72
76
  import { CALL_OPENING_MARKER } from "../voice-control-protocol.js";
73
77
  import {
74
78
  cutFrontDoorContentAtVerdict,
@@ -347,6 +351,67 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
347
351
  });
348
352
  });
349
353
 
354
+ describe("startVoiceTurn hiddenSyntheticPrompt", () => {
355
+ // A caller whose internal instruction is composed per call carries no
356
+ // sentinel for the content comparisons to recognize, so it declares itself.
357
+ const SYNTHETIC_CONTENT =
358
+ "(the background task finished — announce the result)";
359
+
360
+ /** The `user_message_echo` events `turn` publishes to hub subscribers. */
361
+ async function collectUserMessageEchoes(
362
+ turn: () => Promise<unknown>,
363
+ ): Promise<Array<{ type: string }>> {
364
+ const published: Array<{ type: string }> = [];
365
+ const subscription = assistantEventHub.subscribe({
366
+ type: "process",
367
+ filter: { conversationId: "conv-voice-bridge-test" },
368
+ callback: (event) => {
369
+ published.push(event.message);
370
+ },
371
+ });
372
+ try {
373
+ await turn();
374
+ } finally {
375
+ subscription.dispose();
376
+ }
377
+ return published.filter((msg) => msg.type === "user_message_echo");
378
+ }
379
+
380
+ test("a declared prompt persists hidden and suppresses its echo", async () => {
381
+ const fake = makeFakeConversation({ processing: false });
382
+ fakeConversation = fake.conversation;
383
+
384
+ const echoes = await collectUserMessageEchoes(() =>
385
+ startVoiceTurn({
386
+ ...makeTurnOptions(),
387
+ content: SYNTHETIC_CONTENT,
388
+ hiddenSyntheticPrompt: true,
389
+ }),
390
+ );
391
+
392
+ expect(fake.lastPersistOpts()?.content).toBe(SYNTHETIC_CONTENT);
393
+ expect(fake.lastPersistOpts()?.metadata).toEqual({ hidden: true });
394
+ expect(echoes).toHaveLength(0);
395
+ });
396
+
397
+ test("the same content without the flag stays a plain user turn", async () => {
398
+ const fake = makeFakeConversation({ processing: false });
399
+ fakeConversation = fake.conversation;
400
+
401
+ const echoes = await collectUserMessageEchoes(() =>
402
+ startVoiceTurn({
403
+ ...makeTurnOptions(),
404
+ content: SYNTHETIC_CONTENT,
405
+ }),
406
+ );
407
+
408
+ expect(fake.lastPersistOpts()?.metadata).toBeUndefined();
409
+ expect(echoes).toEqual([
410
+ expect.objectContaining({ text: SYNTHETIC_CONTENT }),
411
+ ]);
412
+ });
413
+ });
414
+
350
415
  describe("startVoiceTurn triage-and-escalate control prompt", () => {
351
416
  // Live-voice supplies its own voiceControlPrompt, bypassing
352
417
  // buildVoiceCallControlPrompt where the routing-leg rule is normally injected.
@@ -1101,7 +1166,7 @@ describe("startVoiceTurn tool-event forwarding", () => {
1101
1166
  fakeConversation = fake.conversation;
1102
1167
  }
1103
1168
 
1104
- test("tool_use_start delivers the tool name and toolUseId", async () => {
1169
+ test("tool_use_start delivers the tool name, toolUseId, and input", async () => {
1105
1170
  makeEventEmittingConversation([
1106
1171
  {
1107
1172
  type: "tool_use_start",
@@ -1121,7 +1186,10 @@ describe("startVoiceTurn tool-event forwarding", () => {
1121
1186
  await flushMicrotasks();
1122
1187
 
1123
1188
  expect(starts).toEqual([
1124
- { toolName: "web_search", detail: { toolUseId: "toolu-1" } },
1189
+ {
1190
+ toolName: "web_search",
1191
+ detail: { toolUseId: "toolu-1", input: { query: "weather" } },
1192
+ },
1125
1193
  ]);
1126
1194
  });
1127
1195
 
@@ -1325,7 +1393,7 @@ describe("cutFrontDoorContentAtVerdict", () => {
1325
1393
  });
1326
1394
  });
1327
1395
 
1328
- describe("front-door transcript hygiene (teardown pass)", () => {
1396
+ describe("transcript hygiene (teardown pass)", () => {
1329
1397
  beforeEach(resetCrudLog);
1330
1398
 
1331
1399
  function makeRow(text: string) {
@@ -1415,16 +1483,170 @@ describe("front-door transcript hygiene (teardown pass)", () => {
1415
1483
  expect(events).not.toContain("loadFromDb");
1416
1484
  });
1417
1485
 
1418
- test("a non-routed leg never runs the hygiene pass", async () => {
1419
- makeReservedRowConversation();
1486
+ test("a front-door answer ending with the minimize marker has the marker stripped", async () => {
1487
+ const { events } = makeReservedRowConversation();
1488
+ getMessageByIdImpl = () => makeRow("Here we go, watch the overlay. [-1]");
1489
+
1490
+ await startVoiceTurn({ ...makeTurnOptions(), routingLeg: "front-door" });
1491
+ await flushMicrotasks();
1492
+
1493
+ expect(crudLog.updates).toEqual([
1494
+ {
1495
+ messageId: "assistant-row-1",
1496
+ content: JSON.stringify([
1497
+ { type: "text", text: "Here we go, watch the overlay." },
1498
+ ]),
1499
+ },
1500
+ ]);
1501
+ expect(crudLog.deletes).toHaveLength(0);
1502
+ expect(events).toContain("loadFromDb");
1503
+ });
1504
+
1505
+ test("a marker-only front-door answer row is deleted", async () => {
1506
+ const { events } = makeReservedRowConversation();
1507
+ getMessageByIdImpl = () => makeRow("[-1]");
1508
+
1509
+ await startVoiceTurn({ ...makeTurnOptions(), routingLeg: "front-door" });
1510
+ await flushMicrotasks();
1511
+
1512
+ expect(crudLog.updates).toHaveLength(0);
1513
+ expect(crudLog.deletes).toEqual(["assistant-row-1"]);
1514
+ expect(events).toContain("loadFromDb");
1515
+ });
1516
+
1517
+ test("a non-routed leg leaves verdict-token content untouched (verdict cutting is front-door-only)", async () => {
1518
+ const { events } = makeReservedRowConversation();
1420
1519
  getMessageByIdImpl = () => makeRow("[1] Anything at all");
1421
1520
 
1422
1521
  await startVoiceTurn(makeTurnOptions());
1423
1522
  await flushMicrotasks();
1424
1523
 
1425
- expect(crudLog.reads).toHaveLength(0);
1524
+ expect(crudLog.reads).toEqual(["assistant-row-1"]);
1525
+ expect(crudLog.updates).toHaveLength(0);
1526
+ expect(crudLog.deletes).toHaveLength(0);
1527
+ expect(events).not.toContain("loadFromDb");
1528
+ });
1529
+
1530
+ test("a main-leg row containing the minimize marker persists with the marker stripped", async () => {
1531
+ const { events } = makeReservedRowConversation();
1532
+ getMessageByIdImpl = () => makeRow("Done, take a look [-1]");
1533
+
1534
+ await startVoiceTurn(makeTurnOptions());
1535
+ await flushMicrotasks();
1536
+
1537
+ expect(crudLog.updates).toEqual([
1538
+ {
1539
+ messageId: "assistant-row-1",
1540
+ content: JSON.stringify([{ type: "text", text: "Done, take a look" }]),
1541
+ },
1542
+ ]);
1543
+ expect(crudLog.deletes).toHaveLength(0);
1544
+ // The clean row must reach in-memory history and sync consumers.
1545
+ expect(events).toContain("loadFromDb");
1546
+ });
1547
+
1548
+ test("a mid-text [-1] (content, not command) leaves the row untouched", async () => {
1549
+ const { events } = makeReservedRowConversation();
1550
+ getMessageByIdImpl = () =>
1551
+ makeRow("The array [-1] sorts first, then the rest.");
1552
+
1553
+ await startVoiceTurn(makeTurnOptions());
1554
+ await flushMicrotasks();
1555
+
1556
+ expect(crudLog.updates).toHaveLength(0);
1557
+ expect(crudLog.deletes).toHaveLength(0);
1558
+ expect(events).not.toContain("loadFromDb");
1559
+ });
1560
+
1561
+ test("a marker-only main-leg row is deleted, not persisted as an empty bubble", async () => {
1562
+ const { events } = makeReservedRowConversation();
1563
+ getMessageByIdImpl = () => makeRow("[-1]");
1564
+
1565
+ await startVoiceTurn(makeTurnOptions());
1566
+ await flushMicrotasks();
1567
+
1426
1568
  expect(crudLog.updates).toHaveLength(0);
1569
+ expect(crudLog.deletes).toEqual(["assistant-row-1"]);
1570
+ expect(events).toContain("loadFromDb");
1571
+ });
1572
+
1573
+ test("a terminal marker split across text blocks is stripped whole", async () => {
1574
+ const { events } = makeReservedRowConversation();
1575
+ getMessageByIdImpl = () => ({
1576
+ ...makeRow(""),
1577
+ content: [
1578
+ { type: "text", text: "Done, take a look [-" },
1579
+ { type: "text", text: "1]" },
1580
+ ],
1581
+ });
1582
+
1583
+ await startVoiceTurn(makeTurnOptions());
1584
+ await flushMicrotasks();
1585
+
1586
+ expect(crudLog.updates).toEqual([
1587
+ {
1588
+ messageId: "assistant-row-1",
1589
+ content: JSON.stringify([{ type: "text", text: "Done, take a look" }]),
1590
+ },
1591
+ ]);
1427
1592
  expect(crudLog.deletes).toHaveLength(0);
1593
+ expect(events).toContain("loadFromDb");
1594
+ });
1595
+
1596
+ test("a marker-only row split across text blocks is deleted", async () => {
1597
+ const { events } = makeReservedRowConversation();
1598
+ getMessageByIdImpl = () => ({
1599
+ ...makeRow(""),
1600
+ content: [
1601
+ { type: "text", text: "[-" },
1602
+ { type: "text", text: "1]" },
1603
+ ],
1604
+ });
1605
+
1606
+ await startVoiceTurn(makeTurnOptions());
1607
+ await flushMicrotasks();
1608
+
1609
+ expect(crudLog.updates).toHaveLength(0);
1610
+ expect(crudLog.deletes).toEqual(["assistant-row-1"]);
1611
+ expect(events).toContain("loadFromDb");
1612
+ });
1613
+
1614
+ test("a marker-only row with a surviving non-text block is rewritten, never deleted", async () => {
1615
+ const { events } = makeReservedRowConversation();
1616
+ getMessageByIdImpl = () => ({
1617
+ ...makeRow("[-1]"),
1618
+ content: [
1619
+ { type: "text", text: "[-1]" },
1620
+ { type: "tool_use", id: "tool-1", name: "app_create", input: {} },
1621
+ ],
1622
+ });
1623
+
1624
+ await startVoiceTurn(makeTurnOptions());
1625
+ await flushMicrotasks();
1626
+
1627
+ expect(crudLog.deletes).toHaveLength(0);
1628
+ expect(crudLog.updates).toEqual([
1629
+ {
1630
+ messageId: "assistant-row-1",
1631
+ content: JSON.stringify([
1632
+ { type: "tool_use", id: "tool-1", name: "app_create", input: {} },
1633
+ ]),
1634
+ },
1635
+ ]);
1636
+ expect(events).toContain("loadFromDb");
1637
+ });
1638
+
1639
+ test("a main-leg row without the minimize marker is never rewritten", async () => {
1640
+ const { events } = makeReservedRowConversation();
1641
+ getMessageByIdImpl = () => makeRow("Done, take a look.");
1642
+
1643
+ await startVoiceTurn(makeTurnOptions());
1644
+ await flushMicrotasks();
1645
+
1646
+ expect(crudLog.reads).toEqual(["assistant-row-1"]);
1647
+ expect(crudLog.updates).toHaveLength(0);
1648
+ expect(crudLog.deletes).toHaveLength(0);
1649
+ expect(events).not.toContain("loadFromDb");
1428
1650
  });
1429
1651
 
1430
1652
  test("a discarded speculative leg deletes its reserved assistant row at teardown", async () => {
@@ -316,10 +316,9 @@ describe("escalation continuation content", () => {
316
316
 
317
317
  // This module is the surface-agnostic escalation *policy* (profiles, prompt
318
318
  // rules, the verdict classifier, the bridge cap/fallback decision). The
319
- // two-leg *routing* runs on the in-app Voice Mode surface (LiveVoiceSession),
320
- // gated behind the single voice-mode flag — see
321
- // live-voice/__tests__/live-voice-triage-escalate.test.ts for the orchestration
322
- // coverage (flag gating, verdict-first hand-off, token suppression, fallback
319
+ // two-leg *routing* runs on the in-app Voice Mode surface (LiveVoiceSession)
320
+ // — see live-voice/__tests__/live-voice-triage-escalate.test.ts for the
321
+ // orchestration coverage (verdict-first hand-off, token suppression, fallback
323
322
  // bridge, barge-in). What remains for the manual cli-testing flow is true
324
323
  // end-to-end audio: real TTS timing across the bridge, and the residual
325
324
  // broadcast raw-token leak (issue #37850, shared by both voice surfaces) once
@@ -8,6 +8,7 @@
8
8
  * barge-in, state machine, guardian verification).
9
9
  */
10
10
 
11
+ import type { AssistantEvent } from "../api/index.js";
11
12
  import { revokeScopedApprovalGrantsForContext } from "../approvals/scoped-approval-grants.js";
12
13
  import {
13
14
  expireGuardianRequest,
@@ -16,7 +17,6 @@ import {
16
17
  getRequestByPendingQuestionOrNull,
17
18
  listGuardianRequestDeliveriesOrEmpty,
18
19
  } from "../channels/gateway-guardian-requests.js";
19
- import type { ServerMessage } from "../daemon/message-protocol.js";
20
20
  import type { TrustContext } from "../daemon/trust-context-types.js";
21
21
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
22
22
  import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
@@ -166,7 +166,7 @@ export class CallController {
166
166
  /** Monotonic run id used to suppress stale turn side effects after interruption. */
167
167
  private llmRunVersion = 0;
168
168
  /** Optional broadcast function for emitting events to connected clients. */
169
- private broadcast?: (msg: ServerMessage) => void;
169
+ private broadcast?: (msg: AssistantEvent) => void;
170
170
  /** Assistant identity for scoping guardian bindings. */
171
171
  private assistantId: string;
172
172
  /** Guardian trust context for the current caller, when available. */
@@ -195,7 +195,7 @@ export class CallController {
195
195
  transport: CallTransport,
196
196
  task: string | null,
197
197
  opts?: {
198
- broadcast?: (msg: ServerMessage) => void;
198
+ broadcast?: (msg: AssistantEvent) => void;
199
199
  assistantId?: string;
200
200
  trustContext?: TrustContext;
201
201
  },
@@ -260,8 +260,8 @@ export class CallController {
260
260
  * Kick off the first outbound call utterance from the assistant.
261
261
  */
262
262
  async startInitialGreeting(): Promise<void> {
263
- if (this.initialGreetingStarted) return;
264
- if (this.state !== "idle") return;
263
+ if (this.initialGreetingStarted) {return;}
264
+ if (this.state !== "idle") {return;}
265
265
 
266
266
  this.initialGreetingStarted = true;
267
267
  this.resetSilenceTimer();
@@ -275,8 +275,8 @@ export class CallController {
275
275
  * greet naturally with context that verification just happened.
276
276
  */
277
277
  async startPostVerificationGreeting(): Promise<void> {
278
- if (this.initialGreetingStarted) return;
279
- if (this.state !== "idle") return;
278
+ if (this.initialGreetingStarted) {return;}
279
+ if (this.state !== "idle") {return;}
280
280
 
281
281
  this.initialGreetingStarted = true;
282
282
  this.resetSilenceTimer();
@@ -473,10 +473,10 @@ export class CallController {
473
473
  */
474
474
  destroy(): void {
475
475
  this.destroyed = true;
476
- if (this.silenceTimer) clearTimeout(this.silenceTimer);
476
+ if (this.silenceTimer) {clearTimeout(this.silenceTimer);}
477
477
  this.cancelPendingEndCall();
478
- if (this.durationTimer) clearTimeout(this.durationTimer);
479
- if (this.durationWarningTimer) clearTimeout(this.durationWarningTimer);
478
+ if (this.durationTimer) {clearTimeout(this.durationTimer);}
479
+ if (this.durationWarningTimer) {clearTimeout(this.durationWarningTimer);}
480
480
  if (this.pendingGuardianInput) {
481
481
  clearTimeout(this.pendingGuardianInput.timer);
482
482
  this.pendingGuardianInput = null;
@@ -559,7 +559,7 @@ export class CallController {
559
559
  transcript: string,
560
560
  speaker?: PromptSpeakerContext,
561
561
  ): string {
562
- if (!speaker) return transcript;
562
+ if (!speaker) {return transcript;}
563
563
  const safeId = speaker.speakerId.replaceAll('"', "'");
564
564
  const safeLabel = speaker.speakerLabel.replaceAll('"', "'");
565
565
  const confidencePart =
@@ -580,7 +580,7 @@ export class CallController {
580
580
  }
581
581
 
582
582
  private async runTurnInner(content: string): Promise<void> {
583
- if (this.destroyed) return;
583
+ if (this.destroyed) {return;}
584
584
  const runVersion = ++this.llmRunVersion;
585
585
  const runSignal = this.abortController.signal;
586
586
 
@@ -603,7 +603,7 @@ export class CallController {
603
603
  runVersion,
604
604
  runSignal,
605
605
  );
606
- if (!this.isCurrentRun(runVersion)) return;
606
+ if (!this.isCurrentRun(runVersion)) {return;}
607
607
 
608
608
  await this.handleTurnCompletion(fullResponseText);
609
609
  } catch (err: unknown) {
@@ -838,15 +838,15 @@ export class CallController {
838
838
  enqueueSynthesisSegments(synthProvider, segments);
839
839
  } else {
840
840
  const cleaned = sanitizeForTts(safeText);
841
- if (cleaned.length === 0) return;
841
+ if (cleaned.length === 0) {return;}
842
842
  this.beginSpeakingOnAudioStart(runVersion);
843
843
  this.transport.sendTextToken(cleaned, false);
844
844
  }
845
845
  };
846
846
 
847
847
  const flushSafeText = (): void => {
848
- if (!this.isCurrentRun(runVersion)) return;
849
- if (ttsBuffer.length === 0) return;
848
+ if (!this.isCurrentRun(runVersion)) {return;}
849
+ if (ttsBuffer.length === 0) {return;}
850
850
  const bracketIdx = ttsBuffer.indexOf("[");
851
851
  if (bracketIdx === -1) {
852
852
  // No bracket at all — safe to flush everything
@@ -883,7 +883,7 @@ export class CallController {
883
883
  // Use a promise to track completion of the voice turn
884
884
  const turnComplete = new Promise<void>((resolve, reject) => {
885
885
  const onTextDelta = (text: string): void => {
886
- if (!this.isCurrentRun(runVersion)) return;
886
+ if (!this.isCurrentRun(runVersion)) {return;}
887
887
  fullResponseText += text;
888
888
  ttsBuffer += text;
889
889
  ttsBuffer = stripInternalSpeechMarkers(ttsBuffer);
@@ -989,7 +989,7 @@ export class CallController {
989
989
  // latency; re-check the run wasn't superseded meanwhile so a stale turn
990
990
  // doesn't inject its end-of-turn marker (or fallback text) into the next
991
991
  // turn's output stream.
992
- if (!this.isCurrentRun(runVersion)) return fullResponseText;
992
+ if (!this.isCurrentRun(runVersion)) {return fullResponseText;}
993
993
 
994
994
  // Signal end of this turn's speech. An empty token with `last: true`
995
995
  // tells the transport to start listening — it does NOT trigger TTS
@@ -1447,7 +1447,7 @@ export class CallController {
1447
1447
  }
1448
1448
 
1449
1449
  private clearPendingGuardianInputForCallEnd(): boolean {
1450
- if (!this.pendingGuardianInput) return false;
1450
+ if (!this.pendingGuardianInput) {return false;}
1451
1451
 
1452
1452
  clearTimeout(this.pendingGuardianInput.timer);
1453
1453
 
@@ -1476,7 +1476,7 @@ export class CallController {
1476
1476
  // The teardown has run to completion; drop the token so a later utterance
1477
1477
  // can't read it as a still-pending end-call.
1478
1478
  this.pendingEndCall = null;
1479
- if (this.destroyed) return;
1479
+ if (this.destroyed) {return;}
1480
1480
 
1481
1481
  const currentSession = getCallSession(this.callSessionId);
1482
1482
  if (currentSession && isTerminalState(currentSession.status)) {
@@ -1518,7 +1518,7 @@ export class CallController {
1518
1518
  }
1519
1519
 
1520
1520
  private isExpectedAbortError(err: unknown): boolean {
1521
- if (!(err instanceof Error)) return false;
1521
+ if (!(err instanceof Error)) {return false;}
1522
1522
  return err.name === "AbortError" || err.name === "APIUserAbortError";
1523
1523
  }
1524
1524
 
@@ -1541,7 +1541,7 @@ export class CallController {
1541
1541
  * waiting for the processing lock or generating with no audio yet.
1542
1542
  */
1543
1543
  private beginSpeaking(runVersion: number): void {
1544
- if (!this.isCurrentRun(runVersion)) return;
1544
+ if (!this.isCurrentRun(runVersion)) {return;}
1545
1545
  if (this.state === "processing") {
1546
1546
  this.state = "speaking";
1547
1547
  }
@@ -1650,7 +1650,7 @@ export class CallController {
1650
1650
  !this.pendingGuardianInput ||
1651
1651
  this.pendingGuardianInput.questionId !== pendingQuestion.id
1652
1652
  )
1653
- return;
1653
+ {return;}
1654
1654
 
1655
1655
  log.info(
1656
1656
  { callSessionId: this.callSessionId },
@@ -1727,8 +1727,8 @@ export class CallController {
1727
1727
  * Drain any instructions that were queued while the LLM was active.
1728
1728
  */
1729
1729
  private flushPendingInstructions(): void {
1730
- if (this.destroyed) return;
1731
- if (this.pendingInstructions.length === 0) return;
1730
+ if (this.destroyed) {return;}
1731
+ if (this.pendingInstructions.length === 0) {return;}
1732
1732
 
1733
1733
  const parts = this.pendingInstructions.map((instr) =>
1734
1734
  instr.startsWith("[") ? instr : `[USER_INSTRUCTION: ${instr}]`,
@@ -1814,8 +1814,8 @@ export class CallController {
1814
1814
  }
1815
1815
 
1816
1816
  private resetSilenceTimer(): void {
1817
- if (this.silenceTimer) clearTimeout(this.silenceTimer);
1818
- if (this.destroyed) return;
1817
+ if (this.silenceTimer) {clearTimeout(this.silenceTimer);}
1818
+ if (this.destroyed) {return;}
1819
1819
  this.silenceTimer = setTimeout(() => {
1820
1820
  // During an in-call guardian consultation, suppress the generic
1821
1821
  // "Are you still there?" — it is confusing when the caller is
@@ -31,6 +31,56 @@ export function buildCallCompletionMessage(callSessionId: string): string {
31
31
  return buildCallSummaryLabel(callSession?.status, duration, events.length);
32
32
  }
33
33
 
34
+ /** The `data` payload rendered by the `call_summary` surface. */
35
+ interface CallSummaryEvent {
36
+ eventType: string;
37
+ payloadJson: string;
38
+ createdAt: number;
39
+ }
40
+
41
+ /**
42
+ * Build the `[ui_surface, text]` block pair persisted for a finished call.
43
+ *
44
+ * This is the approval-card pattern (see
45
+ * `notifications/approval-card-builder.ts`). Every provider drops `ui_surface`
46
+ * when serializing history, so the card alone left the model unable to tell
47
+ * that a call happened — the turn reached the wire as a "blocks omitted"
48
+ * sentinel (LUM-2869). The `_surfaceFallback` text sibling carries the same
49
+ * copy for the model, search indexing, CLI display, and channel replies, and
50
+ * its flag keeps surface-capable clients from rendering both the card and a
51
+ * duplicate text line.
52
+ */
53
+ function buildCallSummaryBlocks(
54
+ summaryText: string,
55
+ status: string | undefined,
56
+ duration: number | null,
57
+ events: CallSummaryEvent[],
58
+ ): unknown[] {
59
+ return [
60
+ {
61
+ type: "ui_surface",
62
+ surfaceType: "call_summary",
63
+ surfaceId: crypto.randomUUID(),
64
+ completed: true,
65
+ data: {
66
+ summaryText,
67
+ status: status ?? "completed",
68
+ duration,
69
+ events: events.map((e) => ({
70
+ eventType: e.eventType,
71
+ payloadJson: e.payloadJson,
72
+ createdAt: e.createdAt,
73
+ })),
74
+ },
75
+ },
76
+ {
77
+ type: "text",
78
+ text: summaryText,
79
+ _surfaceFallback: true,
80
+ },
81
+ ];
82
+ }
83
+
34
84
  export async function persistCallCompletionMessage(
35
85
  conversationId: string,
36
86
  callSessionId: string,
@@ -50,24 +100,14 @@ export async function persistCallCompletionMessage(
50
100
  await addMessage(
51
101
  conversationId,
52
102
  "assistant",
53
- JSON.stringify([
54
- {
55
- type: "ui_surface",
56
- surfaceType: "call_summary",
57
- surfaceId: crypto.randomUUID(),
58
- completed: true,
59
- data: {
60
- summaryText,
61
- status: callSession?.status ?? "completed",
62
- duration,
63
- events: events.map((e) => ({
64
- eventType: e.eventType,
65
- payloadJson: e.payloadJson,
66
- createdAt: e.createdAt,
67
- })),
68
- },
69
- },
70
- ]),
103
+ JSON.stringify(
104
+ buildCallSummaryBlocks(
105
+ summaryText,
106
+ callSession?.status,
107
+ duration,
108
+ events,
109
+ ),
110
+ ),
71
111
  {
72
112
  metadata: {
73
113
  userMessageChannel: "phone",
@@ -28,6 +28,15 @@ export const END_CALL_MARKER = "[END_CALL]";
28
28
  export const HOLD_VERDICT_TOKEN = "[0]";
29
29
  export const ESCALATE_VERDICT_TOKEN = "[1]";
30
30
 
31
+ /**
32
+ * Emitted inline by the main/escalated voice leg to ask the live-voice
33
+ * client to minimize the voice room and reveal the screen behind it
34
+ * (e.g. after creating an app worth showing). Advisory: the daemon
35
+ * translates it into a `minimize_room` server frame after the turn's TTS
36
+ * drains; it is never spoken and never persisted.
37
+ */
38
+ export const MINIMIZE_ROOM_MARKER = "[-1]";
39
+
31
40
  // ---------------------------------------------------------------------------
32
41
  // Regexes
33
42
  // ---------------------------------------------------------------------------
@@ -47,6 +56,7 @@ const CALL_OPENING_ACK_MARKER_REGEX = /\[CALL_OPENING_ACK\]/g;
47
56
  const END_CALL_MARKER_REGEX = /\[END_CALL\]/g;
48
57
  const HOLD_VERDICT_TOKEN_REGEX = /\[0\]/g;
49
58
  const ESCALATE_VERDICT_TOKEN_REGEX = /\[1\]/g;
59
+ const MINIMIZE_ROOM_MARKER_REGEX = /\[-1\]/g;
50
60
  const GUARDIAN_TIMEOUT_MARKER_REGEX = /\[GUARDIAN_TIMEOUT\]/g;
51
61
  const GUARDIAN_UNAVAILABLE_MARKER_REGEX = /\[GUARDIAN_UNAVAILABLE\]/g;
52
62
 
@@ -163,6 +173,7 @@ export function stripInternalSpeechMarkers(text: string): string {
163
173
  .replace(END_CALL_MARKER_REGEX, "")
164
174
  .replace(HOLD_VERDICT_TOKEN_REGEX, "")
165
175
  .replace(ESCALATE_VERDICT_TOKEN_REGEX, "")
176
+ .replace(MINIMIZE_ROOM_MARKER_REGEX, "")
166
177
  .replace(GUARDIAN_TIMEOUT_MARKER_REGEX, "")
167
178
  .replace(GUARDIAN_UNAVAILABLE_MARKER_REGEX, "");
168
179
  return result;
@@ -187,6 +198,7 @@ const CONTROL_MARKER_STRINGS = [
187
198
  "[END_CALL]",
188
199
  "[0]",
189
200
  "[1]",
201
+ "[-1]",
190
202
  "[GUARDIAN_TIMEOUT]",
191
203
  "[GUARDIAN_UNAVAILABLE]",
192
204
  ];
@@ -203,3 +215,47 @@ export function couldBeControlMarker(text: string): boolean {
203
215
  (marker) => marker.startsWith(text) || text.startsWith(marker),
204
216
  );
205
217
  }
218
+
219
+ // Colon-style markers whose bodies terminate at the first "]" — their strip
220
+ // regexes are non-greedy (`.+?\]`), so the first bracket IS the terminator.
221
+ // ASK_GUARDIAN_APPROVAL is deliberately absent: its balanced-JSON body may
222
+ // itself contain "]" (arrays, string values), so only the balanced parser can
223
+ // judge it complete.
224
+ const FIRST_BRACKET_TERMINATED_PREFIXES = [
225
+ "[ASK_GUARDIAN:",
226
+ "[USER_ANSWERED:",
227
+ "[USER_INSTRUCTION:",
228
+ ];
229
+
230
+ const GUARDIAN_APPROVAL_PREFIX = "[ASK_GUARDIAN_APPROVAL:";
231
+
232
+ /**
233
+ * Whether `tail` (a buffer starting at a `[`) is a control marker that is
234
+ * still streaming — i.e. holding it back is required because
235
+ * {@link stripInternalSpeechMarkers} cannot yet remove it. Returns false for
236
+ * complete markers (safe to flush: stripping removes them) and for text that
237
+ * is not a marker at all (safe to flush: it is speech).
238
+ *
239
+ * Completion is judged per marker family: a strict prefix of any known
240
+ * marker string is always incomplete; an ASK_GUARDIAN_APPROVAL body is
241
+ * complete only when {@link extractBalancedJson} finds the balanced JSON and
242
+ * its closing bracket (a bare "]" inside the JSON does NOT terminate it);
243
+ * the other colon-style markers terminate at their first "]"; the fixed
244
+ * literal markers are complete the moment they match.
245
+ */
246
+ export function isIncompleteControlMarkerTail(tail: string): boolean {
247
+ if (
248
+ CONTROL_MARKER_STRINGS.some(
249
+ (marker) => marker.length > tail.length && marker.startsWith(tail),
250
+ )
251
+ ) {
252
+ return true;
253
+ }
254
+ if (tail.startsWith(GUARDIAN_APPROVAL_PREFIX)) {
255
+ return extractBalancedJson(tail) === null;
256
+ }
257
+ if (FIRST_BRACKET_TERMINATED_PREFIXES.some((p) => tail.startsWith(p))) {
258
+ return !tail.includes("]");
259
+ }
260
+ return false;
261
+ }