@vellumai/assistant 0.7.2 → 0.7.3

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 (347) hide show
  1. package/ARCHITECTURE.md +16 -1
  2. package/docs/architecture/memory.md +5 -2
  3. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
  4. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
  5. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  6. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  7. package/openapi.yaml +449 -22
  8. package/package.json +1 -1
  9. package/src/__tests__/app-control-flow.test.ts +21 -11
  10. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  11. package/src/__tests__/assistant-event.test.ts +0 -10
  12. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
  13. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
  14. package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
  15. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  16. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  17. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  18. package/src/__tests__/channel-readiness-service.test.ts +4 -2
  19. package/src/__tests__/config-loader-backfill.test.ts +379 -0
  20. package/src/__tests__/config-schema.test.ts +1 -0
  21. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
  22. package/src/__tests__/config-watcher.test.ts +140 -69
  23. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  24. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  25. package/src/__tests__/context-search-fanout.test.ts +0 -1
  26. package/src/__tests__/context-search-memory-source.test.ts +3 -7
  27. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  28. package/src/__tests__/context-search-pkb-source.test.ts +0 -1
  29. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  30. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  31. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  32. package/src/__tests__/conversation-agent-loop.test.ts +454 -5
  33. package/src/__tests__/conversation-error.test.ts +150 -3
  34. package/src/__tests__/conversation-process-callsite.test.ts +43 -0
  35. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  36. package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
  37. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  38. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  39. package/src/__tests__/conversation-store.test.ts +0 -18
  40. package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
  41. package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
  42. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
  43. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  44. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  45. package/src/__tests__/credentials-cli.test.ts +7 -0
  46. package/src/__tests__/cu-unified-flow.test.ts +176 -10
  47. package/src/__tests__/date-context.test.ts +164 -2
  48. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  49. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  50. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  51. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  52. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  53. package/src/__tests__/disk-usage.test.ts +150 -0
  54. package/src/__tests__/events-client-registration.test.ts +52 -0
  55. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  56. package/src/__tests__/file-write-tool.test.ts +4 -10
  57. package/src/__tests__/filing-service.test.ts +3 -4
  58. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  59. package/src/__tests__/heartbeat-service.test.ts +260 -11
  60. package/src/__tests__/host-app-control-proxy.test.ts +195 -25
  61. package/src/__tests__/host-bash-proxy.test.ts +227 -34
  62. package/src/__tests__/host-bash-routes.test.ts +178 -13
  63. package/src/__tests__/host-cu-proxy.test.ts +210 -3
  64. package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
  65. package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
  66. package/src/__tests__/host-file-proxy.test.ts +268 -6
  67. package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
  68. package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
  69. package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
  70. package/src/__tests__/http-user-message-parity.test.ts +107 -1
  71. package/src/__tests__/injector-chain.test.ts +18 -6
  72. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  73. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  74. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  75. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  76. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  77. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  78. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  79. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  80. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  81. package/src/__tests__/openai-provider.test.ts +45 -8
  82. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  83. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  84. package/src/__tests__/platform.test.ts +2 -1
  85. package/src/__tests__/playbook-execution.test.ts +0 -43
  86. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  87. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
  88. package/src/__tests__/provider-tool-name.test.ts +23 -0
  89. package/src/__tests__/relay-server.test.ts +15 -4
  90. package/src/__tests__/runtime-events-sse.test.ts +4 -8
  91. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  92. package/src/__tests__/secret-ingress-http.test.ts +0 -1
  93. package/src/__tests__/suggestion-routes.test.ts +46 -0
  94. package/src/__tests__/twilio-validation.test.ts +2 -2
  95. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  96. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  97. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  98. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
  99. package/src/approvals/guardian-decision-primitive.ts +13 -0
  100. package/src/approvals/guardian-request-resolvers.ts +16 -17
  101. package/src/backup/snapshot-lock.ts +2 -27
  102. package/src/bundler/compiler-tools.ts +3 -2
  103. package/src/calls/call-conversation-messages.ts +46 -10
  104. package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
  105. package/src/cli/commands/bash.ts +35 -108
  106. package/src/cli/commands/contacts.ts +64 -25
  107. package/src/cli/commands/credentials.ts +56 -0
  108. package/src/cli/commands/memory-v2.ts +7 -6
  109. package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
  110. package/src/cli/commands/oauth/connect.ts +127 -1
  111. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
  112. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
  113. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  114. package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
  115. package/src/cli/commands/platform/index.ts +16 -7
  116. package/src/cli/commands/status.ts +57 -0
  117. package/src/cli/program.ts +4 -2
  118. package/src/config/assistant-feature-flags.ts +13 -3
  119. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  120. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
  121. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  122. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  123. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  124. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  125. package/src/config/env.ts +0 -8
  126. package/src/config/feature-flag-registry.json +27 -3
  127. package/src/config/loader.ts +127 -8
  128. package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
  129. package/src/config/schemas/call-site-catalog.ts +14 -0
  130. package/src/config/schemas/channels.ts +0 -5
  131. package/src/config/schemas/heartbeat.ts +1 -1
  132. package/src/config/schemas/llm.ts +2 -0
  133. package/src/config/schemas/memory-lifecycle.ts +13 -0
  134. package/src/config/schemas/memory-v2.ts +75 -11
  135. package/src/config/schemas/platform.ts +43 -3
  136. package/src/config/schemas/services.ts +28 -0
  137. package/src/config/seed-inference-profiles.ts +230 -33
  138. package/src/contacts/contact-store.ts +0 -25
  139. package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
  140. package/src/daemon/assistant-attachments.ts +4 -4
  141. package/src/daemon/config-watcher.ts +85 -57
  142. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  143. package/src/daemon/conversation-agent-loop.ts +170 -33
  144. package/src/daemon/conversation-error.ts +87 -15
  145. package/src/daemon/conversation-lifecycle.ts +1 -3
  146. package/src/daemon/conversation-process.ts +8 -0
  147. package/src/daemon/conversation-runtime-assembly.ts +26 -0
  148. package/src/daemon/conversation-store.ts +2 -2
  149. package/src/daemon/conversation-surfaces.ts +195 -15
  150. package/src/daemon/conversation-tool-setup.ts +57 -14
  151. package/src/daemon/conversation.ts +17 -22
  152. package/src/daemon/date-context.ts +71 -22
  153. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  154. package/src/daemon/disk-pressure-guard.ts +343 -0
  155. package/src/daemon/disk-pressure-policy.ts +163 -0
  156. package/src/daemon/handlers/shared.ts +0 -1
  157. package/src/daemon/handlers/skills.ts +3 -4
  158. package/src/daemon/host-app-control-proxy.ts +137 -41
  159. package/src/daemon/host-bash-proxy.ts +46 -21
  160. package/src/daemon/host-cu-proxy.ts +49 -3
  161. package/src/daemon/host-file-proxy.ts +43 -7
  162. package/src/daemon/host-transfer-proxy.ts +95 -4
  163. package/src/daemon/lifecycle.ts +79 -28
  164. package/src/daemon/meet-host-supervisor.ts +4 -4
  165. package/src/daemon/meet-manifest-loader.ts +0 -1
  166. package/src/daemon/memory-v2-startup.ts +14 -4
  167. package/src/daemon/message-protocol.ts +3 -0
  168. package/src/daemon/message-types/conversations.ts +4 -0
  169. package/src/daemon/message-types/disk-pressure.ts +9 -0
  170. package/src/daemon/message-types/messages.ts +3 -0
  171. package/src/daemon/profiler-run-store.ts +5 -5
  172. package/src/daemon/tool-setup-types.ts +2 -2
  173. package/src/documents/document-store.ts +85 -0
  174. package/src/filing/filing-service.ts +30 -5
  175. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
  176. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
  177. package/src/heartbeat/heartbeat-run-store.ts +13 -0
  178. package/src/heartbeat/heartbeat-service.ts +205 -31
  179. package/src/home/feed-scheduler.ts +18 -0
  180. package/src/inbound/platform-callback-registration.ts +8 -15
  181. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  182. package/src/ipc/assistant-server.ts +56 -2
  183. package/src/ipc/gateway-client.ts +37 -3
  184. package/src/live-voice/live-voice-archive.ts +4 -4
  185. package/src/live-voice/protocol.ts +5 -7
  186. package/src/media/image-service.ts +1 -7
  187. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  188. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
  189. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  190. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  191. package/src/memory/admin.ts +5 -9
  192. package/src/memory/context-search/agent-runner.ts +19 -2
  193. package/src/memory/context-search/sources/conversations.ts +2 -11
  194. package/src/memory/context-search/sources/memory-v2.ts +5 -4
  195. package/src/memory/context-search/sources/memory.ts +0 -1
  196. package/src/memory/context-search/types.ts +0 -1
  197. package/src/memory/conversation-crud.ts +4 -12
  198. package/src/memory/db-init.ts +2 -0
  199. package/src/memory/embedding-runtime-manager.ts +119 -5
  200. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +32 -21
  201. package/src/memory/graph/conversation-graph-memory.ts +42 -54
  202. package/src/memory/graph/extraction.ts +1 -3
  203. package/src/memory/graph/graph-search.test.ts +10 -67
  204. package/src/memory/graph/graph-search.ts +1 -20
  205. package/src/memory/graph/retriever.test.ts +6 -0
  206. package/src/memory/graph/retriever.ts +6 -10
  207. package/src/memory/indexer.ts +54 -45
  208. package/src/memory/job-handlers/backfill.ts +2 -11
  209. package/src/memory/job-handlers/cleanup.ts +43 -0
  210. package/src/memory/job-handlers/embedding.ts +6 -8
  211. package/src/memory/job-handlers/summarization.ts +2 -7
  212. package/src/memory/jobs-store.ts +48 -0
  213. package/src/memory/jobs-worker.ts +81 -43
  214. package/src/memory/memory-v2-activation-log-store.ts +32 -14
  215. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  216. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  217. package/src/memory/migrations/index.ts +1 -0
  218. package/src/memory/pkb/pkb-search.test.ts +6 -0
  219. package/src/memory/qdrant-client.ts +0 -13
  220. package/src/memory/rerank-local.ts +374 -0
  221. package/src/memory/search/semantic.ts +6 -67
  222. package/src/memory/trace-event-store.ts +1 -17
  223. package/src/memory/v2/__tests__/activation.test.ts +311 -250
  224. package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
  225. package/src/memory/v2/__tests__/injection.test.ts +157 -167
  226. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  227. package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
  228. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  229. package/src/memory/v2/__tests__/sim.test.ts +5 -199
  230. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  231. package/src/memory/v2/__tests__/static-context.test.ts +76 -1
  232. package/src/memory/v2/activation.ts +149 -156
  233. package/src/memory/v2/consolidation-job.ts +62 -12
  234. package/src/memory/v2/injection.ts +47 -60
  235. package/src/memory/v2/prompts/consolidation.ts +36 -1
  236. package/src/memory/v2/qdrant.ts +99 -0
  237. package/src/memory/v2/reranker.ts +177 -0
  238. package/src/memory/v2/sim.ts +10 -84
  239. package/src/memory/v2/skill-content.ts +4 -3
  240. package/src/memory/v2/skill-store.ts +82 -59
  241. package/src/memory/v2/static-context.ts +22 -0
  242. package/src/memory/v2/types.ts +10 -10
  243. package/src/notifications/copy-composer.ts +13 -0
  244. package/src/notifications/signal.ts +4 -0
  245. package/src/oauth/AGENTS.md +3 -1
  246. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  247. package/src/oauth/connect-orchestrator.ts +2 -0
  248. package/src/oauth/connection-resolver.test.ts +66 -1
  249. package/src/oauth/connection-resolver.ts +55 -1
  250. package/src/oauth/oauth-connect-state.ts +77 -0
  251. package/src/oauth/seed-providers.ts +58 -1
  252. package/src/plugins/defaults/injectors.ts +35 -2
  253. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  254. package/src/plugins/types.ts +7 -0
  255. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  256. package/src/proactive-artifact/decision.test.ts +226 -0
  257. package/src/proactive-artifact/decision.ts +165 -0
  258. package/src/proactive-artifact/index.ts +7 -0
  259. package/src/proactive-artifact/job.test.ts +867 -0
  260. package/src/proactive-artifact/job.ts +352 -0
  261. package/src/proactive-artifact/message-copy.ts +41 -0
  262. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  263. package/src/proactive-artifact/trigger-state.ts +119 -0
  264. package/src/prompts/normalize-onboarding.ts +80 -0
  265. package/src/prompts/persona-resolver.ts +101 -9
  266. package/src/prompts/system-prompt.ts +21 -7
  267. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  268. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  269. package/src/providers/model-intents.ts +7 -0
  270. package/src/providers/openrouter/client.ts +8 -0
  271. package/src/providers/retry.ts +50 -0
  272. package/src/providers/types.ts +1 -0
  273. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  274. package/src/runtime/agent-wake.ts +238 -100
  275. package/src/runtime/assistant-event-hub.ts +36 -6
  276. package/src/runtime/assistant-event.ts +0 -1
  277. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  278. package/src/runtime/auth/route-policy.ts +14 -1
  279. package/src/runtime/auth/same-actor.ts +216 -0
  280. package/src/runtime/channel-retry-sweep.ts +65 -1
  281. package/src/runtime/guardian-reply-router.ts +10 -0
  282. package/src/runtime/local-actor-identity.ts +52 -11
  283. package/src/runtime/pending-interactions.ts +8 -0
  284. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
  286. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  287. package/src/runtime/routes/client-routes.ts +20 -2
  288. package/src/runtime/routes/contact-routes.ts +0 -25
  289. package/src/runtime/routes/conversation-routes.ts +35 -26
  290. package/src/runtime/routes/debug-bash-routes.ts +163 -0
  291. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  292. package/src/runtime/routes/document-pdf-renderer.ts +6 -2
  293. package/src/runtime/routes/documents-routes.ts +2 -75
  294. package/src/runtime/routes/events-routes.ts +41 -9
  295. package/src/runtime/routes/host-bash-routes.ts +23 -3
  296. package/src/runtime/routes/host-cu-routes.ts +33 -6
  297. package/src/runtime/routes/host-file-routes.ts +32 -6
  298. package/src/runtime/routes/host-transfer-routes.ts +79 -16
  299. package/src/runtime/routes/identity-routes.ts +7 -138
  300. package/src/runtime/routes/inbound-message-handler.ts +77 -12
  301. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
  302. package/src/runtime/routes/index.ts +6 -0
  303. package/src/runtime/routes/memory-item-routes.test.ts +41 -15
  304. package/src/runtime/routes/memory-v2-routes.ts +33 -0
  305. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  306. package/src/runtime/verification-outbound-actions.ts +4 -4
  307. package/src/schedule/run-script.ts +37 -5
  308. package/src/schedule/scheduler.ts +20 -1
  309. package/src/security/encrypted-store.ts +2 -0
  310. package/src/security/secure-keys.ts +55 -0
  311. package/src/skills/remote-skill-policy.ts +4 -10
  312. package/src/subagent/index.ts +1 -7
  313. package/src/subagent/manager.ts +1 -15
  314. package/src/tasks/task-runner.ts +0 -1
  315. package/src/tasks/task-store.ts +0 -3
  316. package/src/tools/background-tool-registry.ts +17 -3
  317. package/src/tools/host-filesystem/edit.test.ts +151 -0
  318. package/src/tools/host-filesystem/edit.ts +43 -1
  319. package/src/tools/host-filesystem/read.test.ts +129 -0
  320. package/src/tools/host-filesystem/read.ts +43 -1
  321. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  322. package/src/tools/host-filesystem/transfer.ts +56 -11
  323. package/src/tools/host-filesystem/write.test.ts +134 -0
  324. package/src/tools/host-filesystem/write.ts +43 -1
  325. package/src/tools/host-terminal/host-shell.ts +13 -6
  326. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  327. package/src/tools/memory/register.test.ts +12 -9
  328. package/src/tools/memory/register.ts +1 -2
  329. package/src/tools/provider-tool-name.ts +28 -0
  330. package/src/tools/registry.ts +30 -9
  331. package/src/tools/terminal/shell.ts +9 -1
  332. package/src/tools/tool-approval-handler.ts +31 -6
  333. package/src/tools/types.ts +24 -2
  334. package/src/tts/provider-catalog.ts +3 -5
  335. package/src/util/disk-usage.ts +138 -0
  336. package/src/util/platform.ts +21 -11
  337. package/src/util/process-liveness.ts +26 -0
  338. package/src/workspace/heartbeat-service.ts +19 -0
  339. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  340. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  341. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
  342. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  343. package/src/workspace/migrations/registry.ts +8 -0
  344. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  345. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  346. package/src/memory/v2/skill-qdrant.ts +0 -404
  347. package/src/signals/bash.ts +0 -198
