@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -5,11 +5,9 @@
5
5
  * embedding backend, Qdrant client, activation pipeline) mocked at the
6
6
  * module level so the suite never starts a real Qdrant/embedding backend.
7
7
  *
8
- * Coverage matrix (PR 21 acceptance criteria):
8
+ * Coverage matrix:
9
9
  * - migrate: wraps `runMemoryV2Migration`; force flag propagates;
10
10
  * `MigrationAlreadyAppliedError` is swallowed (no rethrow).
11
- * - rebuild-edges: every page's `edges:` frontmatter matches `edges.json`;
12
- * `ref_files` is preserved; pages without edges get `edges: []`.
13
11
  * - reembed: enqueues `N + 4` jobs (concept-page slugs plus four reserved
14
12
  * meta-file slugs).
15
13
  * - activation-recompute: walks conversations with rows, runs the pipeline
@@ -206,15 +204,13 @@ const { getDb, resetDb } = await import("../../db-connection.js");
206
204
  const { initializeDb } = await import("../../db-init.js");
207
205
  const { rawExec } = await import("../../raw-query.js");
208
206
  const { conversations, memoryJobs, messages } = await import("../../schema.js");
209
- const { readPage, writePage } = await import("../page-store.js");
210
- const { writeEdges } = await import("../edges.js");
207
+ const { writePage } = await import("../page-store.js");
211
208
  const { save: saveActivation, hydrate: hydrateActivation } =
212
209
  await import("../activation-store.js");
213
210
  const {
214
211
  META_FILE_SLUGS,
215
212
  memoryV2ActivationRecomputeJob,
216
213
  memoryV2MigrateJob,
217
- memoryV2RebuildEdgesJob,
218
214
  memoryV2ReembedJob,
219
215
  } = await import("../backfill-jobs.js");
220
216
 
