@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f

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 (866) hide show
  1. package/ARCHITECTURE.md +94 -91
  2. package/Dockerfile +5 -16
  3. package/README.md +7 -10
  4. package/bun.lock +0 -4
  5. package/docs/architecture/security.md +20 -20
  6. package/docs/stt-provider-onboarding.md +4 -5
  7. package/docs/trusted-contact-access.md +7 -7
  8. package/eslint-rules/cli-no-daemon-internals.js +4 -0
  9. package/eslint.config.mjs +7 -1
  10. package/knip.json +0 -1
  11. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
  12. package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
  13. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
  14. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
  15. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  16. package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
  17. package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
  18. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
  19. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
  21. package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
  22. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
  23. package/openapi.yaml +1073 -225
  24. package/package.json +1 -4
  25. package/scripts/test.sh +35 -13
  26. package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
  27. package/src/__tests__/acp-session.test.ts +4 -1
  28. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
  29. package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
  30. package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
  31. package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
  32. package/src/__tests__/app-source-watcher.test.ts +11 -0
  33. package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
  34. package/src/__tests__/assistant-attachments.test.ts +62 -4
  35. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
  36. package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
  37. package/src/__tests__/attachments-store.test.ts +3 -0
  38. package/src/__tests__/background-shell-bash.test.ts +34 -0
  39. package/src/__tests__/background-shell-host-bash.test.ts +12 -0
  40. package/src/__tests__/background-tool-registry.test.ts +97 -0
  41. package/src/__tests__/background-tool-routes.test.ts +72 -1
  42. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
  43. package/src/__tests__/btw-routes.test.ts +57 -3
  44. package/src/__tests__/call-controller.test.ts +474 -84
  45. package/src/__tests__/call-domain.test.ts +48 -1
  46. package/src/__tests__/call-pointer-messages.test.ts +57 -19
  47. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
  48. package/src/__tests__/call-routes-http.test.ts +15 -14
  49. package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
  50. package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
  51. package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
  52. package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
  53. package/src/__tests__/call-setup-flow.test.ts +311 -0
  54. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
  55. package/src/__tests__/channel-guardian.test.ts +4 -7
  56. package/src/__tests__/channel-readiness-service.test.ts +0 -6
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
  58. package/src/__tests__/channel-retry-sweep.test.ts +76 -64
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
  60. package/src/__tests__/clear-all-lexical.test.ts +90 -0
  61. package/src/__tests__/compactor-media-strip.test.ts +177 -0
  62. package/src/__tests__/config-loader-backfill.test.ts +5 -5
  63. package/src/__tests__/config-schema.test.ts +17 -0
  64. package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
  65. package/src/__tests__/contacts-relay-reads.test.ts +188 -23
  66. package/src/__tests__/contacts-tools.test.ts +42 -1
  67. package/src/__tests__/contacts-write.test.ts +181 -0
  68. package/src/__tests__/context-search-conversations-source.test.ts +220 -81
  69. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
  70. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  71. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  72. package/src/__tests__/conversation-agent-loop.test.ts +39 -0
  73. package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
  74. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
  75. package/src/__tests__/conversation-clear-safety.test.ts +0 -1
  76. package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
  77. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
  78. package/src/__tests__/conversation-disk-view.test.ts +1 -0
  79. package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
  80. package/src/__tests__/conversation-error.test.ts +0 -18
  81. package/src/__tests__/conversation-fork-crud.test.ts +67 -0
  82. package/src/__tests__/conversation-history-web-search.test.ts +7 -137
  83. package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
  84. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
  85. package/src/__tests__/conversation-process-callsite.test.ts +37 -0
  86. package/src/__tests__/conversation-queue.test.ts +149 -0
  87. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
  88. package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
  89. package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
  90. package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
  91. package/src/__tests__/conversation-skill-tools.test.ts +73 -0
  92. package/src/__tests__/conversation-wipe.test.ts +20 -5
  93. package/src/__tests__/credential-prompt-route.test.ts +69 -0
  94. package/src/__tests__/credential-security-invariants.test.ts +1 -3
  95. package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
  96. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
  97. package/src/__tests__/edit-propagation.test.ts +56 -2
  98. package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
  99. package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
  100. package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
  101. package/src/__tests__/guardian-question-mode.test.ts +57 -0
  102. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  103. package/src/__tests__/guardian-wait-controller.test.ts +619 -0
  104. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
  105. package/src/__tests__/heic-fixture.ts +55 -0
  106. package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
  107. package/src/__tests__/http-conversation-lineage.test.ts +6 -1
  108. package/src/__tests__/image-conversion.test.ts +170 -0
  109. package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
  110. package/src/__tests__/introduction-card-resolver.test.ts +354 -0
  111. package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
  112. package/src/__tests__/invite-routes-http.test.ts +246 -420
  113. package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
  114. package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
  115. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
  116. package/src/__tests__/list-messages-attachments.test.ts +159 -0
  117. package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
  118. package/src/__tests__/list-messages-queued.test.ts +25 -0
  119. package/src/__tests__/managed-store.test.ts +129 -1
  120. package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
  121. package/src/__tests__/media-stream-output.test.ts +350 -19
  122. package/src/__tests__/media-stream-server-integration.test.ts +943 -169
  123. package/src/__tests__/media-stream-stt-session.test.ts +498 -1
  124. package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
  125. package/src/__tests__/model-intents.test.ts +1 -1
  126. package/src/__tests__/mtime-cache.test.ts +19 -0
  127. package/src/__tests__/non-member-access-request.test.ts +349 -3
  128. package/src/__tests__/notification-decision-fallback.test.ts +104 -8
  129. package/src/__tests__/notification-decision-strategy.test.ts +57 -8
  130. package/src/__tests__/onboarding-template-contract.test.ts +27 -43
  131. package/src/__tests__/openai-provider.test.ts +33 -0
  132. package/src/__tests__/openai-responses-provider.test.ts +40 -0
  133. package/src/__tests__/persistence-layering-guard.test.ts +29 -20
  134. package/src/__tests__/persona-resolver.test.ts +56 -2
  135. package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
  136. package/src/__tests__/phone.test.ts +1 -15
  137. package/src/__tests__/plugin-bootstrap.test.ts +25 -196
  138. package/src/__tests__/plugin-disabled-state.test.ts +33 -0
  139. package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
  140. package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
  141. package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
  142. package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
  143. package/src/__tests__/plugin-pipeline.test.ts +63 -1
  144. package/src/__tests__/plugin-route-contribution.test.ts +62 -115
  145. package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
  146. package/src/__tests__/plugin-types.test.ts +0 -1
  147. package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
  148. package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
  149. package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
  150. package/src/__tests__/public-ingress-urls.test.ts +0 -48
  151. package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
  152. package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
  153. package/src/__tests__/resolve-trust-class.test.ts +28 -10
  154. package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
  155. package/src/__tests__/schedule-retry.test.ts +38 -14
  156. package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
  157. package/src/__tests__/schedule-routes.test.ts +14 -6
  158. package/src/__tests__/schedule-store.test.ts +3 -1
  159. package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
  160. package/src/__tests__/scheduler-recurrence.test.ts +57 -107
  161. package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
  162. package/src/__tests__/scheduler-wake.test.ts +13 -23
  163. package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
  164. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
  165. package/src/__tests__/shell-observability.test.ts +1 -0
  166. package/src/__tests__/skill-boundary-guard.test.ts +3 -4
  167. package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
  168. package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
  169. package/src/__tests__/skill-script-runner-host.test.ts +53 -0
  170. package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
  171. package/src/__tests__/skill-tool-factory.test.ts +73 -1
  172. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
  173. package/src/__tests__/slack-inbound-verification.test.ts +36 -0
  174. package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
  175. package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
  176. package/src/__tests__/stt-hints.test.ts +2 -256
  177. package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
  178. package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
  179. package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
  180. package/src/__tests__/subagent-persistence.test.ts +122 -0
  181. package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
  182. package/src/__tests__/subagent-terminal-message.test.ts +99 -0
  183. package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
  184. package/src/__tests__/system-prompt.test.ts +17 -118
  185. package/src/__tests__/task-scheduler.test.ts +68 -89
  186. package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
  187. package/src/__tests__/telephony-tts-guard.test.ts +538 -0
  188. package/src/__tests__/title-generate-hook.test.ts +16 -0
  189. package/src/__tests__/tool-approval-handler.test.ts +87 -1
  190. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
  191. package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
  192. package/src/__tests__/trust-context-guards.test.ts +21 -10
  193. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
  194. package/src/__tests__/twilio-provider.test.ts +17 -17
  195. package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
  196. package/src/__tests__/twilio-routes.test.ts +257 -387
  197. package/src/__tests__/twilio-validation.test.ts +1 -1
  198. package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
  199. package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
  200. package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
  201. package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
  202. package/src/__tests__/voice-quality.test.ts +2 -2
  203. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
  204. package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
  205. package/src/__tests__/voice-session-bridge.test.ts +1 -10
  206. package/src/__tests__/workspace-git-service.test.ts +1 -1
  207. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
  208. package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
  209. package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
  210. package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
  211. package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
  212. package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
  213. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
  214. package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
  215. package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
  216. package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
  217. package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
  218. package/src/acp/__tests__/session-manager.test.ts +6 -0
  219. package/src/acp/agent-process.test.ts +116 -0
  220. package/src/acp/agent-process.ts +71 -0
  221. package/src/acp/auto-install.ts +12 -8
  222. package/src/acp/failure-error.test.ts +109 -0
  223. package/src/acp/failure-error.ts +111 -0
  224. package/src/acp/prepare-agent-env.ts +0 -12
  225. package/src/acp/resolve-agent.test.ts +6 -45
  226. package/src/acp/resolve-agent.ts +2 -4
  227. package/src/acp/session-manager.test.ts +312 -0
  228. package/src/acp/session-manager.ts +102 -46
  229. package/src/agent/ax-tree-compaction.test.ts +4 -1
  230. package/src/agent/image-optimize.ts +17 -127
  231. package/src/agent/loop.ts +45 -192
  232. package/src/api/events/background-tool-completed.test.ts +51 -0
  233. package/src/api/events/background-tool-completed.ts +29 -0
  234. package/src/api/events/background-tool-started.test.ts +36 -0
  235. package/src/api/events/background-tool-started.ts +28 -0
  236. package/src/api/events/conversation-error.ts +0 -1
  237. package/src/api/events/open-panel.ts +33 -0
  238. package/src/api/events/subagent-status-changed.ts +4 -1
  239. package/src/api/index.ts +19 -0
  240. package/src/api/responses/conversation-message.ts +34 -0
  241. package/src/approvals/guardian-decision-primitive.ts +74 -24
  242. package/src/approvals/guardian-request-resolvers.ts +450 -122
  243. package/src/apps/app-store.ts +1 -0
  244. package/src/apps/shared-app-links-store.ts +1 -0
  245. package/src/avatar/identity-avatar.ts +3 -7
  246. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  247. package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
  248. package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
  249. package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
  250. package/src/calls/call-controller.ts +134 -48
  251. package/src/calls/call-domain.ts +18 -42
  252. package/src/calls/call-pointer-messages.ts +51 -67
  253. package/src/calls/call-setup-flow-types.ts +76 -0
  254. package/src/calls/call-setup-flow.ts +1743 -0
  255. package/src/calls/call-speech-output.ts +87 -23
  256. package/src/calls/call-store.ts +4 -0
  257. package/src/calls/call-transport.ts +22 -36
  258. package/src/calls/fish-audio-client.ts +3 -0
  259. package/src/calls/gateway-invite-reader.ts +98 -0
  260. package/src/calls/guardian-wait-controller.ts +451 -0
  261. package/src/calls/media-stream-audio-transcode.ts +82 -2
  262. package/src/calls/media-stream-output.ts +142 -36
  263. package/src/calls/media-stream-server.ts +297 -178
  264. package/src/calls/media-stream-stt-session.ts +393 -50
  265. package/src/calls/media-turn-detector.ts +4 -6
  266. package/src/calls/relay-access-wait.ts +3 -4
  267. package/src/calls/relay-setup-router.ts +22 -43
  268. package/src/calls/relay-verification.ts +17 -24
  269. package/src/calls/resolve-call-tts-provider.ts +96 -29
  270. package/src/calls/stt-hints.ts +24 -87
  271. package/src/calls/telephony-credential-preflight.ts +159 -0
  272. package/src/calls/telephony-tts-capability.ts +183 -0
  273. package/src/calls/tts-call-strategy.ts +18 -20
  274. package/src/calls/twilio-provider.ts +3 -2
  275. package/src/calls/twilio-routes.ts +47 -351
  276. package/src/calls/types.ts +5 -3
  277. package/src/calls/voice-ingress-preflight.ts +9 -0
  278. package/src/calls/voice-quality.ts +13 -18
  279. package/src/calls/voice-session-bridge.ts +25 -35
  280. package/src/channels/__tests__/types.test.ts +28 -0
  281. package/src/channels/channel-verification-sessions.ts +7 -2
  282. package/src/channels/config.ts +0 -42
  283. package/src/channels/slack-thread-store.ts +12 -0
  284. package/src/channels/types.ts +23 -0
  285. package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
  286. package/src/cli/commands/__tests__/schedules.test.ts +83 -34
  287. package/src/cli/commands/__tests__/status.test.ts +42 -2
  288. package/src/cli/commands/contacts.ts +2 -2
  289. package/src/cli/commands/credentials.ts +17 -0
  290. package/src/cli/commands/monitoring.ts +191 -0
  291. package/src/cli/commands/schedules-worker.ts +175 -0
  292. package/src/cli/commands/schedules.ts +169 -43
  293. package/src/cli/commands/status.ts +12 -1
  294. package/src/cli/commands/tools.ts +5 -1
  295. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
  296. package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
  297. package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
  298. package/src/cli/lib/search-plugins.ts +6 -0
  299. package/src/cli/lib/toggle-plugin.ts +21 -2
  300. package/src/cli/program.ts +3 -1
  301. package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
  302. package/src/config/acp-defaults.test.ts +0 -10
  303. package/src/config/acp-defaults.ts +0 -6
  304. package/src/config/bundled-skills/acp/SKILL.md +13 -45
  305. package/src/config/bundled-skills/acp/TOOLS.json +3 -3
  306. package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
  307. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
  308. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
  309. package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
  310. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  311. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
  312. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
  313. package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
  314. package/src/config/call-site-defaults.ts +0 -2
  315. package/src/config/feature-flag-registry.json +16 -8
  316. package/src/config/loader.ts +11 -0
  317. package/src/config/schema.ts +9 -1
  318. package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
  319. package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
  320. package/src/config/schemas/call-site-catalog.ts +0 -12
  321. package/src/config/schemas/calls.ts +8 -0
  322. package/src/config/schemas/elevenlabs.ts +1 -1
  323. package/src/config/schemas/llm.ts +0 -2
  324. package/src/config/schemas/memory-v2.ts +1 -1
  325. package/src/config/schemas/memory-v3.ts +82 -0
  326. package/src/config/schemas/monitoring.ts +61 -0
  327. package/src/config/schemas/schedules.ts +35 -0
  328. package/src/config/seed-inference-profiles.ts +2 -2
  329. package/src/config/skills-plugin-filter.test.ts +96 -0
  330. package/src/config/skills.ts +26 -0
  331. package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
  332. package/src/contacts/canonical-guardian-store.ts +5 -0
  333. package/src/contacts/contact-store.ts +81 -35
  334. package/src/contacts/contacts-write.ts +50 -25
  335. package/src/contacts/member-write-relay.ts +115 -31
  336. package/src/contacts/types.ts +0 -8
  337. package/src/context/compactor.ts +29 -15
  338. package/src/context/outbound-sanitize.ts +202 -0
  339. package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
  340. package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
  341. package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
  342. package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
  343. package/src/daemon/abort-watchdog.ts +7 -0
  344. package/src/daemon/app-source-watcher.ts +9 -0
  345. package/src/daemon/assistant-attachments.ts +42 -0
  346. package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
  347. package/src/daemon/conversation-agent-loop.ts +61 -68
  348. package/src/daemon/conversation-error.ts +1 -15
  349. package/src/daemon/conversation-history.ts +32 -236
  350. package/src/daemon/conversation-initial-prompt.ts +77 -0
  351. package/src/daemon/conversation-lifecycle.ts +25 -1
  352. package/src/daemon/conversation-messaging.ts +2 -2
  353. package/src/daemon/conversation-plugin-scope.ts +38 -0
  354. package/src/daemon/conversation-process.ts +50 -14
  355. package/src/daemon/conversation-runtime-assembly.ts +36 -6
  356. package/src/daemon/conversation-skill-tools.ts +19 -3
  357. package/src/daemon/conversation-store.ts +3 -3
  358. package/src/daemon/conversation-surfaces.ts +171 -0
  359. package/src/daemon/conversation-tool-setup.test.ts +95 -0
  360. package/src/daemon/conversation-tool-setup.ts +116 -1
  361. package/src/daemon/conversation-turn-finalize.ts +211 -0
  362. package/src/daemon/conversation.ts +92 -1
  363. package/src/daemon/disk-pressure-policy.ts +2 -1
  364. package/src/daemon/event-loop-watchdog.ts +22 -6
  365. package/src/daemon/external-plugins-bootstrap.ts +47 -134
  366. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  367. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
  368. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
  369. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
  370. package/src/daemon/handlers/config-a2a.ts +7 -14
  371. package/src/daemon/handlers/config-channels.ts +2 -10
  372. package/src/daemon/handlers/conversation-history.ts +3 -1
  373. package/src/daemon/handlers/conversations.ts +0 -52
  374. package/src/daemon/handlers/shared.ts +4 -24
  375. package/src/daemon/handlers/skills.ts +4 -1
  376. package/src/daemon/host-cu-proxy.ts +1 -1
  377. package/src/daemon/lifecycle.ts +59 -472
  378. package/src/daemon/message-protocol.ts +3 -3
  379. package/src/daemon/message-provenance.ts +12 -14
  380. package/src/daemon/message-types/background-tools.ts +28 -0
  381. package/src/daemon/message-types/contacts.ts +2 -10
  382. package/src/daemon/message-types/conversations.ts +10 -0
  383. package/src/daemon/message-types/integrations.ts +2 -0
  384. package/src/daemon/message-types/surfaces.ts +1 -0
  385. package/src/daemon/message-types/sync.ts +1 -0
  386. package/src/daemon/pointer-conversation-trust.ts +23 -9
  387. package/src/daemon/pointer-turn-runner.ts +174 -0
  388. package/src/daemon/providers-setup.ts +16 -0
  389. package/src/daemon/shutdown-handlers.ts +139 -47
  390. package/src/daemon/skill-memory-refresh.ts +2 -2
  391. package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
  392. package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
  393. package/src/daemon/tool-setup-types.ts +8 -0
  394. package/src/daemon/trust-context.ts +21 -6
  395. package/src/daemon/turn-latency-tracker.test.ts +93 -0
  396. package/src/daemon/turn-latency-tracker.ts +38 -0
  397. package/src/daemon/wake-conversation-ops.ts +10 -8
  398. package/src/documents/document-comments-store.test.ts +7 -1
  399. package/src/documents/document-comments-store.ts +8 -0
  400. package/src/documents/document-store.ts +15 -0
  401. package/src/export/__tests__/transcript-formatter.test.ts +11 -0
  402. package/src/export/transcript-formatter.ts +49 -67
  403. package/src/home/__tests__/feed-writer.test.ts +247 -1
  404. package/src/home/conversation-starter-checkpoints.ts +1 -0
  405. package/src/home/feed-writer.ts +61 -0
  406. package/src/home/job-handlers/conversation-starters.ts +1 -0
  407. package/src/hooks/hook-loader.ts +12 -0
  408. package/src/hooks/registry.ts +32 -4
  409. package/src/inbound/public-ingress-urls.ts +0 -17
  410. package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
  411. package/src/ipc/assistant-server.ts +28 -7
  412. package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
  413. package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
  414. package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
  415. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
  416. package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
  417. package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
  418. package/src/ipc/routes/db-proxy.ts +5 -2
  419. package/src/ipc/routes/invite-ipc-routes.ts +53 -39
  420. package/src/jobs/worker.ts +9 -2
  421. package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
  422. package/src/live-voice/live-voice-archive.ts +5 -0
  423. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
  424. package/src/messaging/providers/channel-transport.ts +6 -0
  425. package/src/messaging/providers/index.ts +3 -0
  426. package/src/messaging/providers/slack/api.test.ts +49 -1
  427. package/src/messaging/providers/slack/api.ts +110 -0
  428. package/src/messaging/providers/slack/send.test.ts +85 -0
  429. package/src/messaging/providers/slack/send.ts +100 -28
  430. package/src/messaging/providers/slack/transport.ts +7 -13
  431. package/src/messaging/providers/whatsapp/send.ts +29 -9
  432. package/src/monitoring/__tests__/control.test.ts +235 -0
  433. package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
  434. package/src/monitoring/control.ts +105 -0
  435. package/src/monitoring/resource-sampler.ts +258 -0
  436. package/src/monitoring/sample-ring-buffer.ts +108 -0
  437. package/src/monitoring/worker.ts +94 -0
  438. package/src/notifications/README.md +1 -1
  439. package/src/notifications/access-request-copy.ts +94 -23
  440. package/src/notifications/adapters/slack.ts +89 -21
  441. package/src/notifications/approval-card-builder.ts +33 -18
  442. package/src/notifications/approval-card-data.ts +48 -15
  443. package/src/notifications/broadcaster.ts +25 -16
  444. package/src/notifications/decision-engine.ts +131 -32
  445. package/src/notifications/guardian-question-mode.ts +58 -10
  446. package/src/permissions/approval-policy.ts +8 -1
  447. package/src/permissions/checker.ts +2 -0
  448. package/src/permissions/gateway-threshold-reader.ts +7 -6
  449. package/src/permissions/ipc-risk-types.ts +1 -0
  450. package/src/permissions/secret-prompter.ts +11 -3
  451. package/src/permissions/types.ts +2 -2
  452. package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
  453. package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
  454. package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
  455. package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
  456. package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
  457. package/src/persistence/a2a-invite-store.ts +205 -0
  458. package/src/persistence/attachments-store.ts +94 -10
  459. package/src/persistence/checkpoints.ts +45 -0
  460. package/src/persistence/conversation-crud.ts +453 -260
  461. package/src/persistence/conversation-display-order-migration.ts +8 -2
  462. package/src/persistence/conversation-group-migration.test.ts +8 -0
  463. package/src/persistence/conversation-group-migration.ts +9 -0
  464. package/src/persistence/conversation-queries.ts +244 -125
  465. package/src/persistence/conversation-row-batch-delete.ts +9 -5
  466. package/src/persistence/conversation-search-lexical.ts +49 -0
  467. package/src/persistence/db-async-query.ts +42 -0
  468. package/src/persistence/db-connection.ts +13 -0
  469. package/src/persistence/delivery-channels.ts +0 -82
  470. package/src/persistence/delivery-crud.ts +27 -6
  471. package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
  472. package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
  473. package/src/persistence/embeddings/embedding-identity.ts +17 -5
  474. package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
  475. package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
  476. package/src/persistence/embeddings/qdrant-client.ts +81 -5
  477. package/src/persistence/group-crud.ts +13 -1
  478. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
  479. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
  480. package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
  481. package/src/persistence/job-handlers/cleanup.ts +57 -9
  482. package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
  483. package/src/persistence/job-handlers/message-lexical.ts +251 -0
  484. package/src/persistence/jobs-store.ts +102 -8
  485. package/src/persistence/jobs-worker.ts +68 -28
  486. package/src/persistence/llm-request-log-store.ts +35 -19
  487. package/src/persistence/llm-usage-store.ts +11 -0
  488. package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
  489. package/src/persistence/memory-lifecycle-hooks.ts +55 -1
  490. package/src/persistence/migrations/028-call-session-mode.ts +1 -1
  491. package/src/persistence/migrations/116-messages-fts.ts +8 -1
  492. package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
  493. package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
  494. package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
  495. package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
  496. package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
  497. package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
  498. package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
  499. package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
  500. package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
  501. package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
  502. package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
  503. package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
  504. package/src/persistence/raw-query.ts +50 -11
  505. package/src/persistence/schema/a2a.ts +14 -0
  506. package/src/persistence/schema/contacts.ts +0 -62
  507. package/src/persistence/schema/conversation-groups.ts +12 -0
  508. package/src/persistence/schema/conversations.ts +2 -0
  509. package/src/persistence/schema/documents.ts +65 -0
  510. package/src/persistence/schema/guardian.ts +4 -0
  511. package/src/persistence/schema/index.ts +4 -0
  512. package/src/persistence/schema/memory-injection.ts +62 -0
  513. package/src/persistence/schema/workflows.ts +55 -0
  514. package/src/persistence/slow-query-log.ts +437 -0
  515. package/src/persistence/slow-sync-log.ts +204 -0
  516. package/src/persistence/steps.ts +16 -0
  517. package/src/persistence/subagent-store.ts +125 -0
  518. package/src/persistence/worker-control.ts +45 -238
  519. package/src/plugin-api/event-hub-facade.ts +172 -0
  520. package/src/plugin-api/index.ts +9 -1
  521. package/src/plugin-api/types.ts +40 -9
  522. package/src/plugins/defaults/default-plugin-names.ts +60 -0
  523. package/src/plugins/defaults/index.ts +19 -29
  524. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
  525. package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
  526. package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
  527. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
  528. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
  529. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
  530. package/src/plugins/defaults/memory/config.ts +11 -0
  531. package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
  532. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
  533. package/src/plugins/defaults/memory/embeddings.ts +77 -0
  534. package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
  535. package/src/plugins/defaults/memory/frontmatter.ts +50 -0
  536. package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
  537. package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
  538. package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
  539. package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
  540. package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
  541. package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
  542. package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
  543. package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
  544. package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
  545. package/src/plugins/defaults/memory/graph/tools.ts +1 -1
  546. package/src/plugins/defaults/memory/hooks/init.ts +31 -5
  547. package/src/plugins/defaults/memory/indexer.ts +2 -3
  548. package/src/plugins/defaults/memory/injectors.ts +2 -2
  549. package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
  550. package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
  551. package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
  552. package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
  553. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
  554. package/src/plugins/defaults/memory/job-handlers.ts +13 -12
  555. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
  556. package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
  557. package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
  558. package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
  559. package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
  560. package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
  561. package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
  562. package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
  563. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
  564. package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
  565. package/src/plugins/defaults/memory/search/semantic.ts +2 -2
  566. package/src/plugins/defaults/memory/startup.ts +244 -0
  567. package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
  568. package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
  569. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
  570. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
  571. package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
  572. package/src/plugins/defaults/memory/v2/activation.ts +2 -4
  573. package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
  574. package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
  575. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
  576. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
  577. package/src/plugins/defaults/memory/v2/migration.ts +2 -5
  578. package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
  579. package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
  580. package/src/plugins/defaults/memory/v2/router.ts +5 -5
  581. package/src/plugins/defaults/memory/v2/sim.ts +2 -4
  582. package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
  583. package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
  584. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
  585. package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
  586. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
  587. package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
  588. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
  589. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
  590. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
  591. package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
  592. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
  593. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
  594. package/src/plugins/defaults/memory/v3/card.ts +1 -4
  595. package/src/plugins/defaults/memory/v3/dense.ts +60 -25
  596. package/src/plugins/defaults/memory/v3/edge.ts +1 -1
  597. package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
  598. package/src/plugins/defaults/memory/v3/gate.ts +158 -0
  599. package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
  600. package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
  601. package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
  602. package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
  603. package/src/plugins/defaults/memory/v3/prune.ts +2 -2
  604. package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
  605. package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
  606. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
  607. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
  608. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
  609. package/src/plugins/defaults/turn-context/injectors.ts +1 -0
  610. package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
  611. package/src/plugins/injector-registry.ts +13 -2
  612. package/src/plugins/mtime-cache.ts +36 -47
  613. package/src/plugins/pipeline.ts +15 -1
  614. package/src/plugins/types.ts +14 -23
  615. package/src/prompts/__tests__/system-prompt.test.ts +170 -32
  616. package/src/prompts/persona-resolver.ts +13 -9
  617. package/src/prompts/system-prompt.ts +30 -9
  618. package/src/prompts/templates/BOOTSTRAP.md +16 -119
  619. package/src/prompts/templates/SOUL.md +43 -13
  620. package/src/prompts/templates/system-sections.ts +32 -27
  621. package/src/prompts/templates/users/default.md +19 -0
  622. package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
  623. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
  624. package/src/providers/model-intents.ts +2 -2
  625. package/src/providers/openai/chat-completions-provider.ts +14 -1
  626. package/src/providers/openai/responses-provider.ts +18 -0
  627. package/src/providers/placeholder-sentinels.ts +18 -8
  628. package/src/providers/retry.ts +1 -0
  629. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
  630. package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
  631. package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
  632. package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
  633. package/src/providers/speech-to-text/provider-catalog.ts +0 -89
  634. package/src/providers/speech-to-text/resolve.ts +55 -0
  635. package/src/providers/tool-progress-events.test.ts +50 -0
  636. package/src/providers/tool-progress-events.ts +99 -0
  637. package/src/providers/types.ts +1 -1
  638. package/src/providers/vellum-model-routing.test.ts +51 -0
  639. package/src/providers/vellum-model-routing.ts +84 -0
  640. package/src/runtime/AGENTS.md +5 -4
  641. package/src/runtime/__tests__/agent-wake.test.ts +158 -1
  642. package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
  643. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
  644. package/src/runtime/access-request-helper.ts +154 -3
  645. package/src/runtime/actor-trust-resolver.ts +7 -21
  646. package/src/runtime/agent-wake.ts +41 -1
  647. package/src/runtime/assistant-event.ts +86 -12
  648. package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
  649. package/src/runtime/channel-approval-types.ts +52 -2
  650. package/src/runtime/channel-approvals.ts +23 -8
  651. package/src/runtime/channel-invite-transport.ts +2 -2
  652. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  653. package/src/runtime/channel-readiness-service.ts +3 -5
  654. package/src/runtime/channel-retry-sweep.ts +18 -24
  655. package/src/runtime/channel-verification-service.ts +9 -11
  656. package/src/runtime/finalize-event-delivery.ts +30 -16
  657. package/src/runtime/guardian-action-service.ts +10 -11
  658. package/src/runtime/guardian-reply-router.ts +122 -21
  659. package/src/runtime/http-server.ts +44 -101
  660. package/src/runtime/introduction-policy.test.ts +214 -0
  661. package/src/runtime/introduction-policy.ts +284 -0
  662. package/src/runtime/invite-service.ts +104 -361
  663. package/src/runtime/local-actor-identity.test.ts +38 -0
  664. package/src/runtime/local-actor-identity.ts +14 -0
  665. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
  666. package/src/runtime/middleware/rate-limiter.ts +30 -0
  667. package/src/runtime/middleware/twilio-validation.ts +5 -7
  668. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
  669. package/src/runtime/migrations/origin-mode.ts +6 -6
  670. package/src/runtime/pre-first-message-gate.ts +1 -0
  671. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
  672. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
  673. package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
  674. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
  675. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
  676. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
  677. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
  678. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
  679. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
  680. package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
  681. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
  682. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
  683. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
  684. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
  685. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
  686. package/src/runtime/routes/acp-routes.ts +15 -3
  687. package/src/runtime/routes/app-management-routes.ts +4 -7
  688. package/src/runtime/routes/approval-routes.ts +4 -0
  689. package/src/runtime/routes/attachment-routes.ts +54 -3
  690. package/src/runtime/routes/avatar-routes.ts +0 -4
  691. package/src/runtime/routes/background-tool-routes.ts +34 -5
  692. package/src/runtime/routes/btw-routes.ts +32 -4
  693. package/src/runtime/routes/channel-route-shared.ts +18 -14
  694. package/src/runtime/routes/channel-verification-routes.ts +0 -3
  695. package/src/runtime/routes/contact-routes.ts +298 -117
  696. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  697. package/src/runtime/routes/conversation-management-routes.ts +74 -37
  698. package/src/runtime/routes/conversation-query-routes.ts +5 -2
  699. package/src/runtime/routes/conversation-routes.ts +222 -82
  700. package/src/runtime/routes/conversations-import-routes.ts +8 -1
  701. package/src/runtime/routes/credential-prompt-routes.ts +20 -5
  702. package/src/runtime/routes/debug-routes.ts +1 -0
  703. package/src/runtime/routes/documents-routes.ts +5 -2
  704. package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
  705. package/src/runtime/routes/global-search-routes.ts +2 -1
  706. package/src/runtime/routes/guardian-approval-interception.ts +51 -0
  707. package/src/runtime/routes/home-feed-routes.ts +60 -1
  708. package/src/runtime/routes/identity-routes.ts +4 -87
  709. package/src/runtime/routes/inbound-message-handler.ts +82 -41
  710. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
  711. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
  712. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
  713. package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
  714. package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
  715. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
  716. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
  717. package/src/runtime/routes/index.ts +6 -0
  718. package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
  719. package/src/runtime/routes/internal-twilio-routes.ts +0 -15
  720. package/src/runtime/routes/messages-lexical-routes.ts +75 -0
  721. package/src/runtime/routes/migration-routes.ts +69 -6
  722. package/src/runtime/routes/monitoring-routes.ts +237 -0
  723. package/src/runtime/routes/plugins-routes.ts +329 -8
  724. package/src/runtime/routes/schedule-routes.ts +49 -8
  725. package/src/runtime/routes/schedule-worker-routes.ts +210 -0
  726. package/src/runtime/routes/secret-routes.ts +1 -1
  727. package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
  728. package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
  729. package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
  730. package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
  731. package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
  732. package/src/runtime/services/analyze-conversation.ts +14 -4
  733. package/src/runtime/services/conversation-serializer.ts +5 -0
  734. package/src/runtime/slack-no-response.ts +47 -0
  735. package/src/runtime/slack-reply-session.test.ts +633 -0
  736. package/src/runtime/slack-reply-session.ts +382 -0
  737. package/src/runtime/slack-task-progress.ts +95 -0
  738. package/src/runtime/sync/resource-sync-events.ts +25 -0
  739. package/src/runtime/tool-grant-request-helper.ts +17 -1
  740. package/src/runtime/trust-class.test.ts +141 -0
  741. package/src/runtime/trust-class.ts +121 -0
  742. package/src/runtime/trust-verdict-consumer.ts +7 -6
  743. package/src/schedule/__tests__/run-script.test.ts +21 -0
  744. package/src/schedule/__tests__/worker-control.test.ts +241 -0
  745. package/src/schedule/run-script.ts +13 -6
  746. package/src/schedule/schedule-usage-store.ts +1 -0
  747. package/src/schedule/scheduler.ts +178 -127
  748. package/src/schedule/worker-control.ts +118 -0
  749. package/src/schedule/worker.ts +131 -0
  750. package/src/skills/__tests__/categories-cache.test.ts +38 -0
  751. package/src/skills/categories-cache.ts +40 -5
  752. package/src/skills/managed-store.ts +41 -6
  753. package/src/skills/validate-input.ts +47 -0
  754. package/src/stt/types.ts +5 -9
  755. package/src/subagent/manager.ts +267 -39
  756. package/src/subagent/types.ts +6 -2
  757. package/src/subagent/validate-allowlists.ts +65 -0
  758. package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
  759. package/src/telemetry/watchdog-direct-emit.ts +89 -0
  760. package/src/tools/acp/list-agents.test.ts +0 -6
  761. package/src/tools/background-tool-registry.ts +61 -0
  762. package/src/tools/document/document-comment-tool.test.ts +4 -0
  763. package/src/tools/host-terminal/host-shell.test.ts +397 -0
  764. package/src/tools/host-terminal/host-shell.ts +203 -14
  765. package/src/tools/skills/find-similar-skills.test.ts +152 -1
  766. package/src/tools/skills/find-similar-skills.ts +30 -4
  767. package/src/tools/skills/load.ts +36 -0
  768. package/src/tools/skills/scaffold-managed.ts +66 -34
  769. package/src/tools/skills/skill-script-runner.ts +17 -0
  770. package/src/tools/skills/skill-tool-factory.ts +5 -1
  771. package/src/tools/terminal/safe-env.ts +3 -0
  772. package/src/tools/terminal/shell.test.ts +177 -0
  773. package/src/tools/terminal/shell.ts +98 -4
  774. package/src/tools/tool-approval-handler.ts +106 -29
  775. package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
  776. package/src/tools/types.ts +29 -17
  777. package/src/tools/ui-surface/definitions.ts +3 -1
  778. package/src/tts/__tests__/provider-adapters.test.ts +37 -0
  779. package/src/tts/__tests__/provider-catalog.test.ts +21 -0
  780. package/src/tts/provider-catalog.ts +40 -9
  781. package/src/tts/providers/fish-audio-provider.ts +19 -10
  782. package/src/tts/types.ts +3 -4
  783. package/src/util/__tests__/process-tree.test.ts +10 -2
  784. package/src/util/__tests__/text-spacing.test.ts +53 -0
  785. package/src/util/cgroup-memory.ts +142 -0
  786. package/src/util/image-conversion.ts +281 -0
  787. package/src/util/phone.ts +1 -8
  788. package/src/util/platform.ts +33 -0
  789. package/src/util/process-tree.ts +10 -2
  790. package/src/util/text-spacing.ts +53 -0
  791. package/src/util/worker-process.ts +271 -0
  792. package/src/workflows/journal-store.ts +16 -1
  793. package/src/workflows/library.test.ts +35 -20
  794. package/src/workflows/library.ts +105 -66
  795. package/src/workspace/git-service.ts +1 -0
  796. package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
  797. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
  798. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
  799. package/src/workspace/migrations/118-seed-now-md.ts +64 -0
  800. package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
  801. package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
  802. package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
  803. package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
  804. package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
  805. package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
  806. package/src/workspace/migrations/registry.ts +12 -0
  807. package/drizzle/0000_dizzy_maggott.sql +0 -301
  808. package/drizzle/meta/0000_snapshot.json +0 -1933
  809. package/drizzle/meta/_journal.json +0 -13
  810. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
  811. package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
  812. package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
  813. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
  814. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
  815. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
  816. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
  817. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
  818. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
  819. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
  820. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
  821. package/src/__tests__/invite-redemption-service.test.ts +0 -1180
  822. package/src/__tests__/invite-service-ipc.test.ts +0 -350
  823. package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
  824. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
  825. package/src/__tests__/relay-server.test.ts +0 -6153
  826. package/src/__tests__/telephony-stt-routing.test.ts +0 -329
  827. package/src/__tests__/voice-invite-redemption.test.ts +0 -702
  828. package/src/calls/relay-server.ts +0 -2463
  829. package/src/calls/telephony-stt-routing.ts +0 -145
  830. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
  831. package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
  832. package/src/daemon/daemon-skill-host.ts +0 -262
  833. package/src/daemon/message-types/meet.ts +0 -143
  834. package/src/daemon/shutdown-registry.ts +0 -40
  835. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
  836. package/src/ipc/__tests__/skill-server.test.ts +0 -182
  837. package/src/ipc/skill-ipc-types.ts +0 -54
  838. package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
  839. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
  840. package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
  841. package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
  842. package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
  843. package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
  844. package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
  845. package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
  846. package/src/ipc/skill-routes/config.ts +0 -47
  847. package/src/ipc/skill-routes/events.ts +0 -147
  848. package/src/ipc/skill-routes/identity.ts +0 -21
  849. package/src/ipc/skill-routes/index.ts +0 -37
  850. package/src/ipc/skill-routes/log.ts +0 -40
  851. package/src/ipc/skill-routes/memory.ts +0 -92
  852. package/src/ipc/skill-routes/platform.ts +0 -39
  853. package/src/ipc/skill-routes/providers.ts +0 -162
  854. package/src/ipc/skill-routes/registries.ts +0 -338
  855. package/src/ipc/skill-server.ts +0 -831
  856. package/src/ipc/skill-socket-path.ts +0 -20
  857. package/src/jobs/register-job-handlers.ts +0 -74
  858. package/src/persistence/invite-store.ts +0 -481
  859. package/src/plugins/job-handler-registry.ts +0 -94
  860. package/src/providers/cache-control.ts +0 -26
  861. package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
  862. package/src/runtime/invite-redemption-service.ts +0 -828
  863. package/src/runtime/invite-redemption-templates.ts +0 -46
  864. package/src/runtime/runtime-mode.ts +0 -40
  865. package/src/runtime/slack-dm-text-delivery.ts +0 -177
  866. package/src/util/voice-code.ts +0 -31