@@ -0,0 +1,169 @@
1
+ /**
2
+ * End-to-end test for `assistant clients list` over IPC.
3
+ *
4
+ * Regression test for the gap where the same-user filter on
5
+ * `GET /v1/clients` (which reads `headers["x-vellum-actor-principal-id"]`)
6
+ * silently returned an empty list over IPC because the IPC adapter did
7
+ * not inject the synthetic actor-principal header that the HTTP adapter
8
+ * populates from the verified `AuthContext`.
9
+ *
10
+ * Asserts that in non-dev-bypass mode (`isHttpAuthDisabled() === false`),
11
+ * the CLI sees same-user clients via the IPC path because the IPC server
12
+ * fills in the header from the local guardian principal.
13
+ */
14
+
15
+ import {
16
+ afterAll,
17
+ afterEach,
18
+ beforeEach,
19
+ describe,
20
+ expect,
21
+ mock,
22
+ test,
23
+ } from "bun:test";
24
+
25
+ import { runAssistantCommandFull } from "../../cli/__tests__/run-assistant-command.js";
26
+ import { AssistantIpcServer } from "../assistant-server.js";
27
+
28
+ // ── Module mocks (must be set up before importing the route) ──────────────
29
+
30
+ let fakeHttpAuthDisabled = false;
31
+ let fakeLocalPrincipalId: string | undefined = "guardian-local";
32
+
33
+ mock.module("../../config/env.js", () => ({
34
+ isHttpAuthDisabled: () => fakeHttpAuthDisabled,
35
+ hasUngatedHttpAuthDisabled: () => false,
36
+ }));
37
+
38
+ mock.module("../../runtime/local-actor-identity.js", () => ({
39
+ findLocalGuardianPrincipalId: () => fakeLocalPrincipalId,
40
+ }));
41
+
42
+ // ── Real imports (after mocks) ────────────────────────────────────────────
43
+
44
+ import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
45
+
46
+ // ── Fixtures ──────────────────────────────────────────────────────────────
47
+
48
+ let server: AssistantIpcServer | null = null;
49
+
50
+ function registerClient(args: {
51
+ clientId: string;
52
+ actorPrincipalId?: string;
53
+ }): void {
54
+ assistantEventHub.subscribe({
55
+ type: "client",
56
+ clientId: args.clientId,
57
+ interfaceId: "macos",
58
+ capabilities: ["host_bash", "host_file", "host_cu"],
59
+ actorPrincipalId: args.actorPrincipalId,
60
+ callback: () => {},
61
+ });
62
+ }
63
+
64
+ function clearHub(): void {
65
+ const ids = assistantEventHub.listClients().map((c) => c.clientId);
66
+ for (const id of ids) {
67
+ assistantEventHub.disposeClient(id);
68
+ }
69
+ }
70
+
71
+ async function startServer(): Promise<void> {
72
+ server = new AssistantIpcServer();
73
+ await server.start();
74
+ // Allow the listener to be ready before the CLI tries to connect.
75
+ await new Promise((resolve) => setTimeout(resolve, 50));
76
+ }
77
+
78
+ beforeEach(() => {
79
+ fakeHttpAuthDisabled = false;
80
+ fakeLocalPrincipalId = "guardian-local";
81
+ clearHub();
82
+ });
83
+
84
+ afterEach(() => {
85
+ server?.stop();
86
+ server = null;
87
+ });
88
+
89
+ afterAll(() => {
90
+ mock.restore();
91
+ });
92
+
93
+ // ── Tests ────────────────────────────────────────────────────────────────
94
+
95
+ describe("assistant clients list over IPC — same-user filter", () => {
96
+ test("returns same-user clients in non-dev-bypass mode", async () => {
97
+ registerClient({
98
+ clientId: "client-self-1",
99
+ actorPrincipalId: "guardian-local",
100
+ });
101
+ registerClient({
102
+ clientId: "client-self-2",
103
+ actorPrincipalId: "guardian-local",
104
+ });
105
+ registerClient({
106
+ clientId: "client-other",
107
+ actorPrincipalId: "other-user",
108
+ });
109
+
110
+ await startServer();
111
+
112
+ const { stdout } = await runAssistantCommandFull(
113
+ "clients",
114
+ "list",
115
+ "--json",
116
+ );
117
+
118
+ const parsed = JSON.parse(stdout.trim()) as {
119
+ clients: Array<{ clientId: string }>;
120
+ };
121
+ const ids = parsed.clients.map((c) => c.clientId).sort();
122
+ expect(ids).toEqual(["client-self-1", "client-self-2"]);
123
+ });
124
+
125
+ test("returns empty when no local guardian principal is bound (fail-closed)", async () => {
126
+ fakeLocalPrincipalId = undefined;
127
+ registerClient({
128
+ clientId: "client-self",
129
+ actorPrincipalId: "guardian-local",
130
+ });
131
+
132
+ await startServer();
133
+
134
+ const { stdout } = await runAssistantCommandFull(
135
+ "clients",
136
+ "list",
137
+ "--json",
138
+ );
139
+ const parsed = JSON.parse(stdout.trim()) as {
140
+ clients: Array<{ clientId: string }>;
141
+ };
142
+ expect(parsed.clients).toEqual([]);
143
+ });
144
+
145
+ test("dev-bypass mode returns all clients regardless of principal", async () => {
146
+ fakeHttpAuthDisabled = true;
147
+ registerClient({
148
+ clientId: "client-self",
149
+ actorPrincipalId: "guardian-local",
150
+ });
151
+ registerClient({
152
+ clientId: "client-other",
153
+ actorPrincipalId: "other-user",
154
+ });
155
+
156
+ await startServer();
157
+
158
+ const { stdout } = await runAssistantCommandFull(
159
+ "clients",
160
+ "list",
161
+ "--json",
162
+ );
163
+ const parsed = JSON.parse(stdout.trim()) as {
164
+ clients: Array<{ clientId: string }>;
165
+ };
166
+ const ids = parsed.clients.map((c) => c.clientId).sort();
167
+ expect(ids).toEqual(["client-other", "client-self"]);
168
+ });
169
+ });
@@ -32,9 +32,13 @@ import { existsSync, mkdirSync, unlinkSync } from "node:fs";
32
32
  import { createServer, type Server, type Socket } from "node:net";
