@vellumai/assistant 0.4.56 → 0.4.57

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 (450) hide show
  1. package/ARCHITECTURE.md +10 -10
  2. package/Dockerfile +3 -0
  3. package/README.md +11 -11
  4. package/docs/architecture/integrations.md +2 -2
  5. package/docs/architecture/memory.md +3 -4
  6. package/docs/credential-execution-service.md +13 -20
  7. package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
  8. package/package.json +1 -1
  9. package/src/__tests__/actor-token-service.test.ts +7 -7
  10. package/src/__tests__/anthropic-provider.test.ts +172 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
  12. package/src/__tests__/approval-cascade.test.ts +2 -2
  13. package/src/__tests__/approval-routes-http.test.ts +3 -4
  14. package/src/__tests__/asset-materialize-tool.test.ts +5 -5
  15. package/src/__tests__/asset-search-tool.test.ts +1 -1
  16. package/src/__tests__/assistant-attachments.test.ts +5 -5
  17. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
  19. package/src/__tests__/attachments-store.test.ts +2 -2
  20. package/src/__tests__/avatar-e2e.test.ts +5 -3
  21. package/src/__tests__/browser-skill-endstate.test.ts +0 -1
  22. package/src/__tests__/call-routes-http.test.ts +2 -2
  23. package/src/__tests__/callback-handoff-copy.test.ts +1 -1
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
  25. package/src/__tests__/channel-readiness-routes.test.ts +0 -1
  26. package/src/__tests__/channel-readiness-service.test.ts +0 -1
  27. package/src/__tests__/checker.test.ts +31 -32
  28. package/src/__tests__/chrome-cdp.test.ts +47 -18
  29. package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
  30. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  31. package/src/__tests__/config-schema.test.ts +9 -18
  32. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
  34. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
  35. package/src/__tests__/conversation-agent-loop.test.ts +11 -4
  36. package/src/__tests__/conversation-attachments.test.ts +1 -1
  37. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
  38. package/src/__tests__/conversation-error.test.ts +33 -0
  39. package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
  40. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  41. package/src/__tests__/conversation-pairing.test.ts +1 -1
  42. package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
  43. package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
  44. package/src/__tests__/conversation-queue.test.ts +23 -14
  45. package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +185 -173
  47. package/src/__tests__/conversation-seed-composer.test.ts +1 -1
  48. package/src/__tests__/conversation-slash-queue.test.ts +4 -4
  49. package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
  50. package/src/__tests__/conversation-starter-routes.test.ts +291 -0
  51. package/src/__tests__/conversation-wipe.test.ts +438 -0
  52. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
  53. package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
  54. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
  55. package/src/__tests__/credential-security-e2e.test.ts +20 -0
  56. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  57. package/src/__tests__/credential-vault-unit.test.ts +227 -0
  58. package/src/__tests__/credentials-cli.test.ts +3 -0
  59. package/src/__tests__/date-context.test.ts +59 -377
  60. package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
  61. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
  62. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  63. package/src/__tests__/encrypted-store.test.ts +237 -15
  64. package/src/__tests__/ephemeral-permissions.test.ts +4 -5
  65. package/src/__tests__/event-bus.test.ts +3 -3
  66. package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
  67. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  68. package/src/__tests__/gemini-image-service.test.ts +4 -4
  69. package/src/__tests__/gemini-provider.test.ts +6 -9
  70. package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
  71. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  72. package/src/__tests__/host-shell-tool.test.ts +6 -6
  73. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  74. package/src/__tests__/intent-routing.test.ts +51 -99
  75. package/src/__tests__/invite-routes-http.test.ts +5 -0
  76. package/src/__tests__/list-messages-attachments.test.ts +1 -1
  77. package/src/__tests__/managed-proxy-context.test.ts +2 -5
  78. package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
  79. package/src/__tests__/media-generate-image.test.ts +32 -15
  80. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
  81. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
  82. package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
  83. package/src/__tests__/memory-recall-quality.test.ts +4 -3
  84. package/src/__tests__/memory-regressions.test.ts +86 -90
  85. package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
  86. package/src/__tests__/migration-export-http.test.ts +26 -27
  87. package/src/__tests__/migration-import-commit-http.test.ts +165 -37
  88. package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
  89. package/src/__tests__/migration-validate-http.test.ts +16 -16
  90. package/src/__tests__/model-intents.test.ts +1 -1
  91. package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
  92. package/src/__tests__/notification-broadcaster.test.ts +1 -1
  93. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  94. package/src/__tests__/notification-decision-identity.test.ts +8 -9
  95. package/src/__tests__/notification-decision-strategy.test.ts +1 -1
  96. package/src/__tests__/notification-deep-link.test.ts +1 -1
  97. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  98. package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
  99. package/src/__tests__/oauth-store.test.ts +1 -3
  100. package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
  101. package/src/__tests__/onboarding-template-contract.test.ts +23 -59
  102. package/src/__tests__/provider-error-scenarios.test.ts +154 -0
  103. package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
  104. package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
  105. package/src/__tests__/provider-registry-ollama.test.ts +5 -2
  106. package/src/__tests__/qdrant-manager.test.ts +7 -7
  107. package/src/__tests__/ratelimit.test.ts +0 -74
  108. package/src/__tests__/recording-handler.test.ts +0 -1
  109. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  110. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  111. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  112. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  113. package/src/__tests__/scheduler-recurrence.test.ts +46 -2
  114. package/src/__tests__/schema-transforms.test.ts +114 -54
  115. package/src/__tests__/secret-onetime-send.test.ts +20 -0
  116. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
  117. package/src/__tests__/secret-scanner-executor.test.ts +1 -2
  118. package/src/__tests__/send-endpoint-busy.test.ts +63 -4
  119. package/src/__tests__/send-notification-tool.test.ts +2 -2
  120. package/src/__tests__/shell-credential-ref.test.ts +0 -1
  121. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
  122. package/src/__tests__/skill-memory.test.ts +547 -0
  123. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
  124. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
  125. package/src/__tests__/slack-channel-config.test.ts +109 -94
  126. package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
  127. package/src/__tests__/swarm-recursion.test.ts +2 -2
  128. package/src/__tests__/swarm-tool.test.ts +2 -2
  129. package/src/__tests__/system-prompt.test.ts +19 -66
  130. package/src/__tests__/telegram-config.test.ts +121 -0
  131. package/src/__tests__/terminal-tools.test.ts +1 -1
  132. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
  133. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  134. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  135. package/src/__tests__/tool-executor.test.ts +1 -1
  136. package/src/__tests__/trace-emitter.test.ts +8 -1
  137. package/src/__tests__/trust-store.test.ts +7 -8
  138. package/src/__tests__/twilio-routes.test.ts +1 -18
  139. package/src/__tests__/user-reference.test.ts +82 -2
  140. package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
  141. package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
  142. package/src/approvals/guardian-request-resolvers.ts +3 -3
  143. package/src/avatar/ascii-renderer.ts +2 -2
  144. package/src/avatar/png-renderer.ts +2 -2
  145. package/src/avatar/resvg-lazy.ts +21 -0
  146. package/src/calls/guardian-dispatch.ts +1 -1
  147. package/src/calls/relay-access-wait.ts +2 -2
  148. package/src/calls/twilio-rest.ts +0 -248
  149. package/src/cli/AGENTS.md +5 -8
  150. package/src/cli/__tests__/notifications.test.ts +5 -5
  151. package/src/cli/commands/avatar.ts +64 -2
  152. package/src/cli/commands/conversations.ts +131 -1
  153. package/src/cli/commands/credentials.ts +2 -0
  154. package/src/cli/commands/notifications.ts +3 -3
  155. package/src/cli.ts +10 -0
  156. package/src/config/bundled-skills/acp/SKILL.md +5 -5
  157. package/src/config/bundled-skills/acp/TOOLS.json +6 -6
  158. package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
  159. package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
  160. package/src/config/bundled-skills/browser/SKILL.md +15 -15
  161. package/src/config/bundled-skills/browser/TOOLS.json +14 -14
  162. package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
  163. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
  164. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  165. package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
  166. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  167. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
  168. package/src/config/bundled-skills/contacts/SKILL.md +3 -3
  169. package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
  170. package/src/config/bundled-skills/document/SKILL.md +4 -4
  171. package/src/config/bundled-skills/document/TOOLS.json +2 -2
  172. package/src/config/bundled-skills/followups/TOOLS.json +3 -3
  173. package/src/config/bundled-skills/gmail/SKILL.md +32 -32
  174. package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
  175. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
  176. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
  177. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
  178. package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
  179. package/src/config/bundled-skills/google-calendar/types.ts +1 -1
  180. package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
  181. package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
  182. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
  183. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
  184. package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
  185. package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
  186. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
  187. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
  188. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
  189. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
  190. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
  191. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
  192. package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
  193. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  194. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
  195. package/src/config/bundled-skills/messaging/SKILL.md +29 -25
  196. package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
  197. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
  198. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  199. package/src/config/bundled-skills/notifications/SKILL.md +3 -3
  200. package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
  201. package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
  202. package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
  203. package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
  204. package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
  205. package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
  206. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
  207. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
  208. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
  209. package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
  210. package/src/config/bundled-skills/schedule/SKILL.md +26 -26
  211. package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
  212. package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
  213. package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
  214. package/src/config/bundled-skills/sequences/SKILL.md +2 -2
  215. package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
  216. package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
  217. package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
  218. package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
  219. package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
  220. package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
  221. package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
  222. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
  223. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  224. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
  225. package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
  226. package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
  227. package/src/config/bundled-skills/slack/SKILL.md +2 -2
  228. package/src/config/bundled-skills/slack/TOOLS.json +8 -8
  229. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
  230. package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
  231. package/src/config/bundled-skills/tasks/SKILL.md +1 -1
  232. package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
  233. package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
  234. package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
  235. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
  236. package/src/config/bundled-skills/watcher/SKILL.md +4 -4
  237. package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
  238. package/src/config/feature-flag-registry.json +33 -17
  239. package/src/config/schemas/sandbox.ts +1 -1
  240. package/src/config/schemas/services.ts +13 -3
  241. package/src/config/schemas/timeouts.ts +0 -10
  242. package/src/contacts/contact-store.ts +63 -0
  243. package/src/contacts/contacts-write.ts +1 -1
  244. package/src/daemon/assistant-attachments.ts +2 -2
  245. package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
  246. package/src/daemon/conversation-agent-loop.ts +7 -30
  247. package/src/daemon/conversation-error.ts +24 -0
  248. package/src/daemon/conversation-memory.ts +8 -7
  249. package/src/daemon/conversation-runtime-assembly.ts +139 -274
  250. package/src/daemon/conversation-slash.ts +7 -26
  251. package/src/daemon/conversation-surfaces.ts +14 -0
  252. package/src/daemon/conversation-tool-setup.ts +9 -8
  253. package/src/daemon/conversation.ts +2 -0
  254. package/src/daemon/daemon-control.ts +1 -1
  255. package/src/daemon/date-context.ts +10 -83
  256. package/src/daemon/handlers/config-channels.ts +12 -2
  257. package/src/daemon/handlers/config-slack-channel.ts +7 -1
  258. package/src/daemon/handlers/config-telegram.ts +6 -1
  259. package/src/daemon/handlers/conversations.ts +2 -2
  260. package/src/daemon/handlers/skills.ts +4 -0
  261. package/src/daemon/lifecycle.ts +28 -4
  262. package/src/daemon/providers-setup.ts +1 -1
  263. package/src/daemon/server.ts +1 -5
  264. package/src/daemon/shutdown-handlers.ts +9 -3
  265. package/src/daemon/tool-side-effects.ts +40 -0
  266. package/src/daemon/trace-emitter.ts +25 -2
  267. package/src/events/domain-events.ts +1 -1
  268. package/src/events/tool-permission-telemetry-listener.ts +46 -0
  269. package/src/inbound/platform-callback-registration.ts +0 -18
  270. package/src/media/app-icon-generator.ts +15 -8
  271. package/src/media/avatar-router.ts +15 -8
  272. package/src/media/gemini-image-service.ts +125 -21
  273. package/src/memory/attachments-store.ts +3 -3
  274. package/src/memory/channel-verification-sessions.ts +6 -6
  275. package/src/memory/conversation-crud.ts +196 -1
  276. package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
  277. package/src/memory/conversation-title-service.ts +2 -3
  278. package/src/memory/db-init.ts +25 -1
  279. package/src/memory/invite-store.ts +4 -4
  280. package/src/memory/items-extractor.ts +4 -4
  281. package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
  282. package/src/memory/jobs-store.ts +3 -2
  283. package/src/memory/jobs-worker.ts +7 -5
  284. package/src/memory/lifecycle-events-store.ts +63 -0
  285. package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
  286. package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
  287. package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
  288. package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
  289. package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
  290. package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
  291. package/src/memory/migrations/index.ts +6 -0
  292. package/src/memory/migrations/registry.ts +13 -0
  293. package/src/memory/retriever.test.ts +223 -96
  294. package/src/memory/retriever.ts +115 -138
  295. package/src/memory/schema/calls.ts +1 -1
  296. package/src/memory/schema/contacts.ts +1 -1
  297. package/src/memory/schema/infrastructure.ts +29 -0
  298. package/src/memory/schema/memory-core.ts +7 -17
  299. package/src/memory/schema/notifications.ts +1 -1
  300. package/src/memory/search/formatting.ts +23 -6
  301. package/src/memory/search/lexical.ts +2 -0
  302. package/src/memory/search/semantic.ts +2 -0
  303. package/src/memory/search/staleness.ts +1 -0
  304. package/src/memory/search/types.ts +4 -0
  305. package/src/memory/task-memory-cleanup.ts +96 -6
  306. package/src/memory/trace-event-store.ts +148 -0
  307. package/src/notifications/README.md +1 -1
  308. package/src/notifications/decision-engine.ts +2 -2
  309. package/src/notifications/emit-signal.ts +4 -4
  310. package/src/notifications/events-store.ts +4 -4
  311. package/src/notifications/signal.ts +1 -1
  312. package/src/oauth/manual-token-connection.ts +49 -25
  313. package/src/permissions/checker.ts +6 -5
  314. package/src/permissions/defaults.ts +4 -4
  315. package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
  316. package/src/prompts/cache-boundary.ts +8 -0
  317. package/src/prompts/system-prompt.ts +105 -634
  318. package/src/prompts/templates/BOOTSTRAP.md +166 -33
  319. package/src/prompts/templates/IDENTITY.md +8 -23
  320. package/src/prompts/templates/SOUL.md +20 -41
  321. package/src/prompts/templates/USER.md +3 -19
  322. package/src/prompts/user-reference.ts +14 -16
  323. package/src/providers/anthropic/client.ts +46 -2
  324. package/src/providers/gemini/client.ts +6 -9
  325. package/src/providers/managed-proxy/constants.ts +1 -7
  326. package/src/providers/managed-proxy/context.ts +0 -1
  327. package/src/providers/model-intents.ts +5 -5
  328. package/src/providers/openai/client.ts +10 -1
  329. package/src/providers/openrouter/client.ts +1 -0
  330. package/src/providers/ratelimit.ts +0 -35
  331. package/src/providers/registry.ts +3 -5
  332. package/src/providers/retry.ts +18 -1
  333. package/src/runtime/access-request-helper.ts +1 -1
  334. package/src/runtime/auth/route-policy.ts +7 -0
  335. package/src/runtime/channel-verification-service.ts +1 -1
  336. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  337. package/src/runtime/guardian-vellum-migration.ts +63 -1
  338. package/src/runtime/http-server.ts +8 -4
  339. package/src/runtime/migrations/vbundle-builder.ts +212 -32
  340. package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
  341. package/src/runtime/migrations/vbundle-importer.ts +66 -1
  342. package/src/runtime/migrations/vbundle-validator.ts +17 -3
  343. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
  344. package/src/runtime/routes/attachment-routes.ts +2 -2
  345. package/src/runtime/routes/btw-routes.ts +9 -0
  346. package/src/runtime/routes/channel-verification-routes.ts +19 -2
  347. package/src/runtime/routes/conversation-management-routes.ts +55 -1
  348. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  349. package/src/runtime/routes/conversation-routes.ts +49 -5
  350. package/src/runtime/routes/conversation-starter-routes.ts +207 -0
  351. package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
  352. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
  353. package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
  354. package/src/runtime/routes/migration-routes.ts +25 -13
  355. package/src/runtime/routes/secret-routes.ts +18 -0
  356. package/src/runtime/routes/settings-routes.ts +8 -8
  357. package/src/runtime/routes/telemetry-routes.ts +53 -0
  358. package/src/runtime/routes/trace-event-routes.ts +62 -0
  359. package/src/runtime/tool-grant-request-helper.ts +1 -1
  360. package/src/runtime/verification-outbound-actions.ts +47 -31
  361. package/src/security/encrypted-store.ts +263 -78
  362. package/src/skills/catalog-install.ts +10 -0
  363. package/src/skills/managed-store.ts +2 -0
  364. package/src/skills/skill-memory.ts +220 -0
  365. package/src/subagent/manager.ts +1 -4
  366. package/src/telemetry/types.ts +10 -1
  367. package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
  368. package/src/telemetry/usage-telemetry-reporter.ts +51 -4
  369. package/src/tools/AGENTS.md +11 -11
  370. package/src/tools/acp/spawn.ts +1 -1
  371. package/src/tools/apps/executors.ts +8 -8
  372. package/src/tools/apps/registry.ts +1 -1
  373. package/src/tools/assets/materialize.ts +6 -6
  374. package/src/tools/assets/search.ts +10 -10
  375. package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
  376. package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
  377. package/src/tools/browser/auth-detector.ts +6 -6
  378. package/src/tools/browser/browser-execution.ts +13 -13
  379. package/src/tools/browser/browser-manager.ts +3 -3
  380. package/src/tools/browser/chrome-cdp.ts +5 -5
  381. package/src/tools/browser/jit-auth.ts +2 -2
  382. package/src/tools/browser/network-recorder.test.ts +2 -2
  383. package/src/tools/browser/network-recorder.ts +3 -3
  384. package/src/tools/browser/runtime-check.ts +3 -3
  385. package/src/tools/claude-code/claude-code.ts +2 -2
  386. package/src/tools/computer-use/definitions.ts +18 -18
  387. package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
  388. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
  389. package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
  390. package/src/tools/credentials/broker-types.ts +5 -5
  391. package/src/tools/credentials/broker.ts +15 -15
  392. package/src/tools/credentials/metadata-store.ts +2 -2
  393. package/src/tools/credentials/resolve.ts +1 -1
  394. package/src/tools/credentials/selection.ts +1 -1
  395. package/src/tools/credentials/tool-policy.ts +1 -1
  396. package/src/tools/credentials/vault.ts +115 -25
  397. package/src/tools/execution-target.ts +2 -2
  398. package/src/tools/executor.ts +7 -7
  399. package/src/tools/filesystem/edit.ts +2 -2
  400. package/src/tools/filesystem/read.ts +1 -1
  401. package/src/tools/filesystem/write.ts +1 -1
  402. package/src/tools/host-filesystem/edit.ts +2 -1
  403. package/src/tools/host-filesystem/read.ts +2 -1
  404. package/src/tools/host-filesystem/write.ts +1 -1
  405. package/src/tools/host-terminal/host-shell.ts +9 -8
  406. package/src/tools/mcp/mcp-tool-factory.ts +7 -6
  407. package/src/tools/memory/definitions.ts +6 -5
  408. package/src/tools/memory/handlers.test.ts +1 -1
  409. package/src/tools/network/__tests__/web-search.test.ts +3 -3
  410. package/src/tools/network/domain-normalize.ts +2 -2
  411. package/src/tools/network/script-proxy/session-manager.ts +10 -10
  412. package/src/tools/network/web-fetch.ts +1 -1
  413. package/src/tools/network/web-search.ts +3 -3
  414. package/src/tools/permission-checker.ts +8 -8
  415. package/src/tools/registry.ts +7 -7
  416. package/src/tools/schedule/list.ts +2 -2
  417. package/src/tools/schema-transforms.ts +31 -21
  418. package/src/tools/secret-detection-handler.ts +1 -1
  419. package/src/tools/sensitive-output-placeholders.ts +1 -1
  420. package/src/tools/shared/filesystem/edit-engine.ts +1 -1
  421. package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
  422. package/src/tools/shared/filesystem/image-read.ts +25 -5
  423. package/src/tools/shared/filesystem/path-policy.ts +2 -2
  424. package/src/tools/shared/shell-output.ts +1 -1
  425. package/src/tools/side-effects.ts +1 -1
  426. package/src/tools/skills/execute.ts +1 -1
  427. package/src/tools/skills/load.ts +3 -3
  428. package/src/tools/skills/sandbox-runner.ts +3 -3
  429. package/src/tools/subagent/read.ts +1 -1
  430. package/src/tools/subagent/spawn.ts +2 -2
  431. package/src/tools/swarm/delegate.ts +3 -3
  432. package/src/tools/system/request-permission.ts +5 -4
  433. package/src/tools/terminal/backends/native.ts +4 -4
  434. package/src/tools/terminal/parser.ts +6 -6
  435. package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
  436. package/src/tools/terminal/shell.ts +16 -16
  437. package/src/tools/tool-approval-handler.ts +21 -12
  438. package/src/tools/tool-manifest.ts +4 -4
  439. package/src/tools/types.ts +3 -3
  440. package/src/tools/ui-surface/definitions.ts +9 -37
  441. package/src/tools/watcher/list.ts +1 -1
  442. package/src/util/logger.ts +7 -2
  443. package/src/util/retry.ts +29 -1
  444. package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
  445. package/src/workspace/migrations/registry.ts +2 -0
  446. package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
  447. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
  448. package/src/cli/reference.ts +0 -38
  449. package/src/memory/job-handlers/capability-cards.ts +0 -420
  450. package/src/runtime/routes/thread-starter-routes.ts +0 -294
