@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
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Tests for `memory/v2/skill-content.ts` — v2-owned port of v1's
2
+ * Tests for `substrate/skill-content.ts` — v2-owned port of v1's
3
3
  * `buildSkillContent` plus the `mcp-setup` description augmentation.
4
4
  */
5
5
  import { describe, expect, test } from "bun:test";
6
6
 
7
- import { setConfig } from "../../../../../../__tests__/helpers/set-config.js";
7
+ import { setConfig } from "../../../../../__tests__/helpers/set-config.js";
8
8
  import type { SkillCapabilityInput } from "../skill-content.js";
9
9
 
10
10
  describe("buildSkillContent", () => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Tests for `assistant/src/memory/v2/skill-store.ts`.
2
+ * Tests for `substrate/skill-store.ts`.
3
3
  *
4
4
  * Coverage matrix:
5
5
  * - `seedV2SkillEntries` enumerates the catalog and calls
@@ -25,9 +25,9 @@ import { tmpdir } from "node:os";
25
25
  import { join } from "node:path";
26
26
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
27
27
 
28
- import type { ResolvedSkill } from "../../../../../../config/skill-state.js";
29
- import type { SkillSummary } from "../../../../../../config/skills.js";
30
- import type { CatalogSkill } from "../../../../../../skills/catalog-install.js";
28
+ import type { ResolvedSkill } from "../../../../../config/skill-state.js";
29
+ import type { SkillSummary } from "../../../../../config/skills.js";
30
+ import type { CatalogSkill } from "../../../../../skills/catalog-install.js";
31
31
 
32
32
  // ---------------------------------------------------------------------------
33
33
  // Programmable test state — drives every mocked dependency below.
@@ -89,11 +89,11 @@ const state: TestState = {
89
89
  callSequence: [],
90
90
  };
91
91
 
92
- mock.module("../../../../../../config/skills.js", () => ({
92
+ mock.module("../../../../../config/skills.js", () => ({
93
93
  loadSkillCatalog: () => state.catalog ?? [],
94
94
  }));
95
95
 
96
- mock.module("../../../../../../config/skill-state.js", () => ({
96
+ mock.module("../../../../../config/skill-state.js", () => ({
97
97
  resolveSkillStates: (
98
98
  catalog: SkillSummary[],
99
99
  config: { skills?: { allowBundled?: string[] | null } },
@@ -122,13 +122,13 @@ mock.module("../../../../../../config/skill-state.js", () => ({
122
122
  },
123
123
  }));
124
124
 
125
- mock.module("../../../../../../config/assistant-feature-flags.js", () => ({
125
+ mock.module("../../../../../config/assistant-feature-flags.js", () => ({
126
126
  isAssistantFeatureFlagEnabled: (key: string) =>
127
127
  state.flagsEnabled[key] ?? true,
128
128
  }));
129
129
 
130
130
  mock.module(
131
- "../../../../../../persistence/embeddings/embedding-backend.js",
131
+ "../../../../../persistence/embeddings/embedding-backend.js",
132
132
  () => ({
133
133
  embedWithBackend: async (_config: unknown, inputs: unknown[]) => {
134
134
  if (state.embedThrows) {
@@ -174,7 +174,7 @@ mock.module("../qdrant.js", () => ({
174
174
  },
175
175
  }));
176
176
 
177
- mock.module("../../../../../../skills/catalog-cache.js", () => ({
177
+ mock.module("../../../../../skills/catalog-cache.js", () => ({
178
178
  getCatalog: async () => {
179
179
  if (state.fullCatalogThrows) {
180
180
  throw state.fullCatalogThrows;
@@ -7,7 +7,7 @@ import {
7
7
  SPARSE_VOCAB_SIZE,
8
8
  tokenHash,
9
9
  tokenizeStemmed,
10
- } from "../../../../../../persistence/embeddings/sparse-tokenize.js";
10
+ } from "../../../../../persistence/embeddings/sparse-tokenize.js";
11
11
  import {
12
12
  _resetCorpusStatsForTests,
13
13
  _setCorpusStatsForTests,
@@ -43,12 +43,15 @@ function dotProduct(
43
43
  d: { indices: number[]; values: number[] },
44
44
  ): number {
45
45
  const dMap = new Map<number, number>();
46
- for (let i = 0; i < d.indices.length; i++)
46
+ for (let i = 0; i < d.indices.length; i++) {
47
47
  dMap.set(d.indices[i], d.values[i]);
48
+ }
48
49
  let sum = 0;
49
50
  for (let i = 0; i < q.indices.length; i++) {
50
51
  const dv = dMap.get(q.indices[i]);
51
- if (dv !== undefined) sum += q.values[i] * dv;
52
+ if (dv !== undefined) {
53
+ sum += q.values[i] * dv;
54
+ }
52
55
  }
53
56
  return sum;
54
57
  }
@@ -234,7 +237,9 @@ describe("generateBm25QueryEmbedding", () => {
234
237
  test("emits binary occurrence per distinct token", () => {
235
238
  const vec = generateBm25QueryEmbedding("supplements supplements zinc");
236
239
  expect(vec.indices.length).toBe(2);
237
- for (const v of vec.values) expect(v).toBe(1);
240
+ for (const v of vec.values) {
241
+ expect(v).toBe(1);
242
+ }
238
243
  });
239
244
 
240
245
  test("empty input yields empty vector", () => {
@@ -263,7 +268,9 @@ describe("end-to-end ranking: BM25 fixes the supplements bug", () => {
263
268
  const seen = new Set<number>();
264
269
  for (const t of tokens) {
265
270
  const idx = tokenHash(t, SPARSE_VOCAB_SIZE);
266
- if (seen.has(idx)) continue;
271
+ if (seen.has(idx)) {
272
+ continue;
273
+ }
267
274
  seen.add(idx);
268
275
  df.set(idx, (df.get(idx) ?? 0) + 1);
269
276
  }
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Tests for `substrate/spread.ts` — edge-graph activation
3
+ * spreading.
4
+ *
5
+ * Coverage:
6
+ * - `spreadActivation`: orphan yields A == A_o; spread walks incoming edges
7
+ * only (A→B boosts B but not A); hops=2 reaches second-degree predecessors
8
+ * but not third; bounded in [0,1]; inactive predecessors drop from both
9
+ * sides of the ratio; contribution == final - own.
10
+ *
11
+ * `spreadActivation` is a pure function (no I/O), so no mocks are needed.
12
+ */
13
+
14
+ import { describe, expect, test } from "bun:test";
15
+
16
+ import type { EdgeIndex } from "../edge-index.js";
17
+ import { spreadActivation } from "../spread.js";
18
+
19
+ /**
20
+ * Build a directed `EdgeIndex` from a flat list of `[from, to]` pairs. Each
21
+ * entry is interpreted as a directed edge `from → to`; self-loops are dropped.
22
+ */
23
+ function buildEdgeIndex(edges: Array<[string, string]>): EdgeIndex {
24
+ const outgoing = new Map<string, Set<string>>();
25
+ const incoming = new Map<string, Set<string>>();
26
+ for (const [from, to] of edges) {
27
+ if (from === to) {
28
+ continue;
29
+ }
30
+ let outSet = outgoing.get(from);
31
+ if (!outSet) {
32
+ outSet = new Set<string>();
33
+ outgoing.set(from, outSet);
34
+ }
35
+ outSet.add(to);
36
+ let inSet = incoming.get(to);
37
+ if (!inSet) {
38
+ inSet = new Set<string>();
39
+ incoming.set(to, inSet);
40
+ }
41
+ inSet.add(from);
42
+ }
43
+ return { outgoing, incoming };
44
+ }
45
+
46
+ describe("spreadActivation", () => {
47
+ test("orphan node yields A == A_o", () => {
48
+ const edges = buildEdgeIndex([]);
49
+ const own = new Map([["alice", 0.7]]);
50
+ const out = spreadActivation(own, edges, 0.5, 2);
51
+ expect(out.final.get("alice")).toBeCloseTo(0.7, 6);
52
+ });
53
+
54
+ test("directed edge boosts only the target, not the source", () => {
55
+ // Edge alice→bob: alice activation flows into bob; bob does NOT push back
56
+ // into alice. alice (a pure source under this graph) keeps its own value.
57
+ const edges = buildEdgeIndex([["alice", "bob"]]);
58
+ const own = new Map([
59
+ ["alice", 0.6],
60
+ ["bob", 0.0],
61
+ ]);
62
+ const out = spreadActivation(own, edges, 0.5, 2);
63
+ // alice has no incoming edges → final == own.
64
+ expect(out.final.get("alice")).toBeCloseTo(0.6, 6);
65
+ // bob's incoming = {alice}: numerator = 0 + 0.5*0.6 = 0.3, denom = 1.5.
66
+ expect(out.final.get("bob")).toBeCloseTo(0.3 / 1.5, 6);
67
+ });
68
+
69
+ test("two-cycle (A→B and B→A) lets activation flow both ways", () => {
70
+ // With both directions present, each node is the other's predecessor.
71
+ const edges = buildEdgeIndex([
72
+ ["alice", "bob"],
73
+ ["bob", "alice"],
74
+ ]);
75
+ const own = new Map([
76
+ ["alice", 0.0],
77
+ ["bob", 0.8],
78
+ ]);
79
+ const out = spreadActivation(own, edges, 0.5, 2);
80
+ // alice: incoming {bob}=0.8 → numerator = 0 + 0.5*0.8 = 0.4, denom = 1.5.
81
+ expect(out.final.get("alice")).toBeCloseTo(0.4 / 1.5, 6);
82
+ // bob: incoming {alice}=0.0 → numerator = 0.8 + 0 = 0.8, denom = 1.5.
83
+ expect(out.final.get("bob")).toBeCloseTo(0.8 / 1.5, 6);
84
+ });
85
+
86
+ test("pure source (high outgoing, zero incoming) collapses to final == own", () => {
87
+ // alice → bob → carol; alice has no incoming edges.
88
+ const edges = buildEdgeIndex([
89
+ ["alice", "bob"],
90
+ ["bob", "carol"],
91
+ ]);
92
+ const own = new Map([
93
+ ["alice", 0.5],
94
+ ["bob", 0.0],
95
+ ["carol", 0.0],
96
+ ]);
97
+ const out = spreadActivation(own, edges, 0.5, 2);
98
+ expect(out.final.get("alice")).toBeCloseTo(0.5, 6);
99
+ });
100
+
101
+ test("hops=2 reaches second-degree predecessors but stops there", () => {
102
+ // Directed path: alice → bob → carol → delta
103
+ // From delta's perspective: carol is 1-hop predecessor, bob is 2-hop,
104
+ // alice is 3-hop. Activation on bob (2-hop) reaches delta; activation on
105
+ // alice (3-hop) does NOT.
106
+ const edges = buildEdgeIndex([
107
+ ["alice", "bob"],
108
+ ["bob", "carol"],
109
+ ["carol", "delta"],
110
+ ]);
111
+ const own = new Map([
112
+ ["alice", 1.0], // 3-hop predecessor of delta — must NOT contribute
113
+ ["bob", 1.0], // 2-hop predecessor of delta
114
+ ["carol", 0.0],
115
+ ["delta", 0.0],
116
+ ]);
117
+ const out = spreadActivation(own, edges, 0.5, 2);
118
+ // delta: 1-hop {carol}=0, 2-hop {bob}=1.0.
119
+ // numerator = 0 + 0.5*0 + 0.25*1.0 = 0.25
120
+ // denominator = 1 + 0.5*1 + 0.25*1 = 1.75
121
+ // A = 0.25 / 1.75 ≈ 0.142857
122
+ expect(out.final.get("delta")).toBeCloseTo(0.25 / 1.75, 6);
123
+ });
124
+
125
+ test("output is bounded in [0, 1] for arbitrary inputs", () => {
126
+ const edges = buildEdgeIndex([
127
+ ["alice", "bob"],
128
+ ["bob", "carol"],
129
+ ["alice", "carol"],
130
+ ]);
131
+ const own = new Map([
132
+ ["alice", 1.0],
133
+ ["bob", 1.0],
134
+ ["carol", 1.0],
135
+ ]);
136
+ const out = spreadActivation(own, edges, 0.99, 2);
137
+ for (const [, value] of out.final) {
138
+ expect(value).toBeGreaterThanOrEqual(0);
139
+ expect(value).toBeLessThanOrEqual(1);
140
+ }
141
+ });
142
+
143
+ test("hops=0 collapses to A == A_o", () => {
144
+ const edges = buildEdgeIndex([["alice", "bob"]]);
145
+ const own = new Map([
146
+ ["alice", 0.4],
147
+ ["bob", 0.9],
148
+ ]);
149
+ const out = spreadActivation(own, edges, 0.5, 0);
150
+ expect(out.final.get("alice")).toBeCloseTo(0.4, 6);
151
+ expect(out.final.get("bob")).toBeCloseTo(0.9, 6);
152
+ });
153
+
154
+ test("k=0 collapses to A == A_o", () => {
155
+ const edges = buildEdgeIndex([["alice", "bob"]]);
156
+ const own = new Map([
157
+ ["alice", 0.4],
158
+ ["bob", 0.9],
159
+ ]);
160
+ const out = spreadActivation(own, edges, 0, 5);
161
+ expect(out.final.get("alice")).toBeCloseTo(0.4, 6);
162
+ expect(out.final.get("bob")).toBeCloseTo(0.9, 6);
163
+ });
164
+
165
+ test("predecessors not in the candidate set are dropped from both numerator and denominator", () => {
166
+ // Edge alice→bob: bob has structural predecessor alice, but alice is not
167
+ // in `ownActivation`, so she contributes nothing — hop1 has no active
168
+ // predecessors, so the whole hop drops out of both sides of the ratio.
169
+ // Bob therefore stays at his own activation.
170
+ const edges = buildEdgeIndex([["alice", "bob"]]);
171
+ const own = new Map([["bob", 0.6]]);
172
+ const out = spreadActivation(own, edges, 0.5, 2);
173
+ expect(out.final.get("bob")).toBeCloseTo(0.6, 6);
174
+ });
175
+
176
+ test("L_2 norm over multiple active predecessors rewards strong outliers more than avg would", () => {
177
+ // bob has 4 predecessors in the candidate set: one strong, three weak.
178
+ // L_2 = √((0.8² + 0.1² + 0.1² + 0.1²) / 4) = √(0.1675) ≈ 0.40927
179
+ // Plain avg of the same set = 0.275, so L_2 lifts bob more than avg
180
+ // would — the design goal of preferring quality over quantity.
181
+ const edges = buildEdgeIndex([
182
+ ["a1", "bob"],
183
+ ["a2", "bob"],
184
+ ["a3", "bob"],
185
+ ["a4", "bob"],
186
+ ]);
187
+ const own = new Map([
188
+ ["a1", 0.8],
189
+ ["a2", 0.1],
190
+ ["a3", 0.1],
191
+ ["a4", 0.1],
192
+ ["bob", 0.0],
193
+ ]);
194
+ const out = spreadActivation(own, edges, 0.5, 2);
195
+ const rms = Math.sqrt((0.8 * 0.8 + 3 * 0.1 * 0.1) / 4);
196
+ // numerator = 0 + 0.5 · rms
197
+ // denominator = 1 + 0.5
198
+ expect(out.final.get("bob")).toBeCloseTo((0.5 * rms) / 1.5, 6);
199
+ });
200
+
201
+ test("high-in-degree hub with mostly-inactive predecessors stays near A_o", () => {
202
+ // 100 structural predecessors point at hub; only one (`pred0`) is in
203
+ // the candidate set. Inactive structural predecessors affect neither
204
+ // side of the ratio — the structural in-degree never enters the
205
+ // denominator, and the L_2 averages over the single active predecessor.
206
+ const rawEdges: Array<[string, string]> = [];
207
+ for (let i = 0; i < 100; i++) {
208
+ rawEdges.push([`pred${i}`, "hub"]);
209
+ }
210
+ const edges = buildEdgeIndex(rawEdges);
211
+ const own = new Map([
212
+ ["hub", 0.6],
213
+ ["pred0", 0.5],
214
+ ]);
215
+ const out = spreadActivation(own, edges, 0.5, 2);
216
+ // hop1 active = {pred0}, L_2([0.5]) = 0.5.
217
+ // numerator = 0.6 + 0.5 · 0.5 = 0.85
218
+ // denominator = 1 + 0.5 = 1.5
219
+ expect(out.final.get("hub")).toBeCloseTo(0.85 / 1.5, 6);
220
+ });
221
+
222
+ test("empty own-activation map returns empty result", () => {
223
+ const out = spreadActivation(
224
+ new Map(),
225
+ buildEdgeIndex([["a", "b"]]),
226
+ 0.5,
227
+ 2,
228
+ );
229
+ expect(out.final.size).toBe(0);
230
+ expect(out.contribution.size).toBe(0);
231
+ });
232
+
233
+ test("contribution equals final - own for each slug", () => {
234
+ // Two-cycle: A→B and B→A so both nodes have predecessors and the spread
235
+ // moves each off its own value in opposite directions.
236
+ const edges = buildEdgeIndex([
237
+ ["alice", "bob"],
238
+ ["bob", "alice"],
239
+ ]);
240
+ const own = new Map([
241
+ ["alice", 0.0],
242
+ ["bob", 0.8],
243
+ ]);
244
+ const out = spreadActivation(own, edges, 0.5, 2);
245
+ for (const [slug, finalValue] of out.final) {
246
+ const ownValue = own.get(slug) ?? 0;
247
+ expect(out.contribution.get(slug)).toBeCloseTo(finalValue - ownValue, 6);
248
+ }
249
+ // alice gained spread (predecessor bob=0.8); bob lost some (predecessor
250
+ // alice=0 dilutes its own 0.8).
251
+ expect(out.contribution.get("alice")).toBeGreaterThan(0);
252
+ expect(out.contribution.get("bob")).toBeLessThan(0);
253
+ });
254
+
255
+ test("contribution is 0 for every slug when hops == 0", () => {
256
+ const edges = buildEdgeIndex([["alice", "bob"]]);
257
+ const own = new Map([
258
+ ["alice", 0.4],
259
+ ["bob", 0.9],
260
+ ]);
261
+ const out = spreadActivation(own, edges, 0.5, 0);
262
+ expect(out.contribution.get("alice")).toBe(0);
263
+ expect(out.contribution.get("bob")).toBe(0);
264
+ });
265
+
266
+ test("contribution is 0 for every slug when k == 0", () => {
267
+ const edges = buildEdgeIndex([["alice", "bob"]]);
268
+ const own = new Map([
269
+ ["alice", 0.4],
270
+ ["bob", 0.9],
271
+ ]);
272
+ const out = spreadActivation(own, edges, 0, 5);
273
+ expect(out.contribution.get("alice")).toBe(0);
274
+ expect(out.contribution.get("bob")).toBe(0);
275
+ });
276
+ });
@@ -21,8 +21,8 @@ const noopLogger: Record<string, unknown> = new Proxy(
21
21
  );
22
22
 
23
23
  // eslint-disable-next-line @typescript-eslint/no-require-imports
24
- const realLogger = require("../../../../../../util/logger.js");
25
- mock.module("../../../../../../util/logger.js", () => ({
24
+ const realLogger = require("../../../../../util/logger.js");
25
+ mock.module("../../../../../util/logger.js", () => ({
26
26
  ...realLogger,
27
27
  getLogger: () => noopLogger,
28
28
  getCliLogger: () => noopLogger,
@@ -35,7 +35,7 @@ let configMemoryV2Enabled = true;
35
35
  let configMemoryEnabled = true;
36
36
 
37
37
  // static-context reads its gates through the plugin's own config accessor.
38
- mock.module("../../../config.js", () => ({
38
+ mock.module("../../config.js", () => ({
39
39
  getMemoryConfig: () => ({
40
40
  enabled: configMemoryEnabled,
41
41
  v2: { enabled: configMemoryV2Enabled },
@@ -60,8 +60,9 @@ function writeMemoryFile(name: string, body: string): void {
60
60
 
61
61
  function cleanupMemoryDir(): void {
62
62
  const memoryDir = join(TEST_DIR, "memory");
63
- if (existsSync(memoryDir))
63
+ if (existsSync(memoryDir)) {
64
64
  rmSync(memoryDir, { recursive: true, force: true });
65
+ }
65
66
  }
66
67
 
67
68
  describe("readMemoryV2StaticContent", () => {
@@ -77,13 +78,17 @@ describe("readMemoryV2StaticContent", () => {
77
78
 
78
79
  test("returns null when config.memory.v2.enabled is off", () => {
79
80
  configMemoryV2Enabled = false;
80
- for (const file of MEMORY_FILES) writeMemoryFile(file, `Content ${file}`);
81
+ for (const file of MEMORY_FILES) {
82
+ writeMemoryFile(file, `Content ${file}`);
83
+ }
81
84
  expect(readMemoryV2StaticContent()).toBeNull();
82
85
  });
83
86
 
84
87
  test("returns null when config.memory.enabled is off even with v2 on", () => {
85
88
  configMemoryEnabled = false;
86
- for (const file of MEMORY_FILES) writeMemoryFile(file, `Content ${file}`);
89
+ for (const file of MEMORY_FILES) {
90
+ writeMemoryFile(file, `Content ${file}`);
91
+ }
87
92
  expect(readMemoryV2StaticContent()).toBeNull();
88
93
  });
89
94
 
@@ -120,7 +125,9 @@ describe("readMemoryV2StaticContent", () => {
120
125
  });
121
126
 
122
127
  test("excludeBuffer drops the Buffer section but keeps the other three", () => {
123
- for (const file of MEMORY_FILES) writeMemoryFile(file, `Content ${file}`);
128
+ for (const file of MEMORY_FILES) {
129
+ writeMemoryFile(file, `Content ${file}`);
130
+ }
124
131
 
125
132
  const result = readMemoryV2StaticContent({ excludeBuffer: true });
126
133
  expect(result).not.toBeNull();
@@ -146,7 +153,9 @@ describe("readMemoryV2StaticContent", () => {
146
153
  });
147
154
 
148
155
  test("returns null when every file is empty", () => {
149
- for (const file of MEMORY_FILES) writeMemoryFile(file, "");
156
+ for (const file of MEMORY_FILES) {
157
+ writeMemoryFile(file, "");
158
+ }
150
159
  expect(readMemoryV2StaticContent()).toBeNull();
151
160
  });
152
161
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Tests for `assistant/src/memory/v2/sweep-job.ts`.
2
+ * Tests for `substrate/sweep-job.ts`.
3
3
  *
4
4
  * Coverage matrix:
5
5
  * - v2 disabled in config → no provider/DB calls, returns 0 (early bail).
@@ -62,7 +62,7 @@ mock.module("@vellumai/plugin-api", () => ({
62
62
  // so the failure-path test can assert on `activity.failed` shape and dedupe.
63
63
  const emitCalls: Array<Record<string, unknown>> = [];
64
64
 
65
- mock.module("../../../../../../notifications/emit-signal.js", () => ({
65
+ mock.module("../../../../../notifications/emit-signal.js", () => ({
66
66
  emitNotificationSignal: async (params: Record<string, unknown>) => {
67
67
  emitCalls.push(params);
68
68
  return {
@@ -95,14 +95,12 @@ afterAll(() => {
95
95
  rmSync(tmpWorkspace, { recursive: true, force: true });
96
96
  });
97
97
 
98
- const { getDb } =
99
- await import("../../../../../../persistence/db-connection.js");
98
+ const { getDb } = await import("../../../../../persistence/db-connection.js");
100
99
  const { resetDbForTesting } =
101
- await import("../../../../../../__tests__/db-test-helpers.js");
102
- const { initializeDb } =
103
- await import("../../../../../../persistence/db-init.js");
100
+ await import("../../../../../__tests__/db-test-helpers.js");
101
+ const { initializeDb } = await import("../../../../../persistence/db-init.js");
104
102
  const { messages, conversations } =
105
- await import("../../../../../../persistence/schema/index.js");
103
+ await import("../../../../../persistence/schema/index.js");
106
104
  const { memoryV2SweepJob } = await import("../sweep-job.js");
107
105
 
108
106
  // The handler reads `config.memory.v2.enabled` and `sweep_enabled`, so we
@@ -170,7 +168,9 @@ function makeEntriesProvider(entries: string[]): Provider {
170
168
  */
171
169
  function extractFirstUserText(msgs: { content: unknown }[]): string {
172
170
  const first = msgs[0];
173
- if (!first || !Array.isArray(first.content)) return "";
171
+ if (!first || !Array.isArray(first.content)) {
172
+ return "";
173
+ }
174
174
  const block = first.content.find(
175
175
  (b: unknown) =>
176
176
  typeof b === "object" &&
@@ -1,18 +1,21 @@
1
1
  // ---------------------------------------------------------------------------
2
- // Memory v2 — daemon-startup helpers
2
+ // Memory substrate — daemon-startup helpers
3
3
  // ---------------------------------------------------------------------------
4
4
  //
5
+ // Shared by the v2 injection engine and memory-v3; active whenever
6
+ // `usesConceptPageMemory()` holds.
7
+ //
5
8
  // Small focused module that holds the gating + dispatch logic for v2-specific
6
9
  // startup work invoked from `lifecycle.ts` (and, for the post-credential
7
10
  // capability reseed, from the secrets route). Lives in its own file so the unit
8
11
  // test for the gate does not have to mount the entire lifecycle import graph.
9
12
 
10
- import { usesConceptPageMemory } from "../../../../../config/memory-v3-gate.js";
11
- import type { AssistantConfig } from "../../../../../config/schema.js";
12
- import { getLogger } from "../../logging.js";
13
- import { getWorkspaceDir } from "../../paths.js";
13
+ import { usesConceptPageMemory } from "../../../../config/memory-v3-gate.js";
14
+ import type { AssistantConfig } from "../../../../config/schema.js";
15
+ import { getLogger } from "../logging.js";
16
+ import { getWorkspaceDir } from "../paths.js";
14
17
 
15
- const log = getLogger("memory-v2-startup");
18
+ const log = getLogger("boot-maintenance");
16
19
 
17
20
  /**
18
21
  * Fire-and-forget seed of the v2 skill entries (now indexed alongside concept
@@ -22,8 +25,10 @@ const log = getLogger("memory-v2-startup");
22
25
  * passes. Never awaits — startup must not block on this (see
23
26
  * `assistant/CLAUDE.md` daemon startup philosophy).
24
27
  */
25
- export function maybeSeedMemoryV2Skills(config: AssistantConfig): void {
26
- if (!usesConceptPageMemory(config.memory)) return;
28
+ export function maybeSeedCapabilitySkills(config: AssistantConfig): void {
29
+ if (!usesConceptPageMemory(config.memory)) {
30
+ return;
31
+ }
27
32
  void import("./skill-store.js")
28
33
  .then(({ seedV2SkillEntries }) => seedV2SkillEntries())
29
34
  .catch((err) => log.warn({ err }, "Failed to seed v2 skill entries"));
@@ -43,8 +48,10 @@ export function maybeSeedMemoryV2Skills(config: AssistantConfig): void {
43
48
  * `cli-commands/<name>` slug prefix). Dynamic import keeps v2 code out of the
44
49
  * startup graph when the gate is off. Never awaits — startup must not block.
45
50
  */
46
- export function maybeSeedMemoryV2CliCommands(config: AssistantConfig): void {
47
- if (!usesConceptPageMemory(config.memory)) return;
51
+ export function maybeSeedCliCommandCards(config: AssistantConfig): void {
52
+ if (!usesConceptPageMemory(config.memory)) {
53
+ return;
54
+ }
48
55
  void import("./cli-command-store.js")
49
56
  .then(({ seedV2CliCommandEntries }) => seedV2CliCommandEntries())
50
57
  .catch((err) => log.warn({ err }, "Failed to seed v2 CLI-command entries"));
@@ -76,7 +83,9 @@ async function settledWithin(
76
83
  try {
77
84
  return await Promise.race([p.then(() => true), timedOut]);
78
85
  } finally {
79
- if (timer) clearTimeout(timer);
86
+ if (timer) {
87
+ clearTimeout(timer);
88
+ }
80
89
  }
81
90
  }
82
91
 
@@ -86,7 +95,7 @@ async function settledWithin(
86
95
  * runs before the platform has provisioned the managed embedding credential.
87
96
  *
88
97
  * On a brand-new managed assistant the memory worker fires the startup seed
89
- * (`maybeSeedMemoryV2Skills` / `maybeSeedMemoryV2CliCommands`) seconds after
98
+ * (`maybeSeedCapabilitySkills` / `maybeSeedCliCommandCards`) seconds after
90
99
  * boot, but the platform pushes `vellum:assistant_api_key` (the credential the
91
100
  * managed Gemini embedding backend needs) tens of seconds later. The seed's
92
101
  * `embedWithBackend` call throws `EmbeddingBackendUnavailableError` before the
@@ -132,11 +141,15 @@ export async function maybeReseedCapabilitiesAfterManagedCredential(
132
141
  config: AssistantConfig,
133
142
  opts: { reseedTimeoutMs?: number } = {},
134
143
  ): Promise<void> {
135
- if (!usesConceptPageMemory(config.memory)) return;
144
+ if (!usesConceptPageMemory(config.memory)) {
145
+ return;
146
+ }
136
147
 
137
148
  const { hasManagedProxyPrereqs } =
138
- await import("../../../../../providers/platform-proxy/context.js");
139
- if (!(await hasManagedProxyPrereqs())) return;
149
+ await import("../../../../providers/platform-proxy/context.js");
150
+ if (!(await hasManagedProxyPrereqs())) {
151
+ return;
152
+ }
140
153
 
141
154
  // The managed credential has just landed, so the embedding backend is now
142
155
  // reachable. Retry the embedding-identity reconcile to close the
@@ -151,7 +164,7 @@ export async function maybeReseedCapabilitiesAfterManagedCredential(
151
164
  // never rejects the detached caller.
152
165
  try {
153
166
  const { reconcileEmbeddingIdentity } =
154
- await import("../../../../../daemon/embedding-reconcile.js");
167
+ await import("../../../../daemon/embedding-reconcile.js");
155
168
  await reconcileEmbeddingIdentity(config);
156
169
  } catch (err) {
157
170
  log.warn(
@@ -204,13 +217,15 @@ export async function maybeReseedCapabilitiesAfterManagedCredential(
204
217
  // Resolve the gate + enqueuer once and reuse for the post-barrier enqueue and
205
218
  // the straggler re-enqueue below.
206
219
  const { isMemoryV3Live } =
207
- await import("../../../../../config/memory-v3-gate.js");
220
+ await import("../../../../config/memory-v3-gate.js");
208
221
  const v3Live = isMemoryV3Live(config);
209
222
  const enqueueMaintain = async (): Promise<void> => {
210
- if (!v3Live) return;
223
+ if (!v3Live) {
224
+ return;
225
+ }
211
226
  try {
212
227
  const { enqueueMemoryJob } =
213
- await import("../../../../../persistence/jobs-store.js");
228
+ await import("../../../../persistence/jobs-store.js");
214
229
  enqueueMemoryJob("memory_v3_maintain", {});
215
230
  } catch (err) {
216
231
  log.warn(
@@ -244,7 +259,7 @@ export async function maybeReseedCapabilitiesAfterManagedCredential(
244
259
  * length), then re-seed the v2 skill entries so any skills written during
245
260
  * cold start with the legacy TF encoder get rewritten with stemmed BM25
246
261
  * vectors. The cold-start window exists because the very first
247
- * `maybeSeedMemoryV2Skills` call can race ahead of the corpus-stats build —
262
+ * `maybeSeedCapabilitySkills` call can race ahead of the corpus-stats build —
248
263
  * `skill-store.runSeedOnce` falls back to `generateSparseEmbedding` while
249
264
  * `getConceptPageCorpusStats()` is still `null`, leaving stored skill
250
265
  * sparse vectors in a different hash space than the BM25 query vectors
@@ -260,7 +275,9 @@ export async function maybeReseedCapabilitiesAfterManagedCredential(
260
275
  export async function rebuildBm25CorpusStatsAndReseedSkills(
261
276
  config: AssistantConfig,
262
277
  ): Promise<void> {
263
- if (!usesConceptPageMemory(config.memory)) return;
278
+ if (!usesConceptPageMemory(config.memory)) {
279
+ return;
280
+ }
264
281
 
265
282
  try {
266
283
  const { rebuildConceptPageCorpusStats } = await import("./sparse-bm25.js");
@@ -323,10 +340,12 @@ export async function rebuildBm25CorpusStatsAndReseedSkills(
323
340
  * worker drains its first batch; the body is wrapped in try/catch so a v2
324
341
  * failure never blocks startup.
325
342
  */
326
- export async function maybeRebuildMemoryV2Concepts(
343
+ export async function maybeRebuildConceptCollection(
327
344
  config: AssistantConfig,
328
345
  ): Promise<void> {
329
- if (!usesConceptPageMemory(config.memory)) return;
346
+ if (!usesConceptPageMemory(config.memory)) {
347
+ return;
348
+ }
330
349
 
331
350
  try {
332
351
  const {
@@ -336,7 +355,7 @@ export async function maybeRebuildMemoryV2Concepts(
336
355
  } = await import("./qdrant.js");
337
356
  const { hasConceptPages } = await import("./page-store.js");
338
357
  const { enqueueMemoryJob, hasActiveJobOfType } =
339
- await import("../../../../../persistence/jobs-store.js");
358
+ await import("../../../../persistence/jobs-store.js");
340
359
 
341
360
  const { migrated } = await ensureConceptPageCollection();
342
361