@@ -230,7 +226,6 @@ const TEST_CONFIG = STUB_RUNTIME_CONFIG as Parameters<
230
226
  function makeJob(
231
227
  type:
232
228
  | "memory_v2_migrate"
233
- | "memory_v2_rebuild_edges"
234
229
  | "memory_v2_reembed"
235
230
  | "memory_v2_activation_recompute",
236
231
  payload: Record<string, unknown> = {},
@@ -271,9 +266,6 @@ beforeEach(() => {
271
266
  force: true,
272
267
  });
273
268
  mkdirSync(join(tmpWorkspace, "memory", "concepts"), { recursive: true });
274
- if (existsSync(join(tmpWorkspace, "memory", "edges.json"))) {
275
- rmSync(join(tmpWorkspace, "memory", "edges.json"));
276
- }
277
269
  for (const filename of [
278
270
  "essentials.md",
279
271
  "threads.md",
@@ -325,125 +317,6 @@ describe("memoryV2MigrateJob", () => {
325
317
  });
326
318
  });
327
319
 
328
- // ---------------------------------------------------------------------------
329
- // memoryV2RebuildEdgesJob
330
- // ---------------------------------------------------------------------------
331
-
332
- describe("memoryV2RebuildEdgesJob", () => {
333
- test("rewrites every page's edges: frontmatter from edges.json", async () => {
334
- // Two pages with stale frontmatter — neither matches `edges.json`.
335
- await writePage(tmpWorkspace, {
336
- slug: "alice",
337
- frontmatter: { edges: ["stale"], ref_files: ["alice.png"] },
338
- body: "Alice prefers VS Code.\n",
339
- });
340
- await writePage(tmpWorkspace, {
341
- slug: "bob",
342
- frontmatter: { edges: [], ref_files: [] },
343
- body: "Bob uses zsh.\n",
344
- });
345
- await writeEdges(tmpWorkspace, {
346
- version: 1,
347
- edges: [["alice", "bob"]],
348
- });
349
-
350
- await memoryV2RebuildEdgesJob(
351
- makeJob("memory_v2_rebuild_edges"),
352
- TEST_CONFIG,
353
- );
354
-
355
- const alice = await readPage(tmpWorkspace, "alice");
356
- const bob = await readPage(tmpWorkspace, "bob");
357
- expect(alice?.frontmatter.edges).toEqual(["bob"]);
358
- expect(bob?.frontmatter.edges).toEqual(["alice"]);
359
-
360
- // ref_files is preserved as-is — page is the source of truth there.
361
- expect(alice?.frontmatter.ref_files).toEqual(["alice.png"]);
362
- // Body is preserved.
363
- expect(alice?.body).toBe("Alice prefers VS Code.\n");
364
- });
365
-
366
- test("sets edges: [] for pages without any edges in edges.json", async () => {
367
- await writePage(tmpWorkspace, {
368
- slug: "orphan",
369
- frontmatter: { edges: ["should-be-removed"], ref_files: [] },
370
- body: "Orphan content.\n",
371
- });
372
- await writeEdges(tmpWorkspace, { version: 1, edges: [] });
373
-
374
- await memoryV2RebuildEdgesJob(
375
- makeJob("memory_v2_rebuild_edges"),
376
- TEST_CONFIG,
377
- );
378
-
379
- const orphan = await readPage(tmpWorkspace, "orphan");
380
- expect(orphan?.frontmatter.edges).toEqual([]);
381
- });
382
-
383
- test("emits sorted neighbor lists (deterministic across reruns)", async () => {
384
- await writePage(tmpWorkspace, {
385
- slug: "alice",
386
- frontmatter: { edges: [], ref_files: [] },
387
- body: "Body.\n",
388
- });
389
- await writePage(tmpWorkspace, {
390
- slug: "bob",
391
- frontmatter: { edges: [], ref_files: [] },
392
- body: "Body.\n",
393
- });
394
- await writePage(tmpWorkspace, {
395
- slug: "carol",
396
- frontmatter: { edges: [], ref_files: [] },
397
- body: "Body.\n",
398
- });
399
- await writeEdges(tmpWorkspace, {
400
- version: 1,
401
- edges: [
402
- ["alice", "carol"],
403
- ["alice", "bob"],
404
- ],
405
- });
406
-
407
- await memoryV2RebuildEdgesJob(
408
- makeJob("memory_v2_rebuild_edges"),
409
- TEST_CONFIG,
410
- );
411
-
412
- const alice = await readPage(tmpWorkspace, "alice");
413
- expect(alice?.frontmatter.edges).toEqual(["bob", "carol"]);
414
- });
415
-
416
- test("is a no-op for pages whose frontmatter is already correct", async () => {
417
- // Pre-write the page with the correct edges so the handler should leave
418
- // it untouched. We can't easily observe "no rewrite happened" from the
419
- // outside without instrumenting writePage, but the handler returning
420
- // without error is enough to cover the early-exit branch.
421
- await writePage(tmpWorkspace, {
422
- slug: "alice",
423
- frontmatter: { edges: ["bob"], ref_files: [] },
424
- body: "Alice.\n",
425
- });
426
- await writePage(tmpWorkspace, {
427
- slug: "bob",
428
- frontmatter: { edges: ["alice"], ref_files: [] },
429
- body: "Bob.\n",
430
- });
431
- await writeEdges(tmpWorkspace, {
432
- version: 1,
433
- edges: [["alice", "bob"]],
434
- });
435
-
436
- await memoryV2RebuildEdgesJob(
437
- makeJob("memory_v2_rebuild_edges"),
438
- TEST_CONFIG,
439
- );
440
-
441
- expect((await readPage(tmpWorkspace, "alice"))?.frontmatter.edges).toEqual([
442
- "bob",
443
- ]);
444
- });
445
- });
446
-
447
320
  // ---------------------------------------------------------------------------
448
321
  // memoryV2ReembedJob
449
322
  // ---------------------------------------------------------------------------
@@ -136,10 +136,13 @@ const { CUTOFF_PLACEHOLDER, CONSOLIDATION_PROMPT } =
136
136
  await import("../prompts/consolidation.js");
137
137
 
138
138
  // `isAssistantFeatureFlagEnabled` ignores the `config` argument it receives
139
- // (resolution is purely from the overrides + registry caches), so we hand
140
- // the handler a minimal stand-in instead of materializing the full default
141
- // config.
142
- const CONFIG = {} as Parameters<typeof memoryV2ConsolidateJob>[1];
139
+ // (resolution is purely from the overrides + registry caches), and the
140
+ // resolver only reads `config.memory.v2.consolidation_prompt_path` so a
141
+ // minimal stand-in covers both call sites without materializing the full
142
+ // default config.
143
+ const CONFIG = {
144
+ memory: { v2: { consolidation_prompt_path: null } },
145
+ } as Parameters<typeof memoryV2ConsolidateJob>[1];
143
146
 
144
147
  function makeJob(): Parameters<typeof memoryV2ConsolidateJob>[0] {
145
148
  return {
@@ -279,20 +282,34 @@ describe("memoryV2ConsolidateJob — flag on, non-empty buffer", () => {
279
282
  expect(hint).toContain(`${new Date().getFullYear()}`);
280
283
  });
281
284
 
282
- test("enqueues memory_v2_rebuild_edges and memory_v2_reembed follow-up jobs on success", async () => {
285
+ test("honors memory.v2.consolidation_prompt_path override when set", async () => {
286
+ writeFileSync(
287
+ join(tmpWorkspace, "custom-prompt.md"),
288
+ "CUSTOM CONSOLIDATION at {{CUTOFF}}\n",
289
+ );
290
+ const overrideConfig = {
291
+ memory: { v2: { consolidation_prompt_path: "custom-prompt.md" } },
292
+ } as Parameters<typeof memoryV2ConsolidateJob>[1];
293
+
294
+ const result = await memoryV2ConsolidateJob(makeJob(), overrideConfig);
295
+
296
+ expect(result.kind).toBe("invoked");
297
+ const hint = wakeLastArgs?.hint as string;
298
+ expect(hint).toMatch(/^CUSTOM CONSOLIDATION at \d{4}-/);
299
+ expect(hint).not.toContain("You are running memory consolidation");
300
+ expect(hint).not.toContain(CUTOFF_PLACEHOLDER);
301
+ });
302
+
303
+ test("enqueues the memory_v2_reembed follow-up job on success", async () => {
283
304
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
284
305
 
285
306
  expect(result.kind).toBe("invoked");
286
307
  if (result.kind === "invoked") {
287
- expect(result.followUpJobIds).toEqual(["job-1", "job-2"]);
308
+ expect(result.followUpJobIds).toEqual(["job-1"]);
288
309
  }
289
310
 
290
- expect(enqueuedJobs).toHaveLength(2);
311
+ expect(enqueuedJobs).toHaveLength(1);
291
312
  expect(enqueuedJobs[0]).toEqual({
292
- type: "memory_v2_rebuild_edges",
293
- payload: {},
294
- });
295
- expect(enqueuedJobs[1]).toEqual({
296
313
  type: "memory_v2_reembed",
297
314
  payload: {},
298
315
  });
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Tests for `memory/v2/edge-index.ts` — the in-memory directed edge index
3
+ * derived from concept-page frontmatter.
4
+ *
5
+ * Tests live in temp workspaces (mkdtemp) and never touch `~/.vellum/`.
6
+ */
7
+
8
+ import { existsSync, mkdtempSync, rmSync } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
12
+
13
+ import {
14
+ getEdgeIndex,
15
+ getReachable,
16
+ invalidateEdgeIndex,
17
+ totalEdgeCount,
18
+ validateEdgeTargets,
19
+ } from "../edge-index.js";
20
+ import { deletePage, writePage } from "../page-store.js";
21
+ import type { ConceptPage } from "../types.js";
22
+
23
+ let workspaceDir: string;
24
+
25
+ beforeEach(() => {
26
+ workspaceDir = mkdtempSync(join(tmpdir(), "vellum-memory-v2-edge-index-"));
27
+ });
28
+
29
+ afterEach(() => {
30
+ invalidateEdgeIndex();
31
+ if (existsSync(workspaceDir)) {
32
+ rmSync(workspaceDir, { recursive: true, force: true });
33
+ }
34
+ });
35
+
36
+ function makePage(slug: string, edges: string[] = [], body = ""): ConceptPage {
37
+ return {
38
+ slug,
39
+ frontmatter: { edges, ref_files: [] },
40
+ body,
41
+ };
42
+ }
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // getEdgeIndex
46
+ // ---------------------------------------------------------------------------
47
+
48
+ describe("getEdgeIndex", () => {
49
+ test("returns empty maps when no concept pages exist", async () => {
50
+ const idx = await getEdgeIndex(workspaceDir);
51
+ expect(idx.outgoing.size).toBe(0);
52
+ expect(idx.incoming.size).toBe(0);
53
+ });
54
+
55
+ test("derives outgoing and incoming adjacency from page frontmatter", async () => {
56
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
57
+ await writePage(workspaceDir, makePage("bob", ["carol"]));
58
+ await writePage(workspaceDir, makePage("carol"));
59
+
60
+ const idx = await getEdgeIndex(workspaceDir);
61
+
62
+ expect(Array.from(idx.outgoing.get("alice") ?? new Set<string>())).toEqual([
63
+ "bob",
64
+ ]);
65
+ expect(Array.from(idx.outgoing.get("bob") ?? new Set<string>())).toEqual([
66
+ "carol",
67
+ ]);
68
+ expect(idx.outgoing.get("carol")).toBeUndefined();
69
+
70
+ expect(Array.from(idx.incoming.get("bob") ?? new Set<string>())).toEqual([
71
+ "alice",
72
+ ]);
73
+ expect(Array.from(idx.incoming.get("carol") ?? new Set<string>())).toEqual([
74
+ "bob",
75
+ ]);
76
+ expect(idx.incoming.get("alice")).toBeUndefined();
77
+ });
78
+
79
+ test("[A,B] and [B,A] coexist as distinct directed edges", async () => {
80
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
81
+ await writePage(workspaceDir, makePage("bob", ["alice"]));
82
+
83
+ const idx = await getEdgeIndex(workspaceDir);
84
+
85
+ expect(Array.from(idx.outgoing.get("alice") ?? new Set<string>())).toEqual([
86
+ "bob",
87
+ ]);
88
+ expect(Array.from(idx.outgoing.get("bob") ?? new Set<string>())).toEqual([
89
+ "alice",
90
+ ]);
91
+ expect(Array.from(idx.incoming.get("alice") ?? new Set<string>())).toEqual([
92
+ "bob",
93
+ ]);
94
+ expect(Array.from(idx.incoming.get("bob") ?? new Set<string>())).toEqual([
95
+ "alice",
96
+ ]);
97
+ });
98
+
99
+ test("self-loops are dropped silently", async () => {
100
+ await writePage(workspaceDir, makePage("alice", ["alice", "bob"]));
101
+ await writePage(workspaceDir, makePage("bob"));
102
+
103
+ const idx = await getEdgeIndex(workspaceDir);
104
+
105
+ expect(Array.from(idx.outgoing.get("alice") ?? new Set<string>())).toEqual([
106
+ "bob",
107
+ ]);
108
+ expect(idx.incoming.get("alice")).toBeUndefined();
109
+ });
110
+
111
+ test("caches the result across calls within a workspace", async () => {
112
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
113
+ await writePage(workspaceDir, makePage("bob"));
114
+
115
+ const first = await getEdgeIndex(workspaceDir);
116
+ const second = await getEdgeIndex(workspaceDir);
117
+
118
+ // Same instance — module-level cache returns the prior build.
119
+ expect(second).toBe(first);
120
+ });
121
+
122
+ test("writePage invalidates the cache so subsequent reads see fresh state", async () => {
123
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
124
+ await writePage(workspaceDir, makePage("bob"));
125
+
126
+ const before = await getEdgeIndex(workspaceDir);
127
+ expect([...(before.outgoing.get("alice") ?? [])]).toEqual(["bob"]);
128
+
129
+ await writePage(workspaceDir, makePage("alice", ["bob", "carol"]));
130
+ await writePage(workspaceDir, makePage("carol"));
131
+
132
+ const after = await getEdgeIndex(workspaceDir);
133
+ expect(after).not.toBe(before);
134
+ expect(
135
+ Array.from(after.outgoing.get("alice") ?? new Set<string>()).sort(),
136
+ ).toEqual(["bob", "carol"]);
137
+ });
138
+
139
+ test("deletePage invalidates the cache", async () => {
140
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
141
+ await writePage(workspaceDir, makePage("bob"));
142
+
143
+ const before = await getEdgeIndex(workspaceDir);
144
+ expect(before.outgoing.has("alice")).toBe(true);
145
+
146
+ await deletePage(workspaceDir, "alice");
147
+
148
+ const after = await getEdgeIndex(workspaceDir);
149
+ expect(after.outgoing.has("alice")).toBe(false);
150
+ expect(after.incoming.has("bob")).toBe(false);
151
+ });
152
+ });
153
+
154
+ // ---------------------------------------------------------------------------
155
+ // getReachable
156
+ // ---------------------------------------------------------------------------
157
+
158
+ describe("getReachable", () => {
159
+ // Directed graph used across BFS tests:
160
+ //
161
+ // alice → bob → carol → delta
162
+ // ↘
163
+ // echo
164
+ //
165
+ // (orphan: foxtrot)
166
+ async function setupGraph(): Promise<void> {
167
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
168
+ await writePage(workspaceDir, makePage("bob", ["carol", "echo"]));
169
+ await writePage(workspaceDir, makePage("carol", ["delta"]));
170
+ await writePage(workspaceDir, makePage("delta"));
171
+ await writePage(workspaceDir, makePage("echo"));
172
+ await writePage(workspaceDir, makePage("foxtrot"));
173
+ }
174
+
175
+ test("direction='out' walks outgoing edges only", async () => {
176
+ await setupGraph();
177
+ const idx = await getEdgeIndex(workspaceDir);
178
+ expect(getReachable(idx, "alice", 3, "out")).toEqual(
179
+ new Set(["bob", "carol", "echo", "delta"]),
180
+ );
181
+ });
182
+
183
+ test("direction='in' walks incoming edges only", async () => {
184
+ await setupGraph();
185
+ const idx = await getEdgeIndex(workspaceDir);
186
+ expect(getReachable(idx, "delta", 3, "in")).toEqual(
187
+ new Set(["carol", "bob", "alice"]),
188
+ );
189
+ // Going outward from delta yields nothing — it's a sink.
190
+ expect(getReachable(idx, "delta", 5, "out")).toEqual(new Set());
191
+ });
192
+
193
+ test("hops=1 returns immediate neighbors only", async () => {
194
+ await setupGraph();
195
+ const idx = await getEdgeIndex(workspaceDir);
196
+ expect(getReachable(idx, "bob", 1, "out")).toEqual(
197
+ new Set(["carol", "echo"]),
198
+ );
199
+ });
200
+
201
+ test("never includes the start slug", async () => {
202
+ await setupGraph();
203
+ const idx = await getEdgeIndex(workspaceDir);
204
+ expect(getReachable(idx, "bob", 5, "out").has("bob")).toBe(false);
205
+ });
206
+
207
+ test("orphan node returns the empty set", async () => {
208
+ await setupGraph();
209
+ const idx = await getEdgeIndex(workspaceDir);
210
+ expect(getReachable(idx, "foxtrot", 5, "out")).toEqual(new Set());
211
+ expect(getReachable(idx, "foxtrot", 5, "in")).toEqual(new Set());
212
+ });
213
+
214
+ test("hops<=0 returns the empty set without throwing", async () => {
215
+ await setupGraph();
216
+ const idx = await getEdgeIndex(workspaceDir);
217
+ expect(getReachable(idx, "alice", 0, "out")).toEqual(new Set());
218
+ expect(getReachable(idx, "alice", -1, "out")).toEqual(new Set());
219
+ });
220
+
221
+ test("a directed cycle is traversed without infinite-looping", async () => {
222
+ // A → B → A (two distinct directed edges)
223
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
224
+ await writePage(workspaceDir, makePage("bob", ["alice"]));
225
+ const idx = await getEdgeIndex(workspaceDir);
226
+ expect(getReachable(idx, "alice", 5, "out")).toEqual(new Set(["bob"]));
227
+ expect(getReachable(idx, "bob", 5, "out")).toEqual(new Set(["alice"]));
228
+ });
229
+ });
230
+
231
+ // ---------------------------------------------------------------------------
232
+ // validateEdgeTargets
233
+ // ---------------------------------------------------------------------------
234
+
235
+ describe("validateEdgeTargets", () => {
236
+ test("ok=true when every outgoing target has a known slug", async () => {
237
+ await writePage(workspaceDir, makePage("alice", ["bob"]));
238
+ await writePage(workspaceDir, makePage("bob"));
239
+
240
+ const idx = await getEdgeIndex(workspaceDir);
241
+ const result = validateEdgeTargets(idx, new Set(["alice", "bob"]));
242
+ expect(result).toEqual({ ok: true, missing: [] });
243
+ });
244
+
245
+ test("flags outgoing targets that don't correspond to a known slug", async () => {
246
+ await writePage(workspaceDir, makePage("alice", ["ghost", "bob"]));
247
+ await writePage(workspaceDir, makePage("bob", ["phantom"]));
248
+
249
+ const idx = await getEdgeIndex(workspaceDir);
250
+ const result = validateEdgeTargets(idx, new Set(["alice", "bob"]));
251
+
252
+ expect(result.ok).toBe(false);
253
+ expect(result.missing).toEqual([
254
+ { from: "alice", to: "ghost" },
255
+ { from: "bob", to: "phantom" },
256
+ ]);
257
+ });
258
+ });
259
+
260
+ // ---------------------------------------------------------------------------
261
+ // totalEdgeCount
262
+ // ---------------------------------------------------------------------------
263
+
264
+ describe("totalEdgeCount", () => {
265
+ test("returns the sum of every page's outgoing fanout", async () => {
266
+ await writePage(workspaceDir, makePage("alice", ["bob", "carol"]));
267
+ await writePage(workspaceDir, makePage("bob", ["carol"]));
268
+ await writePage(workspaceDir, makePage("carol"));
269
+
270
+ const idx = await getEdgeIndex(workspaceDir);
271
+ expect(totalEdgeCount(idx)).toBe(3);
272
+ });
273
+
274
+ test("returns 0 for an empty graph", async () => {
275
+ const idx = await getEdgeIndex(workspaceDir);
276
+ expect(totalEdgeCount(idx)).toBe(0);
277
+ });
278
+ });