@vellumai/assistant 0.6.4 → 0.6.5

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 (717) hide show
  1. package/.prettierignore +5 -0
  2. package/ARCHITECTURE.md +32 -36
  3. package/Dockerfile +12 -0
  4. package/README.md +3 -4
  5. package/bun.lock +8 -3
  6. package/docs/architecture/integrations.md +1 -20
  7. package/docs/architecture/security.md +16 -16
  8. package/docs/error-handling.md +111 -0
  9. package/docs/skills.md +10 -10
  10. package/docs/stt-provider-onboarding.md +2 -1
  11. package/knip.json +9 -2
  12. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  14. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  15. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  16. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  17. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  18. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  19. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  20. package/openapi.yaml +123 -11
  21. package/package.json +6 -3
  22. package/scripts/generate-openapi.ts +50 -11
  23. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  24. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  25. package/src/__tests__/agent-loop.test.ts +112 -1
  26. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  27. package/src/__tests__/anthropic-provider.test.ts +171 -2
  28. package/src/__tests__/approval-cascade.test.ts +31 -10
  29. package/src/__tests__/approval-routes-http.test.ts +134 -10
  30. package/src/__tests__/assistant-attachments.test.ts +44 -0
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  32. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  33. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  34. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  35. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  36. package/src/__tests__/btw-routes.test.ts +47 -1
  37. package/src/__tests__/call-controller.test.ts +1 -2
  38. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  39. package/src/__tests__/catalog-cache.test.ts +27 -4
  40. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  41. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  42. package/src/__tests__/checker.test.ts +428 -501
  43. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  44. package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
  45. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  46. package/src/__tests__/config-analysis.test.ts +11 -28
  47. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  48. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  49. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  50. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  51. package/src/__tests__/config-schema.test.ts +427 -114
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  54. package/src/__tests__/contacts-write.test.ts +4 -4
  55. package/src/__tests__/context-token-estimator.test.ts +191 -1
  56. package/src/__tests__/context-window-manager.test.ts +530 -2
  57. package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
  58. package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
  59. package/src/__tests__/conversation-agent-loop.test.ts +412 -82
  60. package/src/__tests__/conversation-attachments.test.ts +1 -1
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
  62. package/src/__tests__/conversation-error.test.ts +37 -6
  63. package/src/__tests__/conversation-history-web-search.test.ts +6 -0
  64. package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
  65. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  66. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  67. package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
  68. package/src/__tests__/conversation-process-callsite.test.ts +306 -0
  69. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
  70. package/src/__tests__/conversation-queue.test.ts +41 -26
  71. package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
  75. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  76. package/src/__tests__/conversation-slash-queue.test.ts +34 -19
  77. package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
  78. package/src/__tests__/conversation-speed-override.test.ts +30 -11
  79. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  80. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  81. package/src/__tests__/conversation-title-service.test.ts +2 -2
  82. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  83. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  84. package/src/__tests__/conversation-usage.test.ts +3 -1
  85. package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
  86. package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
  87. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  89. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  90. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  91. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  92. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  93. package/src/__tests__/credentials-cli.test.ts +1 -9
  94. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  95. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  96. package/src/__tests__/delete-propagation.test.ts +437 -0
  97. package/src/__tests__/dm-backfill.test.ts +417 -0
  98. package/src/__tests__/dm-persistence.test.ts +227 -0
  99. package/src/__tests__/edit-propagation.test.ts +280 -0
  100. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  101. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  102. package/src/__tests__/estimator-calibration.test.ts +213 -0
  103. package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
  104. package/src/__tests__/file-write-tool.test.ts +151 -1
  105. package/src/__tests__/filing-service.test.ts +255 -0
  106. package/src/__tests__/gemini-provider.test.ts +0 -3
  107. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  108. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  109. package/src/__tests__/heartbeat-service.test.ts +96 -15
  110. package/src/__tests__/host-shell-tool.test.ts +124 -18
  111. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  112. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  113. package/src/__tests__/intent-routing.test.ts +1 -40
  114. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  115. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  116. package/src/__tests__/llm-resolver.test.ts +214 -0
  117. package/src/__tests__/llm-schema.test.ts +223 -0
  118. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  119. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  120. package/src/__tests__/migration-import-from-url.test.ts +684 -0
  121. package/src/__tests__/model-intents.test.ts +9 -83
  122. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  123. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  124. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  125. package/src/__tests__/oauth-store.test.ts +10 -7
  126. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  127. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  128. package/src/__tests__/openai-provider.test.ts +7 -0
  129. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  130. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  131. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  132. package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
  133. package/src/__tests__/permission-mode.test.ts +16 -0
  134. package/src/__tests__/permission-types.test.ts +0 -1
  135. package/src/__tests__/persona-resolver.test.ts +13 -13
  136. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  137. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  138. package/src/__tests__/pricing.test.ts +50 -3
  139. package/src/__tests__/profiler-routes.test.ts +1 -1
  140. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  141. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  143. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  144. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  145. package/src/__tests__/proxy-approval-callback.test.ts +0 -1
  146. package/src/__tests__/reaction-persistence.test.ts +560 -0
  147. package/src/__tests__/relay-server.test.ts +1 -1
  148. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  149. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  150. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  151. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  152. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  153. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  154. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  156. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  157. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  158. package/src/__tests__/server-history-render.test.ts +31 -0
  159. package/src/__tests__/shell-parser-property.test.ts +13 -13
  160. package/src/__tests__/skill-cache-store.test.ts +182 -0
  161. package/src/__tests__/skills.test.ts +19 -33
  162. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  163. package/src/__tests__/slack-skill.test.ts +3 -8
  164. package/src/__tests__/starter-bundle.test.ts +35 -0
  165. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  166. package/src/__tests__/suggestion-routes.test.ts +160 -3
  167. package/src/__tests__/system-prompt.test.ts +22 -35
  168. package/src/__tests__/task-runner.test.ts +3 -1
  169. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  170. package/src/__tests__/terminal-tools.test.ts +8 -0
  171. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  172. package/src/__tests__/thread-backfill.test.ts +941 -0
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  175. package/src/__tests__/tool-executor.test.ts +60 -94
  176. package/src/__tests__/trust-store.test.ts +442 -109
  177. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  178. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  179. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  180. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  181. package/src/__tests__/volume-security-guard.test.ts +3 -2
  182. package/src/__tests__/web-search-history.test.ts +337 -0
  183. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  184. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  185. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  186. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  187. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  188. package/src/__tests__/workspace-policy.test.ts +1 -13
  189. package/src/acp/client-handler.ts +1 -2
  190. package/src/agent/loop.ts +209 -17
  191. package/src/avatar/resvg-lazy.test.ts +136 -0
  192. package/src/avatar/resvg-lazy.ts +82 -9
  193. package/src/avatar/traits-png-sync.ts +21 -1
  194. package/src/browser/__tests__/operations.test.ts +163 -0
  195. package/src/browser/identifiers.ts +51 -0
  196. package/src/browser/operations.ts +660 -0
  197. package/src/browser/types.ts +81 -0
  198. package/src/calls/guardian-question-copy.ts +2 -2
  199. package/src/calls/telephony-stt-routing.ts +1 -1
  200. package/src/calls/voice-session-bridge.ts +1 -0
  201. package/src/cli/AGENTS.md +1 -1
  202. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  203. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  204. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  205. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  206. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  207. package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
  208. package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
  209. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  210. package/src/cli/commands/__tests__/task.test.ts +913 -0
  211. package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
  212. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  213. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  214. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  215. package/src/cli/commands/attachment.ts +182 -0
  216. package/src/cli/commands/browser.ts +350 -0
  217. package/src/cli/commands/cache.ts +341 -0
  218. package/src/cli/commands/completions.ts +0 -3
  219. package/src/cli/commands/config.ts +6 -6
  220. package/src/cli/commands/conversations-import.ts +347 -0
  221. package/src/cli/commands/conversations.ts +14 -1
  222. package/src/cli/commands/email.ts +234 -194
  223. package/src/cli/commands/image-generation.ts +300 -0
  224. package/src/cli/commands/inference.ts +200 -0
  225. package/src/cli/commands/memory.ts +127 -17
  226. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  227. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  228. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  229. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  230. package/src/cli/commands/stt.ts +339 -0
  231. package/src/cli/commands/task.ts +795 -0
  232. package/src/cli/commands/trust.ts +50 -19
  233. package/src/cli/commands/tts.ts +273 -0
  234. package/src/cli/commands/ui.ts +670 -0
  235. package/src/cli/commands/watchers.ts +509 -0
  236. package/src/cli/lib/daemon-credential-client.ts +0 -19
  237. package/src/cli/program.ts +23 -4
  238. package/src/cli.ts +0 -37
  239. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
  240. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  241. package/src/config/bundled-skills/messaging/SKILL.md +2 -2
  242. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  243. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
  244. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  245. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  246. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
  247. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  248. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  249. package/src/config/bundled-tool-registry.ts +0 -175
  250. package/src/config/env.ts +7 -2
  251. package/src/config/feature-flag-registry.json +25 -9
  252. package/src/config/llm-resolver.ts +128 -0
  253. package/src/config/loader.ts +194 -10
  254. package/src/config/raw-config-utils.ts +30 -2
  255. package/src/config/sanitize-for-transfer.ts +35 -0
  256. package/src/config/schema.ts +30 -41
  257. package/src/config/schemas/analysis.ts +3 -22
  258. package/src/config/schemas/calls.ts +0 -4
  259. package/src/config/schemas/filing.ts +2 -7
  260. package/src/config/schemas/heartbeat.ts +0 -5
  261. package/src/config/schemas/inference.ts +3 -23
  262. package/src/config/schemas/llm.ts +318 -0
  263. package/src/config/schemas/memory-processing.ts +1 -9
  264. package/src/config/schemas/notifications.ts +4 -11
  265. package/src/config/schemas/platform.ts +3 -9
  266. package/src/config/schemas/security.ts +33 -0
  267. package/src/config/schemas/services.ts +9 -4
  268. package/src/config/schemas/stt.ts +1 -0
  269. package/src/config/schemas/tts.ts +53 -0
  270. package/src/config/schemas/updates.ts +1 -1
  271. package/src/config/schemas/workspace-git.ts +3 -40
  272. package/src/config/skills.ts +2 -2
  273. package/src/context/__tests__/compact-prompt.test.ts +45 -0
  274. package/src/context/__tests__/microcompact.test.ts +805 -0
  275. package/src/context/estimator-calibration.ts +136 -0
  276. package/src/context/microcompact.ts +443 -0
  277. package/src/context/prompts/compact.md +12 -0
  278. package/src/context/token-estimator.ts +61 -3
  279. package/src/context/window-manager.ts +229 -25
  280. package/src/credential-execution/approval-bridge.ts +0 -1
  281. package/src/credential-execution/executable-discovery.ts +19 -8
  282. package/src/credential-execution/process-manager.test.ts +109 -0
  283. package/src/credential-execution/process-manager.ts +65 -2
  284. package/src/daemon/approval-generators.ts +29 -4
  285. package/src/daemon/assistant-attachments.ts +24 -13
  286. package/src/daemon/classifier.ts +2 -2
  287. package/src/daemon/config-watcher.ts +0 -1
  288. package/src/daemon/context-overflow-reducer.ts +4 -1
  289. package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
  290. package/src/daemon/conversation-agent-loop.ts +462 -80
  291. package/src/daemon/conversation-attachments.ts +2 -6
  292. package/src/daemon/conversation-error.ts +36 -1
  293. package/src/daemon/conversation-lifecycle.ts +30 -6
  294. package/src/daemon/conversation-messaging.ts +73 -4
  295. package/src/daemon/conversation-process.ts +10 -4
  296. package/src/daemon/conversation-queue-manager.ts +3 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +760 -29
  298. package/src/daemon/conversation-slash.ts +2 -2
  299. package/src/daemon/conversation-surfaces.ts +389 -1
  300. package/src/daemon/conversation-tool-setup.ts +10 -5
  301. package/src/daemon/conversation-usage.ts +1 -1
  302. package/src/daemon/conversation.ts +118 -30
  303. package/src/daemon/external-skills-bootstrap.ts +41 -0
  304. package/src/daemon/guardian-action-generators.ts +34 -14
  305. package/src/daemon/handlers/config-model.test.ts +86 -0
  306. package/src/daemon/handlers/config-model.ts +54 -12
  307. package/src/daemon/handlers/conversations.ts +9 -2
  308. package/src/daemon/handlers/shared.ts +39 -11
  309. package/src/daemon/handlers/skills.ts +2 -2
  310. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  311. package/src/daemon/lifecycle.ts +76 -14
  312. package/src/daemon/message-types/conversations.ts +14 -0
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/trust.ts +0 -2
  315. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  316. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  317. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  318. package/src/daemon/pkb-context-tracker.ts +125 -0
  319. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  320. package/src/daemon/pkb-reminder-builder.ts +31 -0
  321. package/src/daemon/providers-setup.ts +6 -0
  322. package/src/daemon/server.ts +117 -9
  323. package/src/daemon/tool-side-effects.ts +0 -9
  324. package/src/daemon/watch-handler.ts +4 -4
  325. package/src/daemon/web-search-history.ts +126 -0
  326. package/src/events/domain-events.ts +0 -1
  327. package/src/filing/filing-service.ts +9 -10
  328. package/src/heartbeat/heartbeat-service.ts +76 -28
  329. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  330. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  331. package/src/home/assistant-feed-authoring.ts +4 -0
  332. package/src/home/emit-feed-event.ts +4 -0
  333. package/src/home/feed-scheduler.ts +20 -4
  334. package/src/home/feed-types.ts +56 -2
  335. package/src/home/relationship-state-writer.ts +2 -2
  336. package/src/home/rollup-producer.ts +34 -5
  337. package/src/home/suggested-prompts.ts +101 -0
  338. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  339. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  340. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  341. package/src/ipc/__tests__/socket-path.test.ts +73 -0
  342. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  343. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  344. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  345. package/src/ipc/cli-client.ts +2 -1
  346. package/src/ipc/cli-server.ts +26 -8
  347. package/src/ipc/gateway-client.ts +4 -4
  348. package/src/ipc/routes/attachment.ts +114 -0
  349. package/src/ipc/routes/browser-context.ts +61 -0
  350. package/src/ipc/routes/browser.ts +96 -0
  351. package/src/ipc/routes/cache.ts +96 -0
  352. package/src/ipc/routes/index.ts +17 -1
  353. package/src/ipc/routes/task-queue.ts +226 -0
  354. package/src/ipc/routes/task.ts +173 -0
  355. package/src/ipc/routes/ui-request.ts +50 -0
  356. package/src/ipc/routes/watcher.ts +203 -0
  357. package/src/ipc/socket-path.ts +100 -0
  358. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  359. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  360. package/src/memory/admin.ts +18 -0
  361. package/src/memory/conversation-analyze-job.ts +14 -13
  362. package/src/memory/conversation-attention-store.ts +13 -6
  363. package/src/memory/conversation-crud.ts +103 -3
  364. package/src/memory/conversation-group-migration.ts +38 -6
  365. package/src/memory/conversation-title-service.ts +7 -4
  366. package/src/memory/db-init.ts +2 -0
  367. package/src/memory/embedding-backend.ts +1 -1
  368. package/src/memory/graph/compaction.ts +299 -0
  369. package/src/memory/graph/consolidation.ts +4 -4
  370. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  371. package/src/memory/graph/extraction.test.ts +272 -2
  372. package/src/memory/graph/extraction.ts +173 -51
  373. package/src/memory/graph/graph-search.test.ts +92 -0
  374. package/src/memory/graph/graph-search.ts +4 -1
  375. package/src/memory/graph/narrative.ts +2 -2
  376. package/src/memory/graph/pattern-scan.ts +2 -2
  377. package/src/memory/graph/retriever.test.ts +459 -0
  378. package/src/memory/graph/retriever.ts +230 -48
  379. package/src/memory/graph/store.ts +41 -0
  380. package/src/memory/graph/tool-handlers.ts +27 -0
  381. package/src/memory/graph/tools.ts +6 -1
  382. package/src/memory/indexer.ts +5 -5
  383. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  384. package/src/memory/job-handlers/summarization.ts +2 -2
  385. package/src/memory/job-utils.ts +7 -1
  386. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  387. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  388. package/src/memory/jobs-store.ts +44 -3
  389. package/src/memory/jobs-worker.ts +4 -0
  390. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  391. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  392. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  393. package/src/memory/migrations/index.ts +1 -0
  394. package/src/memory/pkb/pkb-index.test.ts +368 -0
  395. package/src/memory/pkb/pkb-index.ts +255 -0
  396. package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
  397. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  398. package/src/memory/pkb/pkb-search.test.ts +438 -0
  399. package/src/memory/pkb/pkb-search.ts +137 -0
  400. package/src/memory/pkb/types.ts +53 -0
  401. package/src/memory/qdrant-client.ts +122 -1
  402. package/src/memory/slack-thread-store.ts +37 -0
  403. package/src/messaging/providers/gmail/adapter.ts +6 -16
  404. package/src/messaging/providers/gmail/client.ts +22 -0
  405. package/src/messaging/providers/gmail/types.ts +7 -0
  406. package/src/messaging/providers/slack/adapter.ts +14 -2
  407. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  408. package/src/messaging/providers/slack/backfill.ts +101 -0
  409. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  410. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  411. package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
  412. package/src/messaging/providers/slack/render-transcript.ts +443 -0
  413. package/src/messaging/style-analyzer.ts +5 -2
  414. package/src/notifications/README.md +9 -5
  415. package/src/notifications/decision-engine.ts +3 -9
  416. package/src/notifications/preference-extractor.ts +2 -6
  417. package/src/oauth/oauth-store.ts +1 -0
  418. package/src/oauth/platform-connection.test.ts +47 -0
  419. package/src/oauth/platform-connection.ts +15 -5
  420. package/src/oauth/seed-providers.ts +4 -2
  421. package/src/permissions/approval-policy.test.ts +948 -0
  422. package/src/permissions/approval-policy.ts +257 -0
  423. package/src/permissions/bash-risk-classifier.test.ts +1208 -0
  424. package/src/permissions/bash-risk-classifier.ts +707 -0
  425. package/src/permissions/checker.ts +217 -708
  426. package/src/permissions/command-registry.test.ts +535 -0
  427. package/src/permissions/command-registry.ts +825 -0
  428. package/src/permissions/defaults.ts +26 -78
  429. package/src/permissions/file-risk-classifier.test.ts +535 -0
  430. package/src/permissions/file-risk-classifier.ts +274 -0
  431. package/src/permissions/risk-types.ts +205 -0
  432. package/src/permissions/secret-prompter.ts +53 -2
  433. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  434. package/src/permissions/skill-risk-classifier.ts +214 -0
  435. package/src/permissions/trust-client.ts +52 -25
  436. package/src/permissions/trust-store-interface.ts +1 -6
  437. package/src/permissions/trust-store.ts +161 -62
  438. package/src/permissions/types.ts +23 -14
  439. package/src/permissions/web-risk-classifier.test.ts +170 -0
  440. package/src/permissions/web-risk-classifier.ts +89 -0
  441. package/src/permissions/workspace-policy.ts +1 -16
  442. package/src/platform/client.ts +19 -1
  443. package/src/prompts/persona-resolver.ts +3 -3
  444. package/src/prompts/system-prompt.ts +19 -20
  445. package/src/prompts/templates/SOUL.md +2 -2
  446. package/src/prompts/update-bulletin-job.ts +190 -0
  447. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  448. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  449. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  450. package/src/providers/anthropic/client.ts +183 -14
  451. package/src/providers/call-site-routing.ts +71 -0
  452. package/src/providers/gemini/client.ts +65 -2
  453. package/src/providers/managed-proxy/constants.ts +2 -1
  454. package/src/providers/model-catalog.ts +501 -33
  455. package/src/providers/model-intents.ts +4 -4
  456. package/src/providers/openai/chat-completions-provider.ts +57 -1
  457. package/src/providers/openai/responses-provider.ts +86 -9
  458. package/src/providers/openrouter/client.ts +76 -9
  459. package/src/providers/provider-env-vars.ts +56 -0
  460. package/src/providers/provider-send-message.ts +22 -5
  461. package/src/providers/ratelimit.ts +4 -0
  462. package/src/providers/registry.ts +19 -8
  463. package/src/providers/retry.ts +174 -39
  464. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  465. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  466. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  467. package/src/providers/speech-to-text/resolve.ts +7 -0
  468. package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
  469. package/src/providers/speech-to-text/xai-realtime.ts +796 -0
  470. package/src/providers/speech-to-text/xai.test.ts +155 -0
  471. package/src/providers/speech-to-text/xai.ts +97 -0
  472. package/src/providers/types.ts +93 -3
  473. package/src/runtime/AGENTS.md +2 -2
  474. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  475. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  476. package/src/runtime/agent-wake.ts +63 -22
  477. package/src/runtime/auth/route-policy.ts +4 -0
  478. package/src/runtime/btw-sidechain.ts +13 -3
  479. package/src/runtime/channel-reply-delivery.ts +106 -2
  480. package/src/runtime/decision-token.ts +116 -0
  481. package/src/runtime/gateway-client.ts +2 -2
  482. package/src/runtime/http-router.ts +32 -0
  483. package/src/runtime/http-server.ts +52 -1
  484. package/src/runtime/http-types.ts +23 -1
  485. package/src/runtime/interactive-ui.ts +362 -0
  486. package/src/runtime/invite-instruction-generator.ts +2 -2
  487. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  488. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  489. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  490. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  491. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  492. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  493. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  494. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  495. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  496. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  497. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  498. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  499. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  500. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  501. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  502. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  503. package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
  504. package/src/runtime/routes/approval-routes.ts +12 -17
  505. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  506. package/src/runtime/routes/avatar-routes.ts +20 -4
  507. package/src/runtime/routes/btw-routes.ts +1 -4
  508. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  509. package/src/runtime/routes/conversation-routes.ts +133 -27
  510. package/src/runtime/routes/debug-routes.ts +1 -1
  511. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  512. package/src/runtime/routes/events-routes.ts +16 -0
  513. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  514. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  515. package/src/runtime/routes/home-feed-routes.ts +120 -2
  516. package/src/runtime/routes/inbound-message-handler.ts +912 -2
  517. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  518. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  519. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  520. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  521. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  522. package/src/runtime/routes/migration-routes.ts +720 -124
  523. package/src/runtime/routes/settings-routes.ts +4 -2
  524. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  525. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  526. package/src/runtime/routes/work-items-routes.ts +3 -2
  527. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  528. package/src/runtime/services/analyze-conversation.ts +12 -16
  529. package/src/runtime/skill-route-registry.ts +28 -6
  530. package/src/schedule/scheduler.ts +8 -0
  531. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  532. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  533. package/src/security/oauth2.ts +98 -35
  534. package/src/security/secure-keys.ts +7 -8
  535. package/src/security/token-manager.ts +27 -13
  536. package/src/security/untrusted-content.ts +102 -0
  537. package/src/skills/catalog-cache.ts +26 -7
  538. package/src/skills/catalog-install.ts +31 -3
  539. package/src/skills/skill-cache-store.ts +97 -0
  540. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  541. package/src/stt/daemon-batch-transcriber.ts +33 -0
  542. package/src/stt/stt-stream-session.ts +8 -1
  543. package/src/stt/types.ts +5 -1
  544. package/src/subagent/manager.ts +41 -13
  545. package/src/tasks/ephemeral-permissions.ts +9 -4
  546. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  547. package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
  548. package/src/tools/browser/browser-execution.ts +65 -38
  549. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  550. package/src/tools/credentials/tool-policy.ts +39 -5
  551. package/src/tools/credentials/vault.ts +9 -4
  552. package/src/tools/executor.ts +4 -0
  553. package/src/tools/filesystem/write.ts +52 -0
  554. package/src/tools/host-terminal/host-shell.ts +45 -5
  555. package/src/tools/memory/register.test.ts +185 -0
  556. package/src/tools/memory/register.ts +3 -1
  557. package/src/tools/network/web-fetch.ts +20 -10
  558. package/src/tools/network/web-search.ts +19 -4
  559. package/src/tools/permission-checker.ts +36 -15
  560. package/src/tools/policy-context.ts +25 -8
  561. package/src/tools/registry.ts +55 -3
  562. package/src/tools/side-effects.ts +0 -11
  563. package/src/tools/skills/execute.ts +2 -2
  564. package/src/tools/skills/sandbox-runner.ts +5 -2
  565. package/src/tools/terminal/backends/native.ts +51 -2
  566. package/src/tools/terminal/safe-env.ts +3 -2
  567. package/src/tools/terminal/shell.ts +1 -0
  568. package/src/tools/tool-manifest.ts +6 -21
  569. package/src/tools/types.ts +12 -3
  570. package/src/tools/verification-control-plane-policy.ts +1 -1
  571. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  572. package/src/tts/provider-catalog.ts +18 -0
  573. package/src/tts/providers/index.ts +2 -0
  574. package/src/tts/providers/xai-provider.ts +224 -0
  575. package/src/tts/types.ts +46 -0
  576. package/src/types/tar-stream.d.ts +66 -0
  577. package/src/util/json.ts +17 -0
  578. package/src/util/platform.ts +2 -2
  579. package/src/util/pricing.ts +15 -5
  580. package/src/watcher/engine.ts +1 -1
  581. package/src/watcher/providers/google-calendar.ts +134 -8
  582. package/src/watcher/providers/outlook-calendar.ts +42 -2
  583. package/src/workspace/git-service.ts +23 -4
  584. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  585. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  586. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  587. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
  588. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  589. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  590. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  591. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  592. package/src/workspace/migrations/AGENTS.md +1 -1
  593. package/src/workspace/migrations/registry.ts +16 -0
  594. package/src/workspace/provider-commit-message-generator.ts +19 -38
  595. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  596. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  597. package/src/__tests__/gmail-preferences.test.ts +0 -117
  598. package/src/__tests__/outlook-attachments.test.ts +0 -301
  599. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  600. package/src/__tests__/outlook-categories.test.ts +0 -212
  601. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  602. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  603. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  604. package/src/__tests__/outlook-trash.test.ts +0 -77
  605. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  606. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  607. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  608. package/src/__tests__/update-bulletin.test.ts +0 -478
  609. package/src/__tests__/update-template-contract.test.ts +0 -29
  610. package/src/cli/commands/doctor.ts +0 -341
  611. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  612. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  613. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  614. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  615. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  616. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  617. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  618. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  619. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  620. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  621. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  622. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  623. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  624. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  625. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  626. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  627. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  628. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  629. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  630. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  631. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  632. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  633. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  634. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  635. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  636. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  637. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  638. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  639. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  640. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  641. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  642. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  643. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  644. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  645. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  646. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  647. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  648. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  649. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  650. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  651. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  652. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  653. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  654. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  655. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  656. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  657. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  658. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  659. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  660. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  661. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  662. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  663. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  664. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  665. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  666. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  667. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  668. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  669. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  670. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  671. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  672. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  673. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  674. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  675. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  676. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  677. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  678. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  679. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  680. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  681. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  682. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  683. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  684. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  685. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  686. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  687. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  688. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  689. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  690. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  691. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  692. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  693. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  694. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  695. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  696. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  697. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  698. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  699. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  700. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  701. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  702. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  703. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  704. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  705. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  706. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  707. package/src/prompts/templates/UPDATES.md +0 -50
  708. package/src/prompts/update-bulletin-format.ts +0 -85
  709. package/src/prompts/update-bulletin-state.ts +0 -58
  710. package/src/prompts/update-bulletin-template-path.ts +0 -13
  711. package/src/prompts/update-bulletin.ts +0 -139
  712. package/src/shared/provider-env-vars.ts +0 -19
  713. package/src/tools/watcher/create.ts +0 -86
  714. package/src/tools/watcher/delete.ts +0 -36
  715. package/src/tools/watcher/digest.ts +0 -54
  716. package/src/tools/watcher/list.ts +0 -83
  717. package/src/tools/watcher/update.ts +0 -71
