@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
@@ -66,7 +66,7 @@ mock.module("../persistence/conversation-crud.js", () => ({
66
66
  updates: Record<string, unknown>,
67
67
  ) => {
68
68
  const row = persistedRows.find((candidate) => candidate.id === messageId);
69
- if (!row) return;
69
+ if (!row) {return;}
70
70
  const existing =
71
71
  row.metadata && typeof row.metadata === "string"
72
72
  ? (JSON.parse(row.metadata) as Record<string, unknown>)
@@ -78,18 +78,18 @@ mock.module("../persistence/conversation-crud.js", () => ({
78
78
  // `lastAssistantPersisted()` assertions continue to find the row that
79
79
  // was reserved at `llm_call_started` time.
80
80
  const row = persistedRows.find((candidate) => candidate.id === messageId);
81
- if (row) row.content = content;
81
+ if (row) {row.content = content;}
82
82
  const call = addMessageCalls.find((c) => c.id === messageId);
83
- if (call) call.content = content;
83
+ if (call) {call.content = content;}
84
84
  },
85
85
  markMessageContentInflight: () => {},
86
86
  finalizeMessageContent: (messageId: string, content: string) => {
87
87
  // The finalize seam writes through `finalizeMessageContent`; mirror it
88
88
  // into the same captures as `updateMessageContent`.
89
89
  const row = persistedRows.find((candidate) => candidate.id === messageId);
90
- if (row) row.content = content;
90
+ if (row) {row.content = content;}
91
91
  const call = addMessageCalls.find((c) => c.id === messageId);
92
- if (call) call.content = content;
92
+ if (call) {call.content = content;}
93
93
  },
94
94
  // The handler treats provenance as a flat spread; returning {} keeps the
95
95
  // metadata snapshot focused on the fields under test.
@@ -153,6 +153,7 @@ mock.module("../persistence/attachments-store.js", () => ({
153
153
  // ── Imports (after mocks) ──────────────────────────────────────────────────
154
154
 
155
155
  import type { AgentEvent } from "../agent/loop.js";
156
+ import type { AssistantEvent } from "../api/index.js";
156
157
  import type {
157
158
  EventHandlerDeps,
158
159
  EventHandlerState,
@@ -162,7 +163,6 @@ import {
162
163
  handleLlmCallStarted,
163
164
  handleMessageComplete,
164
165
  } from "../daemon/conversation-agent-loop-handlers.js";
165
- import type { ServerMessage } from "../daemon/message-protocol.js";
166
166
  import { readSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
167
167
  import { deliverReplyViaCallback } from "../runtime/channel-reply-delivery.js";
168
168
  import { setConfig } from "./helpers/set-config.js";
@@ -194,7 +194,7 @@ function makeDeps(
194
194
  },
195
195
  clientTimezone: overrides.clientTimezone,
196
196
  } as unknown as EventHandlerDeps["ctx"],
197
- onEvent: (_msg: ServerMessage) => {},
197
+ onEvent: (_msg: AssistantEvent) => {},
198
198
  reqId: "test-req-id",
199
199
  isFirstMessage: false,
200
200
  shouldGenerateTitle: false,
@@ -233,7 +233,7 @@ function makeMessageCompleteEvent(
233
233
  /** Find the most recently persisted assistant-role message in the capture log. */
234
234
  function lastAssistantPersisted(): AddMessageCall {
235
235
  for (let i = addMessageCalls.length - 1; i >= 0; i--) {
236
- if (addMessageCalls[i].role === "assistant") return addMessageCalls[i];
236
+ if (addMessageCalls[i].role === "assistant") {return addMessageCalls[i];}
237
237
  }
238
238
  throw new Error("No assistant message was persisted via addMessage");
239
239
  }
@@ -14,7 +14,9 @@ import {
14
14
  hostPolicy,
15
15
  resolveRealPath,
16
16
  sandboxPolicy,
17
+ sandboxPolicyWithHostFallback,
17
18
  } from "../tools/shared/filesystem/path-policy.js";
19
+ import { getDotEnvPath } from "../util/platform.js";
18
20
 
19
21
  // ── Mock setup for skill path classifier ────────────────────────────────────
20
22
  // The classifier imports getWorkspaceSkillsDir and getBundledSkillsDir, which
@@ -94,6 +96,30 @@ describe("sandboxPolicy", () => {
94
96
  }
95
97
  });
96
98
 
99
+ test("resolveRealPath follows a trailing dangling symlink to its destination", () => {
100
+ const dir = makeTempDir();
101
+ const outside = makeTempDir();
102
+ const destination = join(outside, "not-yet.txt");
103
+ symlinkSync(destination, join(dir, "dangle"));
104
+
105
+ expect(resolveRealPath(join(dir, "dangle"))).toBe(destination);
106
+ });
107
+
108
+ test("rejects a dangling symlink whose destination escapes the boundary", () => {
109
+ const boundary = makeTempDir();
110
+ const outside = makeTempDir();
111
+
112
+ // A dangling link inside the boundary pointing at a nonexistent outside
113
+ // file: a write through it would create the outside destination.
114
+ symlinkSync(join(outside, "not-yet.txt"), join(boundary, "dangle"));
115
+
116
+ const result = sandboxPolicy("dangle", boundary, { mustExist: false });
117
+ expect(result.ok).toBe(false);
118
+ if (!result.ok) {
119
+ expect(result.reason).toBe("out_of_bounds");
120
+ }
121
+ });
122
+
97
123
  test("rejects parent dir symlink escape in mustExist=false flow", () => {
98
124
  const boundary = makeTempDir();
99
125
  const outside = makeTempDir();
@@ -191,6 +217,295 @@ describe("sandboxPolicy", () => {
191
217
  });
192
218
  });
193
219
 
220
+ // ---------------------------------------------------------------------------
221
+ // Sandbox policy with host fallback
222
+ // ---------------------------------------------------------------------------
223
+
224
+ describe("sandboxPolicyWithHostFallback", () => {
225
+ afterEach(() => {
226
+ delete process.env.IS_CONTAINERIZED;
227
+ delete process.env.GATEWAY_SECURITY_DIR;
228
+ delete process.env.CREDENTIAL_SECURITY_DIR;
229
+ });
230
+
231
+ test("matches sandboxPolicy for in-bounds paths", () => {
232
+ const boundary = makeTempDir();
233
+ mkdirSync(join(boundary, "sub"));
234
+
235
+ const result = sandboxPolicyWithHostFallback("sub/file.txt", boundary);
236
+ expect(result).toEqual(sandboxPolicy("sub/file.txt", boundary));
237
+ expect(result.ok).toBe(true);
238
+ if (result.ok) {
239
+ expect(result.resolved).toBe(join(boundary, "sub", "file.txt"));
240
+ }
241
+ });
242
+
243
+ test("allows an absolute path outside the boundary", () => {
244
+ const boundary = makeTempDir();
245
+ const outside = makeTempDir();
246
+ const target = join(outside, "file.txt");
247
+ writeFileSync(target, "x");
248
+
249
+ const result = sandboxPolicyWithHostFallback(target, boundary);
250
+ expect(result.ok).toBe(true);
251
+ if (result.ok) {
252
+ expect(result.resolved).toBe(target);
253
+ }
254
+ });
255
+
256
+ test("allows a relative traversal escape", () => {
257
+ const boundary = makeTempDir();
258
+
259
+ const result = sandboxPolicyWithHostFallback("../escape.txt", boundary, {
260
+ mustExist: false,
261
+ });
262
+ expect(result.ok).toBe(true);
263
+ if (result.ok) {
264
+ expect(result.resolved).toBe(join(boundary, "..", "escape.txt"));
265
+ }
266
+ });
267
+
268
+ test("allows a symlink that escapes the boundary", () => {
269
+ const boundary = makeTempDir();
270
+ const outside = makeTempDir();
271
+ symlinkSync(outside, join(boundary, "escape-link"));
272
+
273
+ const result = sandboxPolicyWithHostFallback("escape-link", boundary);
274
+ expect(result.ok).toBe(true);
275
+ if (result.ok) {
276
+ expect(result.resolved).toBe(join(boundary, "escape-link"));
277
+ }
278
+ });
279
+
280
+ test("denies out-of-bounds denylisted basenames", () => {
281
+ const boundary = makeTempDir();
282
+ const outside = makeTempDir();
283
+
284
+ const result = sandboxPolicyWithHostFallback(
285
+ join(outside, "backup.key"),
286
+ boundary,
287
+ { mustExist: false },
288
+ );
289
+ expect(result.ok).toBe(false);
290
+ if (!result.ok) {
291
+ expect(result.reason).toBe("denied");
292
+ }
293
+ });
294
+
295
+ test("denies paths inside the gateway security dir (env override)", () => {
296
+ const boundary = makeTempDir();
297
+ const securityDir = makeTempDir();
298
+ process.env.GATEWAY_SECURITY_DIR = securityDir;
299
+
300
+ const result = sandboxPolicyWithHostFallback(
301
+ join(securityDir, "trust.json"),
302
+ boundary,
303
+ { mustExist: false },
304
+ );
305
+ expect(result.ok).toBe(false);
306
+ if (!result.ok) {
307
+ expect(result.reason).toBe("denied");
308
+ expect(result.error).toContain("service security directory");
309
+ }
310
+ });
311
+
312
+ test("denies paths inside the CES security dir (env override)", () => {
313
+ const boundary = makeTempDir();
314
+ const securityDir = makeTempDir();
315
+ process.env.CREDENTIAL_SECURITY_DIR = securityDir;
316
+
317
+ for (const basename of ["keys.enc", "store.key"]) {
318
+ const result = sandboxPolicyWithHostFallback(
319
+ join(securityDir, basename),
320
+ boundary,
321
+ { mustExist: false },
322
+ );
323
+ expect(result.ok).toBe(false);
324
+ if (!result.ok) {
325
+ expect(result.reason).toBe("denied");
326
+ }
327
+ }
328
+ });
329
+
330
+ test("a root-configured security dir denies every absolute target", () => {
331
+ const boundary = makeTempDir();
332
+ const outside = makeTempDir();
333
+ process.env.GATEWAY_SECURITY_DIR = "/";
334
+
335
+ const result = sandboxPolicyWithHostFallback(
336
+ join(outside, "trust.json"),
337
+ boundary,
338
+ { mustExist: false },
339
+ );
340
+ expect(result.ok).toBe(false);
341
+ if (!result.ok) {
342
+ expect(result.reason).toBe("denied");
343
+ }
344
+ });
345
+
346
+ test("denies the daemon dotenv", () => {
347
+ const boundary = makeTempDir();
348
+
349
+ const result = sandboxPolicyWithHostFallback(getDotEnvPath(), boundary, {
350
+ mustExist: false,
351
+ });
352
+ expect(result.ok).toBe(false);
353
+ if (!result.ok) {
354
+ expect(result.reason).toBe("denied");
355
+ }
356
+ });
357
+
358
+ test("denies the default gateway security dir when the env is unset", () => {
359
+ const boundary = makeTempDir();
360
+
361
+ const result = sandboxPolicyWithHostFallback(
362
+ join(
363
+ process.env.HOME!,
364
+ ".vellum",
365
+ "protected",
366
+ "actor-token-signing-key",
367
+ ),
368
+ boundary,
369
+ { mustExist: false },
370
+ );
371
+ expect(result.ok).toBe(false);
372
+ if (!result.ok) {
373
+ expect(result.reason).toBe("denied");
374
+ }
375
+ });
376
+
377
+ test("denies the gateway security dir even when it sits inside the boundary", () => {
378
+ const boundary = makeTempDir();
379
+ const securityDir = join(boundary, "protected");
380
+ mkdirSync(securityDir);
381
+ process.env.GATEWAY_SECURITY_DIR = securityDir;
382
+
383
+ for (const policy of [sandboxPolicy, sandboxPolicyWithHostFallback]) {
384
+ const result = policy("protected/trust.json", boundary, {
385
+ mustExist: false,
386
+ });
387
+ expect(result.ok).toBe(false);
388
+ if (!result.ok) {
389
+ expect(result.reason).toBe("denied");
390
+ }
391
+ }
392
+ });
393
+
394
+ test("denies a dangling symlink pointing into the gateway security dir", () => {
395
+ const boundary = makeTempDir();
396
+ const outside = makeTempDir();
397
+ const securityDir = makeTempDir();
398
+ process.env.GATEWAY_SECURITY_DIR = securityDir;
399
+ // The destination does NOT exist — a write through the link would create
400
+ // it inside the security dir.
401
+ symlinkSync(
402
+ join(securityDir, "new-signing-key"),
403
+ join(outside, "innocent.txt"),
404
+ );
405
+
406
+ const result = sandboxPolicyWithHostFallback(
407
+ join(outside, "innocent.txt"),
408
+ boundary,
409
+ { mustExist: false },
410
+ );
411
+ expect(result.ok).toBe(false);
412
+ if (!result.ok) {
413
+ expect(result.reason).toBe("denied");
414
+ }
415
+ });
416
+
417
+ test("denies a long dangling symlink chain into the gateway security dir", () => {
418
+ const boundary = makeTempDir();
419
+ const outside = makeTempDir();
420
+ const securityDir = makeTempDir();
421
+ process.env.GATEWAY_SECURITY_DIR = securityDir;
422
+
423
+ // A 33-link chain exceeds macOS's own 32-link traversal limit but stays
424
+ // within Linux's 40 — the policy must resolve past it either way.
425
+ let target = join(securityDir, "new-signing-key");
426
+ for (let i = 32; i >= 0; i--) {
427
+ const link = join(outside, `link-${i}`);
428
+ symlinkSync(target, link);
429
+ target = link;
430
+ }
431
+
432
+ const result = sandboxPolicyWithHostFallback(target, boundary, {
433
+ mustExist: false,
434
+ });
435
+ expect(result.ok).toBe(false);
436
+ if (!result.ok) {
437
+ expect(result.reason).toBe("denied");
438
+ }
439
+ });
440
+
441
+ test("denies a symlink that resolves into the gateway security dir", () => {
442
+ const boundary = makeTempDir();
443
+ const outside = makeTempDir();
444
+ const securityDir = makeTempDir();
445
+ process.env.GATEWAY_SECURITY_DIR = securityDir;
446
+ writeFileSync(join(securityDir, "trust.json"), "{}");
447
+ symlinkSync(
448
+ join(securityDir, "trust.json"),
449
+ join(outside, "innocent.json"),
450
+ );
451
+
452
+ const result = sandboxPolicyWithHostFallback(
453
+ join(outside, "innocent.json"),
454
+ boundary,
455
+ );
456
+ expect(result.ok).toBe(false);
457
+ if (!result.ok) {
458
+ expect(result.reason).toBe("denied");
459
+ }
460
+ });
461
+
462
+ test("fails closed to the hard boundary when a security-dir override is relative", () => {
463
+ const boundary = makeTempDir();
464
+ const outside = makeTempDir();
465
+ // A relative override resolves against the owning service's cwd, which
466
+ // the daemon cannot know — the deny set is unmirrorable, so no escape
467
+ // is permitted at all.
468
+ process.env.GATEWAY_SECURITY_DIR = "relative/security-dir";
469
+
470
+ const result = sandboxPolicyWithHostFallback(
471
+ join(outside, "file.txt"),
472
+ boundary,
473
+ { mustExist: false },
474
+ );
475
+ expect(result.ok).toBe(false);
476
+ if (!result.ok) {
477
+ expect(result.reason).toBe("out_of_bounds");
478
+ }
479
+ });
480
+
481
+ test("keeps the hard boundary when containerized", () => {
482
+ const boundary = makeTempDir();
483
+ const outside = makeTempDir();
484
+ process.env.IS_CONTAINERIZED = "true";
485
+
486
+ const result = sandboxPolicyWithHostFallback(
487
+ join(outside, "file.txt"),
488
+ boundary,
489
+ { mustExist: false },
490
+ );
491
+ expect(result.ok).toBe(false);
492
+ if (!result.ok) {
493
+ expect(result.reason).toBe("out_of_bounds");
494
+ expect(result.error).toContain("outside the working directory");
495
+ }
496
+ });
497
+
498
+ test("still accepts in-bounds paths when containerized", () => {
499
+ const boundary = makeTempDir();
500
+ process.env.IS_CONTAINERIZED = "true";
501
+
502
+ const result = sandboxPolicyWithHostFallback("file.txt", boundary, {
503
+ mustExist: false,
504
+ });
505
+ expect(result.ok).toBe(true);
506
+ });
507
+ });
508
+
194
509
  // ---------------------------------------------------------------------------
195
510
  // Host policy
196
511
  // ---------------------------------------------------------------------------
@@ -10,14 +10,14 @@
10
10
 
11
11
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
12
12
 
13
- import type { ServerMessage } from "../daemon/message-protocol.js";
13
+ import type { AssistantEvent } from "../api/index.js";
14
14
 
15
15
  // Capture every broadcast emitted by the tracker. The real hub is replaced
16
16
  // with a thin recorder so we can assert payloads deterministically.
17
- const publishedMessages: ServerMessage[] = [];
17
+ const publishedMessages: AssistantEvent[] = [];
18
18
 
19
19
  mock.module("../runtime/assistant-event-hub.js", () => ({
20
- broadcastMessage: (msg: ServerMessage) => {
20
+ broadcastMessage: (msg: AssistantEvent) => {
21
21
  publishedMessages.push(msg);
22
22
  },
23
23
  capabilityForMessageType: () => undefined,
@@ -41,7 +41,7 @@ afterEach(() => {
41
41
  function lastResolvedEvent() {
42
42
  const evt = publishedMessages.find((m) => m.type === "interaction_resolved");
43
43
  expect(evt).toBeDefined();
44
- return evt as Extract<ServerMessage, { type: "interaction_resolved" }>;
44
+ return evt as Extract<AssistantEvent, { type: "interaction_resolved" }>;
45
45
  }
46
46
 
47
47
  describe("pendingInteractions.resolve emits interaction_resolved", () => {
@@ -181,7 +181,7 @@ describe("removeByConversation emits interaction_resolved per entry", () => {
181
181
 
182
182
  const events = publishedMessages.filter(
183
183
  (m) => m.type === "interaction_resolved",
184
- ) as Extract<ServerMessage, { type: "interaction_resolved" }>[];
184
+ ) as Extract<AssistantEvent, { type: "interaction_resolved" }>[];
185
185
  expect(events).toHaveLength(2);
186
186
  expect(events.every((e) => e.state === "superseded")).toBe(true);
187
187
  const requestIds = new Set(events.map((e) => e.requestId));
@@ -207,7 +207,7 @@ describe("removeByConversation emits interaction_resolved per entry", () => {
207
207
  );
208
208
  expect(events).toHaveLength(1);
209
209
  expect(
210
- (events[0] as Extract<ServerMessage, { type: "interaction_resolved" }>)
210
+ (events[0] as Extract<AssistantEvent, { type: "interaction_resolved" }>)
211
211
  .state,
212
212
  ).toBe("cancelled");
213
213
  });
@@ -65,7 +65,7 @@ const PERSISTENCE_TO_MEMORY_ALLOWLIST: Record<string, ReadonlySet<string>> = {
65
65
  *
66
66
  * `steps.ts` is the ordered list of every migration step; it imports each
67
67
  * migration's forward/down function from the domain that owns it (memory's
68
- * `graph/bootstrap`, apps' `app-store`, …). Migrations are append-only and
68
+ * `v1/graph/bootstrap`, apps' `app-store`, …). Migrations are append-only and
69
69
  * checkpointed by stable function name, so they live in their owning feature by
70
70
  * design and are merely *referenced* here by the registry — this is the
71
71
  * registry's job, not a layering violation to ratchet to zero. Validated by the
@@ -73,7 +73,7 @@ const PERSISTENCE_TO_MEMORY_ALLOWLIST: Record<string, ReadonlySet<string>> = {
73
73
  * entry here.
74
74
  */
75
75
  const MIGRATION_REGISTRY_MEMORY_IMPORTS: Record<string, ReadonlySet<string>> = {
76
- "assistant/src/persistence/steps.ts": new Set(["graph/bootstrap"]),
76
+ "assistant/src/persistence/steps.ts": new Set(["v1/graph/bootstrap"]),
77
77
  };
78
78
 
79
79
  /** Match `from "x"`, `import "x"`, `import("x")`, and `mock.module("x", …)`. */
@@ -6,7 +6,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
6
6
  import {
7
7
  getPkbAutoInjectList,
8
8
  readAutoinjectList,
9
- } from "../plugins/defaults/memory/pkb/autoinject.js";
9
+ } from "../plugins/defaults/memory/v1/pkb/autoinject.js";
10
10
 
11
11
  const PKB_DEFAULT_FILES = [
12
12
  "INDEX.md",
@@ -92,6 +92,7 @@ mock.module("../tools/registry.js", () => ({
92
92
 
93
93
  mock.module("../tools/shared/filesystem/path-policy.js", () => ({
94
94
  sandboxPolicy: () => ({ ok: false }),
95
+ sandboxPolicyWithHostFallback: () => ({ ok: false }),
95
96
  hostPolicy: () => ({ ok: false }),
96
97
  }));
97
98
 
@@ -7,27 +7,27 @@ let mockPlatformBaseUrl = "";
7
7
  let mockPlatformAssistantId = "";
8
8
  let mockSecureKeys: Record<string, string> = {};
9
9
 
10
+ // Bun shares mocked modules across test files in a combined run, so each mock
11
+ // spreads the real module and overrides only what this file drives. Replacing
12
+ // a module wholesale drops the exports peer tests import from it and breaks
13
+ // their ESM named-import validation whenever this mock wins evaluation.
14
+ const actualEnvRegistry = await import("../config/env-registry.js");
10
15
  mock.module("../config/env-registry.js", () => ({
16
+ ...actualEnvRegistry,
11
17
  getIsPlatform: () => mockIsPlatform,
12
- // Not called by this test, but the real util/logger.js + util/platform.js
13
- // (loaded now that the logger is silent under test instead of mocked)
14
- // import these names, and ESM named-import validation requires them.
15
- getWorkspaceDirOverride: () => process.env.VELLUM_WORKSPACE_DIR,
16
- getDebugStdoutLogs: () => false,
17
- getIsContainerized: () => false,
18
18
  }));
19
19
 
20
+ const actualEnv = await import("../config/env.js");
20
21
  mock.module("../config/env.js", () => ({
22
+ ...actualEnv,
21
23
  getPlatformBaseUrl: () => mockPlatformBaseUrl,
22
24
  getPlatformAssistantId: () => mockPlatformAssistantId,
23
25
  }));
24
26
 
27
+ const actualSecureKeys = await import("../security/secure-keys.js");
25
28
  mock.module("../security/secure-keys.js", () => ({
29
+ ...actualSecureKeys,
26
30
  getSecureKeyAsync: async (key: string) => mockSecureKeys[key] ?? undefined,
27
- // Bun shares mocked modules across test files in a combined run; peer
28
- // tests import this name from the same module, so stub it to keep their
29
- // ESM named-import validation satisfied when this mock wins evaluation.
30
- deleteSecureKeyAsync: async () => ({ deleted: false }),
31
31
  }));
32
32
 
33
33
  const originalFetch = globalThis.fetch;
@@ -10,13 +10,17 @@
10
10
 
11
11
  import { describe, expect, test } from "bun:test";
12
12
 
13
+ import type { AssistantEventEnvelope } from "../api/index.js";
13
14
  import { assistantEventHub as pluginHub } from "../plugin-api/index.js";
14
- import type { AssistantEvent } from "../runtime/assistant-event.js";
15
15
  import { assistantEventHub as rawHub } from "../runtime/assistant-event-hub.js";
16
16
 
17
+ // The hub's `publish` fans out locally only in the main daemon; elsewhere it
18
+ // forwards over IPC. A test process defaults to "main daemon" (set by the test
19
+ // preload), so these local-delivery assertions hold.
20
+
17
21
  /** Minimal event envelope; the facade guard keys only off `message.type`. */
18
- function envelope(type: string): AssistantEvent {
19
- return { message: { type } } as unknown as AssistantEvent;
22
+ function envelope(type: string): AssistantEventEnvelope {
23
+ return { message: { type } } as unknown as AssistantEventEnvelope;
20
24
  }
21
25
 
22
26
  function eventType(event: unknown): unknown {
@@ -24,7 +28,7 @@ function eventType(event: unknown): unknown {
24
28
  }
25
29
 
26
30
  /** Register a host-capable desktop client subscriber on the raw hub. */
27
- function subscribeHostClient(clientId: string, sink: AssistantEvent[]) {
31
+ function subscribeHostClient(clientId: string, sink: AssistantEventEnvelope[]) {
28
32
  return rawHub.subscribe({
29
33
  type: "client",
30
34
  clientId,
@@ -65,11 +69,14 @@ describe("plugin-facing assistantEventHub facade", () => {
65
69
  const proto = Object.getPrototypeOf(pluginHub) as { publish?: unknown };
66
70
  expect(typeof proto?.publish).not.toBe("function");
67
71
 
68
- const received: AssistantEvent[] = [];
72
+ const received: AssistantEventEnvelope[] = [];
69
73
  const sub = subscribeHostClient("facade-proto-client", received);
70
74
  try {
71
75
  const p = Object.getPrototypeOf(pluginHub) as {
72
- publish?: (event: AssistantEvent, options?: unknown) => Promise<void>;
76
+ publish?: (
77
+ event: AssistantEventEnvelope,
78
+ options?: unknown,
79
+ ) => Promise<void>;
73
80
  } | null;
74
81
  await p?.publish?.call(pluginHub, envelope("host_bash_request"), {
75
82
  targetClientId: "facade-proto-client",
@@ -97,7 +104,7 @@ describe("plugin-facing assistantEventHub facade", () => {
97
104
  });
98
105
 
99
106
  test("snapshots the event so a mutating type getter cannot bypass the guard (Codex P1)", async () => {
100
- const received: AssistantEvent[] = [];
107
+ const received: AssistantEventEnvelope[] = [];
101
108
  const sub = subscribeHostClient("facade-toctou-client", received);
102
109
  try {
103
110
  // `message.type` reads benign first (what the guard would see) then turns
@@ -111,7 +118,7 @@ describe("plugin-facing assistantEventHub facade", () => {
111
118
  return reads === 1 ? "sync_changed" : "host_bash_request";
112
119
  },
113
120
  });
114
- const sneaky = { message } as unknown as AssistantEvent;
121
+ const sneaky = { message } as unknown as AssistantEventEnvelope;
115
122
 
116
123
  await pluginHub.publish(sneaky, {
117
124
  targetClientId: "facade-toctou-client",
@@ -127,7 +134,7 @@ describe("plugin-facing assistantEventHub facade", () => {
127
134
  });
128
135
 
129
136
  test("freezes the published snapshot so a subscriber cannot mutate it mid-fanout (Codex P1)", async () => {
130
- const hostReceived: AssistantEvent[] = [];
137
+ const hostReceived: AssistantEventEnvelope[] = [];
131
138
  // A malicious subscriber registered first tries to turn the in-flight event
132
139
  // into a host request before the host-capable client (registered after)
133
140
  // receives the same fanned-out object.
@@ -154,7 +161,7 @@ describe("plugin-facing assistantEventHub facade", () => {
154
161
  });
155
162
 
156
163
  test("rejects host events disguised as boxed strings (Codex P1)", async () => {
157
- const received: AssistantEvent[] = [];
164
+ const received: AssistantEventEnvelope[] = [];
158
165
  const sub = subscribeHostClient("facade-boxed-client", received);
159
166
  try {
160
167
  // `new String(...)` is typeof "object" (slipping a naive string guard) but
@@ -164,7 +171,7 @@ describe("plugin-facing assistantEventHub facade", () => {
164
171
  const boxedType = new String("host_bash_request");
165
172
  const boxed = {
166
173
  message: { type: boxedType },
167
- } as unknown as AssistantEvent;
174
+ } as unknown as AssistantEventEnvelope;
168
175
  let rejected: unknown;
169
176
  try {
170
177
  await pluginHub.publish(boxed, {
@@ -183,7 +190,7 @@ describe("plugin-facing assistantEventHub facade", () => {
183
190
  });
184
191
 
185
192
  test("delegates non-host publish to the shared singleton", async () => {
186
- const received: AssistantEvent[] = [];
193
+ const received: AssistantEventEnvelope[] = [];
187
194
  // Subscribe on the RAW hub, publish through the FACADE: delivery proves the
188
195
  // facade delegates to the same instance (shared subscriber state). The
189
196
  // delivered event is a snapshot, so it is compared by value, not identity.
@@ -214,7 +221,7 @@ describe("plugin-facing assistantEventHub facade", () => {
214
221
  });
215
222
 
216
223
  test("downgrades plugin client subscriptions to in-process (no host-event interception) (Codex P1)", async () => {
217
- const received: AssistantEvent[] = [];
224
+ const received: AssistantEventEnvelope[] = [];
218
225
  // Ask for a host-capable client subscription; the facade must register a
219
226
  // process subscriber, which never receives capability-targeted host events.
220
227
  const sub = pluginHub.subscribe({
@@ -237,7 +244,7 @@ describe("plugin-facing assistantEventHub facade", () => {
237
244
  });
238
245
 
239
246
  test("isolates plugin callbacks so they cannot mutate the in-flight fanout event (Codex P1)", async () => {
240
- const hostReceived: AssistantEvent[] = [];
247
+ const hostReceived: AssistantEventEnvelope[] = [];
241
248
  // The plugin subscribes first and, from its callback, tries to rewrite the
242
249
  // shared in-flight event into a host request. It must only see an isolated
243
250
  // copy, leaving the real client's event untouched.
@@ -292,7 +299,7 @@ describe("plugin-facing assistantEventHub facade", () => {
292
299
  {
293
300
  message: { type: "host_bash_request" },
294
301
  conversationId: "conv-1",
295
- } as unknown as AssistantEvent,
302
+ } as unknown as AssistantEventEnvelope,
296
303
  { targetCapability: "host_bash" },
297
304
  );
298
305
  expect(getterCalls).toBe(callsAfterSubscribe);