@vellumai/assistant 0.10.12 → 0.11.0-staging.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (776) 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 +246 -10
  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__/approval-cascade.test.ts +5 -5
  39. package/src/__tests__/approval-routes-http.test.ts +3 -3
  40. package/src/__tests__/ask-question-resolver.test.ts +207 -0
  41. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  42. package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
  43. package/src/__tests__/assistant-event-hub.test.ts +13 -11
  44. package/src/__tests__/assistant-event.test.ts +12 -9
  45. package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
  46. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
  47. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
  48. package/src/__tests__/assistant-stream-state.test.ts +17 -7
  49. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  50. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  51. package/src/__tests__/call-conversation-messages.test.ts +134 -18
  52. package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
  53. package/src/__tests__/channel-approvals.test.ts +0 -27
  54. package/src/__tests__/channel-guardian.test.ts +85 -512
  55. package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
  56. package/src/__tests__/channel-retry-sweep.test.ts +88 -1
  57. package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
  58. package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
  59. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
  60. package/src/__tests__/compaction-events.test.ts +8 -8
  61. package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
  62. package/src/__tests__/config-model-image-provider.test.ts +20 -0
  63. package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
  64. package/src/__tests__/config-schema.test.ts +14 -2
  65. package/src/__tests__/config-set-platform-guard.test.ts +11 -12
  66. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  67. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
  68. package/src/__tests__/context-search-memory-source.test.ts +1 -1
  69. package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
  70. package/src/__tests__/context-token-estimator.test.ts +54 -1
  71. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
  72. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
  73. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  74. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
  75. package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
  76. package/src/__tests__/conversation-agent-loop.test.ts +39 -30
  77. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  78. package/src/__tests__/conversation-evictor.test.ts +49 -0
  79. package/src/__tests__/conversation-fork-crud.test.ts +1 -1
  80. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  81. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  82. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
  83. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  84. package/src/__tests__/conversation-queue.test.ts +81 -81
  85. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
  86. package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  90. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  91. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  92. package/src/__tests__/conversation-summarize-route.test.ts +9 -0
  93. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
  94. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  95. package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
  96. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  97. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  98. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  99. package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
  100. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
  101. package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
  102. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  103. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  105. package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
  107. package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
  108. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  109. package/src/__tests__/daemon-assistant-events.test.ts +14 -15
  110. package/src/__tests__/db-test-helpers.ts +13 -27
  111. package/src/__tests__/disk-pressure-routes.test.ts +12 -3
  112. package/src/__tests__/document-tool-security.test.ts +95 -0
  113. package/src/__tests__/drain-kick-guard.test.ts +232 -0
  114. package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
  115. package/src/__tests__/emit-event-signal.test.ts +5 -6
  116. package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
  117. package/src/__tests__/events-tail-route.test.ts +6 -4
  118. package/src/__tests__/feature-flag-test-helpers.ts +10 -20
  119. package/src/__tests__/file-edit-tool.test.ts +24 -4
  120. package/src/__tests__/file-list-tool.test.ts +2 -1
  121. package/src/__tests__/file-read-tool.test.ts +62 -10
  122. package/src/__tests__/file-write-tool.test.ts +24 -5
  123. package/src/__tests__/followup-tools.test.ts +58 -0
  124. package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
  125. package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
  126. package/src/__tests__/guardian-question-mode.test.ts +42 -3
  127. package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
  128. package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
  129. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  130. package/src/__tests__/heartbeat-service.test.ts +1 -0
  131. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  132. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  133. package/src/__tests__/host-file-edit-tool.test.ts +3 -3
  134. package/src/__tests__/host-file-read-tool.test.ts +2 -2
  135. package/src/__tests__/host-file-write-tool.test.ts +7 -3
  136. package/src/__tests__/host-shell-tool.test.ts +17 -5
  137. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  138. package/src/__tests__/image-credentials.test.ts +65 -8
  139. package/src/__tests__/injection-block.test.ts +4 -4
  140. package/src/__tests__/injector-chain.test.ts +1 -1
  141. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  142. package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
  143. package/src/__tests__/injector-v3-suppression.test.ts +6 -4
  144. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
  145. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  146. package/src/__tests__/llm-usage-store.test.ts +67 -4
  147. package/src/__tests__/log-redact.test.ts +18 -0
  148. package/src/__tests__/managed-profile-guard.test.ts +27 -0
  149. package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
  150. package/src/__tests__/media-generate-image.test.ts +62 -11
  151. package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
  152. package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
  153. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  154. package/src/__tests__/notification-decision-strategy.test.ts +115 -11
  155. package/src/__tests__/notification-deep-link.test.ts +12 -12
  156. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  157. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  158. package/src/__tests__/path-policy.test.ts +315 -0
  159. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  160. package/src/__tests__/persistence-layering-guard.test.ts +2 -2
  161. package/src/__tests__/pkb-autoinject.test.ts +1 -1
  162. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
  163. package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
  164. package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
  165. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
  166. package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
  167. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  168. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
  169. package/src/__tests__/require-fresh-approval.test.ts +38 -38
  170. package/src/__tests__/run-due-schedules.test.ts +72 -1
  171. package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
  172. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  173. package/src/__tests__/schedule-routes.test.ts +44 -5
  174. package/src/__tests__/schedule-store.test.ts +3 -3
  175. package/src/__tests__/schedule-tools.test.ts +176 -0
  176. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  177. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  178. package/src/__tests__/secret-response-routing.test.ts +3 -3
  179. package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
  180. package/src/__tests__/secret-scanner.test.ts +36 -0
  181. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  182. package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
  183. package/src/__tests__/starter-task-flow.test.ts +6 -3
  184. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  185. package/src/__tests__/subagent-disposal.test.ts +40 -11
  186. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  187. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  188. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  189. package/src/__tests__/subagent-manager-notify.test.ts +73 -14
  190. package/src/__tests__/subagent-notify-parent.test.ts +48 -4
  191. package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
  192. package/src/__tests__/subagent-tools.test.ts +64 -0
  193. package/src/__tests__/sync-message-contract.test.ts +3 -3
  194. package/src/__tests__/terminal-tools.test.ts +12 -3
  195. package/src/__tests__/test-preload.ts +9 -0
  196. package/src/__tests__/tool-approval-handler.test.ts +583 -43
  197. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
  198. package/src/__tests__/tool-executor.test.ts +116 -0
  199. package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
  200. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
  201. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  202. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  203. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
  204. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  205. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  206. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  207. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  208. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
  209. package/src/__tests__/workspace-policy.test.ts +399 -0
  210. package/src/acp/__tests__/client-handler.test.ts +3 -3
  211. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  212. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  213. package/src/acp/client-handler.ts +3 -3
  214. package/src/acp/session-manager.ts +8 -8
  215. package/src/api/events/subagent-event.ts +2 -2
  216. package/src/api/responses/memory-v2-activation-log.ts +2 -2
  217. package/src/approvals/AGENTS.md +2 -0
  218. package/src/approvals/guardian-request-resolvers.ts +118 -24
  219. package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
  220. package/src/calls/__tests__/voice-session-bridge.test.ts +158 -4
  221. package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
  222. package/src/calls/call-controller.ts +27 -27
  223. package/src/calls/call-conversation-messages.ts +58 -18
  224. package/src/calls/voice-control-protocol.ts +56 -0
  225. package/src/calls/voice-session-bridge.ts +156 -58
  226. package/src/calls/voice-triage-escalate.ts +2 -3
  227. package/src/channels/config.ts +8 -0
  228. package/src/channels/types.ts +1 -0
  229. package/src/cli/commands/config.ts +49 -13
  230. package/src/cli/commands/memory/index.help.ts +4 -2
  231. package/src/cli/commands/memory/memory-retrospective.ts +5 -0
  232. package/src/cli/lib/bundled-marketplace.json +12 -0
  233. package/src/cli.ts +2 -109
  234. package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
  235. package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
  236. package/src/config/assistant-feature-flags.ts +1 -1
  237. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
  238. package/src/config/feature-flag-cache.ts +6 -16
  239. package/src/config/feature-flag-registry.json +14 -30
  240. package/src/config/loader.ts +7 -1
  241. package/src/config/memory-tier.ts +15 -10
  242. package/src/config/memory-v3-gate.test.ts +278 -1
  243. package/src/config/memory-v3-gate.ts +88 -26
  244. package/src/config/raw-config-utils.ts +1 -1
  245. package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
  246. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  247. package/src/config/schemas/live-voice.ts +33 -7
  248. package/src/config/schemas/llm.ts +1 -0
  249. package/src/config/schemas/memory-retrospective.ts +13 -0
  250. package/src/config/schemas/memory-substrate.ts +183 -0
  251. package/src/config/schemas/memory-v2.ts +3 -2
  252. package/src/config/schemas/memory-v3.ts +11 -4
  253. package/src/config/schemas/memory.ts +35 -1
  254. package/src/config/schemas/services.ts +10 -2
  255. package/src/config/substrate-twin-shadowing.ts +195 -0
  256. package/src/config/webhook-routing.ts +67 -0
  257. package/src/context/compactor.ts +10 -3
  258. package/src/context/token-estimator.ts +21 -0
  259. package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
  260. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  261. package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
  262. package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
  263. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  264. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  265. package/src/daemon/channel-ui-capability.ts +70 -1
  266. package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
  267. package/src/daemon/conversation-agent-loop.ts +12 -5
  268. package/src/daemon/conversation-evictor.ts +26 -4
  269. package/src/daemon/conversation-launch.ts +11 -14
  270. package/src/daemon/conversation-messaging.ts +14 -14
  271. package/src/daemon/conversation-notifiers.ts +2 -2
  272. package/src/daemon/conversation-process.ts +133 -21
  273. package/src/daemon/conversation-queue-manager.ts +7 -7
  274. package/src/daemon/conversation-runtime-assembly.ts +16 -0
  275. package/src/daemon/conversation-store.ts +11 -3
  276. package/src/daemon/conversation-surfaces.ts +4 -4
  277. package/src/daemon/conversation-tool-setup.ts +13 -7
  278. package/src/daemon/conversation-usage.ts +12 -11
  279. package/src/daemon/conversation.ts +38 -15
  280. package/src/daemon/disk-pressure-guard.ts +5 -12
  281. package/src/daemon/embedding-reconcile.ts +14 -9
  282. package/src/daemon/handlers/config-channels.ts +40 -134
  283. package/src/daemon/handlers/config-model.ts +15 -7
  284. package/src/daemon/handlers/conversations.ts +4 -2
  285. package/src/daemon/handlers/shared.ts +29 -0
  286. package/src/daemon/host-proxy-base.ts +4 -4
  287. package/src/daemon/lifecycle.ts +13 -0
  288. package/src/daemon/message-protocol.ts +8 -144
  289. package/src/daemon/message-types/computer-use.ts +0 -12
  290. package/src/daemon/message-types/conversations.ts +9 -345
  291. package/src/daemon/message-types/host-app-control.ts +0 -9
  292. package/src/daemon/message-types/host-browser.ts +0 -7
  293. package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
  294. package/src/daemon/message-types/messages.ts +0 -48
  295. package/src/daemon/message-types/notifications.ts +0 -7
  296. package/src/daemon/message-types/skills.ts +0 -5
  297. package/src/daemon/message-types/surfaces.ts +0 -9
  298. package/src/daemon/message-types/sync.ts +0 -2
  299. package/src/daemon/process-message.ts +5 -5
  300. package/src/daemon/skill-memory-refresh.ts +5 -5
  301. package/src/daemon/tool-side-effects.ts +13 -13
  302. package/src/daemon/trust-context.ts +1 -1
  303. package/src/daemon/wake-conversation-ops.ts +4 -4
  304. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
  305. package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
  306. package/src/heartbeat/heartbeat-run-store.ts +81 -4
  307. package/src/heartbeat/heartbeat-service.ts +32 -1
  308. package/src/home/__tests__/feed-writer.test.ts +7 -7
  309. package/src/home/__tests__/home-content-refresh.test.ts +3 -0
  310. package/src/home/__tests__/suggested-prompts.test.ts +1 -0
  311. package/src/home/feed-writer.ts +6 -13
  312. package/src/home/home-content-refresh.ts +6 -9
  313. package/src/home/relationship-state-writer.ts +5 -12
  314. package/src/home/suggested-prompts-cache.ts +6 -19
  315. package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
  316. package/src/ipc/events-publish-client.ts +44 -0
  317. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  318. package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
  319. package/src/ipc/routes/events-ipc-routes.ts +11 -31
  320. package/src/live-voice/__tests__/front-decision.test.ts +4 -176
  321. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
  322. package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
  323. package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
  324. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
  325. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
  326. package/src/live-voice/__tests__/live-voice-vad.test.ts +218 -422
  327. package/src/live-voice/front-decision.ts +5 -155
  328. package/src/live-voice/live-voice-metrics.ts +4 -1
  329. package/src/live-voice/live-voice-session.ts +650 -333
  330. package/src/live-voice/progress-phrases.ts +17 -0
  331. package/src/live-voice/protocol.ts +15 -0
  332. package/src/media/app-icon-generator.ts +15 -8
  333. package/src/media/avatar-router.ts +9 -5
  334. package/src/media/image-credentials.ts +42 -10
  335. package/src/media/image-service.ts +1 -13
  336. package/src/media/types.ts +26 -3
  337. package/src/notifications/AGENTS.md +2 -0
  338. package/src/notifications/__tests__/broadcaster.test.ts +95 -0
  339. package/src/notifications/adapters/macos.ts +3 -3
  340. package/src/notifications/broadcaster.ts +57 -0
  341. package/src/notifications/copy-composer.ts +0 -15
  342. package/src/notifications/decision-engine.ts +21 -22
  343. package/src/notifications/guardian-question-mode.ts +57 -2
  344. package/src/notifications/home-feed-side-effect.ts +4 -0
  345. package/src/notifications/signal.ts +6 -4
  346. package/src/notifications/trusted-contact-payloads.ts +3 -4
  347. package/src/notifications/vellum-card-affinity.ts +39 -0
  348. package/src/oauth/AGENTS.md +1 -1
  349. package/src/permissions/channel-permission-query.test.ts +69 -0
  350. package/src/permissions/channel-permission-query.ts +73 -1
  351. package/src/permissions/checker.test.ts +85 -9
  352. package/src/permissions/checker.ts +17 -22
  353. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  354. package/src/permissions/confirmation-guardian-request.ts +2 -2
  355. package/src/permissions/gateway-threshold-reader.test.ts +224 -17
  356. package/src/permissions/gateway-threshold-reader.ts +82 -10
  357. package/src/permissions/ipc-risk-types.ts +8 -0
  358. package/src/permissions/prompter.ts +5 -5
  359. package/src/permissions/question-guardian-request.test.ts +222 -0
  360. package/src/permissions/question-guardian-request.ts +179 -0
  361. package/src/permissions/question-prompter.test.ts +8 -8
  362. package/src/permissions/question-prompter.ts +18 -0
  363. package/src/permissions/secret-prompter.ts +2 -4
  364. package/src/permissions/workspace-policy.ts +236 -34
  365. package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
  366. package/src/persistence/__tests__/message-content-file.test.ts +58 -3
  367. package/src/persistence/conversation-crud.ts +93 -0
  368. package/src/persistence/conversation-key-store.ts +63 -0
  369. package/src/persistence/db-async-query.ts +1 -1
  370. package/src/persistence/db-singleton.ts +14 -27
  371. package/src/persistence/delivery-crud.ts +45 -0
  372. package/src/persistence/embeddings/embedding-backend.ts +2 -1
  373. package/src/persistence/embeddings/embedding-identity.ts +7 -3
  374. package/src/persistence/job-utils.ts +32 -27
  375. package/src/persistence/jobs-store.ts +92 -3
  376. package/src/persistence/lifecycle-quiesce.ts +80 -0
  377. package/src/persistence/llm-usage-store.ts +45 -8
  378. package/src/persistence/message-content-file.ts +4 -4
  379. package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
  380. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
  381. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
  382. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
  383. package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
  384. package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
  385. package/src/persistence/schema/infrastructure.ts +11 -0
  386. package/src/persistence/steps.ts +7 -1
  387. package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
  388. package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
  389. package/src/plugin-api/conversation-turn.ts +4 -4
  390. package/src/plugin-api/event-hub-facade.ts +15 -6
  391. package/src/plugin-api/index.ts +10 -4
  392. package/src/plugin-api/publish-event.ts +36 -0
  393. package/src/plugins/AGENTS.md +2 -0
  394. package/src/plugins/defaults/compaction/window-manager.ts +9 -0
  395. package/src/plugins/defaults/index.ts +9 -13
  396. package/src/plugins/defaults/memory/AGENTS.md +775 -0
  397. package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
  398. package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
  399. package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
  400. package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
  401. package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
  402. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
  403. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
  404. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
  405. package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
  406. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
  407. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
  408. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
  409. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  410. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
  411. package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
  412. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
  413. package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
  414. package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
  415. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
  416. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
  417. package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
  418. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
  419. package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
  420. package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
  421. package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
  422. package/src/plugins/defaults/memory/graph/store.ts +1 -0
  423. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
  424. package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
  425. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
  426. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
  427. package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
  428. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
  429. package/src/plugins/defaults/memory/indexer.ts +146 -89
  430. package/src/plugins/defaults/memory/injectors.ts +86 -41
  431. package/src/plugins/defaults/memory/job-handlers.ts +130 -39
  432. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
  433. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
  434. package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
  435. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
  436. package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
  437. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
  438. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
  439. package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
  440. package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
  441. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
  442. package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
  443. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
  444. package/src/plugins/defaults/memory/startup.ts +58 -21
  445. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
  446. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
  447. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
  448. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
  449. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
  450. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
  451. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
  452. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
  453. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
  454. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
  455. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
  456. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
  457. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
  458. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
  459. package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
  460. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
  461. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
  462. package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
  463. package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
  464. package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
  465. package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
  466. package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
  467. package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
  468. package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
  469. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
  470. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
  471. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
  472. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
  473. package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
  474. package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
  475. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
  476. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
  477. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
  478. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
  479. package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
  480. package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
  481. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
  482. package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
  483. package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
  484. package/src/plugins/defaults/memory/tools.test.ts +1 -1
  485. package/src/plugins/defaults/memory/tools.ts +1 -1
  486. package/src/plugins/defaults/memory/v1/README.md +5 -0
  487. package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
  488. package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
  489. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
  490. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
  491. package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
  492. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
  493. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
  494. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
  495. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
  496. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
  497. package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
  498. package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
  499. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
  500. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
  501. package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
  502. package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
  503. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
  504. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
  505. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
  506. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
  507. package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
  508. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
  509. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
  510. package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
  511. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
  512. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
  513. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
  514. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
  515. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
  516. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
  517. package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
  518. package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
  519. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
  520. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
  521. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
  522. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
  523. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
  524. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
  525. package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
  526. package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
  527. package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
  528. package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
  529. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
  530. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
  531. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
  532. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  533. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  534. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
  535. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
  536. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
  537. package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
  538. package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
  539. package/src/plugins/defaults/memory/v2/activation.ts +30 -163
  540. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
  541. package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
  542. package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
  543. package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
  544. package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
  545. package/src/plugins/defaults/memory/v2/injection.ts +36 -26
  546. package/src/plugins/defaults/memory/v2/migration.ts +2 -2
  547. package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
  548. package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
  549. package/src/plugins/defaults/memory/v2/router.ts +38 -15
  550. package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
  551. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
  552. package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
  553. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
  554. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
  555. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
  556. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
  557. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
  558. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
  559. package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
  560. package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
  561. package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
  562. package/src/plugins/defaults/memory/v3/card.ts +25 -9
  563. package/src/plugins/defaults/memory/v3/edge.ts +52 -18
  564. package/src/plugins/defaults/memory/v3/gate.ts +4 -4
  565. package/src/plugins/defaults/memory/v3/injector.ts +10 -3
  566. package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
  567. package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
  568. package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
  569. package/src/plugins/defaults/memory/v3/prune.ts +40 -16
  570. package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
  571. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
  572. package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
  573. package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
  574. package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
  575. package/src/plugins/defaults/memory/v3/types.ts +4 -1
  576. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
  577. package/src/plugins/defaults/memory/validation.ts +1 -1
  578. package/src/plugins/defaults/memory/worker.ts +2 -1
  579. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
  580. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
  581. package/src/plugins/types.ts +2 -2
  582. package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
  583. package/src/providers/anthropic/client.ts +15 -6
  584. package/src/providers/content-block-schema.ts +26 -0
  585. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
  586. package/src/providers/inference/adapter-factory.ts +6 -0
  587. package/src/providers/inference/connections.ts +30 -14
  588. package/src/providers/model-catalog.ts +77 -0
  589. package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
  590. package/src/providers/openai/chat-completions-provider.ts +65 -17
  591. package/src/providers/openai/input-audio.ts +76 -0
  592. package/src/providers/openrouter/client.ts +0 -2
  593. package/src/providers/platform-proxy/constants.ts +4 -0
  594. package/src/providers/poolside/client.ts +42 -0
  595. package/src/providers/registry.ts +40 -8
  596. package/src/providers/retry.ts +2 -0
  597. package/src/providers/types.ts +39 -1
  598. package/src/providers/vercel-ai-gateway/client.ts +0 -2
  599. package/src/runtime/AGENTS.md +7 -5
  600. package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
  601. package/src/runtime/__tests__/question-resolution.test.ts +111 -0
  602. package/src/runtime/access-request-helper.ts +7 -15
  603. package/src/runtime/assistant-event-hub.ts +43 -31
  604. package/src/runtime/assistant-event-publish-options.ts +31 -0
  605. package/src/runtime/assistant-event.ts +19 -30
  606. package/src/runtime/assistant-stream-state.ts +4 -4
  607. package/src/runtime/channel-approvals.ts +0 -25
  608. package/src/runtime/channel-readiness-service.ts +99 -40
  609. package/src/runtime/channel-retry-sweep.ts +38 -15
  610. package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
  611. package/src/runtime/guardian-reply-router.ts +108 -0
  612. package/src/runtime/http-server.ts +8 -0
  613. package/src/runtime/http-types.ts +2 -2
  614. package/src/runtime/process-role.ts +42 -0
  615. package/src/runtime/question-request-guardian-bridge.ts +184 -0
  616. package/src/runtime/question-resolution.ts +153 -0
  617. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
  618. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
  619. package/src/runtime/routes/acp-routes.ts +2 -2
  620. package/src/runtime/routes/bookmark-routes.ts +3 -15
  621. package/src/runtime/routes/canned-message-complete.ts +2 -2
  622. package/src/runtime/routes/consolidation-routes.ts +8 -2
  623. package/src/runtime/routes/conversation-list-routes.ts +3 -19
  624. package/src/runtime/routes/conversation-management-routes.ts +1 -5
  625. package/src/runtime/routes/conversation-query-routes.ts +52 -8
  626. package/src/runtime/routes/conversation-routes.ts +36 -22
  627. package/src/runtime/routes/credential-request-routes.ts +0 -1
  628. package/src/runtime/routes/filing-routes.ts +7 -7
  629. package/src/runtime/routes/global-search-routes.ts +1 -1
  630. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  631. package/src/runtime/routes/image-generation-routes.ts +12 -9
  632. package/src/runtime/routes/inbound-message-handler.ts +17 -0
  633. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
  634. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
  635. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
  636. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
  637. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
  638. package/src/runtime/routes/index.ts +2 -0
  639. package/src/runtime/routes/lifecycle-routes.ts +199 -0
  640. package/src/runtime/routes/platform-routes.ts +3 -8
  641. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  642. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  643. package/src/runtime/routes/question-routes.ts +34 -87
  644. package/src/runtime/routes/secret-routes.ts +11 -1
  645. package/src/runtime/routes/settings-routes.ts +8 -18
  646. package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
  647. package/src/runtime/routes/workspace-routes.test.ts +7 -4
  648. package/src/runtime/slack-reply-session.test.ts +12 -12
  649. package/src/runtime/slack-reply-session.ts +17 -17
  650. package/src/runtime/sync/sync-publisher.test.ts +7 -5
  651. package/src/runtime/tool-grant-request-helper.ts +4 -0
  652. package/src/schedule/schedule-store.ts +70 -0
  653. package/src/schedule/scheduler.ts +27 -0
  654. package/src/security/AGENTS.md +1 -1
  655. package/src/security/credential-key.ts +17 -0
  656. package/src/security/secret-ingress.ts +14 -105
  657. package/src/security/secret-patterns.ts +8 -139
  658. package/src/security/secret-scanner.ts +8 -3
  659. package/src/security/store-path-override.ts +6 -16
  660. package/src/sequence/store.ts +8 -0
  661. package/src/signals/emit-event.ts +5 -10
  662. package/src/signals/event-stream.ts +20 -10
  663. package/src/subagent/manager.ts +76 -25
  664. package/src/subagent/notify.ts +8 -0
  665. package/src/subagent/types.ts +13 -3
  666. package/src/telegram/__tests__/webhook-health.test.ts +442 -0
  667. package/src/telegram/webhook-health.ts +478 -0
  668. package/src/telemetry/AGENTS.md +6 -0
  669. package/src/telemetry/memory-corpus-size.test.ts +129 -0
  670. package/src/telemetry/memory-corpus-size.ts +184 -0
  671. package/src/telemetry/memory-tier-reporter.test.ts +67 -2
  672. package/src/telemetry/memory-tier-reporter.ts +30 -3
  673. package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
  674. package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
  675. package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
  676. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
  677. package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
  678. package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
  679. package/src/tools/acp/abort.ts +21 -1
  680. package/src/tools/acp/context.ts +5 -5
  681. package/src/tools/acp/spawn.test.ts +15 -5
  682. package/src/tools/acp/spawn.ts +26 -3
  683. package/src/tools/acp/status.ts +20 -1
  684. package/src/tools/acp/steer.test.ts +20 -0
  685. package/src/tools/acp/steer.ts +23 -2
  686. package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
  687. package/src/tools/ask-question/ask-question-tool.ts +68 -92
  688. package/src/tools/browser/browser-screencast.ts +6 -6
  689. package/src/tools/calls/call-end.ts +24 -3
  690. package/src/tools/calls/call-start.ts +35 -11
  691. package/src/tools/calls/call-status.ts +20 -1
  692. package/src/tools/document/document-comment-tool.test.ts +49 -0
  693. package/src/tools/document/document-comment-tool.ts +45 -6
  694. package/src/tools/document/document-tool.ts +142 -24
  695. package/src/tools/executor.ts +27 -13
  696. package/src/tools/filesystem/edit.ts +62 -60
  697. package/src/tools/filesystem/list.ts +36 -29
  698. package/src/tools/filesystem/read.ts +56 -39
  699. package/src/tools/filesystem/write.ts +44 -38
  700. package/src/tools/followups/followup_create.ts +41 -12
  701. package/src/tools/followups/followup_list.ts +34 -6
  702. package/src/tools/followups/followup_resolve.ts +26 -4
  703. package/src/tools/host-filesystem/edit.ts +50 -60
  704. package/src/tools/host-filesystem/read.ts +45 -39
  705. package/src/tools/host-filesystem/write.ts +31 -36
  706. package/src/tools/host-terminal/host-shell.ts +76 -62
  707. package/src/tools/policy-context.ts +27 -10
  708. package/src/tools/schedule/create.ts +76 -33
  709. package/src/tools/schedule/delete.ts +21 -2
  710. package/src/tools/schedule/list.ts +25 -3
  711. package/src/tools/schedule/update.ts +105 -48
  712. package/src/tools/shared/filesystem/path-policy.ts +246 -40
  713. package/src/tools/shared/zod-tool-schema.ts +117 -0
  714. package/src/tools/subagent/abort.ts +12 -4
  715. package/src/tools/subagent/consult-deadline.ts +9 -3
  716. package/src/tools/subagent/message.ts +21 -5
  717. package/src/tools/subagent/notify-parent.ts +44 -23
  718. package/src/tools/subagent/read.ts +15 -4
  719. package/src/tools/subagent/resolve.ts +26 -4
  720. package/src/tools/subagent/spawn.ts +37 -13
  721. package/src/tools/subagent/status.ts +12 -4
  722. package/src/tools/system/request-permission.ts +35 -26
  723. package/src/tools/terminal/shell.ts +68 -55
  724. package/src/tools/tool-approval-handler.ts +327 -53
  725. package/src/tools/tool-input-schemas.ts +85 -0
  726. package/src/tools/tool-types.ts +7 -0
  727. package/src/tools/types.ts +8 -0
  728. package/src/tools/workflows/manage-workflows.ts +30 -2
  729. package/src/tools/workflows/run-workflow.test.ts +54 -2
  730. package/src/tools/workflows/run-workflow.ts +32 -4
  731. package/src/util/fs-symlinks.ts +30 -0
  732. package/src/util/log-redact.ts +7 -3
  733. package/src/vellum-assistant-namespace.d.ts +80 -0
  734. package/src/watcher/watcher-store.ts +8 -0
  735. package/src/workflows/leaf-runner.test.ts +104 -2
  736. package/src/workflows/leaf-runner.ts +31 -6
  737. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
  738. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
  739. package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
  740. package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
  741. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
  742. package/src/workspace/migrations/registry.ts +4 -0
  743. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  744. package/src/__tests__/secret-patterns.test.ts +0 -27
  745. package/src/config/__tests__/proc-to-skills.test.ts +0 -21
  746. package/src/config/memory-tier.test.ts +0 -44
  747. package/src/daemon/message-types/acp.ts +0 -20
  748. package/src/daemon/message-types/apps.ts +0 -11
  749. package/src/daemon/message-types/background-tools.ts +0 -14
  750. package/src/daemon/message-types/bookmarks.ts +0 -13
  751. package/src/daemon/message-types/contacts.ts +0 -13
  752. package/src/daemon/message-types/document-comments.ts +0 -14
  753. package/src/daemon/message-types/documents.ts +0 -13
  754. package/src/daemon/message-types/home.ts +0 -15
  755. package/src/daemon/message-types/host-bash.ts +0 -12
  756. package/src/daemon/message-types/host-cu.ts +0 -10
  757. package/src/daemon/message-types/host-file.ts +0 -12
  758. package/src/daemon/message-types/host-transfer.ts +0 -12
  759. package/src/daemon/message-types/integrations.ts +0 -90
  760. package/src/daemon/message-types/memory.ts +0 -10
  761. package/src/daemon/message-types/schedules.ts +0 -14
  762. package/src/daemon/message-types/settings.ts +0 -17
  763. package/src/daemon/message-types/subagents.ts +0 -63
  764. package/src/daemon/message-types/upgrades.ts +0 -14
  765. package/src/daemon/message-types/workflows.ts +0 -25
  766. package/src/daemon/message-types/workspace.ts +0 -137
  767. package/src/live-voice/ack-phrases.ts +0 -58
  768. package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
  769. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
  770. package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
  771. package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
  772. package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
  773. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
  774. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
  775. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
  776. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