@@ -4,12 +4,7 @@ import { describe, expect, test } from "bun:test";
4
4
 
5
5
  import type { SlackConversation } from "../messaging/providers/slack/types.js";
6
6
 
7
- const BUNDLED_SKILLS_DIR = join(
8
- import.meta.dir,
9
- "..",
10
- "config",
11
- "bundled-skills",
12
- );
7
+ const REPO_SKILLS_DIR = join(import.meta.dir, "..", "..", "..", "skills");
13
8
 
14
9
  describe("slack adapter isPrivate mapping", () => {
15
10
  // Inline the mapping logic to test it independently of the adapter module
@@ -47,7 +42,7 @@ describe("slack adapter isPrivate mapping", () => {
47
42
  });
48
43
 
49
44
  describe("slack skill has no TOOLS.json (uses Web API via CLI)", () => {
50
- const toolsPath = join(BUNDLED_SKILLS_DIR, "slack", "TOOLS.json");
45
+ const toolsPath = join(REPO_SKILLS_DIR, "slack", "TOOLS.json");
51
46
 
52
47
  test("TOOLS.json does not exist", () => {
53
48
  expect(() => readFileSync(toolsPath)).toThrow();
@@ -56,7 +51,7 @@ describe("slack skill has no TOOLS.json (uses Web API via CLI)", () => {
56
51
 
57
52
  describe("slack skill SKILL.md", () => {
58
53
  const skillMd = readFileSync(
59
- join(BUNDLED_SKILLS_DIR, "slack", "SKILL.md"),
54
+ join(REPO_SKILLS_DIR, "slack", "SKILL.md"),
60
55
  "utf-8",
61
56
  );
62
57
 
@@ -2,6 +2,8 @@ import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
4
4
 
5
+ import { ruleScope } from "@vellumai/ces-contracts";
6
+
5
7
  // Set up a temp directory before importing trust-store
6
8
  const TEST_ROOT = join(
7
9
  import.meta.dirname ?? __dirname,
@@ -135,4 +137,37 @@ describe("Starter approval bundle", () => {
135
137
  expect(defaultIds.has(starterRule.id)).toBe(false);
136
138
  }
137
139
  });
140
+
141
+ test("accepted starter rules have canonical persisted shape after disk round-trip", () => {
142
+ acceptStarterBundle();
143
+
144
+ // Force a disk round-trip by clearing the cache
145
+ clearCache();
146
+ const allRules = getAllRules();
147
+ const starterRuleIds = new Set(getStarterBundleRules().map((r) => r.id));
148
+ const starterRules = allRules.filter((r) => starterRuleIds.has(r.id));
149
+
150
+ expect(starterRules.length).toBe(getStarterBundleRules().length);
151
+
152
+ for (const rule of starterRules) {
153
+ // Effective scope is always "everywhere" — scoped and generic tools
154
+ // carry an explicit scope field, while URL tools omit it (ruleScope
155
+ // returns "everywhere" for rules without a scope field).
156
+ expect(ruleScope(rule)).toBe("everywhere");
157
+
158
+ // Starter rules are all allow decisions — they should not carry
159
+ // family-specific metadata signals (executionTarget).
160
+ // These rules cover read-only/information-gathering tools that are
161
+ // either generic or scoped family, but none require high-risk access.
162
+ expect(rule.executionTarget).toBeUndefined();
163
+
164
+ // Base fields must be present
165
+ expect(rule.id).toBeTruthy();
166
+ expect(rule.tool).toBeTruthy();
167
+ expect(rule.pattern).toBeTruthy();
168
+ expect(rule.decision).toBe("allow");
169
+ expect(rule.priority).toBeGreaterThan(0);
170
+ expect(rule.createdAt).toBeGreaterThan(0);
171
+ }
172
+ });
138
173
  });
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Regression test for the subagent provider routing fix.
3
+ *
4
+ * Before the fix, `SubagentManager.spawn()` constructed the Conversation with
5
+ * `getProvider(appConfig.llm.default.provider)` directly, which meant per-call
6
+ * `llm.callSites.subagentSpawn.provider` overrides only changed the request
7
+ * *metadata* the downstream client saw — the actual HTTP transport still
8
+ * belonged to `llm.default.provider`. After the fix, the provider is wrapped
9
+ * in `CallSiteRoutingProvider`, which consults the resolver per call and
10
+ * routes to the resolved provider's transport when it differs from the
11
+ * default.
12
+ *
13
+ * This test stubs the `Conversation` constructor and the provider registry
14
+ * so we can capture the provider that `SubagentManager` passes into
15
+ * `Conversation`, then verify it's a `CallSiteRoutingProvider` that selects
16
+ * the right transport for the `subagentSpawn` callSite.
17
+ */
18
+ import { describe, expect, mock, test } from "bun:test";
19
+
20
+ import type { ServerMessage } from "../daemon/message-protocol.js";
21
+
22
+ // Capture the provider passed to Conversation.
23
+ let capturedProvider: unknown = undefined;
24
+
25
+ // Stub Conversation so spawn() doesn't try to actually run an agent loop —
26
+ // we only care about what provider it was constructed with.
27
+ class FakeConversation {
28
+ constructor(
29
+ _id: string,
30
+ provider: unknown,
31
+ _systemPrompt: string,
32
+ _maxTokens: number,
33
+ _sendToClient: (msg: ServerMessage) => void,
34
+ ) {
35
+ capturedProvider = provider;
36
+ }
37
+ updateClient() {}
38
+ setIsSubagent() {}
39
+ hasSystemPromptOverride = false;
40
+ setSubagentAllowedTools() {}
41
+ preactivateSkills() {}
42
+ preactivateSkillsAsync() {}
43
+ setSpawnHints() {}
44
+ injectInheritedContext() {}
45
+ setActiveBranchId() {}
46
+ setBranchTag() {}
47
+ setForkPolicy() {}
48
+ setForkParentMessageCount() {}
49
+ setForkParentSystemPrompt() {}
50
+ enqueueMessage() {
51
+ return { rejected: false, queued: true };
52
+ }
53
+ abort() {}
54
+ dispose() {}
55
+ messages = [];
56
+ usageStats = { inputTokens: 0, outputTokens: 0, estimatedCost: 0 };
57
+ sendToClient() {}
58
+ loadFromDb() {
59
+ return Promise.resolve();
60
+ }
61
+ persistUserMessage() {
62
+ return "msg-id";
63
+ }
64
+ runAgentLoop() {
65
+ return Promise.resolve();
66
+ }
67
+ getCurrentSystemPrompt() {
68
+ return "system";
69
+ }
70
+ }
71
+
72
+ mock.module("../daemon/conversation.js", () => ({
73
+ Conversation: FakeConversation,
74
+ }));
75
+
76
+ mock.module("../memory/conversation-bootstrap.js", () => ({
77
+ bootstrapConversation: () => ({ id: "conv-id" }),
78
+ }));
79
+
80
+ mock.module("../prompts/system-prompt.js", () => ({
81
+ buildSystemPrompt: () => "system prompt",
82
+ buildSubagentSystemPrompt: () => "subagent system",
83
+ }));
84
+
85
+ // Provider registry — return distinct stubs so we can verify the selection.
86
+ const anthropicStub = { name: "anthropic" };
87
+ const openaiStub = { name: "openai" };
88
+
89
+ mock.module("../providers/registry.js", () => ({
90
+ getProvider: (name: string) => {
91
+ if (name === "anthropic") return anthropicStub;
92
+ if (name === "openai") return openaiStub;
93
+ throw new Error(`unknown provider: ${name}`);
94
+ },
95
+ }));
96
+
97
+ // Mutable LLM config — tests rewrite this per-case.
98
+ let mockLlmConfig: Record<string, unknown> = {};
99
+
100
+ mock.module("../config/loader.js", () => ({
101
+ getConfig: () => ({
102
+ llm: mockLlmConfig,
103
+ rateLimit: { maxRequestsPerMinute: 0 },
104
+ }),
105
+ }));
106
+
107
+ mock.module("../util/logger.js", () => ({
108
+ getLogger: () =>
109
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
110
+ }));
111
+
112
+ // ── Imports (after mocks) ───────────────────────────────────────────────────
113
+
114
+ import { LLMSchema } from "../config/schemas/llm.js";
115
+ import { CallSiteRoutingProvider } from "../providers/call-site-routing.js";
116
+ import { SubagentManager } from "../subagent/manager.js";
117
+
118
+ function setLlmConfig(raw: unknown): void {
119
+ mockLlmConfig = LLMSchema.parse(raw) as Record<string, unknown>;
120
+ }
121
+
122
+ describe("SubagentManager — provider call-site routing", () => {
123
+ test("wraps the default provider in CallSiteRoutingProvider", async () => {
124
+ setLlmConfig({
125
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
126
+ });
127
+
128
+ capturedProvider = undefined;
129
+ const manager = new SubagentManager();
130
+ await manager.spawn(
131
+ {
132
+ parentConversationId: "parent-1",
133
+ label: "test",
134
+ objective: "test objective",
135
+ },
136
+ () => {},
137
+ );
138
+
139
+ expect(capturedProvider).toBeInstanceOf(CallSiteRoutingProvider);
140
+ });
141
+
142
+ test("the wrapped provider exposes the default provider's name (stable identity for outer wrappers)", async () => {
143
+ setLlmConfig({
144
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
145
+ callSites: {
146
+ subagentSpawn: { provider: "openai", model: "gpt-5.4" },
147
+ },
148
+ });
149
+
150
+ capturedProvider = undefined;
151
+ const manager = new SubagentManager();
152
+ await manager.spawn(
153
+ {
154
+ parentConversationId: "parent-2",
155
+ label: "test",
156
+ objective: "test objective",
157
+ },
158
+ () => {},
159
+ );
160
+
161
+ // The wrapper exposes the *default* provider's name (so wrappers further
162
+ // out — e.g. RateLimitProvider — see a stable identity), but routes the
163
+ // actual sendMessage to the resolved provider. The routing behavior
164
+ // itself is exercised in the next describe block with a fully-stubbed
165
+ // provider pair.
166
+ expect(capturedProvider).toBeInstanceOf(CallSiteRoutingProvider);
167
+ const wrapper = capturedProvider as CallSiteRoutingProvider;
168
+ expect(wrapper.name).toBe("anthropic");
169
+ });
170
+
171
+ test("falls back to default provider when subagentSpawn callSite is absent", async () => {
172
+ setLlmConfig({
173
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
174
+ // No subagentSpawn override.
175
+ });
176
+
177
+ capturedProvider = undefined;
178
+ const manager = new SubagentManager();
179
+ await manager.spawn(
180
+ {
181
+ parentConversationId: "parent-3",
182
+ label: "test",
183
+ objective: "test objective",
184
+ },
185
+ () => {},
186
+ );
187
+
188
+ expect(capturedProvider).toBeInstanceOf(CallSiteRoutingProvider);
189
+ // Default provider's name surfaces.
190
+ expect((capturedProvider as { name: string }).name).toBe("anthropic");
191
+ });
192
+ });
193
+
194
+ // ── Direct unit test for CallSiteRoutingProvider's selection logic ─────────
195
+
196
+ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
197
+ test("routes to the resolved provider when callSite.provider differs from default", async () => {
198
+ setLlmConfig({
199
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
200
+ callSites: {
201
+ subagentSpawn: { provider: "openai", model: "gpt-5.4" },
202
+ },
203
+ });
204
+
205
+ let calledOnDefault = false;
206
+ let calledOnAlternative = false;
207
+
208
+ const defaultProvider = {
209
+ name: "anthropic",
210
+ sendMessage: async () => {
211
+ calledOnDefault = true;
212
+ return {
213
+ content: [],
214
+ model: "anthropic",
215
+ usage: { inputTokens: 0, outputTokens: 0 },
216
+ stopReason: "end_turn" as const,
217
+ };
218
+ },
219
+ };
220
+ const altProvider = {
221
+ name: "openai",
222
+ sendMessage: async () => {
223
+ calledOnAlternative = true;
224
+ return {
225
+ content: [],
226
+ model: "openai",
227
+ usage: { inputTokens: 0, outputTokens: 0 },
228
+ stopReason: "end_turn" as const,
229
+ };
230
+ },
231
+ };
232
+
233
+ const wrapper = new CallSiteRoutingProvider(defaultProvider, (name) => {
234
+ if (name === "openai") return altProvider;
235
+ return undefined;
236
+ });
237
+
238
+ await wrapper.sendMessage([], undefined, undefined, {
239
+ config: { callSite: "subagentSpawn" },
240
+ });
241
+
242
+ expect(calledOnAlternative).toBe(true);
243
+ expect(calledOnDefault).toBe(false);
244
+ });
245
+
246
+ test("routes to default when no callSite provided", async () => {
247
+ setLlmConfig({
248
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
249
+ callSites: {
250
+ subagentSpawn: { provider: "openai", model: "gpt-5.4" },
251
+ },
252
+ });
253
+
254
+ let calledOnDefault = false;
255
+
256
+ const defaultProvider = {
257
+ name: "anthropic",
258
+ sendMessage: async () => {
259
+ calledOnDefault = true;
260
+ return {
261
+ content: [],
262
+ model: "anthropic",
263
+ usage: { inputTokens: 0, outputTokens: 0 },
264
+ stopReason: "end_turn" as const,
265
+ };
266
+ },
267
+ };
268
+
269
+ const wrapper = new CallSiteRoutingProvider(
270
+ defaultProvider,
271
+ () => undefined,
272
+ );
273
+
274
+ await wrapper.sendMessage([], undefined, undefined, {
275
+ config: {},
276
+ });
277
+
278
+ expect(calledOnDefault).toBe(true);
279
+ });
280
+ });
@@ -383,7 +383,164 @@ describe("GET /v1/suggestion", () => {
383
383
  expect(body.suggestion).toBeNull();
384
384
  });
385
385
 
386
- test("uses latency-optimized model intent", async () => {
386
+ test("strips leaked <reply> tags from LLM response", async () => {
387
+ // Realistic output when the model re-emits </reply> before the stop_sequence
388
+ // catches, or when a leading <reply> slips in.
389
+ const provider = makeMockProvider("sounds good</reply>");
390
+ mockGetConfiguredProvider.mockImplementation(async () => provider);
391
+ mockGetConversationByKey.mockImplementation(() => ({
392
+ conversationId: "conv-test",
393
+ }));
394
+ mockGetMessages.mockImplementation(() => [
395
+ {
396
+ id: "msg-asst-1",
397
+ conversationId: "conv-test",
398
+ role: "assistant",
399
+ content: JSON.stringify([{ type: "text", text: "Want to go?" }]),
400
+ createdAt: Date.now(),
401
+ metadata: null,
402
+ },
403
+ ]);
404
+
405
+ const url = makeUrl({ conversationKey: "test-key" });
406
+ const deps = makeDeps();
407
+ const res = await handleGetSuggestion(url, deps);
408
+ const body = (await res.json()) as { suggestion: string };
409
+
410
+ expect(body.suggestion).toBe("sounds good");
411
+ });
412
+
413
+ test("passes prefill message, stop_sequences, and max_tokens", async () => {
414
+ const provider = makeMockProvider("on my way");
415
+ mockGetConfiguredProvider.mockImplementation(async () => provider);
416
+ mockGetConversationByKey.mockImplementation(() => ({
417
+ conversationId: "conv-test",
418
+ }));
419
+ mockGetMessages.mockImplementation(() => [
420
+ {
421
+ id: "msg-user-1",
422
+ conversationId: "conv-test",
423
+ role: "user",
424
+ content: JSON.stringify([{ type: "text", text: "heading out" }]),
425
+ createdAt: Date.now() - 1000,
426
+ metadata: null,
427
+ },
428
+ {
429
+ id: "msg-asst-shape",
430
+ conversationId: "conv-test",
431
+ role: "assistant",
432
+ content: JSON.stringify([
433
+ { type: "text", text: "see you there — which door?" },
434
+ ]),
435
+ createdAt: Date.now(),
436
+ metadata: null,
437
+ },
438
+ ]);
439
+
440
+ const url = makeUrl({ conversationKey: "test-key" });
441
+ const deps = makeDeps();
442
+ await handleGetSuggestion(url, deps);
443
+
444
+ expect(provider.sendMessage).toHaveBeenCalledTimes(1);
445
+ const callArgs = provider.sendMessage.mock.calls[0] as unknown[];
446
+ const messages = callArgs[0] as Array<{
447
+ role: string;
448
+ content: Array<{ type: string; text: string }>;
449
+ }>;
450
+ const options = callArgs[3] as {
451
+ config?: {
452
+ stop_sequences?: string[];
453
+ max_tokens?: number;
454
+ };
455
+ };
456
+
457
+ expect(messages.length).toBe(2);
458
+ expect(messages[1].role).toBe("assistant");
459
+ expect(messages[1].content[0].text).toBe("<reply>");
460
+ expect(options.config?.stop_sequences).toEqual(["</reply>"]);
461
+ expect(options.config?.max_tokens).toBe(60);
462
+ expect(messages[0].content[0].text).toContain("<assistant_message>");
463
+ expect(messages[0].content[0].text).toContain("<user_message>");
464
+ });
465
+
466
+ test("includes prior user message in prompt when present", async () => {
467
+ const provider = makeMockProvider("on my way");
468
+ mockGetConfiguredProvider.mockImplementation(async () => provider);
469
+ mockGetConversationByKey.mockImplementation(() => ({
470
+ conversationId: "conv-test",
471
+ }));
472
+ mockGetMessages.mockImplementation(() => [
473
+ {
474
+ id: "msg-user-1",
475
+ conversationId: "conv-test",
476
+ role: "user",
477
+ content: JSON.stringify([
478
+ { type: "text", text: "running late, should I grab coffee?" },
479
+ ]),
480
+ createdAt: Date.now() - 1000,
481
+ metadata: null,
482
+ },
483
+ {
484
+ id: "msg-asst-1",
485
+ conversationId: "conv-test",
486
+ role: "assistant",
487
+ content: JSON.stringify([
488
+ { type: "text", text: "yes please, an americano would be great" },
489
+ ]),
490
+ createdAt: Date.now(),
491
+ metadata: null,
492
+ },
493
+ ]);
494
+
495
+ const url = makeUrl({ conversationKey: "test-key" });
496
+ const deps = makeDeps();
497
+ await handleGetSuggestion(url, deps);
498
+
499
+ const callArgs = provider.sendMessage.mock.calls[0] as unknown[];
500
+ const messages = callArgs[0] as Array<{
501
+ content: Array<{ text: string }>;
502
+ }>;
503
+ const userPrompt = messages[0].content[0].text;
504
+ expect(userPrompt).toContain(
505
+ "<user_message>running late, should I grab coffee?</user_message>",
506
+ );
507
+ expect(userPrompt).toContain(
508
+ "<assistant_message>yes please, an americano would be great</assistant_message>",
509
+ );
510
+ });
511
+
512
+ test("uses placeholder when no prior user message exists", async () => {
513
+ const provider = makeMockProvider("sure");
514
+ mockGetConfiguredProvider.mockImplementation(async () => provider);
515
+ mockGetConversationByKey.mockImplementation(() => ({
516
+ conversationId: "conv-test",
517
+ }));
518
+ mockGetMessages.mockImplementation(() => [
519
+ {
520
+ id: "msg-asst-first",
521
+ conversationId: "conv-test",
522
+ role: "assistant",
523
+ content: JSON.stringify([{ type: "text", text: "hi there!" }]),
524
+ createdAt: Date.now(),
525
+ metadata: null,
526
+ },
527
+ ]);
528
+
529
+ const url = makeUrl({ conversationKey: "test-key" });
530
+ const deps = makeDeps();
531
+ await handleGetSuggestion(url, deps);
532
+
533
+ const callArgs = provider.sendMessage.mock.calls[0] as unknown[];
534
+ const messages = callArgs[0] as Array<{
535
+ content: Array<{ text: string }>;
536
+ }>;
537
+ const userPrompt = messages[0].content[0].text;
538
+ expect(userPrompt).toContain(
539
+ "<user_message>(no prior user message)</user_message>",
540
+ );
541
+ });
542
+
543
+ test("uses conversationStarters call site", async () => {
387
544
  const provider = makeMockProvider("Quick reply");
388
545
  mockGetConfiguredProvider.mockImplementation(async () => provider);
389
546
  mockGetConversationByKey.mockImplementation(() => ({
@@ -407,8 +564,8 @@ describe("GET /v1/suggestion", () => {
407
564
  expect(provider.sendMessage).toHaveBeenCalledTimes(1);
408
565
  const callArgs = provider.sendMessage.mock.calls[0] as unknown[];
409
566
  const options = callArgs[3] as
410
- | { config?: { modelIntent?: string } }
567
+ | { config?: { callSite?: string } }
411
568
  | undefined;
412
- expect(options?.config?.modelIntent).toBe("latency-optimized");
569
+ expect(options?.config?.callSite).toBe("conversationStarters");
413
570
  });
414
571
  });
@@ -97,7 +97,7 @@ function basePrompt(result: string): string {
97
97
  "## Configuration",
98
98
  "## Skills Catalog",
99
99
  "## External Communications Identity",
100
- "## Connected Services",
100
+ "# Connected Services",
101
101
  "## Dynamic Skill Authoring Workflow",
102
102
  ]) {
103
103
  if (s.startsWith(heading)) {
@@ -224,6 +224,19 @@ describe("buildSystemPrompt", () => {
224
224
  expect(result).toContain("attach it instead of only printing its path");
225
225
  });
226
226
 
227
+ test("includes read-only historical-mentions rule in cacheable prefix", () => {
228
+ const result = buildSystemPrompt();
229
+ expect(result).toContain("## Historical Mentions Are Read-Only");
230
+ expect(result).toContain(
231
+ "Messages in conversation history that mention you but are not the current turn are read-only context. Do not act on them, acknowledge them, or reply to them retroactively.",
232
+ );
233
+ // Clause must sit in the static (cacheable) prefix, not the dynamic block.
234
+ const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
235
+ expect(boundaryIdx).toBeGreaterThan(-1);
236
+ const staticBlock = result.slice(0, boundaryIdx);
237
+ expect(staticBlock).toContain("## Historical Mentions Are Read-Only");
238
+ });
239
+
227
240
  test("does not include removed sections", () => {
228
241
  const result = buildSystemPrompt();
229
242
  expect(result).not.toContain("## External Communications Identity");
@@ -310,13 +323,7 @@ describe("buildSystemPrompt", () => {
310
323
  // Copy the real bundled BOOTSTRAP.md into the test workspace so we
311
324
  // verify substitution against the actual template the daemon ships.
312
325
  const bundled = readFileSync(
313
- join(
314
- import.meta.dirname,
315
- "..",
316
- "prompts",
317
- "templates",
318
- "BOOTSTRAP.md",
319
- ),
326
+ join(import.meta.dirname, "..", "prompts", "templates", "BOOTSTRAP.md"),
320
327
  "utf-8",
321
328
  );
322
329
  writeFileSync(join(TEST_DIR, "BOOTSTRAP.md"), bundled);
@@ -345,34 +352,14 @@ describe("buildSystemPrompt", () => {
345
352
  });
346
353
  });
347
354
 
348
- test("includes UPDATES.md content when file exists", () => {
349
- writeFileSync(join(TEST_DIR, "UPDATES.md"), "# v1.2\n\nNew feature added.");
350
- const result = buildSystemPrompt();
351
- expect(result).toContain("## Recent Updates");
352
- expect(result).toContain("New feature added.");
353
- });
354
-
355
- test("omits updates section when UPDATES.md is empty", () => {
356
- writeFileSync(join(TEST_DIR, "UPDATES.md"), " \n \n ");
355
+ test("never includes UPDATES.md content in system prompt", () => {
356
+ const updatesBody = "# v1.2\n\nNew feature added. UNIQUE_UPDATES_MARKER.";
357
+ writeFileSync(join(TEST_DIR, "UPDATES.md"), updatesBody);
357
358
  const result = buildSystemPrompt();
358
359
  expect(result).not.toContain("## Recent Updates");
359
- });
360
-
361
- test("omits updates section when UPDATES.md does not exist", () => {
362
- const result = buildSystemPrompt();
363
- expect(result).not.toContain("## Recent Updates");
364
- });
365
-
366
- test("includes update handling instructions when UPDATES.md exists", () => {
367
- writeFileSync(join(TEST_DIR, "UPDATES.md"), "# v1.3\n\nSome update notes.");
368
- const result = buildSystemPrompt();
369
- expect(result).toContain("### Update Handling");
370
- expect(result).toContain("Use your judgment");
371
- });
372
-
373
- test("omits update handling instructions when UPDATES.md is absent", () => {
374
- const result = buildSystemPrompt();
375
- expect(result).not.toContain("### Update Handling");
360
+ expect(result).not.toContain(updatesBody);
361
+ expect(result).not.toContain("UNIQUE_UPDATES_MARKER");
362
+ expect(result).not.toContain("Update Handling");
376
363
  });
377
364
 
378
365
  test("strips comment lines starting with _ from prompt files", () => {
@@ -689,7 +676,7 @@ describe("ensurePromptFiles", () => {
689
676
  // SOUL.md and IDENTITY.md are absent (they will be freshly seeded from
690
677
  // templates, but onboarding should not re-trigger).
691
678
  mkdirSync(join(TEST_DIR, "users"), { recursive: true });
692
- writeFileSync(join(TEST_DIR, "users", "sidd.md"), "# Sidd persona");
679
+ writeFileSync(join(TEST_DIR, "users", "alice.md"), "# Alice persona");
693
680
 
694
681
  ensurePromptFiles();
695
682
 
@@ -7,6 +7,8 @@ mock.module("../util/logger.js", () => ({
7
7
  }),
8
8
  }));
9
9
 
10
+ import { ruleScope } from "@vellumai/ces-contracts";
11
+
10
12
  import { getDb, initializeDb } from "../memory/db.js";
11
13
  import { getTaskRunRules } from "../tasks/ephemeral-permissions.js";
12
14
  import { renderTemplate, runTask } from "../tasks/task-runner.js";
@@ -131,7 +133,7 @@ describe("runTask", () => {
131
133
  expect(rulesWhileRunning).toHaveLength(2);
132
134
  expect(rulesWhileRunning[0].tool).toBe("read_file");
133
135
  expect(rulesWhileRunning[1].tool).toBe("write_file");
134
- expect(rulesWhileRunning[0].scope).toBe("everywhere");
136
+ expect(ruleScope(rulesWhileRunning[0])).toBe("everywhere");
135
137
  expect(rulesWhileRunning[0].decision).toBe("allow");
136
138
  expect(rulesWhileRunning[0].priority).toBe(75);
137
139