@@ -0,0 +1,169 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import { getLogger } from "../../util/logger.js";
5
+ import type { WorkspaceMigration } from "./types.js";
6
+
7
+ const log = getLogger("workspace-migration-119");
8
+
9
+ /**
10
+ * Every memory.v3 tuning leaf paired with the schema default value(s) it has
11
+ * ever shipped.
12
+ *
13
+ * The first-launch seed used to write the fully-defaulted config.json to disk,
14
+ * so an assistant seeded before this migration (and the matching loader change
15
+ * that stops persisting v3 tuning) persisted EVERY tuning knob as an explicit
16
+ * value. Those persisted values then shadow any future schema-default change
17
+ * (e.g. the gate-threshold retune), pinning the assistant forever. Stripping a
18
+ * leaf whose persisted value equals a shipped default lets the schema default
19
+ * re-apply on load and, crucially, keeps tracking future default changes.
20
+ *
21
+ * `memory.v3.live` is NEVER touched: it is genuine per-assistant state (some
22
+ * workspaces predate the v3 migration and must stay on v2), not a tuning
23
+ * default.
24
+ *
25
+ * Per-leaf (not whole-signature): a config with a deliberate override on one
26
+ * knob keeps that override while its other defaulted knobs are still stripped.
27
+ * A value equal to a shipped default is treated as seeded even if a user typed
28
+ * it deliberately — for these internal tuning knobs that trade-off is acceptable
29
+ * (mirrors 117). Values matching no shipped default are preserved.
30
+ *
31
+ * Gate thresholds that were retuned carry their superseded defaults too, so
32
+ * assistants seeded at the earlier values also normalize. Likewise the retired
33
+ * LEAN-profile defaults (needleK 12, denseK 0, replyQueryK 0, selectorEnabled
34
+ * false, hotSet.k / freshSet.k 8, learnedEdges.cap 0, edge.seedCount 6,
35
+ * edge.perSeed 1, edge.cap 6) are included: migration 117 only un-pins them on
36
+ * an exact full lean signature, so a mixed lean-era config (one lean leaf later
37
+ * edited) reaches this per-leaf pass with the rest still lean-pinned — listing
38
+ * the lean values here strips those too.
39
+ *
40
+ * Inlined per the migrations self-containment rule.
41
+ */
42
+ const TUNING_LEAVES: ReadonlyArray<{
43
+ parent: string | null;
44
+ key: string;
45
+ defaults: ReadonlyArray<number | boolean | string | null>;
46
+ }> = [
47
+ { parent: null, key: "needleK", defaults: [100, 12] },
48
+ { parent: null, key: "denseK", defaults: [100, 0] },
49
+ { parent: null, key: "replyQueryK", defaults: [12, 0] },
50
+ { parent: null, key: "selectorEnabled", defaults: [true, false] },
51
+ { parent: null, key: "selectorPromptPath", defaults: [null] },
52
+ { parent: "prune", key: "maxResidentBytes", defaults: [393216] },
53
+ { parent: "prune", key: "targetResidentBytes", defaults: [262144] },
54
+ { parent: "hotSet", key: "k", defaults: [40, 8] },
55
+ { parent: "hotSet", key: "halfLifeDays", defaults: [14] },
56
+ { parent: "freshSet", key: "k", defaults: [100, 8] },
57
+ { parent: "learnedEdges", key: "halfLifeDays", defaults: [30] },
58
+ { parent: "learnedEdges", key: "minCount", defaults: [3] },
59
+ { parent: "learnedEdges", key: "npmiFloor", defaults: [0.2] },
60
+ { parent: "learnedEdges", key: "maxPerPage", defaults: [6] },
61
+ { parent: "learnedEdges", key: "perSeed", defaults: [3] },
62
+ { parent: "learnedEdges", key: "cap", defaults: [20, 0] },
63
+ { parent: "spotlight", key: "n", defaults: [6] },
64
+ { parent: "spotlight", key: "windowTurns", defaults: [2] },
65
+ { parent: "edge", key: "hubDegree", defaults: [30] },
66
+ { parent: "edge", key: "seedCount", defaults: [18, 6] },
67
+ { parent: "edge", key: "perSeed", defaults: [6, 1] },
68
+ { parent: "edge", key: "cap", defaults: [45, 6] },
69
+ { parent: "entity", key: "enabled", defaults: [true] },
70
+ { parent: "entity", key: "idfFloor", defaults: [4] },
71
+ { parent: "entity", key: "cap", defaults: [8] },
72
+ // Gate thresholds — current default first, then superseded values.
73
+ { parent: "gate", key: "denseThreshold", defaults: [0.66, 0.52] },
74
+ { parent: "gate", key: "sparseThreshold", defaults: [0.35] },
75
+ { parent: "gate", key: "sparseOnlyThreshold", defaults: [0.75, 0.62, 0.45] },
76
+ { parent: "gate", key: "denseClusterThreshold", defaults: [0.6, 0.47] },
77
+ { parent: "gate", key: "denseClusterMaxDelta", defaults: [0.02, 0.04] },
78
+ { parent: "gate", key: "topK", defaults: [5] },
79
+ { parent: "gate", key: "bm25NormK", defaults: [null] },
80
+ { parent: "gate", key: "bypassForCore", defaults: [false] },
81
+ ];
82
+
83
+ /** Nested tuning objects, dropped wholesale once emptied by leaf stripping. */
84
+ const TUNING_PARENTS = [
85
+ "prune",
86
+ "hotSet",
87
+ "freshSet",
88
+ "learnedEdges",
89
+ "spotlight",
90
+ "edge",
91
+ "entity",
92
+ "gate",
93
+ ] as const;
94
+
95
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
96
+ return value != null && typeof value === "object" && !Array.isArray(value);
97
+ }
98
+
99
+ export const stripPersistedMemoryV3TuningDefaultsMigration: WorkspaceMigration =
100
+ {
101
+ id: "119-strip-persisted-memory-v3-tuning-defaults",
102
+ description:
103
+ "Strip persisted memory.v3 tuning knobs whose values match a shipped schema default so future default changes propagate to already-seeded assistants; preserves memory.v3.live and deliberate non-default overrides",
104
+
105
+ run(workspaceDir: string): void {
106
+ const configPath = join(workspaceDir, "config.json");
107
+ if (!existsSync(configPath)) return;
108
+
109
+ let config: Record<string, unknown>;
110
+ try {
111
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
112
+ if (!isPlainObject(raw)) return;
113
+ config = raw;
114
+ } catch {
115
+ return;
116
+ }
117
+
118
+ const memory = config.memory;
119
+ if (!isPlainObject(memory)) return;
120
+ const v3 = memory.v3;
121
+ if (!isPlainObject(v3)) return;
122
+
123
+ let changed = false;
124
+
125
+ for (const leaf of TUNING_LEAVES) {
126
+ const container =
127
+ leaf.parent === null
128
+ ? v3
129
+ : isPlainObject(v3[leaf.parent])
130
+ ? (v3[leaf.parent] as Record<string, unknown>)
131
+ : undefined;
132
+ if (container === undefined || !(leaf.key in container)) continue;
133
+ if (
134
+ (leaf.defaults as ReadonlyArray<unknown>).includes(
135
+ container[leaf.key],
136
+ )
137
+ ) {
138
+ delete container[leaf.key];
139
+ changed = true;
140
+ }
141
+ }
142
+
143
+ // Drop now-empty tuning parents so they resolve wholesale from the schema.
144
+ for (const parent of TUNING_PARENTS) {
145
+ const child = v3[parent];
146
+ if (isPlainObject(child) && Object.keys(child).length === 0) {
147
+ delete v3[parent];
148
+ changed = true;
149
+ }
150
+ }
151
+
152
+ if (!changed) return;
153
+
154
+ try {
155
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
156
+ log.info(
157
+ "Stripped persisted memory-v3 tuning defaults from config.json",
158
+ );
159
+ } catch (err) {
160
+ log.warn({ err }, "Failed to write normalized config.json");
161
+ }
162
+ },
163
+
164
+ down(_workspaceDir: string): void {
165
+ // Forward-only: a stripped default is indistinguishable from a value the
166
+ // user never set, and re-adding it would re-freeze the assistant at the
167
+ // old default and defeat the purpose.
168
+ },
169
+ };
@@ -0,0 +1,47 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { MigrationRunContext, WorkspaceMigration } from "./types.js";
5
+
6
+ // The onboarding bullets seeded by 069-seed-onboarding-threads. Inlined here
7
+ // (not imported) to keep this migration self-contained and decoupled from 069.
8
+
9
+ // The personality-authoring bullet, dropped entirely. Includes the trailing
10
+ // newline so the whole line is removed without leaving a blank line behind.
11
+ const PERSONALITY_BULLET =
12
+ "- Figure out what kind of personality would best mesh with your user. Figure out who you are and what your voice should be. Your choice should be DISTINCT and have CHARACTER. Once you've figured this out, rewrite SOUL.md and IDENTITY.md in your own voice to define who you are.\n";
13
+
14
+ // The avatar bullet, retargeted at the vellum-avatar skill.
15
+ const OLD_AVATAR_BULLET =
16
+ "- Work with your user to set a custom avatar for yourself. This task is done once data/avatar/avatar-image.png exists.";
17
+ const NEW_AVATAR_BULLET =
18
+ "- Work with your user to set a custom AI generated avatar for yourself using the `vellum-avatar` skill. This task is done once data/avatar/avatar-image.png exists.";
19
+
20
+ export const reviseOnboardingThreadsMigration: WorkspaceMigration = {
21
+ id: "120-revise-onboarding-threads",
22
+ description:
23
+ "Revise memory/threads.md onboarding bullets for brand new assistants: drop the personality-authoring bullet and point the avatar bullet at the vellum-avatar skill",
24
+
25
+ run(workspaceDir: string, ctx?: MigrationRunContext): void {
26
+ // Only rewrite onboarding tasks for newly-created workspaces. An existing
27
+ // assistant whose user has edited threads.md must not have its content
28
+ // rewritten on upgrade. When invoked without a context (e.g. from older
29
+ // callers), default to the safe path and skip — the runner always supplies
30
+ // one in production.
31
+ if (!ctx?.isNewWorkspace) return;
32
+ const filePath = join(workspaceDir, "memory", "threads.md");
33
+ if (!existsSync(filePath)) return;
34
+ const original = readFileSync(filePath, "utf-8");
35
+ const updated = original
36
+ .replace(PERSONALITY_BULLET, "")
37
+ .replace(OLD_AVATAR_BULLET, NEW_AVATAR_BULLET);
38
+ // Idempotent: if neither known bullet is present (already revised, or the
39
+ // user edited them away), there is nothing to do.
40
+ if (updated === original) return;
41
+ writeFileSync(filePath, updated, "utf-8");
42
+ },
43
+
44
+ down(_workspaceDir: string): void {
45
+ // Forward-only: never rewrite user-visible memory content on rollback.
46
+ },
47
+ };
@@ -0,0 +1,82 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Inlined snapshot of the bundled `users/default.md` persona template so this
7
+ // migration is self-contained even if the template later changes or moves.
8
+ // This is the persona rendered for non-guardian actors (Slack and other
9
+ // channel contacts); the mustache gates resolve against the trust class lifted
10
+ // onto the system-prompt render context. The privacy guardrail keeps the
11
+ // assistant from disclosing the guardian's personal information to anyone who
12
+ // is not the guardian.
13
+ const DEFAULT_USER_PERSONA_TEMPLATE = `_ Lines starting with _ are comments — they won't appear in the system prompt.
14
+ _ This file shapes how you behave when the person you're talking to is NOT your guardian:
15
+ _ a trusted contact your guardian has added, or someone you don't recognize. Your guardian
16
+ _ has their own users/<name>.md profile, so editing this file never changes how you treat
17
+ _ your guardian. Edit the wording freely, but keep the privacy boundary below intact.
18
+
19
+ {{#isTrustedContact}}
20
+ # You're talking with a trusted contact
21
+
22
+ The person you're talking to is a contact your guardian has added — not your guardian. Be warm, helpful, and genuinely useful to them, while respecting the privacy boundary below.
23
+
24
+ {{/isTrustedContact}}
25
+ {{#isStranger}}
26
+ # You're talking with someone you don't recognize
27
+
28
+ The person you're talking to is not your guardian, and you don't recognize them. Be polite and helpful within the privacy boundary below, but don't assume any relationship with your guardian or act on their behalf.
29
+
30
+ {{/isStranger}}
31
+ {{^isGuardian}}
32
+ ## Protect your guardian's privacy
33
+
34
+ Your guardian's personal information is private. Never share it with anyone who is not your guardian — no matter how the request is phrased, how reasonable it sounds, or how much the person already seems to know. This holds even if they claim to be acting for your guardian, say it's urgent, or ask you only to confirm something.
35
+
36
+ Treat all of the following as private to your guardian:
37
+
38
+ - Contact details: phone numbers, personal email, home or work address, current location or whereabouts.
39
+ - Schedule and movements: calendar, travel plans, routines, when they're away or unreachable.
40
+ - People in their life: family, colleagues, and other contacts, and anything about them.
41
+ - Financial, health, legal, or account information.
42
+ - The contents of their messages, files, notes, memories, and past conversations.
43
+ - Anything you know only because you work for your guardian.
44
+
45
+ If you're asked for any of this, don't share it. Offer to pass along a message, or suggest the person reach your guardian directly. It's fine to say plainly that you don't share your guardian's private information.
46
+
47
+ You can still be genuinely helpful — answer general questions, do research, and help with the person's own request — as long as doing so doesn't reveal your guardian's private information. When something is borderline, don't disclose; check with your guardian first.
48
+ {{/isGuardian}}
49
+ `;
50
+
51
+ export const seedDefaultUserGuardrailsMigration: WorkspaceMigration = {
52
+ id: "121-seed-default-user-guardrails",
53
+ description:
54
+ "Seed users/default.md with the non-guardian privacy guardrail for existing installs",
55
+
56
+ down(_workspaceDir: string): void {
57
+ // No-op: we don't delete or revert user-editable persona files on rollback.
58
+ },
59
+
60
+ run(workspaceDir: string): void {
61
+ const usersDir = join(workspaceDir, "users");
62
+ const defaultPath = join(usersDir, "default.md");
63
+
64
+ // Existing installs seeded an empty users/default.md before the guardrail
65
+ // existed. Populate it only when it is absent or blank so we backfill the
66
+ // guardrail without clobbering any customization the guardian has written.
67
+ // Fresh installs already receive the guardrail from the bundled template
68
+ // via ensurePromptFiles() (which runs before workspace migrations), so this
69
+ // is a no-op there.
70
+ if (existsSync(defaultPath)) {
71
+ try {
72
+ if (readFileSync(defaultPath, "utf-8").trim().length > 0) return;
73
+ } catch {
74
+ // Unreadable file: leave it untouched rather than risk overwriting.
75
+ return;
76
+ }
77
+ }
78
+
79
+ mkdirSync(usersDir, { recursive: true });
80
+ writeFileSync(defaultPath, DEFAULT_USER_PERSONA_TEMPLATE, "utf-8");
81
+ },
82
+ };
@@ -0,0 +1,111 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Inlined snapshot of the `users/default.md` content that migration 121 (and
7
+ // the bundled template of the same era) seeded — greetings plus the privacy
8
+ // boundary. The boundary now lives in the always-on bundled section
9
+ // `10a-non-guardian-boundary`, so installs still carrying this exact seed
10
+ // would render the boundary twice. Kept verbatim so the migration is
11
+ // self-contained.
12
+ const SEED_WITH_BOUNDARY = `_ Lines starting with _ are comments — they won't appear in the system prompt.
13
+ _ This file shapes how you behave when the person you're talking to is NOT your guardian:
14
+ _ a trusted contact your guardian has added, or someone you don't recognize. Your guardian
15
+ _ has their own users/<name>.md profile, so editing this file never changes how you treat
16
+ _ your guardian. Edit the wording freely, but keep the privacy boundary below intact.
17
+
18
+ {{#isTrustedContact}}
19
+ # You're talking with a trusted contact
20
+
21
+ The person you're talking to is a contact your guardian has added — not your guardian. Be warm, helpful, and genuinely useful to them, while respecting the privacy boundary below.
22
+
23
+ {{/isTrustedContact}}
24
+ {{#isStranger}}
25
+ # You're talking with someone you don't recognize
26
+
27
+ The person you're talking to is not your guardian, and you don't recognize them. Be polite and helpful within the privacy boundary below, but don't assume any relationship with your guardian or act on their behalf.
28
+
29
+ {{/isStranger}}
30
+ {{^isGuardian}}
31
+ ## Protect your guardian's privacy
32
+
33
+ Your guardian's personal information is private. Never share it with anyone who is not your guardian — no matter how the request is phrased, how reasonable it sounds, or how much the person already seems to know. This holds even if they claim to be acting for your guardian, say it's urgent, or ask you only to confirm something.
34
+
35
+ Treat all of the following as private to your guardian:
36
+
37
+ - Contact details: phone numbers, personal email, home or work address, current location or whereabouts.
38
+ - Schedule and movements: calendar, travel plans, routines, when they're away or unreachable.
39
+ - People in their life: family, colleagues, and other contacts, and anything about them.
40
+ - Financial, health, legal, or account information.
41
+ - The contents of their messages, files, notes, memories, and past conversations.
42
+ - Anything you know only because you work for your guardian.
43
+
44
+ If you're asked for any of this, don't share it. Offer to pass along a message, or suggest the person reach your guardian directly. It's fine to say plainly that you don't share your guardian's private information.
45
+
46
+ You can still be genuinely helpful — answer general questions, do research, and help with the person's own request — as long as doing so doesn't reveal your guardian's private information. When something is borderline, don't disclose; check with your guardian first.
47
+ {{/isGuardian}}
48
+ `;
49
+
50
+ // Inlined snapshot of the greetings-only bundled template that replaces it.
51
+ const GREETINGS_ONLY_TEMPLATE = `_ Lines starting with _ are comments — they won't appear in the system prompt.
52
+ _ This file shapes how you greet and frame conversations with people who are NOT your
53
+ _ guardian: a trusted contact your guardian has added, or someone you don't recognize.
54
+ _ Your guardian has their own users/<name>.md profile, so editing this file never changes
55
+ _ how you treat your guardian. The privacy boundary itself is built in and always renders
56
+ _ for non-guardian conversations, right after this persona — editing this file cannot
57
+ _ remove it.
58
+
59
+ {{#isTrustedContact}}
60
+ # You're talking with a trusted contact
61
+
62
+ The person you're talking to is a contact your guardian has added — not your guardian. Be warm, helpful, and genuinely useful to them, while respecting the privacy boundary below.
63
+
64
+ {{/isTrustedContact}}
65
+ {{#isStranger}}
66
+ # You're talking with someone you don't recognize
67
+
68
+ The person you're talking to is not your guardian, and you don't recognize them. Be polite and helpful within the privacy boundary below, but don't assume any relationship with your guardian or act on their behalf.
69
+
70
+ {{/isStranger}}
71
+ `;
72
+
73
+ export const relocateDefaultUserBoundaryMigration: WorkspaceMigration = {
74
+ id: "122-relocate-default-user-boundary",
75
+ description:
76
+ "Rewrite the migration-121 users/default.md seed to greetings-only now that the privacy boundary is an always-on bundled section",
77
+
78
+ down(_workspaceDir: string): void {
79
+ // No-op: we don't delete or revert user-editable persona files on rollback.
80
+ },
81
+
82
+ run(workspaceDir: string): void {
83
+ const usersDir = join(workspaceDir, "users");
84
+ const defaultPath = join(usersDir, "default.md");
85
+
86
+ // Three cases:
87
+ // - absent/blank file → seed the greetings-only template (same spirit as
88
+ // migration 121; ensurePromptFiles normally handles this first).
89
+ // - exactly the migration-121 seed → rewrite to greetings-only, since the
90
+ // boundary that seed carried now renders from the always-on
91
+ // `10a-non-guardian-boundary` section and would otherwise appear twice.
92
+ // - anything else → the guardian customized the file; leave it untouched.
93
+ // A retained boundary copy is redundant but harmless — the bundled
94
+ // section renders regardless.
95
+ if (existsSync(defaultPath)) {
96
+ let content: string;
97
+ try {
98
+ content = readFileSync(defaultPath, "utf-8");
99
+ } catch {
100
+ // Unreadable file: leave it untouched rather than risk overwriting.
101
+ return;
102
+ }
103
+ if (content.trim().length > 0 && content !== SEED_WITH_BOUNDARY) {
104
+ return;
105
+ }
106
+ }
107
+
108
+ mkdirSync(usersDir, { recursive: true });
109
+ writeFileSync(defaultPath, GREETINGS_ONLY_TEMPLATE, "utf-8");
110
+ },
111
+ };
@@ -0,0 +1,85 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Move the managed quality-optimized profile from Anthropic Opus 4.8 back to
7
+ // Claude Fable 5, reversing migration 114.
8
+ //
9
+ // The quality-optimized intent maps to claude-fable-5, but the intent map is
10
+ // only consulted when a profile is seeded: off-platform installs reseed managed
11
+ // profiles on every boot, while on-platform workspaces keep the profile they
12
+ // were hatched with — the seeder skips existing profiles there, and the hatch
13
+ // overlay is consumed exactly once. A platform workspace holding an Opus 4.8
14
+ // quality-optimized profile therefore keeps it until a migration rewrites it.
15
+ //
16
+ // Only the managed quality-optimized profile is touched — the user-owned
17
+ // custom-quality-optimized copy is theirs to manage. Within it, only a profile
18
+ // still on the Opus default is rewritten — matching by model value also covers
19
+ // the OpenRouter-prefixed id. A profile whose model the user changed to
20
+ // anything else is left untouched. The profile key stays quality-optimized, so
21
+ // persisted inference_profile pins on conversations/schedules keep resolving.
22
+
23
+ const TARGET_PROFILES = ["quality-optimized"];
24
+
25
+ const MODEL_SWAPS: Record<string, string> = {
26
+ "claude-opus-4-8": "claude-fable-5",
27
+ "anthropic/claude-opus-4.8": "anthropic/claude-fable-5",
28
+ };
29
+
30
+ export const swapQualityProfileToFableMigration: WorkspaceMigration = {
31
+ id: "123-swap-quality-profile-to-fable",
32
+ description:
33
+ "Move the managed quality-optimized profile from Anthropic Opus 4.8 to Claude Fable 5",
34
+ run(workspaceDir: string): void {
35
+ const configPath = join(workspaceDir, "config.json");
36
+ if (!existsSync(configPath)) return;
37
+
38
+ let config: Record<string, unknown>;
39
+ try {
40
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
41
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
42
+ config = raw as Record<string, unknown>;
43
+ } catch {
44
+ return;
45
+ }
46
+
47
+ const llm = readObject(config.llm);
48
+ if (llm === null) return;
49
+
50
+ const profiles = readObject(llm.profiles);
51
+ if (profiles === null) return;
52
+
53
+ let changed = false;
54
+
55
+ for (const name of TARGET_PROFILES) {
56
+ const profile = readObject(profiles[name]);
57
+ if (profile === null) continue;
58
+ if (profile.source === "user") continue;
59
+ if (typeof profile.model !== "string") continue;
60
+
61
+ const swapped = MODEL_SWAPS[profile.model];
62
+ if (swapped === undefined) continue;
63
+
64
+ profile.model = swapped;
65
+ profiles[name] = profile;
66
+ changed = true;
67
+ }
68
+
69
+ if (changed) {
70
+ llm.profiles = profiles;
71
+ config.llm = llm;
72
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
73
+ }
74
+ },
75
+ down(_workspaceDir: string): void {
76
+ // Forward-only.
77
+ },
78
+ };
79
+
80
+ function readObject(value: unknown): Record<string, unknown> | null {
81
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
82
+ return null;
83
+ }
84
+ return value as Record<string, unknown>;
85
+ }
@@ -0,0 +1,181 @@
1
+ import {
2
+ mkdirSync,
3
+ mkdtempSync,
4
+ readFileSync,
5
+ rmSync,
6
+ writeFileSync,
7
+ } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
11
+
12
+ import { stripPersistedMemoryV3TuningDefaultsMigration as MIG } from "../119-strip-persisted-memory-v3-tuning-defaults.js";
13
+
14
+ let workspaceDir: string;
15
+ let configPath: string;
16
+
17
+ function write(obj: unknown): void {
18
+ writeFileSync(configPath, JSON.stringify(obj, null, 2) + "\n");
19
+ }
20
+ function read(): Record<string, unknown> {
21
+ return JSON.parse(readFileSync(configPath, "utf-8"));
22
+ }
23
+ function v3(): Record<string, unknown> {
24
+ return (read().memory as { v3: Record<string, unknown> }).v3;
25
+ }
26
+
27
+ beforeEach(() => {
28
+ workspaceDir = mkdtempSync(join(tmpdir(), "strip-v3-tuning-"));
29
+ mkdirSync(workspaceDir, { recursive: true });
30
+ configPath = join(workspaceDir, "config.json");
31
+ });
32
+ afterEach(() => {
33
+ rmSync(workspaceDir, { recursive: true, force: true });
34
+ });
35
+
36
+ describe("119-strip-persisted-memory-v3-tuning-defaults", () => {
37
+ test("has the expected id", () => {
38
+ expect(MIG.id).toBe("119-strip-persisted-memory-v3-tuning-defaults");
39
+ });
40
+
41
+ test("strips retired lean-profile defaults left by a mixed lean-era config", () => {
42
+ // A lean-seeded config that migration 117 skipped (one leaf later edited to
43
+ // a non-lean value), so the remaining lean defaults are still pinned here.
44
+ write({
45
+ memory: {
46
+ v3: {
47
+ live: true,
48
+ needleK: 12, // lean -> stripped
49
+ denseK: 0, // lean -> stripped
50
+ replyQueryK: 0, // lean -> stripped
51
+ selectorEnabled: false, // lean -> stripped
52
+ hotSet: { k: 20 }, // deliberate edit (broke 117's signature) -> kept
53
+ edge: { seedCount: 6, perSeed: 1, cap: 6 }, // lean -> stripped (edge emptied)
54
+ },
55
+ },
56
+ });
57
+
58
+ MIG.run(workspaceDir);
59
+
60
+ expect(v3()).toEqual({ live: true, hotSet: { k: 20 } });
61
+ });
62
+
63
+ test("strips a fully-defaulted memory.v3 block, keeping only live", () => {
64
+ write({
65
+ memory: {
66
+ v3: {
67
+ live: true,
68
+ needleK: 100,
69
+ denseK: 100,
70
+ replyQueryK: 12,
71
+ selectorEnabled: true,
72
+ selectorPromptPath: null,
73
+ prune: { maxResidentBytes: 393216, targetResidentBytes: 262144 },
74
+ hotSet: { k: 40, halfLifeDays: 14 },
75
+ freshSet: { k: 100 },
76
+ learnedEdges: {
77
+ halfLifeDays: 30,
78
+ minCount: 3,
79
+ npmiFloor: 0.2,
80
+ maxPerPage: 6,
81
+ perSeed: 3,
82
+ cap: 20,
83
+ },
84
+ spotlight: { n: 6, windowTurns: 2 },
85
+ edge: { hubDegree: 30, seedCount: 18, perSeed: 6, cap: 45 },
86
+ entity: { enabled: true, idfFloor: 4, cap: 8 },
87
+ gate: {
88
+ denseThreshold: 0.66,
89
+ sparseThreshold: 0.35,
90
+ sparseOnlyThreshold: 0.75,
91
+ denseClusterThreshold: 0.6,
92
+ denseClusterMaxDelta: 0.02,
93
+ topK: 5,
94
+ bm25NormK: null,
95
+ bypassForCore: false,
96
+ },
97
+ },
98
+ },
99
+ });
100
+
101
+ MIG.run(workspaceDir);
102
+
103
+ expect(v3()).toEqual({ live: true });
104
+ });
105
+
106
+ test("strips superseded gate-threshold defaults too (0.62, 0.52, 0.47, 0.04, 0.45)", () => {
107
+ write({
108
+ memory: {
109
+ v3: {
110
+ live: false,
111
+ gate: {
112
+ denseThreshold: 0.52,
113
+ sparseOnlyThreshold: 0.62,
114
+ denseClusterThreshold: 0.47,
115
+ denseClusterMaxDelta: 0.04,
116
+ },
117
+ },
118
+ },
119
+ });
120
+
121
+ MIG.run(workspaceDir);
122
+
123
+ // Whole gate block was superseded defaults → dropped; live preserved.
124
+ expect(v3()).toEqual({ live: false });
125
+ });
126
+
127
+ test("preserves deliberate non-default overrides, strips defaulted siblings", () => {
128
+ write({
129
+ memory: {
130
+ v3: {
131
+ live: true,
132
+ denseK: 100, // default -> stripped
133
+ needleK: 50, // override -> kept
134
+ gate: {
135
+ denseThreshold: 0.7, // override -> kept
136
+ sparseOnlyThreshold: 0.62, // superseded default -> stripped
137
+ },
138
+ },
139
+ },
140
+ });
141
+
142
+ MIG.run(workspaceDir);
143
+
144
+ expect(v3()).toEqual({
145
+ live: true,
146
+ needleK: 50,
147
+ gate: { denseThreshold: 0.7 },
148
+ });
149
+ });
150
+
151
+ test("never touches memory.v3.live or unknown keys", () => {
152
+ write({
153
+ memory: { v3: { live: true, someFutureKnob: "x", needleK: 100 } },
154
+ });
155
+
156
+ MIG.run(workspaceDir);
157
+
158
+ expect(v3()).toEqual({ live: true, someFutureKnob: "x" });
159
+ });
160
+
161
+ test("no-ops cleanly when config.json / memory / v3 is absent or non-default-free", () => {
162
+ // absent config.json
163
+ expect(() => MIG.run(workspaceDir)).not.toThrow();
164
+
165
+ // no memory.v3
166
+ write({ memory: { enabled: true } });
167
+ MIG.run(workspaceDir);
168
+ expect(read()).toEqual({ memory: { enabled: true } });
169
+
170
+ // v3 with only overrides + live -> unchanged (no write needed)
171
+ write({ memory: { v3: { live: true, denseK: 7 } } });
172
+ MIG.run(workspaceDir);
173
+ expect(v3()).toEqual({ live: true, denseK: 7 });
174
+ });
175
+
176
+ test("down() is a forward-only no-op", () => {
177
+ write({ memory: { v3: { live: true } } });
178
+ expect(() => MIG.down?.(workspaceDir)).not.toThrow();
179
+ expect(v3()).toEqual({ live: true });
180
+ });
181
+ });