@@ -6,8 +6,25 @@ import {
6
6
  import { isToolAllowedInChannel } from "../channels/permission-profiles.js";
7
7
  import type { ChannelId } from "../channels/types.js";
8
8
  import { getConfig } from "../config/loader.js";
9
+ import { isMemoryEnabled } from "../config/memory-v3-gate.js";
9
10
  import type { AutoApproveThreshold } from "../permissions/approval-policy.js";
10
- import { isDynamicSkillLoadInvocation } from "../permissions/checker.js";
11
+ import {
12
+ buildChannelPermissionCellQuery,
13
+ effectiveChannelCellThreshold,
14
+ } from "../permissions/channel-permission-query.js";
15
+ import {
16
+ isDynamicSkillLoadInvocation,
17
+ isToolOwnerSkillBundled,
18
+ } from "../permissions/checker.js";
19
+ import {
20
+ channelNoCellDefault,
21
+ resolveChannelPermissionCell,
22
+ } from "../permissions/gateway-threshold-reader.js";
23
+ import {
24
+ isControlPlaneWorkspaceWrite,
25
+ isOutOfWorkspaceFileInvocation,
26
+ isWorkspaceWriteTool,
27
+ } from "../permissions/workspace-policy.js";
11
28
  import {
12
29
  isUnparseableToolArgs,
13
30
  unparseableToolArgsMessage,
@@ -22,8 +39,10 @@ import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
22
39
  import { recordToolDenied, recordToolError } from "../telemetry/tool-audit.js";
23
40
  import { getLogger } from "../util/logger.js";
24
41
  import { resolveExecutionTarget } from "./execution-target.js";
42
+ import { channelCoordinatesFromToolContext } from "./policy-context.js";
25
43
  import { getAllTools, getTool, getToolOwner } from "./registry.js";
26
44
  import { isSideEffectTool } from "./side-effects.js";
45
+ import { parseToolInput } from "./tool-input-schemas.js";
27
46
  import { summarizeToolInput } from "./tool-input-summary.js";
28
47
  import { suggestToolName } from "./tool-name-aliases.js";
29
48
  import { recordToolCompletion } from "./tool-profiler.js";
@@ -238,25 +257,40 @@ async function stampFollowupState(
238
257
  const UI_SURFACE_TOOLS = new Set(["ui_show", "ui_update", "ui_dismiss"]);
239
258
 
240
259
  /**
241
- * Tool-sensitivity predicate: does invoking this tool require an approval
242
- * decision at all? This is about the tool, where it executes, and — for
243
- * `skill_load` — whether the invocation will execute embedded shell at load
244
- * time (inline command expansions run outside the tool pipeline, so they must
245
- * be gated like other code execution). Actor identity never feeds in here; it
246
- * enters the decision only through the `CapabilitySet` floor, see
247
- * {@link resolveSensitiveToolDecision}.
260
+ * How far a sensitive invocation reaches — the axis that decides whether a
261
+ * channel's approval cell may lift its floor. See {@link sensitiveToolReach}.
248
262
  */
249
- export function isSensitiveTool(
263
+ export type SensitiveToolReach = "none" | "sandbox" | "host";
264
+
265
+ /**
266
+ * Classify how far a sensitive invocation reaches. This is about the tool,
267
+ * where it executes, and — for `skill_load` — whether the invocation will
268
+ * execute embedded shell at load time (inline command expansions run outside
269
+ * the tool pipeline, so they must be gated like other code execution). Actor
270
+ * identity never feeds in here; it enters the decision only through the
271
+ * `CapabilitySet` floor, see {@link resolveSensitiveToolDecision}.
272
+ *
273
+ * - `"none"`: not sensitive.
274
+ * - `"sandbox"`: side effects confined to the assistant's own workspace. An
275
+ * owner can delegate these per room, so a cell may lift the floor.
276
+ * - `"host"`: reaches the guardian's own machine and accounts — host
277
+ * execution, and sandbox file tools escaping the workspace, which the
278
+ * host-fallback path policy turns into real host access. No cell lifts
279
+ * this: a room-level posture is about what the assistant may do in that
280
+ * room, never a grant of the owner's own machine.
281
+ */
282
+ export function sensitiveToolReach(
250
283
  toolName: string,
251
284
  executionTarget: ExecutionTarget,
252
285
  input?: Record<string, unknown>,
253
- ): boolean {
286
+ workingDir?: string,
287
+ ): SensitiveToolReach {
254
288
  // UI surface tools are passive, user-visible operations (cards, forms,
255
289
  // tables). User input is voluntary and user-controlled — they are not
256
290
  // sensitive, so they work during fresh onboarding before trust is
257
291
  // established.
258
292
  if (UI_SURFACE_TOOLS.has(toolName)) {
259
- return false;
293
+ return "none";
260
294
  }
261
295
 
262
296
  // An inline-command ("dynamic") skill_load executes embedded shell at load
@@ -271,12 +305,67 @@ export function isSensitiveTool(
271
305
  input &&
272
306
  isDynamicSkillLoadInvocation(toolName, input)
273
307
  ) {
274
- return true;
308
+ return "host";
309
+ }
310
+
311
+ // A sandbox file tool targeting a path outside the workspace reaches the
312
+ // host filesystem on non-containerized installs (the host-fallback path
313
+ // policy executes the escape once the permission lane approves). That is
314
+ // host-equivalent access — a read-only escape can leak local secrets — so
315
+ // it carries the same capability floor as executionTarget === "host":
316
+ // non-guardian actors escalate to the guardian, and no risk threshold or
317
+ // trust rule lifts it.
318
+ if (
319
+ input &&
320
+ workingDir &&
321
+ isOutOfWorkspaceFileInvocation(toolName, input, workingDir)
322
+ ) {
323
+ return "host";
324
+ }
325
+
326
+ // Read-only host execution is sensitive too, because it can leak sensitive
327
+ // local information (e.g. shell/file reads).
328
+ if (executionTarget === "host") {
329
+ return "host";
275
330
  }
276
331
 
277
- // Side-effect tools are sensitive. Read-only host execution is too,
278
- // because it can leak sensitive local information (e.g. shell/file reads).
279
- return isSideEffectTool(toolName) || executionTarget === "host";
332
+ // Extension-owned code that is not first-party bundled is unvetted: its
333
+ // manifest declares its own risk, and nothing reviewed it. It is sensitive
334
+ // whatever it is named — a novel name is in no side-effect list, so without
335
+ // this it would not be gated at all, and the risk its own manifest claims
336
+ // would be the only thing standing between it and an auto-approval.
337
+ if (isUnvettedExtensionTool(toolName)) {
338
+ return "sandbox";
339
+ }
340
+
341
+ // Side-effect tools are sensitive, and what is left here acts only on the
342
+ // assistant's own workspace.
343
+ return isSideEffectTool(toolName) ? "sandbox" : "none";
344
+ }
345
+
346
+ /**
347
+ * Whether a tool comes from code nobody in-repo reviewed. Vetted is an
348
+ * allowlist — the built-in default set and first-party bundled skills —
349
+ * and every other owner is unvetted: third-party and workspace skills,
350
+ * plugins, workspace tools (arbitrary on-disk code imported into the
351
+ * daemon), MCP servers, and owner kinds that do not exist yet. An
352
+ * allowlist fails closed when the owner vocabulary grows, the same reason
353
+ * the read-only subagent gate (`conversation-tool-setup.ts`) allowlists
354
+ * names and verifies `ownerKind === "default"` rather than naming the
355
+ * kinds it distrusts.
356
+ *
357
+ * An absent owner record is the built-in registration path, so it reads
358
+ * as `default`; a tool that is not registered at all cannot execute.
359
+ */
360
+ function isUnvettedExtensionTool(toolName: string): boolean {
361
+ const kind = getToolOwner(toolName)?.kind;
362
+ if (kind === undefined || kind === "default") {
363
+ return false;
364
+ }
365
+ if (kind === "skill") {
366
+ return !isToolOwnerSkillBundled(getTool(toolName));
367
+ }
368
+ return true;
280
369
  }
281
370
 
282
371
  /**
@@ -299,37 +388,179 @@ export type SensitiveToolDecision = "proceed" | "escalate-and-wait" | "deny";
299
388
 
300
389
  /**
301
390
  * Single composition point for the sensitive-tool approval decision:
302
- * approval-cell threshold × tool risk level × `CapabilitySet` floor.
391
+ * `CapabilitySet` floor × the actor's approval-matrix cell.
392
+ *
393
+ * The floor is the starting point — a sensitive invocation by a non-guardian
394
+ * needs a scoped grant. The cell is what can lift it: an owner who has given
395
+ * this contact type a non-`none` level in this room has said the assistant
396
+ * may act there without minting a per-call grant.
303
397
  *
304
- * The decision is about the tool; actor identity feeds in only through the
305
- * already-resolved `sensitiveToolApproval` capability. That floor is
306
- * deterministic and cannot be lifted by the other axes: when the capability
307
- * is not `"self"`, a sensitive invocation without a grant always escalates
308
- * or denies. `cellThreshold` and `riskLevel` are composition axes the
309
- * decision does not consult — no threshold/risk combination may lift the
310
- * outcome above the floor.
398
+ * Three things no cell lifts:
399
+ * - `host` reach. A room-level posture says what the assistant may do in that
400
+ * room; it is never a grant of the owner's own machine or accounts, so host
401
+ * execution and workspace escapes stay floored at every level.
402
+ * - `deny` — an actor with no established identity has no cell to stand on.
403
+ * - A `none` cell authorizes nothing, so the floor stands unchanged.
404
+ *
405
+ * Lifting is not approval. It decides only that a scoped grant is not the
406
+ * mechanism; the risk/threshold policy in `permissions/approval-policy.ts`
407
+ * then applies that same cell against the fully-classified risk. Whatever the
408
+ * cell does not cover still reaches the guardian — a lane-B `"prompt"` is
409
+ * promoted to a guardian-bound `tool_approval` request
410
+ * (`permissions/confirmation-guardian-request.ts`), the same principal the
411
+ * escalation path would have asked.
311
412
  */
312
413
  export function resolveSensitiveToolDecision(input: {
313
- sensitive: boolean;
414
+ /** How far the invocation reaches; see {@link sensitiveToolReach}. */
415
+ reach: SensitiveToolReach;
314
416
  /**
315
- * Approval-matrix cell axis. The decision does not consult it — the floor
316
- * alone resolves the outcome — so callers pass `undefined` rather than
317
- * paying a threshold lookup to populate it.
417
+ * Threshold of the approval-matrix cell governing this invocation.
418
+ * `undefined` when no cell covers it — including when the cell could not be
419
+ * read, since an unreadable cell must never lift the floor.
318
420
  */
319
421
  cellThreshold: ApprovalCellThreshold | undefined;
320
- /**
321
- * Risk level as known at gate time. The full risk classification runs
322
- * after this gate (in the permission checker), so callers may only have
323
- * the pre-classification level here — composing decisions on this axis
324
- * requires moving classification ahead of the gate first.
325
- */
326
- riskLevel: string;
327
422
  sensitiveToolApproval: SensitiveToolApproval;
328
423
  }): SensitiveToolDecision {
329
- if (!input.sensitive || input.sensitiveToolApproval === "self") {
424
+ if (input.reach === "none" || input.sensitiveToolApproval === "self") {
330
425
  return "proceed";
331
426
  }
332
- return input.sensitiveToolApproval;
427
+ if (input.sensitiveToolApproval === "deny" || input.reach === "host") {
428
+ return input.sensitiveToolApproval;
429
+ }
430
+ if (input.cellThreshold === undefined || input.cellThreshold === "none") {
431
+ return input.sensitiveToolApproval;
432
+ }
433
+ return "proceed";
434
+ }
435
+
436
+ /**
437
+ * Sandbox tools that execute code. Running code in the workspace is how you
438
+ * write everything else in it — including the directories
439
+ * {@link isControlPlaneWorkspaceWrite} covers — so a cell that lifted one of
440
+ * these would lift those by the back door.
441
+ *
442
+ * `skill_execute` is deliberately absent rather than overlooked: it is
443
+ * dispatch indirection, and `conversation-tool-setup` resolves it to its inner
444
+ * tool name before the gate runs, so the gate already classifies the tool the
445
+ * skill actually calls rather than the wrapper.
446
+ */
447
+ const CODE_EXECUTION_TOOLS: ReadonlySet<string> = new Set(["bash"]);
448
+
449
+ /**
450
+ * Whether an invocation reaches the private network — localhost, which is the
451
+ * daemon's own HTTP surface, the gateway, and whatever else listens on the
452
+ * guardian's machine. Keyed on the input rather than the tool, because the
453
+ * same tool is delegable against a public URL.
454
+ */
455
+ function reachesPrivateNetwork(
456
+ toolName: string,
457
+ input: Record<string, unknown>,
458
+ ): boolean {
459
+ return toolName === "web_fetch" && input.allow_private_network === true;
460
+ }
461
+
462
+ /**
463
+ * Whether a channel's approval cell may lift the floor for this invocation.
464
+ *
465
+ * The cell delegates ordinary work in the assistant's own workspace. Three
466
+ * sandbox side effects are not ordinary, because each is a way back out of
467
+ * the sandbox — and excluding only some of them would be a false safeguard,
468
+ * since any one reaches the others:
469
+ *
470
+ * - `bash` runs code. A room that can run code in the workspace can write
471
+ * anything into it, including the executable directories below, so lifting
472
+ * bash would lift those by the back door.
473
+ * - Control-plane workspace writes ({@link isControlPlaneWorkspaceWrite}) —
474
+ * the directories the daemon imports and executes, and the prompt surfaces
475
+ * it reads as its own instructions. Approving the write approves the later
476
+ * execution.
477
+ * - Unvetted extension-owned tools ({@link isUnvettedExtensionTool}). Nothing
478
+ * reviewed them, so the risk their own manifest claims must not be what
479
+ * decides whether a room may run them unattended.
480
+ * - `web_fetch` with `allow_private_network`. The private network is the
481
+ * guardian's own machine — the daemon's HTTP surface, the gateway, whatever
482
+ * else is listening on it. Fetching a public URL is delegable; reaching
483
+ * localhost is the machine floor by another door.
484
+ *
485
+ * Each stays on the capability floor, so a channel actor escalates to the
486
+ * guardian for them at every level. None of this touches the guardian's own
487
+ * lane — it decides what a *cell* may delegate, not how risk is classified.
488
+ */
489
+ function isChannelLiftable(
490
+ reach: SensitiveToolReach,
491
+ toolName: string,
492
+ input: Record<string, unknown>,
493
+ workingDir: string | undefined,
494
+ ): boolean {
495
+ if (reach !== "sandbox") {
496
+ return false;
497
+ }
498
+ if (CODE_EXECUTION_TOOLS.has(toolName)) {
499
+ return false;
500
+ }
501
+ // A write is liftable only when its target can be resolved and resolves
502
+ // outside the control plane. With no workingDir there is no way to see
503
+ // where the write lands, so the check fails closed rather than being
504
+ // skipped.
505
+ if (
506
+ isWorkspaceWriteTool(toolName) &&
507
+ (!workingDir || isControlPlaneWorkspaceWrite(toolName, input, workingDir))
508
+ ) {
509
+ return false;
510
+ }
511
+ if (isUnvettedExtensionTool(toolName)) {
512
+ return false;
513
+ }
514
+ if (reachesPrivateNetwork(toolName, input)) {
515
+ return false;
516
+ }
517
+ return true;
518
+ }
519
+
520
+ /**
521
+ * Threshold of the approval-matrix cell governing this invocation, read only
522
+ * when it can change the outcome: a channel-liftable invocation whose actor
523
+ * sits on the escalate floor. Guardians, non-sensitive tools, host reach,
524
+ * everything {@link isChannelLiftable} excludes, and identity-less actors
525
+ * return early, so the gateway lookup never lands on the paths where it could
526
+ * only add latency — grant consumption for an already-approved call, and voice
527
+ * abort handling.
528
+ *
529
+ * The permission checker reads this same cell later in the turn, within the
530
+ * reader's cache window, so the lift costs at most one lookup per turn.
531
+ *
532
+ * Returns `undefined` when the turn has no channel coordinates or a lookup
533
+ * fails — nothing lifts the floor then. A successful walk that finds no cell
534
+ * resolves the room's default — the owner's global setting collapsed to the
535
+ * channel's two levels — so an unconfigured room behaves exactly as the
536
+ * picker's "· default" marker and the legend present it
537
+ * ({@link effectiveChannelCellThreshold}).
538
+ */
539
+ async function resolveApprovalCellThreshold(
540
+ reach: SensitiveToolReach,
541
+ toolName: string,
542
+ input: Record<string, unknown>,
543
+ sensitiveToolApproval: SensitiveToolApproval,
544
+ context: ToolContext,
545
+ ): Promise<ApprovalCellThreshold | undefined> {
546
+ if (
547
+ sensitiveToolApproval !== "escalate-and-wait" ||
548
+ !isChannelLiftable(reach, toolName, input, context.workingDir)
549
+ ) {
550
+ return undefined;
551
+ }
552
+ const query = buildChannelPermissionCellQuery(
553
+ channelCoordinatesFromToolContext(context),
554
+ );
555
+ if (!query) {
556
+ return undefined;
557
+ }
558
+ const cell = await resolveChannelPermissionCell(query);
559
+ return effectiveChannelCellThreshold(
560
+ cell,
561
+ query.contactType,
562
+ await channelNoCellDefault(cell, query.contactType),
563
+ );
333
564
  }
334
565
 
335
566
  /**
@@ -347,7 +578,18 @@ function sensitiveToolDeniedMessage(
347
578
  }
348
579
 
349
580
  export type PreExecutionGateResult =
350
- | { allowed: true; tool: Tool; grantConsumed?: boolean }
581
+ | {
582
+ allowed: true;
583
+ tool: Tool;
584
+ grantConsumed?: boolean;
585
+ /**
586
+ * Input parsed against the tool's registered schema in
587
+ * `TOOL_INPUT_SCHEMAS` (with `.catch()` recoveries applied). Set only
588
+ * for built-in tools with a registered schema; the executor substitutes
589
+ * it for the raw input so validation and execution see the same value.
590
+ */
591
+ parsedInput?: Record<string, unknown>;
592
+ }
351
593
  | { allowed: false; result: ToolExecutionResult };
352
594
 
353
595
  /** Configuration for the inline grant wait behavior. */
@@ -506,16 +748,22 @@ export class ToolApprovalHandler {
506
748
  | Parameters<typeof consumeGrantForInvocation>[0]
507
749
  | null = null;
508
750
 
509
- const sensitive = isSensitiveTool(name, executionTarget, input);
751
+ const reach = sensitiveToolReach(
752
+ name,
753
+ executionTarget,
754
+ input,
755
+ context.workingDir,
756
+ );
510
757
  const { sensitiveToolApproval } = resolveCapabilities(context.trustClass);
511
- // cellThreshold stays unresolved: the decision does not consult it
512
- // (the floor is deterministic), and resolving a live threshold here
513
- // would block grant consumption — including already-approved calls and
514
- // voice abort handling — on a gateway IPC read.
515
758
  const sensitiveDecision = resolveSensitiveToolDecision({
516
- sensitive,
517
- cellThreshold: undefined,
518
- riskLevel,
759
+ reach,
760
+ cellThreshold: await resolveApprovalCellThreshold(
761
+ reach,
762
+ name,
763
+ input,
764
+ sensitiveToolApproval,
765
+ context,
766
+ ),
519
767
  sensitiveToolApproval,
520
768
  });
521
769
 
@@ -570,7 +818,7 @@ export class ToolApprovalHandler {
570
818
  if (context.allowedToolNames && !context.allowedToolNames.has(name)) {
571
819
  let memoryEnabled = true;
572
820
  try {
573
- memoryEnabled = getConfig().memory?.enabled !== false;
821
+ memoryEnabled = isMemoryEnabled(getConfig());
574
822
  } catch {
575
823
  // Config unavailable — leave the memory hint out rather than guess.
576
824
  }
@@ -616,10 +864,36 @@ export class ToolApprovalHandler {
616
864
  }
617
865
  }
618
866
 
619
- // All policy gates passed. Now consume the scoped grant if one is
620
- // required. Deferring consumption to this point ensures a downstream
621
- // rejection (allowedToolNames, task-run preflight, registry lookup)
622
- // does not waste the one-time-use grant.
867
+ // All deterministic policy gates passed. Parse model-generated input for
868
+ // built-in tools with a registered schema BEFORE the grant consumption
869
+ // and guardian escalation below: a malformed invocation can never
870
+ // execute, so failing it here means it cannot burn a one-time grant or
871
+ // interrupt the guardian with an approval card (and up to a 60s inline
872
+ // wait) for a call validation would reject anyway. Extension-owned and
873
+ // workspace-override tools own their input contracts and are skipped.
874
+ let parsedInput: Record<string, unknown> | undefined;
875
+ if (getToolOwner(name)?.kind === "default") {
876
+ const parsed = parseToolInput(name, input);
877
+ if (!parsed.ok) {
878
+ this.auditGateError(
879
+ context,
880
+ name,
881
+ input,
882
+ riskLevel,
883
+ startTime,
884
+ parsed.message,
885
+ );
886
+ return {
887
+ allowed: false,
888
+ result: { content: parsed.message, isError: true },
889
+ };
890
+ }
891
+ parsedInput = parsed.data;
892
+ }
893
+
894
+ // Now consume the scoped grant if one is required. Deferring consumption
895
+ // to this point ensures a prior gate rejection (allowedToolNames, input
896
+ // validation, registry lookup) does not waste the one-time-use grant.
623
897
  //
624
898
  // Retry polling is scoped to the voice channel where a race condition
625
899
  // exists between fire-and-forget turn execution and LLM fallback grant
@@ -644,7 +918,7 @@ export class ToolApprovalHandler {
644
918
  "Scoped grant consumed - allowing untrusted actor tool invocation",
645
919
  );
646
920
 
647
- return { allowed: true, tool, grantConsumed: true };
921
+ return { allowed: true, tool, grantConsumed: true, parsedInput };
648
922
  }
649
923
 
650
924
  // Treat abort as a cancellation - not a grant denial. This matches
@@ -738,7 +1012,7 @@ export class ToolApprovalHandler {
738
1012
  },
739
1013
  "Inline grant wait succeeded - allowing trusted contact tool invocation",
740
1014
  );
741
- return { allowed: true, tool, grantConsumed: true };
1015
+ return { allowed: true, tool, grantConsumed: true, parsedInput };
742
1016
  }
743
1017
 
744
1018
  if (waitResult.outcome === "aborted") {
@@ -825,6 +1099,6 @@ export class ToolApprovalHandler {
825
1099
  return { allowed: false, result: { content: reason, isError: true } };
826
1100
  }
827
1101
 
828
- return { allowed: true, tool };
1102
+ return { allowed: true, tool, parsedInput };
829
1103
  }
830
1104
  }
@@ -0,0 +1,85 @@
1
+ import type { z } from "zod";
2
+
3
+ import { askQuestionInputSchema } from "./ask-question/ask-question-tool.js";
4
+ import { fileEditInputSchema } from "./filesystem/edit.js";
5
+ import { fileListInputSchema } from "./filesystem/list.js";
6
+ import { fileReadInputSchema } from "./filesystem/read.js";
7
+ import { fileWriteInputSchema } from "./filesystem/write.js";
8
+ import { hostFileEditInputSchema } from "./host-filesystem/edit.js";
9
+ import { hostFileReadInputSchema } from "./host-filesystem/read.js";
10
+ import { hostFileWriteInputSchema } from "./host-filesystem/write.js";
11
+ import { hostShellInputSchema } from "./host-terminal/host-shell.js";
12
+ import { formatToolInputError } from "./shared/zod-tool-schema.js";
13
+ import { notifyParentInputSchema } from "./subagent/notify-parent.js";
14
+ import { requestSystemPermissionInputSchema } from "./system/request-permission.js";
15
+ import { shellInputSchema } from "./terminal/shell.js";
16
+
17
+ /**
18
+ * Per-tool Zod input schemas, keyed by tool name. Tool calls are a
19
+ * discriminated payload — the tool name determines the shape of `input` —
20
+ * but the model's JSON arrives untrusted, so the pre-execution gate
21
+ * (`ToolApprovalHandler.checkPreExecutionGates`) parses it against this
22
+ * registry (via {@link parseToolInput}) before any executor reads a field —
23
+ * and, crucially, before any one-time grant is consumed or guardian
24
+ * escalation starts, so a malformed call can never interrupt the guardian.
25
+ * Each schema is also the source the tool derives its advertised
26
+ * `input_schema` from (`toToolInputSchema` in `shared/zod-tool-schema.ts`),
27
+ * so the model-facing contract and the runtime validation cannot drift.
28
+ *
29
+ * Covers built-in (`default`-owned) tools only — skill / plugin / MCP /
30
+ * workspace tools own their schemas elsewhere, and the executor skips this
31
+ * registry for them (a workspace override of a built-in name must not be
32
+ * validated against the built-in's schema).
33
+ *
34
+ * Authoring rules, so validation never tightens behavior a tool already
35
+ * tolerates:
36
+ *
37
+ * - Top-level schemas are `z.looseObject` — unknown keys (including the
38
+ * injected `activity` field, see `schema-transforms.ts`) pass through.
39
+ * - A field the tool silently ignores when malformed gets
40
+ * `.optional().catch(undefined)` so a bad value degrades exactly as the
41
+ * tool always degraded, instead of failing the call.
42
+ * - Fields the advertised schema requires only to guide the model (e.g.
43
+ * `activity`, which is status-only and never read by the tool) stay
44
+ * optional-with-`.catch(undefined)` here; the derivation marks them
45
+ * required via `advertiseRequired`.
46
+ */
47
+ export const TOOL_INPUT_SCHEMAS: Readonly<Record<string, z.ZodType>> = {
48
+ ask_question: askQuestionInputSchema,
49
+ bash: shellInputSchema,
50
+ file_edit: fileEditInputSchema,
51
+ file_list: fileListInputSchema,
52
+ file_read: fileReadInputSchema,
53
+ file_write: fileWriteInputSchema,
54
+ host_bash: hostShellInputSchema,
55
+ host_file_edit: hostFileEditInputSchema,
56
+ host_file_read: hostFileReadInputSchema,
57
+ host_file_write: hostFileWriteInputSchema,
58
+ notify_parent: notifyParentInputSchema,
59
+ request_system_permission: requestSystemPermissionInputSchema,
60
+ };
61
+
62
+ /**
63
+ * Validate model-supplied tool input against the registered schema for
64
+ * `name`, returning the parsed value (with `.catch()` recoveries applied) or
65
+ * a descriptive, model-correctable error message. A tool with no registered
66
+ * schema passes through unchanged.
67
+ */
68
+ export function parseToolInput(
69
+ name: string,
70
+ input: Record<string, unknown>,
71
+ ):
72
+ | { ok: true; data: Record<string, unknown> }
73
+ | { ok: false; message: string } {
74
+ const schema = TOOL_INPUT_SCHEMAS[name];
75
+ if (!schema) {
76
+ return { ok: true, data: input };
77
+ }
78
+ const result = schema.safeParse(input);
79
+ if (!result.success) {
80
+ return { ok: false, message: formatToolInputError(name, result.error) };
81
+ }
82
+ // Every registry schema is an object schema, so the parsed value is a
83
+ // plain record; `z.ZodType`'s output is just too wide to say so statically.
84
+ return { ok: true, data: result.data as Record<string, unknown> };
85
+ }
@@ -240,6 +240,13 @@ export interface ToolContext {
240
240
  * equivalent instead of emitting a surface the channel silently drops.
241
241
  */
242
242
  supportsDynamicUi?: boolean;
243
+ /**
244
+ * Whether a parked `ask_question` on this turn's channel can be delivered as
245
+ * a guardian-request card with tappable answer options; `undefined`/`false`
246
+ * means no card delivery is possible. See the ToolContext field of the same
247
+ * name in `types.ts`.
248
+ */
249
+ supportsGuardianQuestionCards?: boolean;
243
250
  /** When true, tools with side effects should always prompt for confirmation. */
244
251
  forcePromptSideEffects?: boolean;
245
252
  /**
@@ -198,6 +198,14 @@ export interface ToolContext {
198
198
  * supported (desktop/web/app clients).
199
199
  */
200
200
  supportsDynamicUi?: boolean;
201
+ /**
202
+ * Whether a parked `ask_question` on this turn's channel can be delivered as
203
+ * a guardian-request card with tappable answer options (via the notification
204
+ * pipeline's channel adapters). `ask_question` parks when this is true even
205
+ * without dynamic UI; otherwise channel turns degrade to the plain-text
206
+ * fallback. `undefined`/`false` means no card delivery is possible.
207
+ */
208
+ supportsGuardianQuestionCards?: boolean;
201
209
  /**
202
210
  * When set, the tool execution is part of a task run. Used to retrieve ephemeral permission rules.
203
211
  * @legacy
@@ -13,19 +13,45 @@
13
13
  * by the type checker.
14
14
  */
15
15
 
16
+ import { z } from "zod";
17
+
16
18
  import { getEffectiveProfiles } from "../../config/default-profile-catalog.js";
17
19
  import { loadConfig } from "../../config/loader.js";
18
20
  import { callerOwnsWorkflowRun } from "../../workflows/capabilities.js";
19
21
  import type { WorkflowRun } from "../../workflows/journal-store.js";
20
22
  import { getWorkflowRunManager } from "../../workflows/run-manager.js";
23
+ import {
24
+ invalidToolInputResult,
25
+ nullAsOmitted,
26
+ } from "../shared/zod-tool-schema.js";
21
27
  import type { ToolContext, ToolExecutionResult } from "../types.js";
22
28
 
29
+ /**
30
+ * Model-input schema, `safeParse`d at the top of
31
+ * {@link executeManageWorkflows}. Same in-tool pattern and TOOLS.json drift
32
+ * guard as the other bundled-skill tools — see the schema block in
33
+ * `tools/document/document-tool.ts` for the framework.
34
+ *
35
+ * `action` is deliberately UNDECLARED (loose passthrough): the switch's
36
+ * default case owns the unknown-action error, and `executor.ts` reads
37
+ * `input.action` / `input.run_id` pre-execution for the requireFreshApproval
38
+ * promotion (those reads are already defensive and see the raw input either
39
+ * way).
40
+ */
41
+ export const manageWorkflowsInputSchema = z.looseObject({
42
+ run_id: nullAsOmitted(z.string()),
43
+ });
44
+
23
45
  export async function executeManageWorkflows(
24
46
  input: Record<string, unknown>,
25
47
  context: ToolContext,
26
48
  ): Promise<ToolExecutionResult> {
49
+ const parsedInput = manageWorkflowsInputSchema.safeParse(input);
50
+ if (!parsedInput.success) {
51
+ return invalidToolInputResult("manage_workflows", parsedInput.error);
52
+ }
27
53
  const action = input.action as string | undefined;
28
- const runId = input.run_id as string | undefined;
54
+ const runId = parsedInput.data.run_id;
29
55
  const manager = getWorkflowRunManager();
30
56
 
31
57
  // Authorization scope ({@link callerOwnsWorkflowRun}, shared with the
@@ -104,7 +130,9 @@ export async function executeManageWorkflows(
104
130
  // Only signal a run the caller owns. A non-owned (or absent) run is a
105
131
  // no-op with the same response shape, so existence is never revealed.
106
132
  const run = manager.status(runId);
107
- if (run && ownsRun(run)) manager.abort(runId);
133
+ if (run && ownsRun(run)) {
134
+ manager.abort(runId);
135
+ }
108
136
  return {
109
137
  content: JSON.stringify({
110
138
  runId,