@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
@@ -9,7 +9,11 @@
9
9
  * PREVIOUS message as separate queries at a smaller budget
10
10
  * (`replyQueryK` per lane), surfacing the threads the assistant is
11
11
  * actively developing that the user's message references without
12
- * naming — and
12
+ * naming —
13
+ * - the span-query pass — the dense lane re-run over the current
14
+ * message's clause chunks as separate queries at a small per-chunk
15
+ * budget (`spanQueryK`), rescuing motifs a long multi-topic message's
16
+ * single query vector averages away — and
13
17
  * - link-graph edge expansion (`edgeExpand`) over the top
14
18
  * user-message needle+dense article seeds, and
15
19
  * - learned-edge expansion (`edgeExpand` over the co-selection NPMI
@@ -61,6 +65,7 @@ import {
61
65
  } from "../../../../daemon/turn-latency-sub-spans.js";
62
66
  import { recordWatchdogEvent } from "../../../../telemetry/watchdog-events-store.js";
63
67
  import { getLogger } from "../logging.js";
68
+ import type { DenseHitScored } from "./dense.js";
64
69
  import { denseLaneScored } from "./dense.js";
65
70
  import type { EdgeGraph } from "./edge.js";
66
71
  import { edgeExpand } from "./edge.js";
@@ -74,6 +79,7 @@ import type {
74
79
  } from "./pool-select.js";
75
80
  import { selectAllPoolCandidates, selectPool } from "./pool-select.js";
76
81
  import type { SectionNeedle } from "./section-needle.js";
82
+ import { spanChunksOf } from "./span-query.js";
77
83
  import type {
78
84
  FinderLane,
79
85
  MemoryRoutingTurn,
@@ -195,6 +201,12 @@ export interface OrchestrateDeps {
195
201
  * over `turn.previousAssistantMessage` as separate queries). `0` or
196
202
  * omitted disables the pass (canonical value: `memory.v3.replyQueryK`). */
197
203
  replyQueryK?: number;
204
+ /** Per-chunk article budget for the span-query pass (dense re-run over the
205
+ * current message's clause chunks as separate queries). `0` or omitted
206
+ * disables the pass; it is also inert when the dense lane is disabled or
207
+ * the message yields fewer than two chunks (canonical value:
208
+ * `memory.v3.spanQueryK`). */
209
+ spanQueryK?: number;
198
210
  /** Number of top needle+dense seeds expanded. When omitted, the edge lane's
199
211
  * own default applies (canonical value: `memory.v3.edge.seedCount`). */
200
212
  edgeSeeds?: number;
@@ -220,9 +232,9 @@ export interface OrchestrateDeps {
220
232
  /** Whether to run the selector LLM. False passes all pooled candidates
221
233
  * straight through as selections, preserving pool-order slug dedup. */
222
234
  selectorEnabled?: boolean;
223
- /** Per-turn injection gate config (`memory.v3.gate` tuning + the flag-derived
224
- * `enabled`, assembled in observeTurn). Omitted/disabled → the gate never
225
- * runs and every turn proceeds to selectPool as before. */
235
+ /** Per-turn injection gate config (the `memory.v3.gate` tuning, threaded
236
+ * through by observeTurn). Omitted/disabled → the gate never runs and every
237
+ * turn proceeds to selectPool as before. */
226
238
  gateConfig?: V3GateConfig;
227
239
  /** Real concept-page count at lane build — the same corpus-size signal
228
240
  * `resolveV3Tuning` switches the lean/full profile on. Reported with each
@@ -359,15 +371,23 @@ export async function orchestrate(
359
371
  // a vector that matches neither) at its own, smaller budget; it runs in the
360
372
  // same parallel batch.
361
373
  // `denseK = 0` disables dense retrieval for the whole turn, including the
362
- // reply-query dense pass.
374
+ // reply-query and span-query dense passes.
363
375
  const replyK = deps.replyQueryK ?? 0;
364
376
  const replyQuery =
365
377
  replyK > 0 ? (turn.previousAssistantMessage ?? "").trim() : "";
366
378
  const denseEnabled = denseK > 0;
367
- const [needled, densed, replyNeedled, replyDensed] = await timeLatencySubSpan(
368
- "v3_lanes",
369
- "Memory search",
370
- () =>
379
+ // The span-query pass re-runs the dense lane over the current message's
380
+ // clause chunks as SEPARATE queries (a single embedding of a multi-topic
381
+ // message averages its intents into a vector that matches none of them —
382
+ // the within-message form of the averaging the reply pass avoids across
383
+ // speakers). A single-chunk message would just duplicate the full-message
384
+ // dense query, so the pass needs at least two chunks to run.
385
+ const spanK = deps.spanQueryK ?? 0;
386
+ const spanChunks =
387
+ spanK > 0 && denseEnabled ? spanChunksOf(turn.currentMessage) : [];
388
+ const spanQueries = spanChunks.length >= 2 ? spanChunks : [];
389
+ const [needled, densed, replyNeedled, replyDensed, spanDensed] =
390
+ await timeLatencySubSpan("v3_lanes", "Memory search", () =>
371
391
  Promise.all([
372
392
  Promise.resolve(deps.needle.queryScored(turn.currentMessage, needleK)),
373
393
  denseEnabled
@@ -381,8 +401,13 @@ export async function orchestrate(
381
401
  replyQuery.length > 0 && denseEnabled
382
402
  ? denseLaneScored(deps.denseConfig, replyQuery, replyK)
383
403
  : Promise.resolve([]),
404
+ Promise.all(
405
+ spanQueries.map((chunk) =>
406
+ denseLaneScored(deps.denseConfig, chunk, spanK),
407
+ ),
408
+ ),
384
409
  ]),
385
- );
410
+ );
386
411
  // Everything from here to the step-3 selection — finder assembly, the
387
412
  // entity lane, the injection gate, edge + learned-edge expansion, pool
388
413
  // assembly — is synchronous in-memory work, measured as one `v3_expand`
@@ -437,18 +462,29 @@ export async function orchestrate(
437
462
  // Step 1b: dense hits — `section` is the matched ORDINAL; resolve it to the
438
463
  // concrete `Section` via the section index. Falls back to undefined (blank
439
464
  // descriptor) if the ordinal is not in the in-memory index.
465
+ //
466
+ // `denseOwnedSection` tracks the articles whose recorded matched section
467
+ // came from THIS loop (needle records first and wins ties), along with the
468
+ // hit's cosine score — the span pass upgrades those sections when a clause
469
+ // query finds a strictly stronger match under the same metric.
470
+ const denseOwnedSection = new Map<Slug, number>();
440
471
  for (const hit of densed) {
441
472
  // A deleted page's points can linger in Qdrant; keep only live-index
442
473
  // articles. The section index is rebuilt from `getPageIndex` at `initLanes`,
443
474
  // so `byArticle` holds exactly the live pages (synthetic capability slugs
444
475
  // included) — only truly-deleted pages are dropped here.
445
- if (!deps.sectionIndex.byArticle.has(hit.article)) continue;
446
- addFinder(
476
+ if (!deps.sectionIndex.byArticle.has(hit.article)) {
477
+ continue;
478
+ }
479
+ const section = sectionByOrdinal(
480
+ deps.sectionIndex,
447
481
  hit.article,
448
- sectionByOrdinal(deps.sectionIndex, hit.article, hit.section),
449
- undefined,
450
- "dense",
482
+ hit.section,
451
483
  );
484
+ if (section && !matchedSections.has(hit.article)) {
485
+ denseOwnedSection.set(hit.article, hit.score);
486
+ }
487
+ addFinder(hit.article, section, undefined, "dense");
452
488
  }
453
489
 
454
490
  // Step 1b': reply-query hits — candidates the user-message lanes already
@@ -469,7 +505,53 @@ export async function orchestrate(
469
505
  );
470
506
  }
471
507
 
472
- // Step 1b'': entity lanesections whose `## ` heading NAMES a distinctive
508
+ // Step 1b'': span-query hitsunion-additive at the pass's own small
509
+ // budget. Candidates the primary or reply lanes already surfaced keep their
510
+ // attribution (`addFinder`'s first-lane-wins dedupe); only genuinely
511
+ // span-surfaced articles tag `"span"`. Like the reply pass, span hits are
512
+ // excluded from the injection gate (which scores current-message needle +
513
+ // dense only) and from the edge-expansion seeds.
514
+ //
515
+ // An article can be surfaced by SEVERAL chunks; dedupe by best cosine score
516
+ // before `addFinder`, since chunk order would otherwise decide which section
517
+ // gets recorded — letting an earlier chunk's weak match mask the strong
518
+ // buried-clause match the pass exists to recover.
519
+ const bestSpanHits = new Map<Slug, DenseHitScored>();
520
+ for (const hit of spanDensed.flat()) {
521
+ const prev = bestSpanHits.get(hit.article);
522
+ if (!prev || hit.score > prev.score) {
523
+ bestSpanHits.set(hit.article, hit);
524
+ }
525
+ }
526
+ // For an article a primary lane already surfaced, upgrade its matched
527
+ // section/descriptor ONLY when the existing section was recorded by the
528
+ // full-message dense hit and the span's cosine is strictly higher — same
529
+ // encoder, same collection, so the comparison is evidence, not judgment.
530
+ // Needle- and reply-recorded sections stay (BM25 and cosine scores are not
531
+ // comparable, and the reply pass's own convention is first-wins); lane
532
+ // attribution never changes here.
533
+ for (const hit of bestSpanHits.values()) {
534
+ if (!deps.sectionIndex.byArticle.has(hit.article)) {
535
+ continue;
536
+ }
537
+ const section = sectionByOrdinal(
538
+ deps.sectionIndex,
539
+ hit.article,
540
+ hit.section,
541
+ );
542
+ const denseScore = denseOwnedSection.get(hit.article);
543
+ if (section && denseScore !== undefined && hit.score > denseScore) {
544
+ matchedSections.set(hit.article, section);
545
+ const existing = finder.find((c) => c.slug === hit.article);
546
+ if (existing) {
547
+ existing.descriptor = section.text;
548
+ }
549
+ continue;
550
+ }
551
+ addFinder(hit.article, section, undefined, "span");
552
+ }
553
+
554
+ // Step 1b''': entity lane — sections whose `## ` heading NAMES a distinctive
473
555
  // entity the message mentions. Additive BM25 buries a single named entity
474
556
  // under a long, multi-topic message's bulk theme; this keys on the heading
475
557
  // vocabulary so the page the user named surfaces regardless of the bulk
@@ -501,8 +583,8 @@ export async function orchestrate(
501
583
  }
502
584
  }
503
585
 
504
- // Step 1b''': opt-in injection gate. With the CURRENT-message finder lanes in
505
- // hand (needle + dense — NOT reply/entity/edge, which only add recall), decide
586
+ // Step 1b'''': opt-in injection gate. With the CURRENT-message finder lanes in
587
+ // hand (needle + dense — NOT reply/span/entity/edge, which only add recall), decide
506
588
  // whether retrieval is confident enough to spend the selectPool LLM call this
507
589
  // turn. Default-off via `?.enabled`; pass-open on any throw (a gate bug must
508
590
  // never drop a turn's memory). A closed gate either hard-skips selection
@@ -1,8 +1,8 @@
1
1
  import { getWorkspaceDir } from "../paths.js";
2
+ import { injectedConceptHeader } from "../substrate/injected-block-slugs.js";
3
+ import { readPage, renderPageContent } from "../substrate/page-store.js";
2
4
  import { renderCapabilityContent } from "./capabilities.js";
3
5
  import { renderCard } from "./card.js";
4
- import { injectedConceptHeader } from "./substrate/injected-block-slugs.js";
5
- import { readPage, renderPageContent } from "./substrate/page-store.js";
6
6
  import type { Section, Slug } from "./types.js";
7
7
 
8
8
  /**
@@ -35,12 +35,18 @@ function withConceptHeader(slug: Slug, body: string): string {
35
35
  */
36
36
  export async function renderV3PageContent(slug: Slug): Promise<string> {
37
37
  const capability = renderCapabilityContent(slug);
38
- if (capability !== null) return capability;
38
+ if (capability !== null) {
39
+ return capability;
40
+ }
39
41
  try {
40
42
  const page = await readPage(getWorkspaceDir(), slug);
41
- if (!page) return "";
43
+ if (!page) {
44
+ return "";
45
+ }
42
46
  const content = renderPageContent(page).trim();
43
- if (content.length === 0) return "";
47
+ if (content.length === 0) {
48
+ return "";
49
+ }
44
50
  return withConceptHeader(slug, content);
45
51
  } catch {
46
52
  return "";
@@ -62,10 +68,14 @@ export async function renderV3PageContent(slug: Slug): Promise<string> {
62
68
  */
63
69
  export async function renderV3CardContent(slug: Slug): Promise<string> {
64
70
  const capability = renderCapabilityContent(slug);
65
- if (capability !== null) return capability;
71
+ if (capability !== null) {
72
+ return capability;
73
+ }
66
74
  try {
67
75
  const page = await readPage(getWorkspaceDir(), slug);
68
- if (!page) return "";
76
+ if (!page) {
77
+ return "";
78
+ }
69
79
  return renderCard(slug, renderPageContent(page));
70
80
  } catch {
71
81
  return "";
@@ -93,10 +103,16 @@ export async function renderV3SectionContent(
93
103
  section: Section | undefined,
94
104
  ): Promise<string> {
95
105
  const capability = renderCapabilityContent(slug);
96
- if (capability !== null) return capability;
97
- if (!section) return renderV3PageContent(slug);
106
+ if (capability !== null) {
107
+ return capability;
108
+ }
109
+ if (!section) {
110
+ return renderV3PageContent(slug);
111
+ }
98
112
 
99
113
  const text = section.text.trim();
100
- if (text.length === 0) return "";
114
+ if (text.length === 0) {
115
+ return "";
116
+ }
101
117
  return withConceptHeader(slug, text);
102
118
  }
@@ -65,6 +65,10 @@ import { getMemoryConfig } from "../config.js";
65
65
  import { getLogger } from "../logging.js";
66
66
  import { memorySqliteOrNull } from "../memory-db.js";
67
67
  import { unwrapMemoryBlock, wrapMemoryBlock } from "../memory-marker.js";
68
+ import {
69
+ INJECTED_CONCEPT_HEADER_REGEX,
70
+ readInjectedBlock,
71
+ } from "../substrate/injected-block-slugs.js";
68
72
  import {
69
73
  getActiveEntries,
70
74
  getPrunedSlugs,
@@ -72,10 +76,6 @@ import {
72
76
  MEMORY_V3_INJECTED_BLOCK_METADATA_KEY,
73
77
  residentBytes,
74
78
  } from "./ever-injected-store.js";
75
- import {
76
- INJECTED_CONCEPT_HEADER_REGEX,
77
- readInjectedBlock,
78
- } from "./substrate/injected-block-slugs.js";
79
79
 
80
80
  const log = getLogger("memory-v3-shadow");
81
81
 
@@ -133,7 +133,9 @@ export function parseCardSections(inner: string): {
133
133
  cardMatches.map((match) => ({ index: match.index!, slug: match[1]! }));
134
134
  for (const match of inner.matchAll(TOP_LEVEL_HEADER_REGEX)) {
135
135
  const i = match.index!;
136
- if (cardStarts.has(i)) continue;
136
+ if (cardStarts.has(i)) {
137
+ continue;
138
+ }
137
139
  // Foreign header on a `\n\n` seam → starts its own chunk.
138
140
  if (i >= 2 && inner[i - 1] === "\n" && inner[i - 2] === "\n") {
139
141
  boundaries.push({ index: i, slug: null });
@@ -175,16 +177,24 @@ export function filterPrunedCardSections(
175
177
  prunedSlugs: ReadonlySet<string>,
176
178
  ): string {
177
179
  const { preamble, sections, pieces } = parseCardSections(inner);
178
- if (sections.length === 0) return inner;
180
+ if (sections.length === 0) {
181
+ return inner;
182
+ }
179
183
 
180
184
  const kept = pieces.filter(
181
185
  (piece) => piece.kind !== "card" || !prunedSlugs.has(piece.slug),
182
186
  );
183
- if (kept.length === pieces.length) return inner;
184
- if (kept.length === 0) return "";
187
+ if (kept.length === pieces.length) {
188
+ return inner;
189
+ }
190
+ if (kept.length === 0) {
191
+ return "";
192
+ }
185
193
 
186
194
  const texts = kept.map((piece) => piece.text);
187
- if (preamble.length > 0) texts.unshift(preamble);
195
+ if (preamble.length > 0) {
196
+ texts.unshift(preamble);
197
+ }
188
198
  return texts.join("\n\n");
189
199
  }
190
200
 
@@ -226,7 +236,9 @@ export function planPrune(
226
236
  ): PrunePlan | null {
227
237
  const activeEntries = getActiveEntries(conversationId);
228
238
  const resident = activeEntries.reduce((sum, e) => sum + e.bytes, 0);
229
- if (resident <= deps.maxResidentBytes) return null;
239
+ if (resident <= deps.maxResidentBytes) {
240
+ return null;
241
+ }
230
242
 
231
243
  const memoryRaw = memorySqliteOrNull("planPrune");
232
244
  const selectionRows = memoryRaw
@@ -256,7 +268,9 @@ export function planPrune(
256
268
  const slugs: string[] = [];
257
269
  let bytesFreed = 0;
258
270
  for (const candidate of candidates) {
259
- if (resident - bytesFreed <= deps.targetResidentBytes) break;
271
+ if (resident - bytesFreed <= deps.targetResidentBytes) {
272
+ break;
273
+ }
260
274
  slugs.push(candidate.slug);
261
275
  bytesFreed += candidate.bytes;
262
276
  }
@@ -293,7 +307,9 @@ export function collectPersistedV3Cards(conversationId: string): Set<string> {
293
307
  row.metadata,
294
308
  MEMORY_V3_INJECTED_BLOCK_METADATA_KEY,
295
309
  );
296
- if (block === null) continue;
310
+ if (block === null) {
311
+ continue;
312
+ }
297
313
  for (const section of parseCardSections(unwrapMemoryBlock(block))
298
314
  .sections) {
299
315
  sections.add(section.text);
@@ -321,7 +337,9 @@ export function stripPrunedCardsFromMessages(
321
337
  ): number {
322
338
  let strippedBlocks = 0;
323
339
  for (const message of messages) {
324
- if (message.role !== "user") continue;
340
+ if (message.role !== "user") {
341
+ continue;
342
+ }
325
343
  let changed = false;
326
344
  const nextContent: ContentBlock[] = [];
327
345
  for (const block of message.content) {
@@ -355,7 +373,9 @@ export function stripPrunedCardsFromMessages(
355
373
  nextContent.push({ type: "text", text: wrapMemoryBlock(filtered) });
356
374
  }
357
375
  }
358
- if (changed) message.content = nextContent;
376
+ if (changed) {
377
+ message.content = nextContent;
378
+ }
359
379
  }
360
380
  return strippedBlocks;
361
381
  }
@@ -400,7 +420,9 @@ export async function runPruneValve(
400
420
  ): Promise<PrunePlan | null> {
401
421
  // Defensive read: test configs may omit the prune block entirely.
402
422
  const pruneConfig = getMemoryConfig()?.v3?.prune;
403
- if (!pruneConfig) return null;
423
+ if (!pruneConfig) {
424
+ return null;
425
+ }
404
426
 
405
427
  // Planning needs only the store (cheap); the persisted-metadata scan for
406
428
  // the live strip's ownership test runs only once a plan exists — a
@@ -413,7 +435,9 @@ export async function runPruneValve(
413
435
  },
414
436
  conversationId,
415
437
  );
416
- if (!plan) return null;
438
+ if (!plan) {
439
+ return null;
440
+ }
417
441
 
418
442
  markPruned(conversationId, plan.slugs, options.now ?? Date.now());
419
443
 
@@ -22,12 +22,12 @@ import { isMemoryV3Live } from "../../../../config/memory-v3-gate.js";
22
22
  import { getDb, getSqliteFrom } from "../../../../persistence/db-connection.js";
23
23
  import { memorySqliteOrNull } from "../memory-db.js";
24
24
  import { getWorkspaceDir } from "../paths.js";
25
+ import { readPage } from "../substrate/page-store.js";
25
26
  import { capabilityOrDiskBody } from "./capabilities.js";
26
27
  import { sectionByOrdinal } from "./orchestrate.js";
27
28
  import { renderV3SectionContent } from "./page-content.js";
28
29
  import { renderMemoryBlock } from "./render-injection.js";
29
30
  import { buildSectionIndex } from "./sections.js";
30
- import { readPage } from "./substrate/page-store.js";
31
31
  import {
32
32
  type Section,
33
33
  SELECTION_SOURCES,
@@ -63,7 +63,9 @@ function rowsForTurn(conversationId: string, turn: number): SelectionRow[] {
63
63
  }
64
64
 
65
65
  function rowsForMessageIds(messageIds: string[]): SelectionRow[] {
66
- if (messageIds.length === 0) return [];
66
+ if (messageIds.length === 0) {
67
+ return [];
68
+ }
67
69
  const raw = memorySqliteOrNull("rowsForMessageIds");
68
70
  if (!raw) {
69
71
  return [];
@@ -87,7 +89,9 @@ const MAX_FORK_HOPS = 64;
87
89
  * stamps onto every message a fork copies, for the given message ids.
88
90
  */
89
91
  function forkSourceIdsOf(messageIds: string[]): string[] {
90
- if (messageIds.length === 0) return [];
92
+ if (messageIds.length === 0) {
93
+ return [];
94
+ }
91
95
  const placeholders = messageIds.map(() => "?").join(", ");
92
96
  const rows = getSqliteFrom(getDb())
93
97
  .query(
@@ -117,10 +121,16 @@ function rowsViaForkSource(messageIds: string[]): SelectionRow[] {
117
121
  const visited = new Set(messageIds);
118
122
  for (let hop = 0; hop < MAX_FORK_HOPS; hop++) {
119
123
  const sources = forkSourceIdsOf(frontier).filter((id) => !visited.has(id));
120
- if (sources.length === 0) return [];
121
- for (const id of sources) visited.add(id);
124
+ if (sources.length === 0) {
125
+ return [];
126
+ }
127
+ for (const id of sources) {
128
+ visited.add(id);
129
+ }
122
130
  const rows = rowsForMessageIds(sources);
123
- if (rows.length > 0) return rows;
131
+ if (rows.length > 0) {
132
+ return rows;
133
+ }
124
134
  frontier = sources;
125
135
  }
126
136
  return [];
@@ -140,7 +150,9 @@ async function reconstructMatchedSections(
140
150
  const sectionSlugs = rows
141
151
  .filter((r) => r.section_ordinal != null)
142
152
  .map((r) => r.slug);
143
- if (sectionSlugs.length === 0) return new Map();
153
+ if (sectionSlugs.length === 0) {
154
+ return new Map();
155
+ }
144
156
 
145
157
  const workspaceDir = getWorkspaceDir();
146
158
  const pageBody = (slug: Slug): Promise<string> =>
@@ -155,9 +167,13 @@ async function reconstructMatchedSections(
155
167
 
156
168
  const sectionBySlug = new Map<Slug, Section>();
157
169
  for (const row of rows) {
158
- if (row.section_ordinal == null) continue;
170
+ if (row.section_ordinal == null) {
171
+ continue;
172
+ }
159
173
  const section = sectionByOrdinal(index, row.slug, row.section_ordinal);
160
- if (section) sectionBySlug.set(row.slug, section);
174
+ if (section) {
175
+ sectionBySlug.set(row.slug, section);
176
+ }
161
177
  }
162
178
  return sectionBySlug;
163
179
  }
@@ -165,7 +181,9 @@ async function reconstructMatchedSections(
165
181
  async function buildSelectionLog(
166
182
  rows: SelectionRow[],
167
183
  ): Promise<MemoryV3SelectionLog | null> {
168
- if (rows.length === 0) return null;
184
+ if (rows.length === 0) {
185
+ return null;
186
+ }
169
187
 
170
188
  const config = getConfig();
171
189
  const selections = rows.map((r) => ({
@@ -226,7 +244,9 @@ export async function getMemoryV3SelectionForInspector(
226
244
  conversationId: string,
227
245
  turn: number | null | undefined,
228
246
  ): Promise<MemoryV3SelectionLog | null> {
229
- if (turn == null) return null;
247
+ if (turn == null) {
248
+ return null;
249
+ }
230
250
  return buildSelectionLog(rowsForTurn(conversationId, turn));
231
251
  }
232
252
 
@@ -280,7 +300,9 @@ export function summarizeSelections(conversationId: string): SelectionSummary {
280
300
  const turns = new Set<number>();
281
301
  const slugs = new Set<string>();
282
302
  for (const row of rows) {
283
- if (isSelectionSource(row.source)) bySource[row.source] += 1;
303
+ if (isSelectionSource(row.source)) {
304
+ bySource[row.source] += 1;
305
+ }
284
306
  turns.add(row.turn);
285
307
  slugs.add(row.slug);
286
308
  }
@@ -32,6 +32,7 @@ import {
32
32
  } from "@vellumai/plugin-api";
33
33
 
34
34
  import { getConfig } from "../../../../config/loader.js";
35
+ import { isMemoryEnabled } from "../../../../config/memory-v3-gate.js";
35
36
  import type { AssistantConfig } from "../../../../config/schema.js";
36
37
  import {
37
38
  recordLatencySubSpan,
@@ -41,6 +42,8 @@ import { stripCommentLines } from "../host-utils.js";
41
42
  import { getLogger } from "../logging.js";
42
43
  import { memorySqliteOrNull } from "../memory-db.js";
43
44
  import { getWorkspaceDir, getWorkspacePromptPath } from "../paths.js";
45
+ import { getPageIndex, invalidatePageIndex } from "../substrate/page-index.js";
46
+ import { readPage, renderPageContent } from "../substrate/page-store.js";
44
47
  import {
45
48
  capabilityOrDiskBody,
46
49
  renderCapabilityContent,
@@ -53,7 +56,6 @@ import type { EntityIndex } from "./entity-lane.js";
53
56
  import { buildEntityIndex } from "./entity-lane.js";
54
57
  import { getActiveSlugs } from "./ever-injected-store.js";
55
58
  import { computeFreshSet } from "./fresh-set.js";
56
- import { isMemoryV3InjectionGateEnabled } from "./gate-flag.js";
57
59
  import { computeHotSet } from "./hot-set.js";
58
60
  import { bumpLanesVersion, readLanesVersion } from "./lanes-version-store.js";
59
61
  import { computeLearnedEdgeGraph } from "./learned-edges.js";
@@ -67,8 +69,6 @@ import { ensureSectionCollection } from "./section-dense-store.js";
67
69
  import type { SectionNeedle } from "./section-needle.js";
68
70
  import { buildSectionNeedle } from "./section-needle.js";
69
71
  import { buildSectionIndex } from "./sections.js";
70
- import { getPageIndex, invalidatePageIndex } from "./substrate/page-index.js";
71
- import { readPage, renderPageContent } from "./substrate/page-store.js";
72
72
  import { resolveV3Tuning } from "./tuning-profile.js";
73
73
  import {
74
74
  type MemoryRoutingTurn,
@@ -690,7 +690,7 @@ export async function observeTurn(
690
690
  }
691
691
 
692
692
  const cfg = getConfig();
693
- if (cfg.memory.enabled === false) {
693
+ if (!isMemoryEnabled(cfg)) {
694
694
  return null;
695
695
  }
696
696
  // Lane init is module-memoized: the first turn after daemon start pays
@@ -702,10 +702,6 @@ export async function observeTurn(
702
702
  () => getLanes(cfg),
703
703
  );
704
704
  const v3 = cfg.memory.v3;
705
- // Resolve the effective gate enable once for the turn: the feature flag
706
- // AND the `memory.v3.gate.enabled` config kill-switch. Tuning lives in
707
- // `memory.v3.gate`.
708
- const gateEnabled = isMemoryV3InjectionGateEnabled(cfg);
709
705
  // Re-resolve the corpus-adaptive tuning each turn from the CURRENT config
710
706
  // (with the lane-build corpus-size signal) so a live config.json edit to a
711
707
  // per-turn knob (selectorEnabled, denseK, replyQueryK, edge.*) takes effect
@@ -733,6 +729,7 @@ export async function observeTurn(
733
729
  activeSlugs: getActiveSlugs(conversationId),
734
730
  entityCap: v3.entity.cap,
735
731
  replyQueryK: tuning.replyQueryK,
732
+ spanQueryK: tuning.spanQueryK,
736
733
  edgeSeeds: tuning.edgeSeedCount,
737
734
  edgePerSeed: tuning.edgePerSeed,
738
735
  edgeCap: tuning.edgeCap,
@@ -744,11 +741,10 @@ export async function observeTurn(
744
741
  v3.selectorPromptPath,
745
742
  getWorkspaceDir(),
746
743
  ),
747
- // Per-turn injection gate: the `memory.v3.gate` tuning with the raw
748
- // config `enabled` overwritten by the effective enable (flag AND config).
749
- // The spread is the compile-time drift guard — if the gate schema and
750
- // `V3GateConfig` diverge, this stops typechecking.
751
- gateConfig: { ...v3.gate, enabled: gateEnabled },
744
+ // Per-turn injection gate: the `memory.v3.gate` tuning, `enabled`
745
+ // kill-switch included. Read-only downstream, so the config object is
746
+ // passed as-is.
747
+ gateConfig: v3.gate,
752
748
  });
753
749
 
754
750
  // A zero-selection turn over a non-trivial pool is unusual enough to be
@@ -0,0 +1,86 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { MAX_SPAN_CHUNKS, spanChunksOf } from "./span-query.js";
4
+
5
+ describe("spanChunksOf", () => {
6
+ test("short message passes through as its clause spans", () => {
7
+ const chunks = spanChunksOf(
8
+ "the first sentence is here. and a second sentence follows!",
9
+ );
10
+ expect(chunks).toEqual([
11
+ "the first sentence is here.",
12
+ "and a second sentence follows!",
13
+ ]);
14
+ });
15
+
16
+ test("newlines split spans like sentence punctuation", () => {
17
+ const chunks = spanChunksOf(
18
+ "a line without terminal punctuation\nanother line of the message",
19
+ );
20
+ expect(chunks).toEqual([
21
+ "a line without terminal punctuation",
22
+ "another line of the message",
23
+ ]);
24
+ });
25
+
26
+ test("sub-15-char fragments are dropped", () => {
27
+ const chunks = spanChunksOf("ok. this sentence is long enough to keep.");
28
+ expect(chunks).toEqual(["this sentence is long enough to keep."]);
29
+ });
30
+
31
+ test("empty and whitespace-only messages yield no chunks", () => {
32
+ expect(spanChunksOf("")).toEqual([]);
33
+ expect(spanChunksOf(" \n\n ")).toEqual([]);
34
+ });
35
+
36
+ test("fullwidth CJK terminators split without trailing whitespace", () => {
37
+ const chunks = spanChunksOf(
38
+ "这是消息里的第一句完整的话。这是紧跟着的第二句完整的话!第三句也一样长够十五个字符?",
39
+ );
40
+ expect(chunks).toEqual([
41
+ "这是消息里的第一句完整的话。",
42
+ "这是紧跟着的第二句完整的话!",
43
+ "第三句也一样长够十五个字符?",
44
+ ]);
45
+ });
46
+
47
+ test("non-ASCII spaced terminators split like ASCII ones", () => {
48
+ const chunks = spanChunksOf(
49
+ "पहला वाक्य यहाँ लिखा गया है। दूसरा वाक्य भी यहाँ मौजूद है।",
50
+ );
51
+ expect(chunks).toEqual([
52
+ "पहला वाक्य यहाँ लिखा गया है।",
53
+ "दूसरा वाक्य भी यहाँ मौजूद है।",
54
+ ]);
55
+ });
56
+
57
+ test("ASCII periods still do not split decimals or dotted numbers", () => {
58
+ expect(spanChunksOf("the value came out to 3.14159 in the final run.")) //
59
+ .toEqual(["the value came out to 3.14159 in the final run."]);
60
+ });
61
+
62
+ test("a message at the cap is returned unchanged", () => {
63
+ const sentences = Array.from(
64
+ { length: MAX_SPAN_CHUNKS },
65
+ (_, i) => `sentence number ${i} padded for length.`,
66
+ );
67
+ expect(spanChunksOf(sentences.join(" "))).toEqual(sentences);
68
+ });
69
+
70
+ test("over-cap messages merge into ≤cap contiguous chunks covering every span", () => {
71
+ const sentences = Array.from(
72
+ { length: 30 },
73
+ (_, i) => `sentence number ${i} padded for length.`,
74
+ );
75
+ const chunks = spanChunksOf(sentences.join(" "));
76
+ expect(chunks.length).toBe(MAX_SPAN_CHUNKS);
77
+ // Contiguous coverage: rejoining the chunks reproduces every span in order.
78
+ expect(chunks.join(" ")).toBe(sentences.join(" "));
79
+ // Near-equal partition: no chunk hoards spans (30/8 → sizes 3 or 4).
80
+ for (const chunk of chunks) {
81
+ const n = chunk.match(/sentence number/g)?.length ?? 0;
82
+ expect(n).toBeGreaterThanOrEqual(3);
83
+ expect(n).toBeLessThanOrEqual(4);
84
+ }
85
+ });
86
+ });