@@ -34,13 +34,14 @@ function toArrayBuffer(data: Uint8Array): ArrayBuffer {
34
34
  const testDir = realpathSync(
35
35
  mkdtempSync(join(tmpdir(), "migration-import-preflight-http-test-")),
36
36
  );
37
- const testDbDir = join(testDir, "db");
37
+ const testDbDir = join(testDir, "data", "db");
38
38
  const testDbPath = join(testDbDir, "assistant.db");
39
39
  const testConfigPath = join(testDir, "config.json");
40
40
 
41
41
  mock.module("../util/platform.js", () => ({
42
42
  getRootDir: () => testDir,
43
- getDataDir: () => testDir,
43
+ getDataDir: () => join(testDir, "data"),
44
+ getWorkspaceDir: () => testDir,
44
45
  getWorkspaceConfigPath: () => testConfigPath,
45
46
  isMacOS: () => process.platform === "darwin",
46
47
  isLinux: () => process.platform === "linux",
@@ -64,9 +65,8 @@ mock.module("../config/loader.js", () => ({
64
65
  model: "test",
65
66
  provider: "test",
66
67
  memory: { enabled: false },
67
- rateLimit: { maxRequestsPerMinute: 0, maxTokensPerSession: 0 },
68
+ rateLimit: { maxRequestsPerMinute: 0 },
68
69
  secretDetection: { enabled: false },
69
- sandbox: { enabled: false },
70
70
  }),
71
71
  }));
72
72
 
@@ -525,8 +525,8 @@ describe("handleMigrationImportPreflight — validation failures", () => {
525
525
  describe("analyzeImport", () => {
526
526
  test("detects create when file does not exist on disk", () => {
527
527
  const resolver = new DefaultPathResolver(
528
- join(testDir, "nonexistent.db"),
529
- join(testDir, "nonexistent-config.json"),
528
+ undefined,
529
+ join(testDir, "nonexistent-workspace"),
530
530
  );
531
531
 
532
532
  const report = analyzeImport({
@@ -553,7 +553,7 @@ describe("analyzeImport", () => {
553
553
  });
554
554
 
555
555
  test("detects unchanged when file on disk matches bundle", () => {
556
- const resolver = new DefaultPathResolver(testDbPath, testConfigPath);
556
+ const resolver = new DefaultPathResolver(undefined, testDir);
557
557
 
558
558
  const report = analyzeImport({
559
559
  manifest: {
@@ -577,7 +577,7 @@ describe("analyzeImport", () => {
577
577
  });
578
578
 
579
579
  test("detects overwrite when file on disk differs from bundle", () => {
580
- const resolver = new DefaultPathResolver(testDbPath, testConfigPath);
580
+ const resolver = new DefaultPathResolver(undefined, testDir);
581
581
 
582
582
  const report = analyzeImport({
583
583
  manifest: {
@@ -602,7 +602,7 @@ describe("analyzeImport", () => {
602
602
  });
603
603
 
604
604
  test("flags unknown archive paths as conflicts with skip action", () => {
605
- const resolver = new DefaultPathResolver(testDbPath, testConfigPath);
605
+ const resolver = new DefaultPathResolver(undefined, testDir);
606
606
 
607
607
  const report = analyzeImport({
608
608
  manifest: {
@@ -640,7 +640,7 @@ describe("analyzeImport", () => {
640
640
  });
641
641
 
642
642
  test("includes manifest in report", () => {
643
- const resolver = new DefaultPathResolver(testDbPath, testConfigPath);
643
+ const resolver = new DefaultPathResolver(undefined, testDir);
644
644
  const manifest = {
645
645
  schema_version: "1.0",
646
646
  created_at: "2024-01-01T00:00:00.000Z",
@@ -668,29 +668,90 @@ describe("analyzeImport", () => {
668
668
  // ---------------------------------------------------------------------------
669
669
 
670
670
  describe("DefaultPathResolver", () => {
671
- test("resolves data/db/assistant.db to configured db path", () => {
671
+ test("resolves data/db/assistant.db to workspace db path (backward compat)", () => {
672
672
  const resolver = new DefaultPathResolver(
673
- "/some/db.db",
674
- "/some/config.json",
673
+ undefined,
674
+ "/home/user/.vellum/workspace",
675
+ );
676
+ expect(resolver.resolve("data/db/assistant.db")).toBe(
677
+ "/home/user/.vellum/workspace/data/db/assistant.db",
675
678
  );
676
- expect(resolver.resolve("data/db/assistant.db")).toBe("/some/db.db");
677
679
  });
678
680
 
679
- test("resolves config/settings.json to configured config path", () => {
681
+ test("resolves config/settings.json to workspace config path (backward compat)", () => {
680
682
  const resolver = new DefaultPathResolver(
681
- "/some/db.db",
682
- "/some/config.json",
683
+ undefined,
684
+ "/home/user/.vellum/workspace",
685
+ );
686
+ expect(resolver.resolve("config/settings.json")).toBe(
687
+ "/home/user/.vellum/workspace/config.json",
683
688
  );
684
- expect(resolver.resolve("config/settings.json")).toBe("/some/config.json");
685
689
  });
686
690
 
687
691
  test("returns null for unknown paths", () => {
688
692
  const resolver = new DefaultPathResolver(
689
- "/some/db.db",
690
- "/some/config.json",
693
+ undefined,
694
+ "/home/user/.vellum/workspace",
691
695
  );
692
696
  expect(resolver.resolve("unknown/path.txt")).toBeNull();
693
697
  });
698
+
699
+ test("resolves valid skills path via backward compat", () => {
700
+ const resolver = new DefaultPathResolver(
701
+ undefined,
702
+ "/home/user/.vellum/workspace",
703
+ );
704
+ expect(resolver.resolve("skills/my-skill/SKILL.md")).toBe(
705
+ "/home/user/.vellum/workspace/skills/my-skill/SKILL.md",
706
+ );
707
+ });
708
+
709
+ test("resolves workspace/ prefix paths", () => {
710
+ const resolver = new DefaultPathResolver(
711
+ undefined,
712
+ "/home/user/.vellum/workspace",
713
+ );
714
+ expect(resolver.resolve("workspace/data/db/assistant.db")).toBe(
715
+ "/home/user/.vellum/workspace/data/db/assistant.db",
716
+ );
717
+ expect(resolver.resolve("workspace/config.json")).toBe(
718
+ "/home/user/.vellum/workspace/config.json",
719
+ );
720
+ expect(resolver.resolve("workspace/skills/my-skill/SKILL.md")).toBe(
721
+ "/home/user/.vellum/workspace/skills/my-skill/SKILL.md",
722
+ );
723
+ });
724
+
725
+ test("returns null for workspace/ path traversal attempt", () => {
726
+ const resolver = new DefaultPathResolver(
727
+ undefined,
728
+ "/home/user/.vellum/workspace",
729
+ );
730
+ expect(resolver.resolve("workspace/../../etc/passwd")).toBeNull();
731
+ });
732
+
733
+ test("returns null for skills path traversal attempt (../../etc/passwd)", () => {
734
+ const resolver = new DefaultPathResolver(
735
+ undefined,
736
+ "/home/user/.vellum/workspace",
737
+ );
738
+ expect(resolver.resolve("skills/../../etc/passwd")).toBeNull();
739
+ });
740
+
741
+ test("returns null for skills path traversal attempt (../../../.ssh/authorized_keys)", () => {
742
+ const resolver = new DefaultPathResolver(
743
+ undefined,
744
+ "/home/user/.vellum/workspace",
745
+ );
746
+ expect(
747
+ resolver.resolve("skills/../../../.ssh/authorized_keys"),
748
+ ).toBeNull();
749
+ });
750
+
751
+ test("returns null for skills paths when workspaceDir is not provided", () => {
752
+ const resolver = new DefaultPathResolver();
753
+ expect(resolver.resolve("skills/my-skill/SKILL.md")).toBeNull();
754
+ });
694
755
  });
695
756
 
696
757
  // ---------------------------------------------------------------------------
@@ -53,9 +53,8 @@ mock.module("../config/loader.js", () => ({
53
53
  model: "test",
54
54
  provider: "test",
55
55
  memory: { enabled: false },
56
- rateLimit: { maxRequestsPerMinute: 0, maxTokensPerSession: 0 },
56
+ rateLimit: { maxRequestsPerMinute: 0 },
57
57
  secretDetection: { enabled: false },
58
- sandbox: { enabled: false },
59
58
  }),
60
59
  }));
61
60
 
@@ -307,26 +306,27 @@ describe("validateVBundle", () => {
307
306
  expect(manifestError).toBeDefined();
308
307
  });
309
308
 
310
- test("missing data/db/assistant.db returns MISSING_ENTRY error", () => {
311
- const manifestData = new TextEncoder().encode(
312
- JSON.stringify({
313
- schema_version: "1.0",
314
- created_at: new Date().toISOString(),
315
- files: [],
316
- manifest_sha256: "placeholder",
317
- }),
318
- );
309
+ test("bundle with only manifest (no data files) is structurally valid", () => {
310
+ // After the workspace walk refactor, only manifest.json is required.
311
+ // But the manifest checksum must match for full validity.
312
+ const manifestWithoutChecksum = {
313
+ schema_version: "1.0",
314
+ created_at: new Date().toISOString(),
315
+ files: [],
316
+ };
317
+ const manifestSha256 = sha256Hex(canonicalizeJson(manifestWithoutChecksum));
318
+ const manifest = {
319
+ ...manifestWithoutChecksum,
320
+ manifest_sha256: manifestSha256,
321
+ };
322
+ const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
319
323
  const tar = createTarArchive([
320
324
  { name: "manifest.json", data: manifestData },
321
325
  ]);
322
326
  const vbundle = gzipSync(tar);
323
327
  const result = validateVBundle(vbundle);
324
328
 
325
- expect(result.is_valid).toBe(false);
326
- const dbError = result.errors.find(
327
- (e) => e.code === "MISSING_ENTRY" && e.path === "data/db/assistant.db",
328
- );
329
- expect(dbError).toBeDefined();
329
+ expect(result.is_valid).toBe(true);
330
330
  });
331
331
 
332
332
  test("invalid manifest JSON returns INVALID_MANIFEST_JSON error", () => {
@@ -62,7 +62,7 @@ describe("model intents", () => {
62
62
  "claude-opus-4-6",
63
63
  );
64
64
  expect(resolveModelIntent("anthropic", "vision-optimized")).toBe(
65
- "claude-sonnet-4-6",
65
+ "claude-opus-4-6",
66
66
  );
67
67
  expect(resolveModelIntent("openai", "latency-optimized")).toBe(
68
68
  "gpt-4o-mini",
@@ -5,7 +5,7 @@ import { describe, expect, test } from "bun:test";
5
5
  /**
6
6
  * Guard test: domain-specific routing sections must NOT appear in the system
7
7
  * prompt source file. Routing cues now live in skill frontmatter
8
- * (`activation-hints` / `avoid-when`) and are projected into `<available_skills>` XML.
8
+ * (`activation-hints` / `avoid-when`) and are projected into the skills catalog.
9
9
  *
10
10
  * If this test fails, you are re-introducing hardcoded routing into the system
11
11
  * prompt. Instead, add `activation-hints` to the skill's SKILL.md frontmatter.
@@ -115,7 +115,7 @@ function makeSignal(
115
115
  signalId: "sig-broadcast-001",
116
116
  createdAt: Date.now(),
117
117
  sourceChannel: "scheduler",
118
- sourceSessionId: "sess-001",
118
+ sourceContextId: "sess-001",
119
119
  sourceEventName: "test.event",
120
120
  contextPayload: {},
121
121
  attentionHints: {
@@ -65,7 +65,7 @@ function makeSignal(
65
65
  signalId: "sig-fallback-guardian-1",
66
66
  createdAt: Date.now(),
67
67
  sourceChannel: "phone",
68
- sourceSessionId: "call-session-1",
68
+ sourceContextId: "call-session-1",
69
69
  sourceEventName: "guardian.question",
70
70
  contextPayload: {
71
71
  questionText: "What is the gate code?",
@@ -308,7 +308,7 @@ describe("access-request instruction enforcement", () => {
308
308
  signalId: "sig-access-req-1",
309
309
  createdAt: Date.now(),
310
310
  sourceChannel: "telegram",
311
- sourceSessionId: "tg-session-1",
311
+ sourceContextId: "tg-session-1",
312
312
  sourceEventName: "ingress.access_request",
313
313
  contextPayload: {
314
314
  senderIdentifier: "Alice",
@@ -45,7 +45,9 @@ mock.module("../prompts/system-prompt.js", () => ({
45
45
 
46
46
  // ── Provider mock with system prompt capture ──────────────────────────
47
47
 
48
- let configuredProvider: { sendMessage: (...args: unknown[]) => Promise<unknown> } | null = null;
48
+ let configuredProvider: {
49
+ sendMessage: (...args: unknown[]) => Promise<unknown>;
50
+ } | null = null;
49
51
  let extractedToolUse: unknown = null;
50
52
  let capturedSystemPrompt: string | undefined;
51
53
 
@@ -81,7 +83,7 @@ function makeSignal(
81
83
  signalId: "sig-identity-test-1",
82
84
  createdAt: Date.now(),
83
85
  sourceChannel: "phone",
84
- sourceSessionId: "call-session-1",
86
+ sourceContextId: "call-session-1",
85
87
  sourceEventName: "guardian.question",
86
88
  contextPayload: {
87
89
  questionText: "What is the gate code?",
@@ -141,9 +143,7 @@ describe("identity context in notification decision engine", () => {
141
143
 
142
144
  expect(capturedSystemPrompt).toBeDefined();
143
145
  expect(capturedSystemPrompt).toContain("<assistant-identity>");
144
- expect(capturedSystemPrompt).toContain(
145
- "I am Jarvis, a helpful assistant",
146
- );
146
+ expect(capturedSystemPrompt).toContain("I am Jarvis, a helpful assistant");
147
147
  expect(capturedSystemPrompt).toContain("</assistant-identity>");
148
148
  });
149
149
 
@@ -192,10 +192,9 @@ describe("identity context in notification decision engine", () => {
192
192
  configuredProvider = null;
193
193
 
194
194
  const signal = makeSignal();
195
- const decision = await evaluateSignal(
196
- signal,
197
- ["vellum"] as NotificationChannel[],
198
- );
195
+ const decision = await evaluateSignal(signal, [
196
+ "vellum",
197
+ ] as NotificationChannel[]);
199
198
 
200
199
  // Fallback should produce valid copy regardless of identity context
201
200
  expect(decision.fallbackUsed).toBe(true);
@@ -38,7 +38,7 @@ function makeSignal(
38
38
  signalId: "sig-test-001",
39
39
  createdAt: Date.now(),
40
40
  sourceChannel: "scheduler",
41
- sourceSessionId: "sess-001",
41
+ sourceContextId: "sess-001",
42
42
  sourceEventName: "test.event",
43
43
  contextPayload: {},
44
44
  attentionHints: {
@@ -89,7 +89,7 @@ function makeSignal(
89
89
  signalId: "sig-deeplink-001",
90
90
  createdAt: Date.now(),
91
91
  sourceChannel: "scheduler",
92
- sourceSessionId: "sess-001",
92
+ sourceContextId: "sess-001",
93
93
  sourceEventName: "test.event",
94
94
  contextPayload: {},
95
95
  attentionHints: {
@@ -239,7 +239,6 @@ describe("ASK_GUARDIAN canonical notification path", () => {
239
239
 
240
240
  const signalParams = emitCalls[0] as Record<string, unknown>;
241
241
  expect(typeof signalParams.onConversationCreated).toBe("function");
242
- expect(signalParams.skipVellumThread).toBeUndefined();
243
242
  });
244
243
 
245
244
  test("creates guardian action deliveries from notification pipeline delivery results", async () => {
@@ -72,7 +72,7 @@ function makeSignal(
72
72
  signalId: `sig-${crypto.randomUUID()}`,
73
73
  createdAt: Date.now(),
74
74
  sourceChannel: "scheduler",
75
- sourceSessionId: "schedule-123",
75
+ sourceContextId: "schedule-123",
76
76
  sourceEventName: "schedule.complete",
77
77
  contextPayload: { scheduleId: "schedule-123", name: "Drink water" },
78
78
  attentionHints: {
@@ -118,7 +118,7 @@ describe("recurring schedule notification dedup", () => {
118
118
  id: firstSignal.signalId,
119
119
  sourceEventName: "schedule.complete",
120
120
  sourceChannel: "scheduler",
121
- sourceSessionId: "schedule-123",
121
+ sourceContextId: "schedule-123",
122
122
  attentionHints: firstSignal.attentionHints,
123
123
  payload: firstSignal.contextPayload,
124
124
  // No dedupeKey — this is the bug scenario
@@ -132,7 +132,7 @@ describe("recurring schedule notification dedup", () => {
132
132
  id: secondSignal.signalId,
133
133
  sourceEventName: "schedule.complete",
134
134
  sourceChannel: "scheduler",
135
- sourceSessionId: "schedule-123",
135
+ sourceContextId: "schedule-123",
136
136
  attentionHints: secondSignal.attentionHints,
137
137
  payload: secondSignal.contextPayload,
138
138
  });
@@ -160,7 +160,7 @@ describe("recurring schedule notification dedup", () => {
160
160
  id: firstSignal.signalId,
161
161
  sourceEventName: "schedule.complete",
162
162
  sourceChannel: "scheduler",
163
- sourceSessionId: "schedule-123",
163
+ sourceContextId: "schedule-123",
164
164
  attentionHints: firstSignal.attentionHints,
165
165
  payload: firstSignal.contextPayload,
166
166
  dedupeKey: `schedule:complete:schedule-123:${Date.now() - 60_000}`,
@@ -173,7 +173,7 @@ describe("recurring schedule notification dedup", () => {
173
173
  id: secondSignal.signalId,
174
174
  sourceEventName: "schedule.complete",
175
175
  sourceChannel: "scheduler",
176
- sourceSessionId: "schedule-123",
176
+ sourceContextId: "schedule-123",
177
177
  attentionHints: secondSignal.attentionHints,
178
178
  payload: secondSignal.contextPayload,
179
179
  dedupeKey: `schedule:complete:schedule-123:${Date.now()}`,
@@ -204,7 +204,7 @@ describe("recurring schedule notification dedup", () => {
204
204
  id: firstSignal.signalId,
205
205
  sourceEventName: "schedule.notify",
206
206
  sourceChannel: "scheduler",
207
- sourceSessionId: "schedule-123",
207
+ sourceContextId: "schedule-123",
208
208
  attentionHints: firstSignal.attentionHints,
209
209
  payload: firstSignal.contextPayload,
210
210
  dedupeKey: `schedule:notify:schedule-123:${Date.now() - 60_000}`,
@@ -219,7 +219,7 @@ describe("recurring schedule notification dedup", () => {
219
219
  id: secondSignal.signalId,
220
220
  sourceEventName: "schedule.notify",
221
221
  sourceChannel: "scheduler",
222
- sourceSessionId: "schedule-123",
222
+ sourceContextId: "schedule-123",
223
223
  attentionHints: secondSignal.attentionHints,
224
224
  payload: secondSignal.contextPayload,
225
225
  dedupeKey: `schedule:notify:schedule-123:${Date.now()}`,
@@ -83,9 +83,7 @@ async function createTestApp(providerKey = "github", clientId = "client-1") {
83
83
  }
84
84
 
85
85
  beforeEach(() => {
86
- resetDb();
87
- initializeDb();
88
- // Explicitly clear all OAuth tables to prevent cross-test state pollution.
86
+ // Clear OAuth tables between tests instead of full DB reset + migration.
89
87
  // Delete in FK-dependency order: connections → apps → providers.
90
88
  resetTestTables("oauth_connections", "oauth_apps", "oauth_providers");
91
89
  mockDeleteSecureKeyAsync.mockClear();
@@ -484,17 +484,22 @@ describe("OAuth2 gateway transport", () => {
484
484
  };
485
485
 
486
486
  let capturedAuthUrl = "";
487
+ let urlReady!: () => void;
488
+ const urlReadyPromise = new Promise<void>((r) => {
489
+ urlReady = r;
490
+ });
487
491
  const flowPromise = startOAuth2Flow(
488
492
  BASE_OAUTH_CONFIG,
489
493
  {
490
494
  openUrl: (url) => {
491
495
  capturedAuthUrl = url;
496
+ urlReady();
492
497
  },
493
498
  },
494
499
  { callbackTransport: "loopback" },
495
500
  );
496
501
 
497
- await new Promise((r) => setTimeout(r, 50));
502
+ await urlReadyPromise;
498
503
 
499
504
  const authUrl = new URL(capturedAuthUrl);
500
505
  const redirectUri = authUrl.searchParams.get("redirect_uri")!;
@@ -9,14 +9,19 @@ const user = readFileSync(join(templatesDir, "USER.md"), "utf-8");
9
9
 
10
10
  describe("onboarding template contracts", () => {
11
11
  describe("BOOTSTRAP.md", () => {
12
- test("contains identity question prompts", () => {
12
+ test("preserves comment line format instruction", () => {
13
+ expect(bootstrap).toMatch(/^_ Lines starting with _/);
14
+ });
15
+
16
+ test("contains identity discovery prompts", () => {
13
17
  const lower = bootstrap.toLowerCase();
14
- expect(lower).toContain("who am i");
18
+ expect(lower).toContain("your name");
19
+ expect(lower).toContain("personality");
20
+ expect(lower).toContain("avatar");
15
21
  });
16
22
 
17
23
  test("infers personality organically instead of asking directly", () => {
18
24
  const lower = bootstrap.toLowerCase();
19
- // Personality step must instruct organic discovery via conversation
20
25
  expect(lower).toContain("personality");
21
26
  expect(lower).toContain("emerge");
22
27
  expect(lower).toContain("vibe");
@@ -28,28 +33,17 @@ describe("onboarding template contracts", () => {
28
33
  expect(lower).toContain("change it later");
29
34
  });
30
35
 
31
- test("contains naming intent markers so the first reply includes naming cues", () => {
32
- const lower = bootstrap.toLowerCase();
33
- // The template must prompt the assistant to ask about names.
34
- expect(lower).toContain("name");
35
- // The first step should be about the assistant's name
36
- expect(lower).toContain("your name");
37
- // The conversation sequence must include identity/naming
38
- expect(lower).toContain("who am i");
39
- });
40
-
41
- test("asks user name AFTER assistant identity is established", () => {
42
- // Step 1 is the assistant's name, step 4 is asking the user's name
43
- const assistantNameIdx = bootstrap.indexOf("Your name:");
44
- const userNameIdx = bootstrap.indexOf("who am I talking to?");
45
- expect(assistantNameIdx).toBeGreaterThan(-1);
46
- expect(userNameIdx).toBeGreaterThan(-1);
47
- expect(assistantNameIdx).toBeLessThan(userNameIdx);
36
+ test("asks about user after assistant identity", () => {
37
+ const nameIdx = bootstrap.indexOf("Your name");
38
+ const theirNameIdx = bootstrap.indexOf("Their name");
39
+ expect(nameIdx).toBeGreaterThan(-1);
40
+ expect(theirNameIdx).toBeGreaterThan(-1);
41
+ expect(nameIdx).toBeLessThan(theirNameIdx);
48
42
  });
49
43
 
50
44
  test("gathers user context: work role, hobbies, daily tools", () => {
51
45
  const lower = bootstrap.toLowerCase();
52
- expect(lower).toContain("work");
46
+ expect(lower).toContain("work role");
53
47
  expect(lower).toContain("hobbies");
54
48
  expect(lower).toContain("tools");
55
49
  });
@@ -57,51 +51,32 @@ describe("onboarding template contracts", () => {
57
51
  test("shows exactly 2 suggestions via ui_show card with relay_prompt actions", () => {
58
52
  expect(bootstrap).toContain("ui_show");
59
53
  expect(bootstrap).toContain("exactly 2");
60
- // Must use card surface with relay_prompt action buttons
61
- expect(bootstrap).toContain('surface_type: "card"');
62
54
  expect(bootstrap).toContain("relay_prompt");
63
55
  });
64
56
 
65
- test("contains completion gate with all required conditions", () => {
57
+ test("contains wrapping-up criteria with required conditions", () => {
66
58
  const lower = bootstrap.toLowerCase();
67
- expect(lower).toContain("completion gate");
68
- expect(lower).toContain("do not delete this file");
69
- // Assistant name is hard-required
70
- expect(lower).toContain("you have a name");
71
- expect(lower).toContain("hard-required");
59
+ expect(lower).toContain("wrapping up");
60
+ expect(lower).toContain("done with onboarding");
72
61
  expect(lower).toContain("vibe");
73
- // User detail fields must be resolved (provided, inferred, or declined)
74
- expect(lower).toContain("resolved");
75
- expect(lower).toContain("work role");
76
- expect(lower).toContain("2 suggestions from step 6");
62
+ expect(lower).toContain("two suggestions");
77
63
  });
78
64
 
79
65
  test("contains refusal policy", () => {
80
66
  const lower = bootstrap.toLowerCase();
81
- // Assistant name is hard-required, user details are best-effort
82
67
  expect(lower).toContain("hard-required");
83
68
  expect(lower).toContain("best-effort");
84
- // Refusal is a valid resolution
85
69
  expect(lower).toContain("declined");
86
- expect(lower).toContain("do not push");
70
+ expect(lower).toContain("not interrogation");
87
71
  });
88
72
 
89
73
  test("defines resolved as provided, inferred, or declined", () => {
90
74
  const lower = bootstrap.toLowerCase();
91
- // The template must define what "resolved" means
92
75
  expect(lower).toContain("resolved");
93
76
  expect(lower).toContain("inferred");
94
77
  expect(lower).toContain("declined");
95
78
  });
96
79
 
97
- // em-dash and technical jargon instructions are now hardcoded in the system
98
- // prompt builder (buildSystemPrompt) rather than in the BOOTSTRAP.md template.
99
-
100
- test("preserves comment line format instruction", () => {
101
- // The template must start with the comment format explanation
102
- expect(bootstrap).toMatch(/^_ Lines starting with _/);
103
- });
104
-
105
80
  test("instructs saving to IDENTITY.md, USER.md, and SOUL.md via file_edit", () => {
106
81
  expect(bootstrap).toContain("IDENTITY.md");
107
82
  expect(bootstrap).toContain("USER.md");
@@ -118,18 +93,13 @@ describe("onboarding template contracts", () => {
118
93
  expect(identity).toContain("**Emoji:**");
119
94
  });
120
95
 
121
- test("contains the emoji overwrite instruction", () => {
122
- const lower = identity.toLowerCase();
123
- expect(lower).toContain("change their emoji");
124
- });
125
-
126
- test("contains the style tendency field", () => {
127
- expect(identity).toContain("**Style tendency:**");
96
+ test("contains parsed field format guidance", () => {
97
+ expect(identity).toContain("parsed by the app");
128
98
  });
129
99
  });
130
100
 
131
101
  describe("USER.md", () => {
132
- test("contains onboarding snapshot with all required fields", () => {
102
+ test("contains profile fields", () => {
133
103
  expect(user).toContain("Preferred name/reference:");
134
104
  expect(user).toContain("Goals:");
135
105
  expect(user).toContain("Locale:");
@@ -137,11 +107,5 @@ describe("onboarding template contracts", () => {
137
107
  expect(user).toContain("Hobbies/fun:");
138
108
  expect(user).toContain("Daily tools:");
139
109
  });
140
-
141
- test("documents resolved-field status conventions", () => {
142
- const lower = user.toLowerCase();
143
- expect(lower).toContain("declined_by_user");
144
- expect(lower).toContain("resolved");
145
- });
146
110
  });
147
111
  });