@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -174,6 +174,8 @@ export interface ConversationRow {
174
174
  contextSummary: string | null;
175
175
  contextCompactedMessageCount: number;
176
176
  contextCompactedAt: number | null;
177
+ slackContextCompactionWatermarkTs: string | null;
178
+ slackContextCompactionWatermarkAt: number | null;
177
179
  conversationType: string;
178
180
  source: string;
179
181
  memoryScopeId: string;
@@ -202,6 +204,8 @@ export const parseConversation = createRowMapper<
202
204
  contextSummary: "contextSummary",
203
205
  contextCompactedMessageCount: "contextCompactedMessageCount",
204
206
  contextCompactedAt: "contextCompactedAt",
207
+ slackContextCompactionWatermarkTs: "slackContextCompactionWatermarkTs",
208
+ slackContextCompactionWatermarkAt: "slackContextCompactionWatermarkAt",
205
209
  conversationType: "conversationType",
206
210
  source: "source",
207
211
  memoryScopeId: "memoryScopeId",
@@ -225,10 +229,7 @@ export interface MessageRow {
225
229
  metadata: string | null;
226
230
  }
227
231
 
228
- const parseMessage = createRowMapper<
229
- typeof messages.$inferSelect,
230
- MessageRow
231
- >({
232
+ const parseMessage = createRowMapper<typeof messages.$inferSelect, MessageRow>({
232
233
  id: "id",
233
234
  conversationId: "conversationId",
234
235
  role: "role",
@@ -295,6 +296,8 @@ export function createConversation(
295
296
  contextSummary: null as string | null,
296
297
  contextCompactedMessageCount: 0,
297
298
  contextCompactedAt: null as number | null,
299
+ slackContextCompactionWatermarkTs: null as string | null,
300
+ slackContextCompactionWatermarkAt: null as number | null,
298
301
  conversationType,
299
302
  source,
300
303
  memoryScopeId,
@@ -542,6 +545,12 @@ export function forkConversation(params: {
542
545
  contextCompactedAt: preserveSourceCompactionState
543
546
  ? sourceConversation.contextCompactedAt
544
547
  : null,
548
+ slackContextCompactionWatermarkTs: preserveSourceCompactionState
549
+ ? sourceConversation.slackContextCompactionWatermarkTs
550
+ : null,
551
+ slackContextCompactionWatermarkAt: preserveSourceCompactionState
552
+ ? sourceConversation.slackContextCompactionWatermarkAt
553
+ : null,
545
554
  inferenceProfile: sourceConversation.inferenceProfile,
546
555
  })
547
556
  .where(eq(conversations.id, fc.id))
@@ -1180,6 +1189,22 @@ export function updateConversationContextWindow(
1180
1189
  .run();
1181
1190
  }
1182
1191
 
1192
+ export function updateConversationSlackContextWatermark(
1193
+ id: string,
1194
+ watermarkTs: string,
1195
+ compactedAt: number = Date.now(),
1196
+ ): void {
1197
+ const db = getDb();
1198
+ db.update(conversations)
1199
+ .set({
1200
+ slackContextCompactionWatermarkTs: watermarkTs,
1201
+ slackContextCompactionWatermarkAt: compactedAt,
1202
+ updatedAt: Date.now(),
1203
+ })
1204
+ .where(eq(conversations.id, id))
1205
+ .run();
1206
+ }
1207
+
1183
1208
  export function archiveConversation(id: string): boolean {
1184
1209
  const conv = getConversation(id);
1185
1210
  if (!conv) return false;
@@ -43,11 +43,7 @@ const log = getLogger("conversation-disk-view");
43
43
  // Directory helpers
44
44
  // ---------------------------------------------------------------------------
45
45
 
46
- export {
47
- getConversationDirName,
48
- getConversationDirPath,
49
- getResolvedConversationDirPath,
50
- };
46
+ export { getConversationDirName, getConversationDirPath };
51
47
 
52
48
  function ensureConversationDirPath(id: string, createdAtMs: number): string {
53
49
  const dirPath = getResolvedConversationDirPath(id, createdAtMs);
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Shared checkpoint helpers for conversation starters.
3
+ *
4
+ * Used by both the job handler (generation) and the route handler (refresh decisions).
5
+ */
6
+
7
+ import { eq } from "drizzle-orm";
8
+
9
+ import { getDb } from "./db-connection.js";
10
+ import { rawGet } from "./raw-query.js";
11
+ import { memoryCheckpoints } from "./schema.js";
12
+
13
+ // ── Checkpoint keys ──────────────────────────────────────────────
14
+
15
+ export const CK_ITEM_COUNT = "conversation_starters:item_count_at_last_gen";
16
+ export const CK_BATCH = "conversation_starters:generation_batch";
17
+ export const CK_LAST_GEN_AT = "conversation_starters:last_gen_at";
18
+
19
+ export function checkpointKey(base: string, scopeId: string): string {
20
+ return `${base}:${scopeId}`;
21
+ }
22
+
23
+ export function parseCheckpointInt(value: string | undefined): number | null {
24
+ if (value == null) return null;
25
+ const n = parseInt(value, 10);
26
+ return Number.isNaN(n) ? null : n;
27
+ }
28
+
29
+ export function getCheckpointValue(key: string): string | undefined {
30
+ return getDb()
31
+ .select({ value: memoryCheckpoints.value })
32
+ .from(memoryCheckpoints)
33
+ .where(eq(memoryCheckpoints.key, key))
34
+ .get()?.value;
35
+ }
36
+
37
+ // ── Writes ───────────────────────────────────────────────────────
38
+
39
+ export function upsertCheckpoint(
40
+ key: string,
41
+ value: string,
42
+ now: number = Date.now(),
43
+ ): void {
44
+ getDb()
45
+ .insert(memoryCheckpoints)
46
+ .values({ key, value, updatedAt: now })
47
+ .onConflictDoUpdate({
48
+ target: memoryCheckpoints.key,
49
+ set: { value, updatedAt: now },
50
+ })
51
+ .run();
52
+ }
53
+
54
+ // ── Queries ──────────────────────────────────────────────────────
55
+
56
+ export function countActiveMemoryNodes(scopeId: string): number {
57
+ return (
58
+ rawGet<{ c: number }>(
59
+ `SELECT COUNT(*) AS c FROM memory_graph_nodes WHERE fidelity != 'gone' AND scope_id = ?`,
60
+ scopeId,
61
+ )?.c ?? 0
62
+ );
63
+ }
@@ -1,3 +1,6 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { basename, dirname, join, resolve, sep } from "node:path";
1
4
  import { Database } from "bun:sqlite";
2
5
 
3
6
  import { drizzle } from "drizzle-orm/bun-sqlite";
@@ -9,8 +12,67 @@ export type DrizzleDb = ReturnType<typeof drizzle<typeof schema>>;
9
12
 
10
13
  let db: DrizzleDb | null = null;
11
14
 
15
+ function canonicalizePathThroughExistingParent(path: string): string {
16
+ const resolvedPath = resolve(path);
17
+ const pendingSegments: string[] = [];
18
+ let currentPath = resolvedPath;
19
+
20
+ while (true) {
21
+ try {
22
+ return resolve(realpathSync(currentPath), ...pendingSegments.reverse());
23
+ } catch {
24
+ const parentPath = dirname(currentPath);
25
+ if (parentPath === currentPath) {
26
+ return resolvedPath;
27
+ }
28
+ pendingSegments.push(basename(currentPath));
29
+ currentPath = parentPath;
30
+ }
31
+ }
32
+ }
33
+
34
+ function assertTestDbIsIsolated(): void {
35
+ if (
36
+ process.env.NODE_ENV !== "test" ||
37
+ process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS === "1"
38
+ ) {
39
+ return;
40
+ }
41
+
42
+ const workspaceDir = process.env.VELLUM_WORKSPACE_DIR?.trim();
43
+ if (!workspaceDir) {
44
+ throw new Error(
45
+ [
46
+ "Refusing to open the assistant DB during tests without VELLUM_WORKSPACE_DIR.",
47
+ "Run assistant tests from the assistant package so the test preload can isolate state:",
48
+ " cd assistant && bun test src/path/to/file.test.ts",
49
+ ].join("\n"),
50
+ );
51
+ }
52
+
53
+ const resolvedWorkspaceDir =
54
+ canonicalizePathThroughExistingParent(workspaceDir);
55
+ const realWorkspaceDir = canonicalizePathThroughExistingParent(
56
+ process.env.VELLUM_TEST_REAL_WORKSPACE_DIR?.trim() ||
57
+ join(homedir(), ".vellum", "workspace"),
58
+ );
59
+ if (
60
+ resolvedWorkspaceDir === realWorkspaceDir ||
61
+ resolvedWorkspaceDir.startsWith(realWorkspaceDir + sep)
62
+ ) {
63
+ throw new Error(
64
+ [
65
+ "Refusing to open the real assistant workspace DB during tests.",
66
+ `VELLUM_WORKSPACE_DIR resolved to ${resolvedWorkspaceDir}.`,
67
+ "Use a temp workspace for tests instead.",
68
+ ].join("\n"),
69
+ );
70
+ }
71
+ }
72
+
12
73
  export function getDb(): DrizzleDb {
13
74
  if (!db) {
75
+ assertTestDbIsIsolated();
14
76
  ensureDataDir();
15
77
  const sqlite = new Database(getDbPath());
16
78
  sqlite.exec("PRAGMA journal_mode=WAL");
@@ -11,6 +11,7 @@ import { dirname, join } from "node:path";
11
11
 
12
12
  import { getLogger } from "../util/logger.js";
13
13
  import { ensureDataDir, getDbPath } from "../util/platform.js";
14
+ import { backfillAppConversationIds } from "./app-store.js";
14
15
  import { getDb, getSqlite } from "./db-connection.js";
15
16
  import { migrateToolCreatedItems } from "./graph/bootstrap.js";
16
17
  import {
@@ -66,6 +67,7 @@ import {
66
67
  migrateConversationsLastMessageAt,
67
68
  migrateConversationsThreadTypeIndex,
68
69
  migrateCreateConversationGraphMemoryState,
70
+ migrateCreateDocumentConversations,
69
71
  migrateCreateMemoryGraphNodeEdits,
70
72
  migrateCreateMemoryGraphTables,
71
73
  migrateCreateMemoryRecallLogs,
@@ -105,9 +107,11 @@ import {
105
107
  migrateLlmRequestLogMessageId,
106
108
  migrateLlmRequestLogProvider,
107
109
  migrateLlmRequestLogsCreatedAtIndex,
110
+ migrateLlmUsageAttribution,
108
111
  migrateMemoryGraphImageRefs,
109
112
  migrateMemoryItemSupersession,
110
113
  migrateMemoryRecallLogsQueryContext,
114
+ migrateMemoryV2ActivationLogs,
111
115
  migrateMessagesConversationCreatedAtIndex,
112
116
  migrateMessagesFtsBackfill,
113
117
  migrateNormalizePhoneIdentities,
@@ -154,9 +158,11 @@ import {
154
158
  migrateScheduleWakeConversationId,
155
159
  migrateSchemaIndexesAndColumns,
156
160
  migrateScrubCorruptedImageAttachments,
161
+ migrateSlackCompactionWatermark,
157
162
  migrateStripIntegrationPrefixFromProviderKeys,
158
163
  migrateStripPlaceholderSentinelsFromMessages,
159
164
  migrateStripThinkingFromConsolidated,
165
+ migrateToolInvocationsMatchedRuleId,
160
166
  migrateUsageDashboardIndexes,
161
167
  migrateUsageLlmCallCount,
162
168
  migrateVoiceInviteColumns,
@@ -390,6 +396,14 @@ export function initializeDb(): void {
390
396
  migrate230AcpSessionHistory,
391
397
  migrate231RepairMemoryGraphEventDates,
392
398
  migrateActivationState,
399
+ migrateMemoryV2ActivationLogs,
400
+ migrateCreateDocumentConversations,
401
+ migrateLlmUsageAttribution,
402
+ migrateSlackCompactionWatermark,
403
+ migrateToolInvocationsMatchedRuleId,
404
+ function migrateBackfillAppConversationIds() {
405
+ backfillAppConversationIds();
406
+ },
393
407
  ];
394
408
 
395
409
  // Run each migration step, catching and logging individual failures so one
@@ -11,8 +11,11 @@ import { GeminiEmbeddingBackend } from "./embedding-gemini.js";
11
11
  import { OllamaEmbeddingBackend } from "./embedding-ollama.js";
12
12
  import { OpenAIEmbeddingBackend } from "./embedding-openai.js";
13
13
  import {
14
+ type EmbeddingBackend,
14
15
  type EmbeddingInput,
15
16
  embeddingInputContentHash,
17
+ type EmbeddingProviderName,
18
+ type EmbeddingRequestOptions,
16
19
  type MultimodalEmbeddingInput,
17
20
  normalizeEmbeddingInput,
18
21
  type SparseEmbedding,
@@ -20,7 +23,6 @@ import {
20
23
  } from "./embedding-types.js";
21
24
 
22
25
  export type { EmbeddingInput, MultimodalEmbeddingInput, TextEmbeddingInput };
23
- export { embeddingInputContentHash, normalizeEmbeddingInput };
24
26
 
25
27
  const log = getLogger("memory-embeddings");
26
28
 
@@ -263,22 +265,6 @@ function geminiCacheExtras(config: AssistantConfig): string[] {
263
265
  return extras;
264
266
  }
265
267
 
266
- export type EmbeddingProviderName = "local" | "openai" | "gemini" | "ollama";
267
-
268
- export interface EmbeddingRequestOptions {
269
- signal?: AbortSignal;
270
- }
271
-
272
- export interface EmbeddingBackend {
273
- readonly provider: EmbeddingProviderName;
274
- readonly model: string;
275
- embed(
276
- inputs: EmbeddingInput[],
277
- options?: EmbeddingRequestOptions,
278
- ): Promise<number[][]>;
279
- dispose?(): void;
280
- }
281
-
282
268
  export interface EmbeddingBackendSelection {
283
269
  backend: EmbeddingBackend | null;
284
270
  reason: string | null;
@@ -637,10 +623,6 @@ export async function embedWithBackend(
637
623
  throw lastErr;
638
624
  }
639
625
 
640
- export function logMemoryEmbeddingWarning(err: unknown, context: string): void {
641
- log.warn({ err }, `Memory embeddings failed (${context})`);
642
- }
643
-
644
626
  async function selectFallbackBackends(
645
627
  config: AssistantConfig,
646
628
  exclude: EmbeddingProviderName,
@@ -2,8 +2,6 @@ import type {
2
2
  EmbeddingBackend,
3
3
  EmbeddingInput,
4
4
  EmbeddingRequestOptions,
5
- } from "./embedding-backend.js";
6
- import type {
7
5
  EmbeddingTaskType,
8
6
  MultimodalEmbeddingInput,
9
7
  } from "./embedding-types.js";
@@ -14,13 +14,13 @@ import {
14
14
  getEmbedWorkerPidPath,
15
15
  } from "../util/platform.js";
16
16
  import { PromiseGuard } from "../util/promise-guard.js";
17
- import type {
18
- EmbeddingBackend,
19
- EmbeddingInput,
20
- EmbeddingRequestOptions,
21
- } from "./embedding-backend.js";
22
17
  import { EmbeddingRuntimeManager } from "./embedding-runtime-manager.js";
23
- import { normalizeEmbeddingInput } from "./embedding-types.js";
18
+ import {
19
+ type EmbeddingBackend,
20
+ type EmbeddingInput,
21
+ type EmbeddingRequestOptions,
22
+ normalizeEmbeddingInput,
23
+ } from "./embedding-types.js";
24
24
 
25
25
  const log = getLogger("memory-embedding-local");
26
26
 
@@ -1,10 +1,10 @@
1
1
  import { getOllamaBaseUrlEnv } from "../config/env.js";
2
- import type {
3
- EmbeddingBackend,
4
- EmbeddingInput,
5
- EmbeddingRequestOptions,
6
- } from "./embedding-backend.js";
7
- import { normalizeEmbeddingInput } from "./embedding-types.js";
2
+ import {
3
+ type EmbeddingBackend,
4
+ type EmbeddingInput,
5
+ type EmbeddingRequestOptions,
6
+ normalizeEmbeddingInput,
7
+ } from "./embedding-types.js";
8
8
 
9
9
  interface OllamaEmbeddingsResponse {
10
10
  data?: Array<{ embedding: number[] }>;
@@ -1,11 +1,11 @@
1
1
  import OpenAI from "openai";
2
2
 
3
- import type {
4
- EmbeddingBackend,
5
- EmbeddingInput,
6
- EmbeddingRequestOptions,
7
- } from "./embedding-backend.js";
8
- import { normalizeEmbeddingInput } from "./embedding-types.js";
3
+ import {
4
+ type EmbeddingBackend,
5
+ type EmbeddingInput,
6
+ type EmbeddingRequestOptions,
7
+ normalizeEmbeddingInput,
8
+ } from "./embedding-types.js";
9
9
 
10
10
  export class OpenAIEmbeddingBackend implements EmbeddingBackend {
11
11
  readonly provider = "openai" as const;
@@ -67,3 +67,24 @@ export function embeddingInputContentHash(input: EmbeddingInput): string {
67
67
  }
68
68
  return hash.digest("hex");
69
69
  }
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Backend interface types (extracted from embedding-backend.ts to break
73
+ // circular imports between the factory and provider implementations)
74
+ // ---------------------------------------------------------------------------
75
+
76
+ export type EmbeddingProviderName = "local" | "openai" | "gemini" | "ollama";
77
+
78
+ export interface EmbeddingRequestOptions {
79
+ signal?: AbortSignal;
80
+ }
81
+
82
+ export interface EmbeddingBackend {
83
+ readonly provider: EmbeddingProviderName;
84
+ readonly model: string;
85
+ embed(
86
+ inputs: EmbeddingInput[],
87
+ options?: EmbeddingRequestOptions,
88
+ ): Promise<number[][]>;
89
+ dispose?(): void;
90
+ }
@@ -140,10 +140,6 @@ beforeAll(() => {
140
140
  // Seed v2 layout with a single concept page so the real injection module
141
141
  // has something concrete to render. Generic placeholders only.
142
142
  mkdirSync(join(tmpWorkspace, "memory", "concepts"), { recursive: true });
143
- writeFileSync(
144
- join(tmpWorkspace, "memory", "edges.json"),
145
- JSON.stringify({ version: 1, edges: [] }),
146
- );
147
143
  writeFileSync(
148
144
  join(tmpWorkspace, "memory", "concepts", "alice-vscode.md"),
149
145
  `---\nedges: []\nref_files: []\n---\nAlice prefers VS Code as her editor.`,
@@ -337,7 +333,7 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
337
333
 
338
334
  expect(result.mode).toBe("per-turn");
339
335
  expect(result.injectedBlockText).not.toBeNull();
340
- expect(result.injectedBlockText).toContain("<memory __injected>");
336
+ expect(result.injectedBlockText).toContain("<memory>");
341
337
  expect(result.injectedBlockText).toContain("### alice-vscode");
342
338
 
343
339
  // The leading content block on the user message is the v2 block.
@@ -346,7 +342,7 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
346
342
  const firstBlock = lastMsg?.content[0];
347
343
  expect(firstBlock?.type).toBe("text");
348
344
  if (firstBlock?.type !== "text") throw new Error("unexpected block type");
349
- expect(firstBlock.text).toContain("<memory __injected>");
345
+ expect(firstBlock.text).toContain("<memory>");
350
346
  });
351
347
 
352
348
  test("flag on + config on with empty Qdrant hits → no v2 block, v1 fallback skipped", async () => {
@@ -388,7 +384,7 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load pat
388
384
 
389
385
  expect(result.mode).toBe("context-load");
390
386
  expect(result.injectedBlockText).not.toBeNull();
391
- expect(result.injectedBlockText).toContain("<memory __injected>");
387
+ expect(result.injectedBlockText).toContain("<memory>");
392
388
  });
393
389
 
394
390
  test("flag off → v2 not run on first turn either", async () => {
@@ -235,7 +235,7 @@ export class ConversationGraphMemory {
235
235
  }
236
236
  // Re-track node IDs since onCompacted evicted them
237
237
  this.tracker.add(this.lastInjectedNodeIds);
238
- // Strip any existing <memory __injected> blocks from the last user message
238
+ // Strip any existing <memory> blocks from the last user message
239
239
  // before re-injecting, so compaction sites don't end up with duplicates.
240
240
  const cleaned = stripExistingMemoryInjections(messages);
241
241
 
@@ -264,7 +264,7 @@ export class ConversationGraphMemory {
264
264
  * Re-register cached node IDs with the InContextTracker after compaction
265
265
  * WITHOUT modifying messages. Use this at post-agent-loop compaction sites
266
266
  * where the memory block already survives on the original user message
267
- * (since `<memory __injected>` is not stripped by stripInjectionsForCompaction).
267
+ * (since `<memory>` is not stripped by stripInjectionsForCompaction).
268
268
  *
269
269
  * Calling reinjectCachedMemory at these sites would inject a duplicate
270
270
  * onto the last user message — which after tool calls is a tool_result,
@@ -403,11 +403,17 @@ export class ConversationGraphMemory {
403
403
  // assistantMessage is empty: context-load fires on turn 1 / post-
404
404
  // compaction, so there is no immediately-prior assistant turn to
405
405
  // weight the activation against.
406
+ //
407
+ // Use the raw user text (no >10-char filter) so even short greetings
408
+ // ("hi") get a fresh top-K activation dump on the first user message.
409
+ // The activation pipeline is robust to weak ANN signal — it still falls
410
+ // back to spreading + nowText to surface candidates.
411
+ const rawUserText = readRawUserText(messages[messages.length - 1]);
406
412
  const v2 = await this.maybeRouteV2Injection(
407
413
  messages,
408
414
  config,
409
415
  "context-load",
410
- userQuery ?? "",
416
+ rawUserText ?? userQuery ?? "",
411
417
  "",
412
418
  );
413
419
  if (v2.routed) {
@@ -699,7 +705,7 @@ export class ConversationGraphMemory {
699
705
  * Count the leading content blocks on a user message that were added by
700
706
  * `injectMemoryBlock`. Memory-injected images use a 3-block pattern
701
707
  * (opening `<memory_image>` text + image + closing `</memory_image>` text),
702
- * followed by a `<memory __injected>…</memory>` text block. A legacy
708
+ * followed by a `<memory>…</memory>` text block (legacy `<memory __injected>` is also accepted). A legacy
703
709
  * 2-block image pattern (no closing tag) is also accepted for backward
704
710
  * compatibility. The injection prefix is always contiguous at the start,
705
711
  * so we stop at the first non-memory block.
@@ -712,7 +718,8 @@ export function countMemoryPrefixBlocks(content: ContentBlock[]): number {
712
718
  const block = content[firstNonMemory];
713
719
  if (
714
720
  block.type === "text" &&
715
- block.text.startsWith("<memory __injected>\n")
721
+ (block.text.startsWith("<memory>\n") ||
722
+ block.text.startsWith("<memory __injected>\n"))
716
723
  ) {
717
724
  firstNonMemory++;
718
725
  prevWasMemoryImageMarker = false;
@@ -747,7 +754,7 @@ export function countMemoryPrefixBlocks(content: ContentBlock[]): number {
747
754
  *
748
755
  * `injectMemoryBlock` always prepends blocks in this order:
749
756
  * 1. For each image: `<memory_image __injected>…` text + `image` + `</memory_image>` text (3-block group)
750
- * 2. `<memory __injected>…</memory>` text block
757
+ * 2. `<memory>…</memory>` text block
751
758
  *
752
759
  * We strip all leading blocks that match this pattern so that
753
760
  * `reinjectCachedMemory` is idempotent — no duplicate images after compaction.
@@ -795,7 +802,7 @@ function injectTextBlock(messages: Message[], text: string): Message[] {
795
802
  content: [
796
803
  {
797
804
  type: "text" as const,
798
- text: `<memory __injected>\n${text}\n</memory>`,
805
+ text: `<memory>\n${text}\n</memory>`,
799
806
  },
800
807
  ...userTail.content,
801
808
  ],
@@ -839,7 +846,7 @@ function injectMemoryBlock(
839
846
 
840
847
  blocks.push({
841
848
  type: "text" as const,
842
- text: `<memory __injected>\n${text}\n</memory>`,
849
+ text: `<memory>\n${text}\n</memory>`,
843
850
  });
844
851
 
845
852
  return [
@@ -848,20 +855,35 @@ function injectMemoryBlock(
848
855
  ];
849
856
  }
850
857
 
851
- /** Extract text content from a user message. */
858
+ /**
859
+ * Extract text content from a user message for v1's `loadContextMemory`,
860
+ * skipping very short messages because v1's path embeds a single dense
861
+ * vector and short queries produce vague results.
862
+ */
852
863
  function extractUserText(message: Message): string | null {
864
+ const joined = readRawUserText(message);
865
+ if (!joined) return null;
866
+ return joined.length > 10 ? joined : null;
867
+ }
868
+
869
+ /**
870
+ * Raw user-text reader (no length filter). The v2 activation pipeline can
871
+ * use even short queries because it spreads activation through the edge
872
+ * graph and combines user/assistant/now signals, so the ≤10-char guard
873
+ * v1 needs would unnecessarily starve v2 on short greetings.
874
+ */
875
+ function readRawUserText(message: Message | undefined): string | null {
876
+ if (!message) return null;
853
877
  const texts = message.content
854
878
  .filter((b): b is Extract<typeof b, { type: "text" }> => b.type === "text")
855
879
  .map((b) => b.text.trim())
856
880
  .filter((t) => t.length > 0);
857
881
  if (texts.length === 0) return null;
858
- const joined = texts.join(" ");
859
- // Skip very short messages ("hi", "yes") — they produce vague embeddings
860
- return joined.length > 10 ? joined : null;
882
+ return texts.join(" ");
861
883
  }
862
884
 
863
885
  /**
864
- * Prepend a pre-rendered `<memory __injected>` block (produced by
886
+ * Prepend a pre-rendered `<memory>` block (produced by
865
887
  * `injectMemoryV2Block`) to the last user message. Unlike v1's
866
888
  * {@link injectMemoryBlock}, the input here is already wrapped — we
867
889
  * just need to attach it as a leading text block. We still strip any
@@ -192,9 +192,9 @@ describe("assembleContextBlock", () => {
192
192
  expect(assembleContextBlock([])).toBe("");
193
193
  });
194
194
 
195
- test("includes the main heading", () => {
195
+ test("omits the legacy `What I Remember Right Now` heading", () => {
196
196
  const result = assembleContextBlock([makeScored()]);
197
- expect(result).toContain("## What I Remember Right Now");
197
+ expect(result).not.toContain("## What I Remember Right Now");
198
198
  });
199
199
 
200
200
  test("puts prospective nodes under Active Threads", () => {
@@ -381,7 +381,7 @@ export function assembleContextBlock(
381
381
  }
382
382
 
383
383
  if (parts.length === 0) return "";
384
- return `## What I Remember Right Now\n\n${parts.join("\n\n")}`;
384
+ return parts.join("\n\n");
385
385
  }
386
386
 
387
387
  function buildSection(nodes: ScoredNode[], maxItems: number): string[] {