33
33
  import { dirname } from "node:path";
34
34
 
35
+ import { findLocalGuardianPrincipalId } from "../runtime/local-actor-identity.js";
35
36
  import { RouteError } from "../runtime/routes/errors.js";
36
37
  import { ROUTES } from "../runtime/routes/index.js";
37
- import type { RouteDefinition } from "../runtime/routes/types.js";
38
+ import type {
39
+ RouteDefinition,
40
+ RouteHandlerArgs,
41
+ } from "../runtime/routes/types.js";
38
42
  import { getLogger } from "../util/logger.js";
39
43
  import {
40
44
  type IpcEnvelope,
@@ -256,7 +260,8 @@ export class AssistantIpcServer {
256
260
  void binary;
257
261
 
258
262
  try {
259
- const result = handler(req.params ?? {});
263
+ const handlerArgs = injectLocalActorHeader(req.params);
264
+ const result = handler(handlerArgs);
260
265
 
261
266
  if (result instanceof Promise) {
262
267
  result
@@ -454,3 +459,52 @@ export class AssistantIpcServer {
454
459
  // ---------------------------------------------------------------------------
455
460
  // Helpers
456
461
  // ---------------------------------------------------------------------------
462
+
463
+ /**
464
+ * Inject a synthetic `x-vellum-actor-principal-id` header from the local
465
+ * guardian principal when the caller hasn't already provided one.
466
+ *
467
+ * Local IPC is intra-process and owned by the same user as the daemon, so
468
+ * routes that consume `headers["x-vellum-actor-principal-id"]` (e.g. the
469
+ * same-user filter on `GET /v1/clients`) need an actor identity to function
470
+ * over IPC. The HTTP adapter does this from the verified `AuthContext`
471
+ * (`http-adapter.ts`); this helper mirrors that convention for IPC.
472
+ *
473
+ * Existing headers from the caller (e.g. the gateway's IPC runtime proxy,
474
+ * which forwards real `x-vellum-*` headers from the authenticated HTTP
475
+ * request) are preserved — we only fill in the gap for direct CLI/local
476
+ * IPC callers.
477
+ */
478
+ function injectLocalActorHeader(
479
+ params: Record<string, unknown> | undefined,
480
+ ): RouteHandlerArgs {
481
+ const args = (params ?? {}) as RouteHandlerArgs;
482
+ const existingHeaders = args.headers;
483
+ if (existingHeaders?.["x-vellum-actor-principal-id"]) {
484
+ return args;
485
+ }
486
+
487
+ // Defensive: the guardian lookup queries the contacts table, which may
488
+ // not yet exist on a very early boot path or in test fixtures that don't
489
+ // initialize the DB. A failure here must not block IPC dispatch — routes
490
+ // that require the header will fail-closed on their own.
491
+ let localActor: string | undefined;
492
+ try {
493
+ localActor = findLocalGuardianPrincipalId();
494
+ } catch (err) {
495
+ log.debug(
496
+ { err },
497
+ "failed to resolve local actor principal for IPC header injection",
498
+ );
499
+ return args;
500
+ }
501
+ if (!localActor) return args;
502
+
503
+ return {
504
+ ...args,
505
+ headers: {
506
+ ...existingHeaders,
507
+ "x-vellum-actor-principal-id": localActor,
508
+ },
509
+ };
510
+ }
@@ -38,9 +38,10 @@ const log = getLogger("gateway-ipc-client");
38
38
  export async function ipcCall(
39
39
  method: string,
40
40
  params?: Record<string, unknown>,
41
+ timeoutMs?: number,
41
42
  ): Promise<unknown> {
42
43
  const socketPath = getGatewaySocketPath();
43
- return packageIpcCall(socketPath, method, params, log);
44
+ return packageIpcCall(socketPath, method, params, log, timeoutMs);
44
45
  }
45
46
 
46
47
  // ---------------------------------------------------------------------------
@@ -90,9 +91,15 @@ export function resetPersistentClient(): void {
90
91
  /**
91
92
  * Fetch all merged feature flags from the gateway via IPC.
92
93
  * Returns an empty record on any failure.
94
+ *
95
+ * @param timeoutMs - Optional timeout override forwarded to the IPC
96
+ * transport. Pass a small value (e.g. 200) for CLI startup paths where
97
+ * a slow/absent gateway should fail fast.
93
98
  */
94
- export async function ipcGetFeatureFlags(): Promise<Record<string, boolean>> {
95
- const result = await ipcCall("get_feature_flags");
99
+ export async function ipcGetFeatureFlags(
100
+ timeoutMs?: number,
101
+ ): Promise<Record<string, boolean>> {
102
+ const result = await ipcCall("get_feature_flags", undefined, timeoutMs);
96
103
  if (result && typeof result === "object" && !Array.isArray(result)) {
97
104
  const filtered: Record<string, boolean> = {};
98
105
  for (const [k, v] of Object.entries(result as Record<string, unknown>)) {
@@ -103,6 +110,33 @@ export async function ipcGetFeatureFlags(): Promise<Record<string, boolean>> {
103
110
  return {};
104
111
  }
105
112
 
113
+ // ---------------------------------------------------------------------------
114
+ // Velay tunnel status
115
+ // ---------------------------------------------------------------------------
116
+
117
+ export interface VelayTunnelStatus {
118
+ connected: boolean;
119
+ publicUrl: string | null;
120
+ }
121
+
122
+ /**
123
+ * Fetch the current Velay tunnel status from the gateway via IPC.
124
+ * Returns `null` when the gateway is unreachable or returns an unexpected
125
+ * response — callers should treat `null` as "gateway not running".
126
+ */
127
+ export async function ipcGetVelayStatus(): Promise<VelayTunnelStatus | null> {
128
+ const result = await ipcCall("get_velay_status");
129
+ if (!result || typeof result !== "object" || Array.isArray(result)) {
130
+ return null;
131
+ }
132
+ const obj = result as Record<string, unknown>;
133
+ if (typeof obj.connected !== "boolean") return null;
134
+ return {
135
+ connected: obj.connected,
136
+ publicUrl: typeof obj.publicUrl === "string" ? obj.publicUrl : null,
137
+ };
138
+ }
139
+
106
140
  /**
107
141
  * Classify risk for a tool invocation via the gateway's persistent IPC
108
142
  * connection.
@@ -17,7 +17,7 @@ const LIVE_VOICE_AUDIO_SOURCE = "live-voice";
17
17
 
18
18
  export type LiveVoiceAudioArchiveRole = "user" | "assistant";
19
19
 
20
- export type LiveVoiceAudioSource =
20
+ type LiveVoiceAudioSource =
21
21
  | {
22
22
  type: "base64";
23
23
  dataBase64: string;
@@ -28,7 +28,7 @@ export type LiveVoiceAudioSource =
28
28
  sizeBytes?: number;
29
29
  };
30
30
 
31
- export interface ArchiveLiveVoiceAudioInput {
31
+ interface ArchiveLiveVoiceAudioInput {
32
32
  messageId: string;
33
33
  sessionId: string;
34
34
  turnId: string;
@@ -55,7 +55,7 @@ export interface LiveVoiceAudioArtifactMetadata {
55
55
  archivedAt: number;
56
56
  }
57
57
 
58
- export type LiveVoiceAudioArchiveWarningCode =
58
+ type LiveVoiceAudioArchiveWarningCode =
59
59
  | "archive_failed"
60
60
  | "attachment_not_found"
61
61
  | "invalid_audio_source"
@@ -591,7 +591,7 @@ type LinkLiveVoiceRolelessAudioInput = Omit<
591
591
  messageId?: string | null;
592
592
  };
593
593
 
594
- export interface LinkLiveVoiceAudioArtifactInput {
594
+ interface LinkLiveVoiceAudioArtifactInput {
595
595
  messageId?: string | null;
596
596
  artifact: LiveVoiceAudioArtifactMetadata;
597
597
  position?: number;
@@ -6,8 +6,7 @@ const LIVE_VOICE_CLIENT_FRAME_TYPES = [
6
6
  "end",
7
7
  ] as const;
8
8
 
9
- export type LiveVoiceClientFrameType =
10
- (typeof LIVE_VOICE_CLIENT_FRAME_TYPES)[number];
9
+ type LiveVoiceClientFrameType = (typeof LIVE_VOICE_CLIENT_FRAME_TYPES)[number];
11
10
 
12
11
  const _LIVE_VOICE_SERVER_FRAME_TYPES = [
13
12
  "ready",
@@ -23,8 +22,7 @@ const _LIVE_VOICE_SERVER_FRAME_TYPES = [
23
22
  "error",
24
23
  ] as const;
25
24
 
26
- export type LiveVoiceServerFrameType =
27
- (typeof _LIVE_VOICE_SERVER_FRAME_TYPES)[number];
25
+ type LiveVoiceServerFrameType = (typeof _LIVE_VOICE_SERVER_FRAME_TYPES)[number];
28
26
 
29
27
  export const LiveVoiceProtocolErrorCode = {
30
28
  InvalidJson: "invalid_json",
@@ -45,7 +43,7 @@ export interface LiveVoiceProtocolError {
45
43
  readonly frameType?: string;
46
44
  }
47
45
 
48
- export type LiveVoiceParseResult<T> =
46
+ type LiveVoiceParseResult<T> =
49
47
  | { ok: true; frame: T }
50
48
  | { ok: false; error: LiveVoiceProtocolError };
51
49
 
@@ -85,12 +83,12 @@ export type LiveVoiceClientFrame =
85
83
  | LiveVoiceClientInterruptFrame
86
84
  | LiveVoiceClientEndFrame;
87
85
 
88
- export interface LiveVoiceBinaryAudioFrame {
86
+ interface LiveVoiceBinaryAudioFrame {
89
87
  readonly type: "binary_audio";
90
88
  readonly data: Uint8Array;
91
89
  }
92
90
 
93
- export interface LiveVoiceServerFrameBase {
91
+ interface LiveVoiceServerFrameBase {
94
92
  readonly type: LiveVoiceServerFrameType;
95
93
  readonly seq: number;
96
94
  }
@@ -76,10 +76,4 @@ export function providerForModel(
76
76
  return fallback;
77
77
  }
78
78
 
79
- export type {
80
- GeneratedImage,
81
- ImageGenCredentials,
82
- ImageGenerationRequest,
83
- ImageGenerationResult,
84
- ImageGenProvider,
85
- } from "./types.js";
79
+ export type { ImageGenCredentials } from "./types.js";
@@ -1,7 +1,6 @@
1
1
  import type {
2
2
  MemoryV2ConceptRowRecord,
3
3
  MemoryV2ConfigSnapshot,
4
- MemoryV2SkillRowRecord,
5
4
  } from "../../memory-v2-activation-log-store.js";
6
5
 
7
6
  export const sampleConcepts: MemoryV2ConceptRowRecord[] = [
@@ -13,10 +12,28 @@ export const sampleConcepts: MemoryV2ConceptRowRecord[] = [
13
12
  simUser: 0.6,
14
13
  simAssistant: 0.4,
15
14
  simNow: 0.3,
15
+ simUserRerankBoost: 0,
16
+ simAssistantRerankBoost: 0,
17
+ inRerankPool: false,
16
18
  spreadContribution: 0.2,
17
19
  source: "both",
18
20
  status: "injected",
19
21
  },
22
+ {
23
+ slug: "skills/skill-1",
24
+ finalActivation: 0.8,
25
+ ownActivation: 0.8,
26
+ priorActivation: 0,
27
+ simUser: 0.5,
28
+ simAssistant: 0.4,
29
+ simNow: 0.3,
30
+ simUserRerankBoost: 0,
31
+ simAssistantRerankBoost: 0,
32
+ inRerankPool: false,
33
+ spreadContribution: 0,
34
+ source: "ann_top50",
35
+ status: "injected",
36
+ },
20
37
  {
21
38
  slug: "concept-b",
22
39
  finalActivation: 0.4,
@@ -25,23 +42,15 @@ export const sampleConcepts: MemoryV2ConceptRowRecord[] = [
25
42
  simUser: 0.2,
26
43
  simAssistant: 0.1,
27
44
  simNow: 0.05,
45
+ simUserRerankBoost: 0,
46
+ simAssistantRerankBoost: 0,
47
+ inRerankPool: false,
28
48
  spreadContribution: 0.0,
29
49
  source: "ann_top50",
30
50
  status: "not_injected",
31
51
  },
32
52
  ];
33
53
 
34
- export const sampleSkills: MemoryV2SkillRowRecord[] = [
35
- {
36
- id: "skill-1",
37
- activation: 0.8,
38
- simUser: 0.5,
39
- simAssistant: 0.4,
40
- simNow: 0.3,
41
- status: "injected",
42
- },
43
- ];
44
-
45
54
  export const sampleConfig: MemoryV2ConfigSnapshot = {
46
55
  d: 0.85,
47
56
  c_user: 1.0,
@@ -50,6 +59,5 @@ export const sampleConfig: MemoryV2ConfigSnapshot = {
50
59
  k: 5,
51
60
  hops: 2,
52
61
  top_k: 10,
53
- top_k_skills: 3,
54
62
  epsilon: 0.001,
55
63
  };
@@ -1,23 +1,23 @@
1
1
  /**
2
- * Tests for the v2 consolidation entry in `maybeEnqueueGraphMaintenanceJobs`.
2
+ * Tests for v1/v2 mutual exclusion in `maybeEnqueueGraphMaintenanceJobs`.
3
3
  *
4
- * Coverage matrix (from PR 24 acceptance criteria):
5
- * - Flag off → no `memory_v2_consolidate` row enqueued, even after the
6
- * interval has elapsed.
7
- * - Flag on + config off still no row enqueued (both gates required).
8
- * - Flag on + config on, no prior checkpoint → row enqueued, checkpoint
9
- * stamped to `nowMs`.
10
- * - Flag on + config on, recent checkpoint no row enqueued (interval
11
- * not yet elapsed).
12
- * - Flag on + config on, stale checkpoint → row enqueued, checkpoint
4
+ * The schedule is now mutually exclusive: when both the `memory-v2-enabled`
5
+ * flag and `memory.v2.enabled` config are on, only `memory_v2_consolidate`
6
+ * is scheduled; otherwise the four v1 entries (decay, consolidate,
7
+ * pattern_scan, narrative) fire and the v2 entry does not.
8
+ *
9
+ * Coverage:
10
+ * - Flag off only v1 entries fire (no `memory_v2_consolidate`).
11
+ * - Flag on + config off → only v1 entries fire.
12
+ * - Flag on + config on, no prior checkpoint → only the v2 entry fires.
13
+ * - Flag on + config on, recent checkpoint → no v2 row (interval not
14
+ * yet elapsed).
15
+ * - Flag on + config on, stale checkpoint → v2 row enqueued, checkpoint
13
16
  * refreshed.
14
- * - The v1 maintenance entries (decay, consolidate, pattern_scan,
15
- * narrative) still fire under the v2 path — adding the v2 entry must
16
- * not regress v1 scheduling.
17
17
  *
18
- * The sweep job is intentionally NOT scheduled here: PR 24 wires it into
19
- * the `graph_extract` debounce in `indexer.ts`. Those triggers are covered
20
- * by the separate trigger-path tests; this file owns only the cron entries.
18
+ * The sweep job is intentionally NOT scheduled here: it is wired into the
19
+ * `graph_extract` debounce in `indexer.ts`. Those triggers are covered by
20
+ * the separate trigger-path tests; this file owns only the cron entries.
21
21
  *
22
22
  * Tests use a temp workspace pinned via `VELLUM_WORKSPACE_DIR` so the DB
23
23
  * lives under `tmpdir()` and `~/.vellum/` is never touched.
@@ -145,6 +145,11 @@ describe("maybeEnqueueGraphMaintenanceJobs — memory v2 consolidation", () => {
145
145
  maybeEnqueueGraphMaintenanceJobs(config, Date.now());
146
146
 
147
147
  expect(countPendingJobs("memory_v2_consolidate")).toBe(1);
148
+ // v1 entries are suppressed when v2 is active.
149
+ expect(countPendingJobs("graph_decay")).toBe(0);
150
+ expect(countPendingJobs("graph_consolidate")).toBe(0);
151
+ expect(countPendingJobs("graph_pattern_scan")).toBe(0);
152
+ expect(countPendingJobs("graph_narrative_refine")).toBe(0);
148
153
  });
149
154
 
150
155
  test("does not enqueue consolidate before the interval has elapsed", () => {
@@ -200,11 +205,30 @@ describe("maybeEnqueueGraphMaintenanceJobs — memory v2 consolidation", () => {
200
205
  expect(countPendingJobs("memory_v2_consolidate")).toBe(1);
201
206
  });
202
207
 
203
- test("v1 graph maintenance entries still fire alongside the v2 entry", () => {
208
+ test("v1 maintenance entries are suppressed when v2 is active", () => {
204
209
  _setOverridesForTesting({ "memory-v2-enabled": true });
205
210
  const config = buildConfig({ v2Enabled: true, intervalHours: 1 });
206
211
 
207
- // No checkpoints set — every entry should be due.
212
+ // No checkpoints set — every entry would be due if it were scheduled.
213
+ deleteMemoryCheckpoint("graph_maintenance:decay:last_run");
214
+ deleteMemoryCheckpoint("graph_maintenance:consolidate:last_run");
215
+ deleteMemoryCheckpoint("graph_maintenance:pattern_scan:last_run");
216
+ deleteMemoryCheckpoint("graph_maintenance:narrative:last_run");
217
+ deleteMemoryCheckpoint(CONSOLIDATE_CHECKPOINT_KEY);
218
+
219
+ maybeEnqueueGraphMaintenanceJobs(config, Date.now());
220
+
221
+ expect(countPendingJobs("graph_decay")).toBe(0);
222
+ expect(countPendingJobs("graph_consolidate")).toBe(0);
223
+ expect(countPendingJobs("graph_pattern_scan")).toBe(0);
224
+ expect(countPendingJobs("graph_narrative_refine")).toBe(0);
225
+ expect(countPendingJobs("memory_v2_consolidate")).toBe(1);
226
+ });
227
+
228
+ test("flag-off path fires v1 entries and does not enqueue v2", () => {
229
+ _setOverridesForTesting({ "memory-v2-enabled": false });
230
+ const config = buildConfig({ v2Enabled: true, intervalHours: 1 });
231
+
208
232
  deleteMemoryCheckpoint("graph_maintenance:decay:last_run");
209
233
  deleteMemoryCheckpoint("graph_maintenance:consolidate:last_run");
210
234
  deleteMemoryCheckpoint("graph_maintenance:pattern_scan:last_run");
@@ -217,19 +241,25 @@ describe("maybeEnqueueGraphMaintenanceJobs — memory v2 consolidation", () => {
217
241
  expect(countPendingJobs("graph_consolidate")).toBe(1);
218
242
  expect(countPendingJobs("graph_pattern_scan")).toBe(1);
219
243
  expect(countPendingJobs("graph_narrative_refine")).toBe(1);
220
- expect(countPendingJobs("memory_v2_consolidate")).toBe(1);
244
+ expect(countPendingJobs("memory_v2_consolidate")).toBe(0);
221
245
  });
222
246
 
223
- test("flag-off path does not enqueue v2 but still fires the v1 entries", () => {
224
- _setOverridesForTesting({ "memory-v2-enabled": false });
225
- const config = buildConfig({ v2Enabled: true, intervalHours: 1 });
247
+ test("config-gate-off path fires v1 entries and does not enqueue v2", () => {
248
+ _setOverridesForTesting({ "memory-v2-enabled": true });
249
+ const config = buildConfig({ v2Enabled: false, intervalHours: 1 });
226
250
 
227
251
  deleteMemoryCheckpoint("graph_maintenance:decay:last_run");
252
+ deleteMemoryCheckpoint("graph_maintenance:consolidate:last_run");
253
+ deleteMemoryCheckpoint("graph_maintenance:pattern_scan:last_run");
254
+ deleteMemoryCheckpoint("graph_maintenance:narrative:last_run");
228
255
  deleteMemoryCheckpoint(CONSOLIDATE_CHECKPOINT_KEY);
229
256
 
230
257
  maybeEnqueueGraphMaintenanceJobs(config, Date.now());
231
258
 
232
259
  expect(countPendingJobs("graph_decay")).toBe(1);
260
+ expect(countPendingJobs("graph_consolidate")).toBe(1);
261
+ expect(countPendingJobs("graph_pattern_scan")).toBe(1);
262
+ expect(countPendingJobs("graph_narrative_refine")).toBe(1);
233
263
  expect(countPendingJobs("memory_v2_consolidate")).toBe(0);
234
264
  });
235
265
  });
@@ -29,7 +29,6 @@ import { memoryV2ActivationLogs } from "../schema.js";
29
29
  import {
30
30
  sampleConcepts,
31
31
  sampleConfig,
32
- sampleSkills,
33
32
  } from "./fixtures/memory-v2-activation-fixtures.js";
34
33
 
35
34
  initializeDb();
@@ -53,7 +52,6 @@ describe("memory-v2-activation-log-store", () => {
53
52
  turn: 3,
54
53
  mode: "per-turn",
55
54
  concepts: sampleConcepts,
56
- skills: sampleSkills,
57
55
  config: sampleConfig,
58
56
  });
59
57
 
@@ -65,7 +63,6 @@ describe("memory-v2-activation-log-store", () => {
65
63
  expect(result!.turn).toBe(3);
66
64
  expect(result!.mode).toBe("per-turn");
67
65
  expect(result!.concepts).toEqual(sampleConcepts);
68
- expect(result!.skills).toEqual(sampleSkills);
69
66
  expect(result!.config).toEqual(sampleConfig);
70
67
  });
71
68
 
@@ -82,7 +79,6 @@ describe("memory-v2-activation-log-store", () => {
82
79
  turn: 1,
83
80
  mode: "context-load",
84
81
  concepts: sampleConcepts,
85
- skills: sampleSkills,
86
82
  config: sampleConfig,
87
83
  });
88
84
  recordMemoryV2ActivationLog({
@@ -90,7 +86,6 @@ describe("memory-v2-activation-log-store", () => {
90
86
  turn: 2,
91
87
  mode: "per-turn",
92
88
  concepts: sampleConcepts,
93
- skills: sampleSkills,
94
89
  config: sampleConfig,
95
90
  });
96
91
 
@@ -110,7 +105,6 @@ describe("memory-v2-activation-log-store", () => {
110
105
  turn: 3,
111
106
  mode: "per-turn",
112
107
  concepts: sampleConcepts,
113
- skills: sampleSkills,
114
108
  config: sampleConfig,
115
109
  });
116
110