@vellumai/assistant 0.5.15 → 0.6.0

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 (503) hide show
  1. package/ARCHITECTURE.md +3 -3
  2. package/Dockerfile +0 -3
  3. package/docs/architecture/integrations.md +15 -14
  4. package/knip.json +4 -1
  5. package/openapi.yaml +670 -122
  6. package/package.json +1 -1
  7. package/src/__tests__/actor-token-service.test.ts +68 -0
  8. package/src/__tests__/agent-loop.test.ts +0 -32
  9. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  10. package/src/__tests__/anthropic-provider.test.ts +57 -3
  11. package/src/__tests__/app-compiler.test.ts +120 -0
  12. package/src/__tests__/assistant-feature-flags-integration.test.ts +5 -377
  13. package/src/__tests__/call-conversation-messages.test.ts +2 -6
  14. package/src/__tests__/call-domain.test.ts +2 -6
  15. package/src/__tests__/call-pointer-messages.test.ts +2 -14
  16. package/src/__tests__/call-recovery.test.ts +2 -6
  17. package/src/__tests__/call-routes-http.test.ts +2 -6
  18. package/src/__tests__/call-store.test.ts +2 -6
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
  20. package/src/__tests__/canonical-guardian-store.test.ts +2 -6
  21. package/src/__tests__/ces-rpc-credential-backend.test.ts +4 -1
  22. package/src/__tests__/channel-delivery-store.test.ts +2 -6
  23. package/src/__tests__/channel-retry-sweep.test.ts +2 -6
  24. package/src/__tests__/checker.test.ts +84 -3
  25. package/src/__tests__/clawhub.test.ts +54 -24
  26. package/src/__tests__/cli-command-risk-guard.test.ts +108 -6
  27. package/src/__tests__/cli-memory.test.ts +377 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -2
  29. package/src/__tests__/config-schema.test.ts +1 -3
  30. package/src/__tests__/config-set-platform-guard.test.ts +302 -0
  31. package/src/__tests__/config-watcher-feature-flags.test.ts +211 -0
  32. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
  33. package/src/__tests__/contacts-tools.test.ts +31 -0
  34. package/src/__tests__/context-overflow-reducer.test.ts +86 -0
  35. package/src/__tests__/context-token-estimator.test.ts +175 -10
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +9 -0
  37. package/src/__tests__/conversation-agent-loop.test.ts +9 -0
  38. package/src/__tests__/conversation-attachments.test.ts +2 -6
  39. package/src/__tests__/conversation-attention-store.test.ts +2 -6
  40. package/src/__tests__/conversation-clear-safety.test.ts +2 -6
  41. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
  42. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
  43. package/src/__tests__/conversation-disk-view.test.ts +2 -6
  44. package/src/__tests__/conversation-error.test.ts +33 -2
  45. package/src/__tests__/conversation-fork-crud.test.ts +2 -6
  46. package/src/__tests__/conversation-history-web-search.test.ts +5 -0
  47. package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
  48. package/src/__tests__/conversation-media-retry.test.ts +91 -0
  49. package/src/__tests__/conversation-runtime-assembly.test.ts +7 -4
  50. package/src/__tests__/conversation-slash-commands.test.ts +2 -6
  51. package/src/__tests__/conversation-starter-routes.test.ts +20 -11
  52. package/src/__tests__/conversation-store.test.ts +2 -6
  53. package/src/__tests__/conversation-usage.test.ts +3 -6
  54. package/src/__tests__/conversation-wipe.test.ts +11 -408
  55. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  56. package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
  57. package/src/__tests__/credential-security-e2e.test.ts +6 -1
  58. package/src/__tests__/docker-signing-key-bootstrap.test.ts +7 -73
  59. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -7
  60. package/src/__tests__/followup-tools.test.ts +2 -6
  61. package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
  62. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
  63. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
  64. package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
  65. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
  66. package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
  67. package/src/__tests__/guardian-action-store.test.ts +2 -6
  68. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
  69. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
  70. package/src/__tests__/guardian-dispatch.test.ts +2 -6
  71. package/src/__tests__/guardian-grant-minting.test.ts +2 -14
  72. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
  73. package/src/__tests__/guardian-routing-invariants.test.ts +343 -6
  74. package/src/__tests__/guardian-routing-state.test.ts +2 -6
  75. package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
  76. package/src/__tests__/heartbeat-service.test.ts +1 -3
  77. package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
  78. package/src/__tests__/injection-block.test.ts +154 -0
  79. package/src/__tests__/install-meta.test.ts +506 -0
  80. package/src/__tests__/install-skill-routing.test.ts +292 -0
  81. package/src/__tests__/intent-routing.test.ts +6 -18
  82. package/src/__tests__/invite-redemption-service.test.ts +2 -6
  83. package/src/__tests__/invite-routes-http.test.ts +2 -6
  84. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -14
  85. package/src/__tests__/list-messages-attachments.test.ts +2 -6
  86. package/src/__tests__/llm-context-route-provider.test.ts +2 -6
  87. package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
  88. package/src/__tests__/llm-usage-store.test.ts +2 -6
  89. package/src/__tests__/log-export-workspace.test.ts +4 -34
  90. package/src/__tests__/managed-skill-lifecycle.test.ts +7 -37
  91. package/src/__tests__/managed-store.test.ts +40 -21
  92. package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
  93. package/src/__tests__/memory-recall-log-store.test.ts +2 -6
  94. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
  95. package/src/__tests__/messaging-send-tool.test.ts +6 -6
  96. package/src/__tests__/migration-cross-version-compatibility.test.ts +1 -29
  97. package/src/__tests__/migration-export-http.test.ts +3 -34
  98. package/src/__tests__/migration-import-commit-http.test.ts +1 -29
  99. package/src/__tests__/migration-import-preflight-http.test.ts +3 -34
  100. package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +2 -1
  101. package/src/__tests__/non-member-access-request.test.ts +2 -6
  102. package/src/__tests__/notification-guardian-path.test.ts +2 -6
  103. package/src/__tests__/oauth-apps-routes.test.ts +120 -10
  104. package/src/__tests__/oauth-cli.test.ts +364 -2
  105. package/src/__tests__/oauth-connect-orchestrator.test.ts +709 -0
  106. package/src/__tests__/oauth-provider-serializer.test.ts +2 -1
  107. package/src/__tests__/oauth-provider-visibility.test.ts +149 -0
  108. package/src/__tests__/oauth-providers-routes.test.ts +5 -2
  109. package/src/__tests__/oauth-store.test.ts +0 -5
  110. package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
  111. package/src/__tests__/outlook-attachments.test.ts +301 -0
  112. package/src/__tests__/outlook-automation-tools.test.ts +425 -0
  113. package/src/__tests__/outlook-categories.test.ts +212 -0
  114. package/src/__tests__/outlook-client-automation.test.ts +246 -0
  115. package/src/__tests__/outlook-compose-tools.test.ts +325 -0
  116. package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
  117. package/src/__tests__/outlook-email-watcher.test.ts +322 -0
  118. package/src/__tests__/outlook-follow-up.test.ts +196 -0
  119. package/src/__tests__/outlook-messaging-provider.test.ts +1071 -0
  120. package/src/__tests__/outlook-trash.test.ts +77 -0
  121. package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
  122. package/src/__tests__/path-policy.test.ts +2 -17
  123. package/src/__tests__/permission-types.test.ts +0 -1
  124. package/src/__tests__/platform-callback-registration.test.ts +7 -11
  125. package/src/__tests__/playbook-execution.test.ts +76 -80
  126. package/src/__tests__/playbook-tools.test.ts +5 -7
  127. package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
  128. package/src/__tests__/provider-error-scenarios.test.ts +21 -2
  129. package/src/__tests__/qdrant-manager.test.ts +68 -21
  130. package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
  131. package/src/__tests__/registry.test.ts +2 -2
  132. package/src/__tests__/require-fresh-approval.test.ts +64 -3
  133. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
  134. package/src/__tests__/runtime-events-sse.test.ts +2 -6
  135. package/src/__tests__/sandbox-diagnostics.test.ts +20 -29
  136. package/src/__tests__/scaffold-managed-skill-tool.test.ts +2 -10
  137. package/src/__tests__/schedule-store.test.ts +2 -6
  138. package/src/__tests__/schedule-tools.test.ts +2 -6
  139. package/src/__tests__/scheduler-recurrence.test.ts +1 -5
  140. package/src/__tests__/scoped-approval-grants.test.ts +2 -6
  141. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
  142. package/src/__tests__/search-skills-unified.test.ts +421 -0
  143. package/src/__tests__/secret-allowlist.test.ts +20 -35
  144. package/src/__tests__/secret-onetime-send.test.ts +2 -0
  145. package/src/__tests__/send-endpoint-busy.test.ts +2 -6
  146. package/src/__tests__/sequence-store.test.ts +2 -6
  147. package/src/__tests__/server-history-render.test.ts +2 -6
  148. package/src/__tests__/shell-credential-ref.test.ts +0 -5
  149. package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
  150. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  151. package/src/__tests__/skill-load-feature-flag.test.ts +13 -54
  152. package/src/__tests__/skill-load-inline-command.test.ts +3 -65
  153. package/src/__tests__/skill-load-inline-includes.test.ts +3 -65
  154. package/src/__tests__/skill-load-tool.test.ts +3 -67
  155. package/src/__tests__/skill-memory.test.ts +480 -195
  156. package/src/__tests__/skills-uninstall.test.ts +2 -2
  157. package/src/__tests__/skills.test.ts +23 -50
  158. package/src/__tests__/slack-channel-config.test.ts +2 -21
  159. package/src/__tests__/slack-inbound-verification.test.ts +2 -6
  160. package/src/__tests__/starter-bundle.test.ts +2 -8
  161. package/src/__tests__/stt-hints.test.ts +7 -2
  162. package/src/__tests__/system-prompt.test.ts +25 -45
  163. package/src/__tests__/task-compiler.test.ts +2 -27
  164. package/src/__tests__/task-management-tools.test.ts +2 -27
  165. package/src/__tests__/task-memory-cleanup.test.ts +173 -250
  166. package/src/__tests__/task-runner.test.ts +2 -27
  167. package/src/__tests__/task-scheduler.test.ts +2 -27
  168. package/src/__tests__/terminal-tools.test.ts +1 -17
  169. package/src/__tests__/test-preload.ts +3 -0
  170. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +0 -79
  171. package/src/__tests__/tool-approval-handler.test.ts +4 -27
  172. package/src/__tests__/tool-execution-abort-cleanup.test.ts +2 -11
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -25
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  175. package/src/__tests__/tool-executor.test.ts +0 -1
  176. package/src/__tests__/tool-grant-request-escalation.test.ts +4 -27
  177. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -20
  178. package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
  179. package/src/__tests__/trust-store.test.ts +10 -42
  180. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -30
  181. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +3 -27
  182. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -28
  183. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -28
  184. package/src/__tests__/trusted-contact-verification.test.ts +2 -28
  185. package/src/__tests__/turn-boundary-resolution.test.ts +2 -34
  186. package/src/__tests__/twilio-provider.test.ts +0 -16
  187. package/src/__tests__/twilio-routes-twiml.test.ts +7 -12
  188. package/src/__tests__/twilio-routes.test.ts +0 -24
  189. package/src/__tests__/update-bulletin.test.ts +17 -89
  190. package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -26
  191. package/src/__tests__/usage-routes.test.ts +2 -27
  192. package/src/__tests__/user-reference.test.ts +1 -5
  193. package/src/__tests__/vbundle-pax-and-symlink.test.ts +4 -34
  194. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +2 -53
  195. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  196. package/src/__tests__/voice-invite-redemption.test.ts +2 -27
  197. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -30
  198. package/src/__tests__/voice-session-bridge.test.ts +2 -27
  199. package/src/__tests__/volume-security-guard.test.ts +2 -0
  200. package/src/__tests__/workspace-lifecycle.test.ts +29 -1
  201. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -29
  202. package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +2 -2
  203. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +4 -29
  204. package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
  205. package/src/__tests__/workspace-migration-down-functions.test.ts +0 -6
  206. package/src/__tests__/workspace-policy.test.ts +1 -1
  207. package/src/acp/client-handler.ts +1 -2
  208. package/src/agent/attachments.ts +7 -2
  209. package/src/agent/image-optimize.ts +165 -0
  210. package/src/agent/loop.ts +1 -15
  211. package/src/bundler/app-compiler.ts +179 -2
  212. package/src/bundler/package-resolver.ts +3 -5
  213. package/src/cli/__tests__/notifications.test.ts +1 -24
  214. package/src/cli/cli-memory.ts +179 -0
  215. package/src/cli/commands/avatar.ts +3 -3
  216. package/src/cli/commands/config.ts +26 -13
  217. package/src/cli/commands/doctor.ts +2 -2
  218. package/src/cli/commands/memory.ts +41 -55
  219. package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
  220. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
  221. package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
  222. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
  223. package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
  224. package/src/cli/commands/oauth/connect.ts +26 -6
  225. package/src/cli/commands/oauth/mode.ts +7 -0
  226. package/src/cli/commands/oauth/providers.ts +49 -42
  227. package/src/cli/commands/oauth/shared.ts +39 -3
  228. package/src/cli/commands/platform/__tests__/connect.test.ts +3 -49
  229. package/src/cli/commands/platform/__tests__/disconnect.test.ts +3 -49
  230. package/src/cli/commands/platform/__tests__/status.test.ts +5 -55
  231. package/src/cli/commands/platform/index.ts +16 -16
  232. package/src/cli/commands/skills.ts +88 -16
  233. package/src/cli/commands/trust.ts +2 -2
  234. package/src/cli/lib/daemon-credential-client.ts +2 -3
  235. package/src/config/bundled-skills/acp/TOOLS.json +1 -1
  236. package/src/config/bundled-skills/computer-use/TOOLS.json +7 -7
  237. package/src/config/bundled-skills/contacts/SKILL.md +0 -1
  238. package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
  239. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
  240. package/src/config/bundled-skills/gmail/SKILL.md +2 -10
  241. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
  242. package/src/config/bundled-skills/messaging/SKILL.md +26 -19
  243. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
  244. package/src/config/bundled-skills/outlook/SKILL.md +189 -0
  245. package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
  246. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
  247. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
  248. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
  249. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
  250. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
  251. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
  252. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
  253. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
  254. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
  255. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
  256. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
  257. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
  258. package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
  259. package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
  260. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
  261. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
  262. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
  263. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
  264. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
  265. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
  266. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
  267. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
  268. package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
  269. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
  270. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
  271. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
  272. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
  273. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  274. package/src/config/bundled-skills/slack/SKILL.md +1 -7
  275. package/src/config/bundled-tool-registry.ts +56 -4
  276. package/src/config/env-registry.ts +15 -8
  277. package/src/config/feature-flag-registry.json +29 -116
  278. package/src/config/loader.ts +4 -0
  279. package/src/config/schemas/platform.ts +8 -0
  280. package/src/config/schemas/security.ts +0 -6
  281. package/src/config/schemas/services.ts +8 -0
  282. package/src/config/schemas/timeouts.ts +1 -1
  283. package/src/config/skills.ts +18 -7
  284. package/src/context/token-estimator.ts +25 -18
  285. package/src/context/window-manager.ts +32 -9
  286. package/src/credential-execution/approval-bridge.ts +0 -1
  287. package/src/credential-execution/process-manager.ts +3 -1
  288. package/src/daemon/config-watcher.ts +51 -0
  289. package/src/daemon/context-overflow-reducer.ts +46 -2
  290. package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
  291. package/src/daemon/conversation-agent-loop.ts +99 -63
  292. package/src/daemon/conversation-error.ts +31 -8
  293. package/src/daemon/conversation-lifecycle.ts +33 -0
  294. package/src/daemon/conversation-media-retry.ts +85 -7
  295. package/src/daemon/conversation-notifiers.ts +4 -1
  296. package/src/daemon/conversation-process.ts +1 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +5 -0
  298. package/src/daemon/conversation-usage.ts +1 -0
  299. package/src/daemon/conversation.ts +41 -2
  300. package/src/daemon/daemon-control.ts +8 -2
  301. package/src/daemon/handlers/shared.ts +22 -12
  302. package/src/daemon/handlers/skills.ts +423 -201
  303. package/src/daemon/lifecycle.ts +52 -4
  304. package/src/daemon/main.ts +5 -1
  305. package/src/daemon/message-types/conversations.ts +5 -1
  306. package/src/daemon/message-types/messages.ts +3 -1
  307. package/src/daemon/message-types/skills.ts +97 -36
  308. package/src/daemon/providers-setup.ts +7 -0
  309. package/src/daemon/server.ts +35 -22
  310. package/src/daemon/tool-side-effects.ts +27 -5
  311. package/src/events/domain-events.ts +1 -2
  312. package/src/heartbeat/heartbeat-service.ts +1 -0
  313. package/src/hooks/cli.ts +2 -2
  314. package/src/hooks/runner.ts +15 -38
  315. package/src/inbound/platform-callback-registration.ts +14 -14
  316. package/src/memory/admin.ts +11 -45
  317. package/src/memory/conversation-bootstrap.ts +2 -0
  318. package/src/memory/conversation-crud.ts +242 -348
  319. package/src/memory/conversation-group-migration.ts +157 -0
  320. package/src/memory/conversation-queries.ts +4 -2
  321. package/src/memory/db-init.ts +39 -3
  322. package/src/memory/embed.ts +73 -0
  323. package/src/memory/embedding-backend.ts +8 -14
  324. package/src/memory/embedding-runtime-manager.ts +12 -114
  325. package/src/memory/fingerprint.ts +2 -2
  326. package/src/memory/graph/bootstrap.ts +512 -0
  327. package/src/memory/graph/capability-seed.ts +297 -0
  328. package/src/memory/graph/consolidation.ts +691 -0
  329. package/src/memory/graph/conversation-graph-memory.ts +630 -0
  330. package/src/memory/graph/decay.test.ts +208 -0
  331. package/src/memory/graph/decay.ts +195 -0
  332. package/src/memory/graph/extraction-job.ts +69 -0
  333. package/src/memory/graph/extraction.test.ts +936 -0
  334. package/src/memory/graph/extraction.ts +1254 -0
  335. package/src/memory/graph/graph-search.ts +266 -0
  336. package/src/memory/graph/image-ref-utils.ts +29 -0
  337. package/src/memory/graph/injection.test.ts +513 -0
  338. package/src/memory/graph/injection.ts +439 -0
  339. package/src/memory/graph/inspect.ts +534 -0
  340. package/src/memory/graph/narrative.ts +267 -0
  341. package/src/memory/graph/pattern-scan.ts +269 -0
  342. package/src/memory/graph/retriever.ts +1008 -0
  343. package/src/memory/graph/scoring.test.ts +548 -0
  344. package/src/memory/graph/scoring.ts +232 -0
  345. package/src/memory/graph/serendipity.ts +65 -0
  346. package/src/memory/graph/store.test.ts +1050 -0
  347. package/src/memory/graph/store.ts +699 -0
  348. package/src/memory/graph/tool-handlers.ts +426 -0
  349. package/src/memory/graph/tools.ts +141 -0
  350. package/src/memory/graph/triggers.test.ts +487 -0
  351. package/src/memory/graph/triggers.ts +223 -0
  352. package/src/memory/graph/types.ts +271 -0
  353. package/src/memory/group-crud.ts +191 -0
  354. package/src/memory/indexer.ts +37 -19
  355. package/src/memory/job-handlers/cleanup.ts +0 -53
  356. package/src/memory/job-handlers/conversation-starters.ts +91 -53
  357. package/src/memory/job-handlers/embedding.test.ts +3 -27
  358. package/src/memory/job-handlers/embedding.ts +5 -31
  359. package/src/memory/job-handlers/index-maintenance.ts +23 -11
  360. package/src/memory/job-handlers/summarization.ts +32 -17
  361. package/src/memory/job-utils.ts +1 -1
  362. package/src/memory/jobs-store.ts +50 -70
  363. package/src/memory/jobs-worker.ts +147 -112
  364. package/src/memory/llm-usage-store.ts +35 -2
  365. package/src/memory/message-content.ts +1 -0
  366. package/src/memory/migrations/201-oauth-providers-feature-flag.ts +11 -0
  367. package/src/memory/migrations/202-drop-callback-transport-column.ts +13 -0
  368. package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
  369. package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -0
  370. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
  371. package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
  372. package/src/memory/migrations/index.ts +6 -0
  373. package/src/memory/migrations/registry.ts +8 -0
  374. package/src/memory/qdrant-client.ts +44 -17
  375. package/src/memory/qdrant-manager.ts +26 -5
  376. package/src/memory/schema/index.ts +1 -0
  377. package/src/memory/schema/memory-graph.ts +139 -0
  378. package/src/memory/schema/oauth.ts +1 -1
  379. package/src/memory/search/semantic.ts +47 -91
  380. package/src/memory/slack-thread-store.ts +17 -0
  381. package/src/memory/task-memory-cleanup.ts +28 -50
  382. package/src/messaging/providers/outlook/adapter.ts +200 -0
  383. package/src/messaging/providers/outlook/client.ts +610 -0
  384. package/src/messaging/providers/outlook/types.ts +201 -0
  385. package/src/notifications/adapters/macos.ts +1 -0
  386. package/src/notifications/adapters/slack.ts +1 -1
  387. package/src/notifications/copy-composer.ts +9 -0
  388. package/src/notifications/signal.ts +16 -0
  389. package/src/oauth/__tests__/identity-verifier.test.ts +1 -1
  390. package/src/oauth/connect-orchestrator.ts +10 -3
  391. package/src/oauth/oauth-store.ts +10 -11
  392. package/src/oauth/provider-serializer.ts +3 -0
  393. package/src/oauth/provider-visibility.ts +16 -0
  394. package/src/oauth/seed-providers.ts +50 -17
  395. package/src/permissions/checker.ts +62 -9
  396. package/src/permissions/defaults.ts +4 -4
  397. package/src/permissions/types.ts +2 -4
  398. package/src/permissions/workspace-policy.ts +1 -1
  399. package/src/playbooks/playbook-compiler.ts +19 -18
  400. package/src/playbooks/types.ts +4 -3
  401. package/src/prompts/system-prompt.ts +6 -93
  402. package/src/prompts/templates/UPDATES.md +6 -0
  403. package/src/providers/anthropic/client.ts +47 -19
  404. package/src/providers/gemini/client.ts +1 -1
  405. package/src/providers/openai/client.ts +1 -1
  406. package/src/providers/registry.ts +1 -1
  407. package/src/providers/retry.ts +19 -3
  408. package/src/runtime/actor-trust-resolver.ts +5 -1
  409. package/src/runtime/auth/__tests__/credential-service.test.ts +1 -27
  410. package/src/runtime/auth/__tests__/token-service.test.ts +1 -25
  411. package/src/runtime/auth/route-policy.ts +7 -4
  412. package/src/runtime/guardian-reply-router.ts +10 -2
  413. package/src/runtime/http-server.ts +23 -3
  414. package/src/runtime/middleware/auth.ts +20 -0
  415. package/src/runtime/routes/attachment-routes.test.ts +106 -0
  416. package/src/runtime/routes/attachment-routes.ts +106 -16
  417. package/src/runtime/routes/brain-graph-routes.ts +21 -22
  418. package/src/runtime/routes/btw-routes.ts +8 -0
  419. package/src/runtime/routes/conversation-management-routes.ts +2 -0
  420. package/src/runtime/routes/conversation-query-routes.ts +2 -58
  421. package/src/runtime/routes/conversation-starter-routes.ts +2 -2
  422. package/src/runtime/routes/debug-routes.ts +1 -1
  423. package/src/runtime/routes/global-search-routes.ts +21 -19
  424. package/src/runtime/routes/group-routes.ts +207 -0
  425. package/src/runtime/routes/guardian-action-routes.ts +21 -10
  426. package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
  427. package/src/runtime/routes/inbound-message-handler.ts +19 -0
  428. package/src/runtime/routes/inbound-stages/background-dispatch.ts +43 -2
  429. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
  430. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
  431. package/src/runtime/routes/memory-item-routes.test.ts +2 -31
  432. package/src/runtime/routes/memory-item-routes.ts +385 -341
  433. package/src/runtime/routes/oauth-apps.ts +18 -1
  434. package/src/runtime/routes/oauth-providers.ts +13 -1
  435. package/src/runtime/routes/schedule-routes.ts +2 -0
  436. package/src/runtime/routes/settings-routes.ts +1 -0
  437. package/src/runtime/routes/skills-routes.ts +103 -37
  438. package/src/runtime/routes/usage-routes.ts +19 -2
  439. package/src/runtime/routes/work-items-routes.test.ts +2 -27
  440. package/src/runtime/routes/workspace-routes.test.ts +3 -27
  441. package/src/schedule/scheduler.ts +8 -1
  442. package/src/security/oauth2.ts +1 -1
  443. package/src/security/secret-allowlist.ts +4 -4
  444. package/src/security/secure-keys.ts +4 -8
  445. package/src/shared/provider-env-vars.ts +19 -0
  446. package/src/skills/catalog-cache.ts +5 -0
  447. package/src/skills/catalog-install.ts +15 -14
  448. package/src/skills/clawhub.ts +134 -154
  449. package/src/skills/install-meta.ts +208 -0
  450. package/src/skills/managed-store.ts +27 -16
  451. package/src/skills/skill-memory.ts +210 -96
  452. package/src/skills/skillssh-registry.ts +19 -17
  453. package/src/tasks/task-runner.ts +3 -1
  454. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
  455. package/src/tools/browser/runtime-check.ts +3 -1
  456. package/src/tools/memory/register.ts +63 -46
  457. package/src/tools/permission-checker.ts +7 -19
  458. package/src/tools/shared/filesystem/image-read.ts +22 -85
  459. package/src/tools/skills/skill-script-runner.ts +1 -1
  460. package/src/tools/terminal/safe-env.ts +1 -0
  461. package/src/tools/tool-manifest.ts +3 -3
  462. package/src/util/browser.ts +25 -10
  463. package/src/util/bun-runtime.ts +172 -0
  464. package/src/util/device-id.ts +3 -65
  465. package/src/watcher/providers/outlook-calendar.ts +343 -0
  466. package/src/watcher/providers/outlook.ts +198 -0
  467. package/src/workspace/git-service.ts +27 -6
  468. package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
  469. package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
  470. package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
  471. package/src/workspace/migrations/registry.ts +6 -0
  472. package/src/__tests__/context-memory-e2e.test.ts +0 -415
  473. package/src/__tests__/journal-context.test.ts +0 -268
  474. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
  475. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
  476. package/src/__tests__/memory-query-builder.test.ts +0 -59
  477. package/src/__tests__/memory-recall-quality.test.ts +0 -1046
  478. package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
  479. package/src/__tests__/memory-regressions.test.ts +0 -3696
  480. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
  481. package/src/daemon/conversation-memory.ts +0 -207
  482. package/src/memory/conversation-starters-cadence.ts +0 -74
  483. package/src/memory/items-extractor.ts +0 -860
  484. package/src/memory/job-handlers/batch-extraction.ts +0 -741
  485. package/src/memory/job-handlers/extraction.ts +0 -40
  486. package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -383
  487. package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
  488. package/src/memory/journal-memory.ts +0 -224
  489. package/src/memory/query-builder.ts +0 -47
  490. package/src/memory/query-expansion.ts +0 -83
  491. package/src/memory/retriever.test.ts +0 -1590
  492. package/src/memory/retriever.ts +0 -1323
  493. package/src/memory/search/formatting.test.ts +0 -140
  494. package/src/memory/search/formatting.ts +0 -262
  495. package/src/memory/search/mmr.ts +0 -136
  496. package/src/memory/search/ranking.ts +0 -15
  497. package/src/memory/search/staleness.ts +0 -40
  498. package/src/memory/search/tier-classifier.ts +0 -18
  499. package/src/memory/search/types.ts +0 -121
  500. package/src/prompts/journal-context.ts +0 -156
  501. package/src/tools/memory/definitions.ts +0 -69
  502. package/src/tools/memory/handlers.test.ts +0 -590
  503. package/src/tools/memory/handlers.ts +0 -434
