@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
@@ -15,12 +15,14 @@ mock.module("../config/assistant-feature-flags.js", () => ({
15
15
  }));
16
16
 
17
17
  // `buildPolicyContext` (used by the integration tests below) precomputes the
18
- // proc-to-skills gate via `isProcToSkillsActive`. Drive it through this slot so
19
- // a test can put the production threading path in the active / inactive state.
20
- let mockProcToSkillsActive = true;
18
+ // proc-to-skills gate via `isV3TierActive`. Drive it through this slot so a
19
+ // test can put the production threading path in the active / inactive state.
20
+ let mockV3TierActive = true;
21
21
  mock.module("../config/memory-v3-gate.js", () => ({
22
- isProcToSkillsActive: () => mockProcToSkillsActive,
23
- isMemoryV3Live: () => mockProcToSkillsActive,
22
+ isMemoryEnabled: (config?: { memory?: { enabled?: boolean } }) =>
23
+ config?.memory?.enabled !== false,
24
+ isV3TierActive: () => mockV3TierActive,
25
+ isMemoryV3Live: () => mockV3TierActive,
24
26
  usesConceptPageMemory: (memory?: {
25
27
  enabled?: boolean;
26
28
  v2?: { enabled?: boolean };
@@ -30,10 +32,35 @@ mock.module("../config/memory-v3-gate.js", () => ({
30
32
  (memory?.v3?.live === true || memory?.v2?.enabled === true),
31
33
  }));
32
34
 
33
- // Mock skill resolution — return null by default (no skill found).
35
+ // Mock skill resolution — return null by default (no skill found). The
36
+ // `skill_load` predicate tests drive both slots to model a locally installed
37
+ // skill with or without inline command expansions.
38
+ type MockSkill = {
39
+ id: string;
40
+ directoryPath: string;
41
+ inlineCommandExpansions?: string[];
42
+ includes?: string[];
43
+ };
44
+ let mockSkillCatalog: MockSkill[] = [];
45
+ let mockResolvedSkill: MockSkill | null = null;
46
+ // Set to make the corresponding skills-module call throw, modelling an
47
+ // unreadable catalog or a selector resolution that hits the filesystem and
48
+ // fails.
49
+ let mockCatalogError: Error | null = null;
50
+ let mockSelectorError: Error | null = null;
34
51
  mock.module("../config/skills.js", () => ({
35
- loadSkillCatalog: () => [],
36
- resolveSkillSelector: () => ({ skill: null }),
52
+ loadSkillCatalog: () => {
53
+ if (mockCatalogError) {
54
+ throw mockCatalogError;
55
+ }
56
+ return mockSkillCatalog;
57
+ },
58
+ resolveSkillSelector: () => {
59
+ if (mockSelectorError) {
60
+ throw mockSelectorError;
61
+ }
62
+ return { skill: mockResolvedSkill };
63
+ },
37
64
  }));
38
65
 
39
66
  // Mock skills helpers used for file context building.
@@ -42,9 +69,9 @@ mock.module("../skills/path-classifier.js", () => ({
42
69
  getSkillRoots: () => ["/mock/skills/managed/", "/mock/skills/bundled/"],
43
70
  }));
44
71
 
45
- mock.module("../skills/include-graph.js", () => ({
46
- indexCatalogById: () => new Map(),
47
- }));
72
+ // `../skills/include-graph.js` is intentionally left unmocked: it is a pure,
73
+ // side-effect-free traversal, and the `skill_load` predicate tests below need
74
+ // the production include walk to run over `mockSkillCatalog`.
48
75
 
49
76
  mock.module("../skills/transitive-version-hash.js", () => ({
50
77
  computeTransitiveSkillVersionHash: () => "mock-transitive-hash",
@@ -115,10 +142,14 @@ mock.module("./trust-store.js", () => ({
115
142
  onRulesChanged: () => {},
116
143
  }));
117
144
 
118
- // Mock workspace policy.
145
+ // Mock workspace policy. Spread the real module so pure path helpers
146
+ // (resolveSandboxBase) keep their real behavior for param building.
147
+ const realWorkspacePolicy = await import("./workspace-policy.js");
119
148
  let mockIsPathWithinWorkspaceRoot = true;
120
149
  mock.module("./workspace-policy.js", () => ({
150
+ ...realWorkspacePolicy,
121
151
  isWorkspaceScopedInvocation: () => false,
152
+ isOutOfWorkspaceFileInvocation: () => false,
122
153
  isPathWithinWorkspaceRoot: () => mockIsPathWithinWorkspaceRoot,
123
154
  }));
124
155
 
@@ -143,9 +174,13 @@ mock.module("../tools/network/url-safety.js", () => ({
143
174
  import type { ClassificationResult } from "./ipc-risk-types.js";
144
175
 
145
176
  let mockIpcClassifyRiskResult: ClassificationResult | undefined;
177
+ let lastClassifyRiskParams: Record<string, unknown> | undefined;
146
178
 
147
179
  mock.module("../ipc/gateway-client.js", () => ({
148
- ipcClassifyRisk: async () => mockIpcClassifyRiskResult,
180
+ ipcClassifyRisk: async (params: Record<string, unknown>) => {
181
+ lastClassifyRiskParams = params;
182
+ return mockIpcClassifyRiskResult;
183
+ },
149
184
  ipcCall: async () => undefined,
150
185
  ipcCallPersistent: async () => undefined,
151
186
  resetPersistentClient: () => {},
@@ -155,6 +190,7 @@ mock.module("../ipc/gateway-client.js", () => ({
155
190
 
156
191
  import {
157
192
  mkdtempSync,
193
+ realpathSync,
158
194
  rmSync,
159
195
  symlinkSync,
160
196
  unlinkSync,
@@ -171,6 +207,7 @@ import {
171
207
  generateAllowlistOptions,
172
208
  generateScopeOptions,
173
209
  getCachedAssessment,
210
+ isInstalledStaticSkillLoad,
174
211
  } from "./checker.js";
175
212
  import { RiskLevel } from "./types.js";
176
213
 
@@ -180,10 +217,15 @@ describe("Permission Checker (gateway IPC)", () => {
180
217
  beforeEach(() => {
181
218
  mockIsContainerized = false;
182
219
  mockIpcClassifyRiskResult = undefined;
220
+ lastClassifyRiskParams = undefined;
183
221
  mockCachedThreshold = "low";
184
222
  mockRefreshedThreshold = null;
185
- mockProcToSkillsActive = true;
223
+ mockV3TierActive = true;
186
224
  thresholdCallLog.length = 0;
225
+ mockSkillCatalog = [];
226
+ mockResolvedSkill = null;
227
+ mockCatalogError = null;
228
+ mockSelectorError = null;
187
229
  });
188
230
 
189
231
  // ── classifyRisk ──────────────────────────────────────────────────────────
@@ -246,6 +288,70 @@ describe("Permission Checker (gateway IPC)", () => {
246
288
  );
247
289
  });
248
290
 
291
+ test("sends canonicalized boundary params for sandbox file tools", async () => {
292
+ mockIpcClassifyRiskResult = {
293
+ risk: "medium",
294
+ reason: "File write outside the workspace",
295
+ matchType: "registry",
296
+ scopeOptions: [],
297
+ };
298
+ const workingDir = mkdtempSync(join(tmpdir(), "checker-boundary-"));
299
+ try {
300
+ await classifyRisk(
301
+ "file_write",
302
+ { path: "/tmp/checker-boundary-outside.txt" },
303
+ workingDir,
304
+ );
305
+ expect(lastClassifyRiskParams?.isContainerized).toBe(false);
306
+ // The boundary is canonicalized so the gateway compares canonical
307
+ // against canonical (macOS tmpdir lives behind a /var symlink).
308
+ expect(lastClassifyRiskParams?.resolvedWorkingDir).toBe(
309
+ realpathSync(workingDir),
310
+ );
311
+ } finally {
312
+ rmSync(workingDir, { recursive: true, force: true });
313
+ }
314
+ });
315
+
316
+ test("classifies a dangling symlink by its destination", async () => {
317
+ mockIpcClassifyRiskResult = {
318
+ risk: "medium",
319
+ reason: "File write outside the workspace",
320
+ matchType: "registry",
321
+ scopeOptions: [],
322
+ };
323
+ const workingDir = realpathSync(
324
+ mkdtempSync(join(tmpdir(), "checker-dangling-")),
325
+ );
326
+ const outside = realpathSync(
327
+ mkdtempSync(join(tmpdir(), "checker-dangling-out-")),
328
+ );
329
+ try {
330
+ const destination = join(outside, "not-yet.txt");
331
+ symlinkSync(destination, join(workingDir, "dangle"));
332
+ await classifyRisk("file_write", { path: "dangle" }, workingDir);
333
+ // The destination does not exist, but a write through the link
334
+ // creates it — classification must see the destination.
335
+ expect(lastClassifyRiskParams?.resolvedPath).toBe(destination);
336
+ } finally {
337
+ rmSync(workingDir, { recursive: true, force: true });
338
+ rmSync(outside, { recursive: true, force: true });
339
+ }
340
+ });
341
+
342
+ test("omits the canonicalized boundary for host file tools", async () => {
343
+ mockIpcClassifyRiskResult = {
344
+ risk: "medium",
345
+ reason: "Host file write (default)",
346
+ matchType: "registry",
347
+ scopeOptions: [],
348
+ };
349
+ await classifyRisk("host_file_write", {
350
+ path: "/tmp/checker-boundary-host.txt",
351
+ });
352
+ expect(lastClassifyRiskParams?.resolvedWorkingDir).toBeUndefined();
353
+ });
354
+
249
355
  test("caches results for identical inputs", async () => {
250
356
  mockIpcClassifyRiskResult = {
251
357
  risk: "low",
@@ -1085,7 +1191,7 @@ describe("Permission Checker (gateway IPC)", () => {
1085
1191
  // Same retrospective ToolContext, but the feature is inactive (flag off
1086
1192
  // or v3 not live). buildPolicyContext stamps `procToSkillsActive: false`,
1087
1193
  // so the grant is dead and the high-risk scaffold prompts.
1088
- mockProcToSkillsActive = false;
1194
+ mockV3TierActive = false;
1089
1195
  mockIpcClassifyRiskResult = {
1090
1196
  risk: "high",
1091
1197
  reason: "Skill scaffold",
@@ -1262,4 +1368,181 @@ describe("Permission Checker (gateway IPC)", () => {
1262
1368
  expect(options).toEqual([]);
1263
1369
  });
1264
1370
  });
1371
+
1372
+ // ── isInstalledStaticSkillLoad ────────────────────────────────────────────
1373
+
1374
+ describe("isInstalledStaticSkillLoad", () => {
1375
+ function installSkill(inlineCommandExpansions?: string[]): void {
1376
+ const skill: MockSkill = {
1377
+ id: "note-taker",
1378
+ directoryPath: "/mock/skills/bundled/note-taker",
1379
+ inlineCommandExpansions,
1380
+ };
1381
+ mockResolvedSkill = skill;
1382
+ mockSkillCatalog = [skill];
1383
+ }
1384
+
1385
+ /**
1386
+ * Install a `note-taker` parent whose selector resolves, plus whichever
1387
+ * children are given. Children the parent includes but that are absent
1388
+ * from `children` model an include that is not installed locally.
1389
+ */
1390
+ function installGraph(
1391
+ parentIncludes: string[],
1392
+ children: MockSkill[],
1393
+ parentInlineCommandExpansions?: string[],
1394
+ ): void {
1395
+ const parent: MockSkill = {
1396
+ id: "note-taker",
1397
+ directoryPath: "/mock/skills/bundled/note-taker",
1398
+ inlineCommandExpansions: parentInlineCommandExpansions,
1399
+ includes: parentIncludes,
1400
+ };
1401
+ mockResolvedSkill = parent;
1402
+ mockSkillCatalog = [parent, ...children];
1403
+ }
1404
+
1405
+ function child(id: string, overrides: Partial<MockSkill> = {}): MockSkill {
1406
+ return {
1407
+ id,
1408
+ directoryPath: `/mock/skills/bundled/${id}`,
1409
+ ...overrides,
1410
+ };
1411
+ }
1412
+
1413
+ test("returns false for a tool other than skill_load", () => {
1414
+ installSkill();
1415
+ expect(isInstalledStaticSkillLoad("bash", { skill: "note-taker" })).toBe(
1416
+ false,
1417
+ );
1418
+ });
1419
+
1420
+ test("returns false when the selector is missing", () => {
1421
+ installSkill();
1422
+ expect(isInstalledStaticSkillLoad("skill_load", {})).toBe(false);
1423
+ });
1424
+
1425
+ test("returns false when the selector is blank", () => {
1426
+ installSkill();
1427
+ expect(isInstalledStaticSkillLoad("skill_load", { skill: " " })).toBe(
1428
+ false,
1429
+ );
1430
+ });
1431
+
1432
+ test("returns false when the skill is not installed locally", () => {
1433
+ mockResolvedSkill = null;
1434
+ mockSkillCatalog = [];
1435
+ expect(
1436
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1437
+ ).toBe(false);
1438
+ });
1439
+
1440
+ test("returns false when the resolved skill has inline expansions", () => {
1441
+ installSkill(["git status"]);
1442
+ expect(
1443
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1444
+ ).toBe(false);
1445
+ });
1446
+
1447
+ test("returns true for an installed skill with no inline expansions", () => {
1448
+ installSkill();
1449
+ expect(
1450
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1451
+ ).toBe(true);
1452
+ });
1453
+
1454
+ // ── Transitive include graph ────────────────────────────────────────────
1455
+ // Loading a parent auto-installs its missing includes and renders inline
1456
+ // commands in included children, so the predicate must clear the whole
1457
+ // graph, not just the target.
1458
+
1459
+ test("returns false when an included skill is missing locally", () => {
1460
+ installGraph(["formatting"], []);
1461
+ expect(
1462
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1463
+ ).toBe(false);
1464
+ });
1465
+
1466
+ test("returns false when an included skill has inline expansions", () => {
1467
+ installGraph(
1468
+ ["formatting"],
1469
+ [child("formatting", { inlineCommandExpansions: ["git status"] })],
1470
+ );
1471
+ expect(
1472
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1473
+ ).toBe(false);
1474
+ });
1475
+
1476
+ test("returns false when a grandchild include is missing locally", () => {
1477
+ installGraph(
1478
+ ["formatting"],
1479
+ [child("formatting", { includes: ["typography"] })],
1480
+ );
1481
+ expect(
1482
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1483
+ ).toBe(false);
1484
+ });
1485
+
1486
+ test("returns false when a grandchild include has inline expansions", () => {
1487
+ installGraph(
1488
+ ["formatting"],
1489
+ [
1490
+ child("formatting", { includes: ["typography"] }),
1491
+ child("typography", { inlineCommandExpansions: ["date"] }),
1492
+ ],
1493
+ );
1494
+ expect(
1495
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1496
+ ).toBe(false);
1497
+ });
1498
+
1499
+ test("returns false for a cyclic include graph", () => {
1500
+ installGraph(
1501
+ ["formatting"],
1502
+ [child("formatting", { includes: ["note-taker"] })],
1503
+ );
1504
+ expect(
1505
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1506
+ ).toBe(false);
1507
+ });
1508
+
1509
+ test("returns true when every transitive include is installed and static", () => {
1510
+ installGraph(
1511
+ ["formatting"],
1512
+ [
1513
+ child("formatting", { includes: ["typography"] }),
1514
+ child("typography"),
1515
+ ],
1516
+ );
1517
+ expect(
1518
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1519
+ ).toBe(true);
1520
+ });
1521
+
1522
+ // ── Fail-closed ─────────────────────────────────────────────────────────
1523
+ // The live-voice contention gate calls this from a synchronous event
1524
+ // callback, so a throw would abort the rest of the frame's dispatch.
1525
+
1526
+ test("returns false when the catalog cannot be read", () => {
1527
+ installSkill();
1528
+ mockCatalogError = new Error("catalog unreadable");
1529
+ expect(() =>
1530
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1531
+ ).not.toThrow();
1532
+ expect(
1533
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1534
+ ).toBe(false);
1535
+ });
1536
+
1537
+ test("returns false when selector resolution throws", () => {
1538
+ installSkill();
1539
+ mockSelectorError = new Error("skill directory unreadable");
1540
+ expect(() =>
1541
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1542
+ ).not.toThrow();
1543
+ expect(
1544
+ isInstalledStaticSkillLoad("skill_load", { skill: "note-taker" }),
1545
+ ).toBe(false);
1546
+ });
1547
+ });
1265
1548
  });
@@ -4,13 +4,17 @@ import { dirname, join, resolve } from "node:path";
4
4
 
5
5
  import { getIsContainerized } from "../config/env-registry.js";
6
6
  import { getConfig } from "../config/loader.js";
7
- import { loadSkillCatalog, resolveSkillSelector } from "../config/skills.js";
7
+ import {
8
+ loadSkillCatalog,
9
+ resolveSkillSelector,
10
+ type SkillSummary,
11
+ } from "../config/skills.js";
8
12
  import { ipcClassifyRisk } from "../ipc/gateway-client.js";
9
13
  import {
10
14
  MEMORY_RETROSPECTIVE_ORIGIN,
11
15
  SKILL_MANAGEMENT_SKILL_ID,
12
16
  } from "../plugins/defaults/memory/memory-retrospective-constants.js";
13
- import { indexCatalogById } from "../skills/include-graph.js";
17
+ import { indexCatalogById, validateIncludes } from "../skills/include-graph.js";
14
18
  import { getSkillRoots } from "../skills/path-classifier.js";
15
19
  import { computeTransitiveSkillVersionHash } from "../skills/transitive-version-hash.js";
16
20
  import { computeSkillVersionHash } from "../skills/version-hash.js";
@@ -53,6 +57,7 @@ import {
53
57
  import {
54
58
  isPathWithinWorkspaceRoot,
55
59
  isWorkspaceScopedInvocation,
60
+ resolveSandboxBase,
56
61
  } from "./workspace-policy.js";
57
62
 
58
63
  // ── Risk classification cache ────────────────────────────────────────────────
@@ -155,7 +160,7 @@ function fileToolFsStateKey(
155
160
  return undefined;
156
161
  }
157
162
  const resolved = resolveFileToolPaths(toolName, input, workingDir);
158
- return `${resolved.resolvedPath ?? ""}\0${resolved.resolvedTransferDestPath ?? ""}`;
163
+ return `${resolved.resolvedPath ?? ""}\0${resolved.resolvedTransferDestPath ?? ""}\0${resolved.resolvedWorkingDir ?? ""}`;
159
164
  }
160
165
 
161
166
  /** Clear the risk classification cache. Called when trust rules change. Exported for test setup. */
@@ -210,7 +215,7 @@ function resolveSkillIdAndHash(
210
215
  * registry (`getToolOwner(name)`) rather than read from the `Tool` object,
211
216
  * since ownership lives on the registry, not on the tool itself.
212
217
  */
213
- function isToolOwnerSkillBundled(tool: Tool | undefined): boolean {
218
+ export function isToolOwnerSkillBundled(tool: Tool | undefined): boolean {
214
219
  if (!tool) {
215
220
  return false;
216
221
  }
@@ -223,18 +228,44 @@ function isToolOwnerSkillBundled(tool: Tool | undefined): boolean {
223
228
  }
224
229
 
225
230
  /**
226
- * Check whether a skill (by id) has parsed inline command expansions.
227
- * Returns false when the skill is not found in the catalog.
231
+ * Whether a catalog entry carries parsed inline command expansions, which
232
+ * execute shell commands at load time. Returns false for an absent entry.
228
233
  */
229
- function hasInlineExpansions(skillId: string): boolean {
230
- const catalog = loadSkillCatalog();
231
- const skill = catalog.find((s) => s.id === skillId);
234
+ function summaryHasInlineExpansions(skill: SkillSummary | undefined): boolean {
232
235
  return (
233
236
  skill?.inlineCommandExpansions != null &&
234
237
  skill.inlineCommandExpansions.length > 0
235
238
  );
236
239
  }
237
240
 
241
+ /**
242
+ * Check whether a skill (by id) has parsed inline command expansions.
243
+ * Returns false when the skill is not found in the catalog.
244
+ */
245
+ function hasInlineExpansions(skillId: string): boolean {
246
+ const catalog = loadSkillCatalog();
247
+ return summaryHasInlineExpansions(catalog.find((s) => s.id === skillId));
248
+ }
249
+
250
+ /**
251
+ * The id of the skill a `skill_load` invocation targets, or `null` for any
252
+ * other tool, a blank selector, or a selector that names no skill in the
253
+ * local catalog.
254
+ */
255
+ function resolveSkillLoadTargetId(
256
+ toolName: string,
257
+ input: Record<string, unknown>,
258
+ ): string | null {
259
+ if (toolName !== "skill_load") {
260
+ return null;
261
+ }
262
+ const selector = getStringField(input, "skill").trim();
263
+ if (!selector) {
264
+ return null;
265
+ }
266
+ return resolveSkillIdAndHash(selector)?.id ?? null;
267
+ }
268
+
238
269
  /**
239
270
  * Whether this invocation is an inline-command ("dynamic") skill load: a
240
271
  * `skill_load` whose resolved skill carries inline command expansions,
@@ -249,15 +280,56 @@ export function isDynamicSkillLoadInvocation(
249
280
  toolName: string,
250
281
  input: Record<string, unknown>,
251
282
  ): boolean {
252
- if (toolName !== "skill_load") {
253
- return false;
254
- }
255
- const selector = getStringField(input, "skill").trim();
256
- if (!selector) {
283
+ const skillId = resolveSkillLoadTargetId(toolName, input);
284
+ return skillId !== null && hasInlineExpansions(skillId);
285
+ }
286
+
287
+ /**
288
+ * Whether a `skill_load` invocation is a pure read: the target skill and every
289
+ * skill reachable through its `includes` graph are installed locally and carry
290
+ * no inline command expansions.
291
+ *
292
+ * The whole graph matters because the load executor (tools/skills/load.ts)
293
+ * auto-installs missing includes from the remote catalog
294
+ * (`autoInstallFromCatalog`) and renders inline command expansions for both the
295
+ * target and its included children. So a missing include anywhere in the graph
296
+ * writes to the workspace, an inline expansion anywhere in it executes shell,
297
+ * and either makes the load something other than a read.
298
+ *
299
+ * Fails closed and never throws — an unresolvable selector, a target absent
300
+ * from the catalog, a missing include, a cycle, or an unreadable catalog all
301
+ * return false. Selector resolution and catalog reads both touch the
302
+ * filesystem, so both sit inside the guard: callers include a synchronous
303
+ * live-voice event callback where a throw would abort the rest of the frame's
304
+ * dispatch. Exported for gates that must not proceed on anything capable of
305
+ * writing local state.
306
+ */
307
+ export function isInstalledStaticSkillLoad(
308
+ toolName: string,
309
+ input: Record<string, unknown>,
310
+ ): boolean {
311
+ try {
312
+ const skillId = resolveSkillLoadTargetId(toolName, input);
313
+ if (skillId === null) {
314
+ return false;
315
+ }
316
+ const catalogIndex = indexCatalogById(loadSkillCatalog());
317
+ if (!catalogIndex.has(skillId)) {
318
+ return false;
319
+ }
320
+ // `validateIncludes` is the shared include-graph walk: it reports the first
321
+ // missing child or cycle, and on success yields every transitively included
322
+ // id in DFS order.
323
+ const validation = validateIncludes(skillId, catalogIndex);
324
+ if (!validation.ok) {
325
+ return false;
326
+ }
327
+ return validation.visited.every(
328
+ (id) => !summaryHasInlineExpansions(catalogIndex.get(id)),
329
+ );
330
+ } catch {
257
331
  return false;
258
332
  }
259
- const resolved = resolveSkillIdAndHash(selector);
260
- return resolved !== null && hasInlineExpansions(resolved.id);
261
333
  }
262
334
 
263
335
  /**
@@ -389,25 +461,6 @@ function buildFileContext(): FileContext {
389
461
  * filesystem this process cannot see (e.g. host_file paths proxied to a remote
390
462
  * client), so this never regresses below today's lexical behavior.
391
463
  */
392
- // The Docker sandbox mounts the workspace at /workspace, and the model emits
393
- // container-scoped paths (e.g. "/workspace/tools/evil.ts") even on local turns.
394
- // Mirror the gateway's resolveSandboxPath remap so the symlink-resolved path we
395
- // forward lines up with the gateway's lexical fallback and the protected dirs.
396
- const CONTAINER_WORKSPACE_PREFIX = "/workspace/";
397
- const CONTAINER_WORKSPACE_EXACT = "/workspace";
398
-
399
- function resolveSandboxBase(rawPath: string, workingDir: string): string {
400
- let effectivePath = rawPath;
401
- if (!rawPath.startsWith(workingDir + "/") && rawPath !== workingDir) {
402
- if (rawPath.startsWith(CONTAINER_WORKSPACE_PREFIX)) {
403
- effectivePath = rawPath.slice(CONTAINER_WORKSPACE_PREFIX.length);
404
- } else if (rawPath === CONTAINER_WORKSPACE_EXACT) {
405
- effectivePath = ".";
406
- }
407
- }
408
- return resolve(workingDir, effectivePath);
409
- }
410
-
411
464
  function resolveClassificationPath(
412
465
  filePath: string,
413
466
  workingDir: string,
@@ -441,6 +494,13 @@ interface FileToolResolution {
441
494
  effectiveWorkingDir: string;
442
495
  isHostTool: boolean;
443
496
  resolvedPath?: string;
497
+ /**
498
+ * Symlink-canonicalized working dir for sandbox file tools, paired with
499
+ * `resolvedPath` so the gateway's workspace-boundary check compares
500
+ * canonical against canonical (a symlinked workspace prefix, e.g. macOS
501
+ * /var → /private/var, must not read as an escape). Unset for host tools.
502
+ */
503
+ resolvedWorkingDir?: string;
444
504
  transferSandboxDestPath?: string;
445
505
  transferSandboxWorkingDir?: string;
446
506
  resolvedTransferDestPath?: string;
@@ -490,6 +550,9 @@ function resolveFileToolPaths(
490
550
  effectiveWorkingDir,
491
551
  isHostTool,
492
552
  ),
553
+ resolvedWorkingDir: isHostTool
554
+ ? undefined
555
+ : resolveRealPath(effectiveWorkingDir),
493
556
  transferSandboxDestPath,
494
557
  transferSandboxWorkingDir,
495
558
  // The to_sandbox destination is a workspace write — symlink-resolve it too
@@ -573,7 +636,9 @@ function buildClassifyRiskParams(
573
636
  tool: toolName,
574
637
  path: resolved.filePath,
575
638
  resolvedPath: resolved.resolvedPath,
639
+ resolvedWorkingDir: resolved.resolvedWorkingDir,
576
640
  workingDir: resolved.effectiveWorkingDir,
641
+ isContainerized: getIsContainerized(),
577
642
  fileContext: buildFileContext(),
578
643
  transferSandboxDestPath: resolved.transferSandboxDestPath,
579
644
  transferSandboxWorkingDir: resolved.transferSandboxWorkingDir,
@@ -797,7 +862,8 @@ export async function classifyRisk(
797
862
  // prompt. The grant resolves these tools to ALLOW non-interactively, and ONLY
798
863
  // when all of these hold:
799
864
  // - procedural-memory-as-skills is active (`policyContext.procToSkillsActive`,
800
- // precomputed by buildPolicyContext: memory-v3 is live),
865
+ // precomputed by buildPolicyContext: the v3 tier is active — memory is on
866
+ // and memory-v3 is live),
801
867
  // - the turn is the retrospective background source — guardian trust, `vellum`
802
868
  // source channel, `memory_retrospective` origin (set in
803
869
  // memory-retrospective-job.ts).
@@ -50,7 +50,7 @@ mock.module("../runtime/confirmation-request-guardian-bridge.js", () => ({
50
50
  },
51
51
  }));
52
52
 
53
- import type { ServerMessage } from "../daemon/message-protocol.js";
53
+ import type { AssistantEvent } from "../api/index.js";
54
54
  import { createGuardianRequestForConfirmation } from "./confirmation-guardian-request.js";
55
55
 
56
56
  const MSG = {
@@ -59,7 +59,7 @@ const MSG = {
59
59
  toolName: "Bash",
60
60
  input: { command: "ls" },
61
61
  riskLevel: "medium",
62
- } as unknown as ServerMessage & { type: "confirmation_request" };
62
+ } as unknown as AssistantEvent & { type: "confirmation_request" };
63
63
 
64
64
  describe("createGuardianRequestForConfirmation", () => {
65
65
  beforeEach(() => {
@@ -17,7 +17,7 @@
17
17
  * therefore the emitters — stays cheap and free of import-time side effects.
18
18
  */
19
19
 
20
- import type { ServerMessage } from "../daemon/message-protocol.js";
20
+ import type { ConfirmationRequestEvent } from "../api/index.js";
21
21
  import { IntegrityError } from "../util/errors.js";
22
22
  import { getLogger } from "../util/logger.js";
23
23
 
@@ -30,7 +30,7 @@ const log = getLogger("confirmation-guardian-request");
30
30
  * never thrown.
31
31
  */
32
32
  export async function createGuardianRequestForConfirmation(
33
- msg: ServerMessage & { type: "confirmation_request" },
33
+ msg: ConfirmationRequestEvent,
34
34
  conversationId: string,
35
35
  opts?: {
36
36
  /**