@@ -7,8 +7,6 @@ import {
7
7
  rmSync,
8
8
  writeFileSync,
9
9
  } from "node:fs";
10
- import { mkdtempSync } from "node:fs";
11
- import { tmpdir } from "node:os";
12
10
  import { join } from "node:path";
13
11
  import {
14
12
  afterEach,
@@ -22,12 +20,7 @@ import {
22
20
 
23
21
  import { parse as parseYaml } from "yaml";
24
22
 
25
- let TEST_DIR = "";
26
-
27
- mock.module("../util/platform.js", () => ({
28
- getProtectedDir: () => join(TEST_DIR, "protected"),
29
- getWorkspaceSkillsDir: () => join(TEST_DIR, "skills"),
30
- }));
23
+ const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
31
24
 
32
25
  mock.module("../util/logger.js", () => ({
33
26
  getLogger: () =>
@@ -48,12 +41,11 @@ import {
48
41
  } from "../skills/managed-store.js";
49
42
 
50
43
  beforeEach(() => {
51
- TEST_DIR = mkdtempSync(join(tmpdir(), "managed-store-test-"));
52
44
  mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
53
45
  });
54
46
 
55
47
  afterEach(() => {
56
- rmSync(TEST_DIR, { recursive: true, force: true });
48
+ rmSync(join(TEST_DIR, "skills"), { recursive: true, force: true });
57
49
  });
58
50
 
59
51
  describe("validateManagedSkillId", () => {
@@ -504,9 +496,9 @@ describe("atomic write safety", () => {
504
496
  });
505
497
 
506
498
  const skillDir = join(TEST_DIR, "skills", "atomic-overwrite");
507
- const files = readdirSync(skillDir);
508
- // Only SKILL.md should exist — no .tmp-* leftover files
509
- expect(files).toEqual(["SKILL.md"]);
499
+ const files = readdirSync(skillDir).sort();
500
+ // SKILL.md and install-meta.json should exist — no .tmp-* leftover files
501
+ expect(files).toEqual(["SKILL.md", "install-meta.json"]);
510
502
 
511
503
  const content = readFileSync(join(skillDir, "SKILL.md"), "utf-8");
512
504
  expect(content).toContain('name: "V2"');
@@ -657,7 +649,7 @@ describe("version metadata", () => {
657
649
  expect(readSkillVersion("no-version")).toBeNull();
658
650
  });
659
651
 
660
- test("createManagedSkill writes version.json when version is provided", () => {
652
+ test("createManagedSkill writes install-meta.json when version is provided", () => {
661
653
  createManagedSkill({
662
654
  id: "versioned",
663
655
  name: "Versioned",
@@ -670,7 +662,7 @@ describe("version metadata", () => {
670
662
  expect(version).toBe("v1:abc123");
671
663
  });
672
664
 
673
- test("version.json contains valid JSON with version and installedAt", () => {
665
+ test("install-meta.json contains valid JSON with origin, version, and installedAt", () => {
674
666
  createManagedSkill({
675
667
  id: "version-meta",
676
668
  name: "Meta",
@@ -679,16 +671,43 @@ describe("version metadata", () => {
679
671
  version: "v1:deadbeef",
680
672
  });
681
673
 
682
- const metaPath = join(TEST_DIR, "skills", "version-meta", "version.json");
674
+ const metaPath = join(
675
+ TEST_DIR,
676
+ "skills",
677
+ "version-meta",
678
+ "install-meta.json",
679
+ );
683
680
  expect(existsSync(metaPath)).toBe(true);
684
681
  const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
682
+ expect(meta.origin).toBe("custom");
685
683
  expect(meta.version).toBe("v1:deadbeef");
686
684
  expect(typeof meta.installedAt).toBe("string");
687
685
  // installedAt should be a valid ISO date
688
686
  expect(new Date(meta.installedAt).toISOString()).toBe(meta.installedAt);
689
687
  });
690
688
 
691
- test("overwrite updates version.json", () => {
689
+ test("install-meta.json includes installedBy when contactId is provided", () => {
690
+ createManagedSkill({
691
+ id: "with-contact",
692
+ name: "With Contact",
693
+ description: "Has contactId",
694
+ bodyMarkdown: "Body.",
695
+ contactId: "contact-uuid-456",
696
+ });
697
+
698
+ const metaPath = join(
699
+ TEST_DIR,
700
+ "skills",
701
+ "with-contact",
702
+ "install-meta.json",
703
+ );
704
+ expect(existsSync(metaPath)).toBe(true);
705
+ const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
706
+ expect(meta.origin).toBe("custom");
707
+ expect(meta.installedBy).toBe("contact-uuid-456");
708
+ });
709
+
710
+ test("overwrite updates install-meta.json", () => {
692
711
  createManagedSkill({
693
712
  id: "update-version",
694
713
  name: "V1",
@@ -709,21 +728,21 @@ describe("version metadata", () => {
709
728
  expect(readSkillVersion("update-version")).toBe("v1:second");
710
729
  });
711
730
 
712
- test("readSkillVersion returns null for corrupted version.json", () => {
731
+ test("readSkillVersion returns null for corrupted install-meta.json", () => {
713
732
  createManagedSkill({
714
733
  id: "corrupt-version",
715
734
  name: "Corrupt",
716
- description: "Will corrupt version file",
735
+ description: "Will corrupt meta file",
717
736
  bodyMarkdown: "Body.",
718
737
  version: "v1:valid",
719
738
  });
720
739
 
721
- // Corrupt the version.json
740
+ // Corrupt the install-meta.json
722
741
  const metaPath = join(
723
742
  TEST_DIR,
724
743
  "skills",
725
744
  "corrupt-version",
726
- "version.json",
745
+ "install-meta.json",
727
746
  );
728
747
  writeFileSync(metaPath, "{invalid json!!!", "utf-8");
729
748
 
@@ -34,15 +34,9 @@ mock.module("../memory/jobs-store.js", () => ({
34
34
  deferMemoryJob: () => "deferred",
35
35
  failMemoryJob: () => {},
36
36
  failStalledJobs: () => 0,
37
- enqueueCleanupStaleSupersededItemsJob: () => null,
38
37
  enqueuePruneOldConversationsJob: () => null,
39
38
  }));
40
39
 
41
- // Mock db.js (rawRun used in sweepStaleItems)
42
- mock.module("../memory/db.js", () => ({
43
- rawRun: () => 0,
44
- }));
45
-
46
40
  import {
47
41
  POLL_INTERVAL_MAX_MS,
48
42
  POLL_INTERVAL_MIN_MS,
@@ -90,7 +84,7 @@ describe("memory jobs worker adaptive poll interval", () => {
90
84
  timeoutDelays.push(delay);
91
85
  pendingCallbacks.push(fn);
92
86
  }
93
- return 999 as unknown as ReturnType<typeof setTimeout>;
87
+ return (999 as unknown) as ReturnType<typeof setTimeout>;
94
88
  }) as typeof setTimeout;
95
89
  globalThis.clearTimeout = (() => {}) as typeof clearTimeout;
96
90
 
@@ -129,7 +123,7 @@ describe("memory jobs worker adaptive poll interval", () => {
129
123
 
130
124
  // Should eventually reach the cap
131
125
  expect(timeoutDelays[timeoutDelays.length - 1]).toBe(
132
- POLL_INTERVAL_MAX_MS,
126
+ POLL_INTERVAL_MAX_MS
133
127
  );
134
128
  } finally {
135
129
  globalThis.setTimeout = originalSetTimeout;
@@ -1,4 +1,4 @@
1
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  mock.module("../util/logger.js", () => ({
4
4
  getLogger: () =>
@@ -18,7 +18,7 @@ mock.module("../config/loader.js", () => ({
18
18
  }),
19
19
  }));
20
20
 
21
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
21
+ import { getDb, initializeDb } from "../memory/db.js";
22
22
  import {
23
23
  backfillMemoryRecallLogMessageId,
24
24
  getMemoryRecallLogByMessageIds,
@@ -33,10 +33,6 @@ function resetTables(): void {
33
33
  db.delete(memoryRecallLogs).run();
34
34
  }
35
35
 
36
- afterAll(() => {
37
- resetDb();
38
- });
39
-
40
36
  describe("memory-recall-log-store", () => {
41
37
  beforeEach(() => {
42
38
  resetTables();
@@ -16,7 +16,7 @@
16
16
  * processes and is not tested here.
17
17
  */
18
18
 
19
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
19
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
20
20
 
21
21
  import { eq } from "drizzle-orm";
22
22
 
@@ -59,27 +59,17 @@ mock.module("../config/loader.js", () => ({
59
59
  invalidateConfigCache: () => {},
60
60
  }));
61
61
 
62
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
62
+ import { getDb, initializeDb } from "../memory/db.js";
63
63
  import { indexMessageNow } from "../memory/indexer.js";
64
- import {
65
- conversations,
66
- memoryItems,
67
- memorySegments,
68
- messages,
69
- } from "../memory/schema.js";
64
+ import { conversations, memorySegments, messages } from "../memory/schema.js";
70
65
 
71
66
  // Initialize DB once for the entire file. Each test cleans its own tables.
72
67
  initializeDb();
73
68
 
74
- afterAll(() => {
75
- resetDb();
76
- });
77
-
78
69
  function resetTables() {
79
70
  const db = getDb();
80
- db.run("DELETE FROM memory_item_sources");
81
71
  db.run("DELETE FROM memory_embeddings");
82
- db.run("DELETE FROM memory_items");
72
+ db.run("DELETE FROM memory_graph_nodes");
83
73
  db.run("DELETE FROM memory_segments");
84
74
  db.run("DELETE FROM memory_jobs");
85
75
  db.run("DELETE FROM messages");
@@ -559,101 +549,3 @@ describe("memory segment job atomicity under repeated indexer invocations", () =
559
549
  });
560
550
  });
561
551
 
562
- // ─────────────────────────────────────────────────────────────────────────────
563
- // Test suite: memory_items fingerprint uniqueness under race conditions
564
- // ─────────────────────────────────────────────────────────────────────────────
565
-
566
- describe("memory_items fingerprint uniqueness under race conditions", () => {
567
- beforeEach(() => {
568
- resetTables();
569
- });
570
-
571
- test("duplicate inserts with identical fingerprints produce exactly one row", () => {
572
- // The memory_items table has a unique constraint on (fingerprint, scope_id).
573
- // Two sequential inserts for the same fingerprint simulate duplicate extractor
574
- // runs. Only one INSERT must land; the second must be absorbed by ON CONFLICT.
575
- const db = getDb();
576
- const now = Date.now();
577
- const fingerprint = "fp-race-unique-test-concurrency";
578
- const scopeId = "default";
579
-
580
- // Use raw SQL to replicate what the items-extractor would do when a second
581
- // run tries to INSERT the same fingerprint that already exists.
582
- const raw = (db as unknown as { $client: import("bun:sqlite").Database })
583
- .$client;
584
-
585
- raw.run(`
586
- INSERT INTO memory_items (
587
- id, kind, subject, statement, status, confidence, importance,
588
- fingerprint, verification_state, scope_id, first_seen_at, last_seen_at
589
- ) VALUES (
590
- 'item-race-1', 'preference', 'code style', 'I prefer tabs over spaces.',
591
- 'active', 0.8, 0.6, '${fingerprint}', 'user_reported', '${scopeId}',
592
- ${now}, ${now}
593
- )
594
- `);
595
-
596
- // Second "worker" tries to insert the same fingerprint — must not create a
597
- // duplicate. INSERT OR IGNORE / ON CONFLICT DO NOTHING is the expected
598
- // behavior for the unique constraint.
599
- expect(() => {
600
- raw.run(`
601
- INSERT OR IGNORE INTO memory_items (
602
- id, kind, subject, statement, status, confidence, importance,
603
- fingerprint, verification_state, scope_id, first_seen_at, last_seen_at
604
- ) VALUES (
605
- 'item-race-2', 'preference', 'code style', 'I prefer tabs over spaces.',
606
- 'active', 0.8, 0.6, '${fingerprint}', 'user_reported', '${scopeId}',
607
- ${now + 1}, ${now + 1}
608
- )
609
- `);
610
- }).not.toThrow();
611
-
612
- const rows = db
613
- .select()
614
- .from(memoryItems)
615
- .all()
616
- .filter((r) => r.fingerprint === fingerprint);
617
-
618
- // Only the first insert must have landed.
619
- expect(rows).toHaveLength(1);
620
- expect(rows[0].id).toBe("item-race-1");
621
- });
622
-
623
- test("bare INSERT without IGNORE throws on duplicate fingerprint+scopeId", () => {
624
- // Verify the DB-level unique constraint is actually enforced so that any code
625
- // path that accidentally omits ON CONFLICT will fail loudly rather than silently
626
- // producing inconsistent state.
627
- const db = getDb();
628
- const now = Date.now();
629
- const fingerprint = "fp-constraint-enforcement-test";
630
-
631
- const raw = (db as unknown as { $client: import("bun:sqlite").Database })
632
- .$client;
633
-
634
- raw.run(`
635
- INSERT INTO memory_items (
636
- id, kind, subject, statement, status, confidence, importance,
637
- fingerprint, verification_state, scope_id, first_seen_at, last_seen_at
638
- ) VALUES (
639
- 'item-constraint-a', 'preference', 'editor', 'I use VS Code.',
640
- 'active', 0.9, 0.7, '${fingerprint}', 'user_reported', 'default',
641
- ${now}, ${now}
642
- )
643
- `);
644
-
645
- // A bare INSERT (no ON CONFLICT) for the same fingerprint+scope_id must throw.
646
- expect(() => {
647
- raw.run(`
648
- INSERT INTO memory_items (
649
- id, kind, subject, statement, status, confidence, importance,
650
- fingerprint, verification_state, scope_id, first_seen_at, last_seen_at
651
- ) VALUES (
652
- 'item-constraint-b', 'preference', 'editor', 'I use VS Code.',
653
- 'active', 0.9, 0.7, '${fingerprint}', 'user_reported', 'default',
654
- ${now + 1}, ${now + 1}
655
- )
656
- `);
657
- }).toThrow();
658
- });
659
- });
@@ -64,16 +64,16 @@ const getConversationMock = mock(
64
64
  );
65
65
 
66
66
  const syncMessageToDiskMock = mock(
67
- (
68
- _conversationId: string,
69
- _messageId: string,
70
- _createdAtMs: number,
71
- ) => {},
67
+ (_conversationId: string, _messageId: string, _createdAtMs: number) => {},
72
68
  );
73
69
 
74
70
  const getBindingByChannelChatMock = mock(
75
71
  (_sourceChannel: string, _externalChatId: string) =>
76
- null as { conversationId: string; sourceChannel: string; externalChatId: string } | null,
72
+ null as {
73
+ conversationId: string;
74
+ sourceChannel: string;
75
+ externalChatId: string;
76
+ } | null,
77
77
  );
78
78
 
79
79
  mock.module("../memory/conversation-crud.js", () => ({
@@ -20,19 +20,15 @@
20
20
  import { createHash } from "node:crypto";
21
21
  import {
22
22
  mkdirSync,
23
- mkdtempSync,
24
23
  readdirSync,
25
24
  readFileSync,
26
- realpathSync,
27
25
  rmSync,
28
26
  unlinkSync,
29
27
  writeFileSync,
30
28
  } from "node:fs";
31
- import { tmpdir } from "node:os";
32
29
  import { join } from "node:path";
33
30
  import { gzipSync } from "node:zlib";
34
31
  import {
35
- afterAll,
36
32
  afterEach,
37
33
  beforeAll,
38
34
  beforeEach,
@@ -50,27 +46,11 @@ function toArrayBuffer(data: Uint8Array): ArrayBuffer {
50
46
  ) as ArrayBuffer;
51
47
  }
52
48
 
53
- const testDir = realpathSync(
54
- mkdtempSync(join(tmpdir(), "migration-cross-version-test-")),
55
- );
49
+ const testDir = process.env.VELLUM_WORKSPACE_DIR!;
56
50
  const testDbDir = join(testDir, "data", "db");
57
51
  const testDbPath = join(testDbDir, "assistant.db");
58
52
  const testConfigPath = join(testDir, "config.json");
59
53
 
60
- mock.module("../util/platform.js", () => ({
61
- getProtectedDir: () => join(testDir, "protected"),
62
- getDataDir: () => join(testDir, "data"),
63
- getWorkspaceDir: () => testDir,
64
- getWorkspaceConfigPath: () => testConfigPath,
65
- isMacOS: () => process.platform === "darwin",
66
- isLinux: () => process.platform === "linux",
67
- isWindows: () => process.platform === "win32",
68
- getPidPath: () => join(testDir, "test.pid"),
69
- getDbPath: () => testDbPath,
70
- getLogPath: () => join(testDir, "test.log"),
71
- ensureDataDir: () => {},
72
- }));
73
-
74
54
  mock.module("../util/logger.js", () => ({
75
55
  getLogger: () =>
76
56
  new Proxy({} as Record<string, unknown>, {
@@ -137,14 +117,6 @@ beforeAll(() => {
137
117
  writeFileSync(testConfigPath, JSON.stringify(EXISTING_CONFIG, null, 2));
138
118
  });
139
119
 
140
- afterAll(() => {
141
- try {
142
- rmSync(testDir, { recursive: true });
143
- } catch {
144
- /* best effort */
145
- }
146
- });
147
-
148
120
  // Restore test files before each test
149
121
  beforeEach(() => {
150
122
  mkdirSync(testDbDir, { recursive: true });
@@ -12,39 +12,16 @@
12
12
  * - Integration: existing routes are unaffected by the new endpoint
13
13
  */
14
14
  import { createHash } from "node:crypto";
15
- import {
16
- mkdirSync,
17
- mkdtempSync,
18
- realpathSync,
19
- rmSync,
20
- writeFileSync,
21
- } from "node:fs";
22
- import { tmpdir } from "node:os";
15
+ import { mkdirSync, writeFileSync } from "node:fs";
23
16
  import { join } from "node:path";
24
17
  import { gunzipSync } from "node:zlib";
25
- import { afterAll, beforeAll, describe, expect, mock, test } from "bun:test";
18
+ import { beforeAll, describe, expect, mock, test } from "bun:test";
26
19
 
27
- const testDir = realpathSync(
28
- mkdtempSync(join(tmpdir(), "migration-export-http-test-")),
29
- );
20
+ const testDir = process.env.VELLUM_WORKSPACE_DIR!;
30
21
  const testDbDir = join(testDir, "data", "db");
31
22
  const testDbPath = join(testDbDir, "assistant.db");
32
23
  const testConfigPath = join(testDir, "config.json");
33
24
 
34
- mock.module("../util/platform.js", () => ({
35
- getProtectedDir: () => join(testDir, "protected"),
36
- getDataDir: () => join(testDir, "data"),
37
- getWorkspaceDir: () => testDir,
38
- getWorkspaceConfigPath: () => testConfigPath,
39
- isMacOS: () => process.platform === "darwin",
40
- isLinux: () => process.platform === "linux",
41
- isWindows: () => process.platform === "win32",
42
- getPidPath: () => join(testDir, "test.pid"),
43
- getDbPath: () => testDbPath,
44
- getLogPath: () => join(testDir, "test.log"),
45
- ensureDataDir: () => {},
46
- }));
47
-
48
25
  mock.module("../util/logger.js", () => ({
49
26
  getLogger: () =>
50
27
  new Proxy({} as Record<string, unknown>, {
@@ -101,14 +78,6 @@ beforeAll(() => {
101
78
  writeFileSync(testConfigPath, JSON.stringify(TEST_CONFIG, null, 2));
102
79
  });
103
80
 
104
- afterAll(() => {
105
- try {
106
- rmSync(testDir, { recursive: true });
107
- } catch {
108
- /* best effort */
109
- }
110
- });
111
-
112
81
  // ---------------------------------------------------------------------------
113
82
  // Tar parsing helper (mirrors vbundle-validator's internal parser)
114
83
  // ---------------------------------------------------------------------------
@@ -15,19 +15,15 @@ import { createHash } from "node:crypto";
15
15
  import {
16
16
  existsSync,
17
17
  mkdirSync,
18
- mkdtempSync,
19
18
  readdirSync,
20
19
  readFileSync,
21
- realpathSync,
22
20
  rmSync,
23
21
  unlinkSync,
24
22
  writeFileSync,
25
23
  } from "node:fs";
26
- import { tmpdir } from "node:os";
27
24
  import { join } from "node:path";
28
25
  import { gzipSync } from "node:zlib";
29
26
  import {
30
- afterAll,
31
27
  afterEach,
32
28
  beforeAll,
33
29
  beforeEach,
@@ -45,27 +41,11 @@ function toArrayBuffer(data: Uint8Array): ArrayBuffer {
45
41
  ) as ArrayBuffer;
46
42
  }
47
43
 
48
- const testDir = realpathSync(
49
- mkdtempSync(join(tmpdir(), "migration-import-commit-http-test-")),
50
- );
44
+ const testDir = process.env.VELLUM_WORKSPACE_DIR!;
51
45
  const testDbDir = join(testDir, "data", "db");
52
46
  const testDbPath = join(testDbDir, "assistant.db");
53
47
  const testConfigPath = join(testDir, "config.json");
54
48
 
55
- mock.module("../util/platform.js", () => ({
56
- getProtectedDir: () => join(testDir, "protected"),
57
- getDataDir: () => join(testDir, "data"),
58
- getWorkspaceDir: () => testDir,
59
- getWorkspaceConfigPath: () => testConfigPath,
60
- isMacOS: () => process.platform === "darwin",
61
- isLinux: () => process.platform === "linux",
62
- isWindows: () => process.platform === "win32",
63
- getPidPath: () => join(testDir, "test.pid"),
64
- getDbPath: () => testDbPath,
65
- getLogPath: () => join(testDir, "test.log"),
66
- ensureDataDir: () => {},
67
- }));
68
-
69
49
  mock.module("../util/logger.js", () => ({
70
50
  getLogger: () =>
71
51
  new Proxy({} as Record<string, unknown>, {
@@ -119,14 +99,6 @@ beforeAll(() => {
119
99
  writeFileSync(testConfigPath, JSON.stringify(EXISTING_CONFIG, null, 2));
120
100
  });
121
101
 
122
- afterAll(() => {
123
- try {
124
- rmSync(testDir, { recursive: true });
125
- } catch {
126
- /* best effort */
127
- }
128
- });
129
-
130
102
  // Restore test files before each test so mutations from previous tests
131
103
  // do not leak across test cases.
132
104
  beforeEach(() => {
@@ -11,17 +11,10 @@
11
11
  * - Integration: existing routes are unaffected by the new endpoint
12
12
  */
13
13
  import { createHash } from "node:crypto";
14
- import {
15
- mkdirSync,
16
- mkdtempSync,
17
- realpathSync,
18
- rmSync,
19
- writeFileSync,
20
- } from "node:fs";
21
- import { tmpdir } from "node:os";
14
+ import { mkdirSync, writeFileSync } from "node:fs";
22
15
  import { join } from "node:path";
23
16
  import { gzipSync } from "node:zlib";
24
- import { afterAll, beforeAll, describe, expect, mock, test } from "bun:test";
17
+ import { beforeAll, describe, expect, mock, test } from "bun:test";
25
18
 
26
19
  /** Convert a Uint8Array to an ArrayBuffer for BodyInit compatibility. */
27
20
  function toArrayBuffer(data: Uint8Array): ArrayBuffer {
@@ -31,27 +24,11 @@ function toArrayBuffer(data: Uint8Array): ArrayBuffer {
31
24
  ) as ArrayBuffer;
32
25
  }
33
26
 
34
- const testDir = realpathSync(
35
- mkdtempSync(join(tmpdir(), "migration-import-preflight-http-test-")),
36
- );
27
+ const testDir = process.env.VELLUM_WORKSPACE_DIR!;
37
28
  const testDbDir = join(testDir, "data", "db");
38
29
  const testDbPath = join(testDbDir, "assistant.db");
39
30
  const testConfigPath = join(testDir, "config.json");
40
31
 
41
- mock.module("../util/platform.js", () => ({
42
- getProtectedDir: () => join(testDir, "protected"),
43
- getDataDir: () => join(testDir, "data"),
44
- getWorkspaceDir: () => testDir,
45
- getWorkspaceConfigPath: () => testConfigPath,
46
- isMacOS: () => process.platform === "darwin",
47
- isLinux: () => process.platform === "linux",
48
- isWindows: () => process.platform === "win32",
49
- getPidPath: () => join(testDir, "test.pid"),
50
- getDbPath: () => testDbPath,
51
- getLogPath: () => join(testDir, "test.log"),
52
- ensureDataDir: () => {},
53
- }));
54
-
55
32
  mock.module("../util/logger.js", () => ({
56
33
  getLogger: () =>
57
34
  new Proxy({} as Record<string, unknown>, {
@@ -107,14 +84,6 @@ beforeAll(() => {
107
84
  writeFileSync(testConfigPath, JSON.stringify(EXISTING_CONFIG, null, 2));
108
85
  });
109
86
 
110
- afterAll(() => {
111
- try {
112
- rmSync(testDir, { recursive: true });
113
- } catch {
114
- /* best effort */
115
- }
116
- });
117
-
118
87
  // ---------------------------------------------------------------------------
119
88
  // Tar archive builder helpers (mirrors validate test)
120
89
  // ---------------------------------------------------------------------------
@@ -5,7 +5,8 @@ import { describe, expect, test } from "bun:test";
5
5
  /**
6
6
  * Guard test: domain-specific routing sections must NOT appear in the system
7
7
  * prompt source file. Routing cues now live in skill frontmatter
8
- * (`activation-hints` / `avoid-when`) and are projected into the skills catalog.
8
+ * (`activation-hints` / `avoid-when`) and are seeded as capability memories
9
+ * for semantic discovery.
9
10
  *
10
11
  * If this test fails, you are re-introducing hardcoded routing into the system
11
12
  * prompt. Instead, add `activation-hints` to the skill's SKILL.md frontmatter.
@@ -7,7 +7,7 @@
7
7
  * 3. Create a guardian approval request for the access request
8
8
  * 4. Deduplicate: don't create duplicate requests for repeated messages
9
9
  */
10
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
10
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
11
 
12
12
  // ---------------------------------------------------------------------------
13
13
  // Test isolation: in-memory SQLite via temp directory
@@ -66,17 +66,13 @@ import {
66
66
  listCanonicalGuardianDeliveries,
67
67
  listCanonicalGuardianRequests,
68
68
  } from "../memory/canonical-guardian-store.js";
69
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
69
+ import { getDb, initializeDb } from "../memory/db.js";
70
70
  import { notifyGuardianOfAccessRequest } from "../runtime/access-request-helper.js";
71
71
  import { ensureVellumGuardianBinding } from "../runtime/guardian-vellum-migration.js";
72
72
  import { handleChannelInbound } from "../runtime/routes/channel-routes.js";
73
73
 
74
74
  initializeDb();
75
75
 
76
- afterAll(() => {
77
- resetDb();
78
- });
79
-
80
76
  // ---------------------------------------------------------------------------
81
77
  // Helpers
82
78
  // ---------------------------------------------------------------------------
@@ -5,7 +5,7 @@
5
5
  * pipeline (including conversation-created callbacks) without a custom dispatch path.
6
6
  */
7
7
 
8
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
8
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
9
9
 
10
10
  import type { ConversationCreatedInfo } from "../notifications/broadcaster.js";
11
11
  import type { NotificationDeliveryResult } from "../notifications/types.js";
@@ -80,7 +80,7 @@ import {
80
80
  createPendingQuestion,
81
81
  } from "../calls/call-store.js";
82
82
  import { dispatchGuardianQuestion } from "../calls/guardian-dispatch.js";
83
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
83
+ import { getDb, initializeDb } from "../memory/db.js";
84
84
  import { conversations } from "../memory/schema.js";
85
85
 
86
86
  initializeDb();
@@ -134,10 +134,6 @@ describe("ASK_GUARDIAN canonical notification path", () => {
134
134
  resetTables();
135
135
  });
136
136
 
137
- afterAll(() => {
138
- resetDb();
139
- });
140
-
141
137
  test("dispatches through emitNotificationSignal with guardian context metadata", async () => {
142
138
  const convId = "conv-guardian-notif-1";
143
139
  ensureConversation(convId);