@vellumai/assistant 0.5.5 → 0.5.7

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 (382) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +4 -5
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docs/architecture/keychain-broker.md +45 -240
  7. package/docs/architecture/security.md +0 -17
  8. package/docs/credential-execution-service.md +2 -2
  9. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  10. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +119 -0
  11. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  12. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  13. package/package.json +2 -3
  14. package/src/__tests__/actor-token-service.test.ts +1 -2
  15. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  16. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  17. package/src/__tests__/btw-routes.test.ts +0 -39
  18. package/src/__tests__/call-domain.test.ts +0 -128
  19. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  20. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  21. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  22. package/src/__tests__/checker.test.ts +4 -2
  23. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  24. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  25. package/src/__tests__/config-schema.test.ts +3 -3
  26. package/src/__tests__/context-window-manager.test.ts +78 -0
  27. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  28. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  29. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  30. package/src/__tests__/conversation-title-service.test.ts +117 -1
  31. package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
  32. package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
  33. package/src/__tests__/credential-security-e2e.test.ts +0 -66
  34. package/src/__tests__/credential-security-invariants.test.ts +4 -45
  35. package/src/__tests__/credentials-cli.test.ts +78 -0
  36. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  37. package/src/__tests__/docker-signing-key-bootstrap.test.ts +98 -0
  38. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  39. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  40. package/src/__tests__/host-shell-tool.test.ts +6 -7
  41. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  42. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  43. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  44. package/src/__tests__/intent-routing.test.ts +0 -13
  45. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  46. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  47. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  48. package/src/__tests__/memory-regressions.test.ts +8 -30
  49. package/src/__tests__/migration-export-http.test.ts +2 -2
  50. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  51. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  52. package/src/__tests__/migration-validate-http.test.ts +2 -2
  53. package/src/__tests__/non-member-access-request.test.ts +0 -5
  54. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  55. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  56. package/src/__tests__/permission-types.test.ts +1 -0
  57. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  58. package/src/__tests__/qdrant-manager.test.ts +28 -2
  59. package/src/__tests__/registry.test.ts +0 -6
  60. package/src/__tests__/require-fresh-approval.test.ts +4 -0
  61. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  62. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  63. package/src/__tests__/secure-keys.test.ts +83 -263
  64. package/src/__tests__/shell-identity.test.ts +96 -6
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  66. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  67. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  68. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  69. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  70. package/src/__tests__/skill-load-tool.test.ts +0 -2
  71. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  72. package/src/__tests__/skills.test.ts +0 -2
  73. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  74. package/src/__tests__/suggestion-routes.test.ts +1 -32
  75. package/src/__tests__/system-prompt.test.ts +0 -1
  76. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -0
  77. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  78. package/src/__tests__/tool-executor.test.ts +4 -0
  79. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  80. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  81. package/src/__tests__/update-bulletin.test.ts +0 -2
  82. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  83. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -6
  84. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  85. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +218 -0
  86. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  87. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  88. package/src/calls/audio-store.test.ts +97 -0
  89. package/src/calls/audio-store.ts +205 -0
  90. package/src/calls/call-controller.ts +85 -7
  91. package/src/calls/call-domain.ts +3 -0
  92. package/src/calls/call-store.ts +10 -3
  93. package/src/calls/fish-audio-client.ts +117 -0
  94. package/src/calls/relay-server.ts +27 -0
  95. package/src/calls/twilio-routes.ts +2 -1
  96. package/src/calls/types.ts +1 -0
  97. package/src/calls/voice-ingress-preflight.ts +0 -42
  98. package/src/calls/voice-quality.ts +26 -5
  99. package/src/calls/voice-session-bridge.ts +6 -12
  100. package/src/cli/commands/config.ts +1 -4
  101. package/src/cli/commands/conversations.ts +0 -18
  102. package/src/cli/commands/credentials.ts +34 -4
  103. package/src/cli/commands/oauth/index.ts +7 -0
  104. package/src/cli/commands/oauth/platform.ts +179 -0
  105. package/src/cli/commands/platform.ts +3 -3
  106. package/src/config/assistant-feature-flags.ts +186 -5
  107. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  108. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  109. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  110. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  111. package/src/config/bundled-tool-registry.ts +1 -11
  112. package/src/config/env-registry.ts +1 -1
  113. package/src/config/env.ts +16 -16
  114. package/src/config/feature-flag-registry.json +48 -16
  115. package/src/config/loader.ts +98 -31
  116. package/src/config/schema.ts +4 -25
  117. package/src/config/schemas/calls.ts +13 -0
  118. package/src/config/schemas/fish-audio.ts +39 -0
  119. package/src/config/schemas/memory.ts +0 -4
  120. package/src/config/schemas/platform.ts +1 -1
  121. package/src/config/schemas/security.ts +4 -4
  122. package/src/config/types.ts +0 -1
  123. package/src/contacts/contact-store.ts +39 -0
  124. package/src/contacts/types.ts +2 -0
  125. package/src/context/window-manager.ts +53 -2
  126. package/src/credential-execution/approval-bridge.ts +1 -0
  127. package/src/credential-execution/executable-discovery.ts +28 -4
  128. package/src/credential-execution/feature-gates.ts +16 -0
  129. package/src/credential-execution/process-manager.ts +38 -0
  130. package/src/daemon/assistant-attachments.ts +9 -0
  131. package/src/daemon/config-watcher.ts +6 -4
  132. package/src/daemon/conversation-agent-loop.ts +0 -60
  133. package/src/daemon/conversation-memory.ts +0 -117
  134. package/src/daemon/conversation-runtime-assembly.ts +0 -2
  135. package/src/daemon/conversation-tool-setup.ts +0 -105
  136. package/src/daemon/conversation.ts +10 -1
  137. package/src/daemon/handlers/config-vercel.ts +92 -0
  138. package/src/daemon/handlers/conversations.ts +0 -11
  139. package/src/daemon/handlers/skills.ts +2 -15
  140. package/src/daemon/install-symlink.ts +195 -0
  141. package/src/daemon/lifecycle.ts +229 -96
  142. package/src/daemon/message-types/conversations.ts +3 -4
  143. package/src/daemon/message-types/diagnostics.ts +3 -22
  144. package/src/daemon/message-types/messages.ts +0 -2
  145. package/src/daemon/message-types/upgrades.ts +8 -0
  146. package/src/daemon/server.ts +30 -92
  147. package/src/events/domain-events.ts +2 -1
  148. package/src/followups/followup-store.ts +5 -2
  149. package/src/inbound/platform-callback-registration.ts +3 -3
  150. package/src/instrument.ts +8 -5
  151. package/src/memory/conversation-crud.ts +0 -236
  152. package/src/memory/conversation-title-service.ts +76 -11
  153. package/src/memory/db-init.ts +15 -11
  154. package/src/memory/indexer.ts +15 -106
  155. package/src/memory/items-extractor.ts +15 -1
  156. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  157. package/src/memory/job-handlers/embedding.ts +0 -79
  158. package/src/memory/job-utils.ts +1 -1
  159. package/src/memory/jobs-store.ts +30 -13
  160. package/src/memory/jobs-worker.ts +31 -27
  161. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  162. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  163. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  164. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  165. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  166. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  167. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  168. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  169. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  170. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  171. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  172. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  173. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  174. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  175. package/src/memory/migrations/116-messages-fts.ts +106 -1
  176. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  177. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  178. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  179. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  180. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  181. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  182. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  183. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  184. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  185. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  186. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  187. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  188. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  189. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  190. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  191. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  192. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  193. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  194. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  195. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  196. package/src/memory/migrations/189-drop-simplified-memory.ts +42 -0
  197. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  198. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  199. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  200. package/src/memory/migrations/index.ts +5 -3
  201. package/src/memory/migrations/registry.ts +90 -0
  202. package/src/memory/migrations/validate-migration-state.ts +137 -11
  203. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  204. package/src/memory/qdrant-client.ts +4 -6
  205. package/src/memory/qdrant-manager.ts +64 -7
  206. package/src/memory/schema/calls.ts +1 -0
  207. package/src/memory/schema/contacts.ts +1 -0
  208. package/src/memory/schema/conversations.ts +0 -3
  209. package/src/memory/schema/index.ts +0 -2
  210. package/src/messaging/draft-store.ts +2 -2
  211. package/src/notifications/decision-engine.ts +4 -1
  212. package/src/oauth/connection-resolver.ts +6 -4
  213. package/src/permissions/checker.ts +0 -38
  214. package/src/permissions/defaults.ts +3 -3
  215. package/src/permissions/shell-identity.ts +76 -22
  216. package/src/permissions/trust-client.ts +2 -13
  217. package/src/permissions/trust-store.ts +8 -3
  218. package/src/permissions/types.ts +4 -2
  219. package/src/platform/client.ts +35 -7
  220. package/src/prompts/persona-resolver.ts +138 -0
  221. package/src/prompts/system-prompt.ts +36 -4
  222. package/src/prompts/templates/users/default.md +1 -0
  223. package/src/providers/registry.ts +27 -40
  224. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  225. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  226. package/src/runtime/auth/external-assistant-id.ts +13 -59
  227. package/src/runtime/auth/route-policy.ts +29 -1
  228. package/src/runtime/auth/token-service.ts +53 -15
  229. package/src/runtime/channel-readiness-service.ts +1 -16
  230. package/src/runtime/http-server.ts +29 -2
  231. package/src/runtime/middleware/error-handler.ts +1 -9
  232. package/src/runtime/routes/audio-routes.ts +40 -0
  233. package/src/runtime/routes/btw-routes.ts +0 -17
  234. package/src/runtime/routes/conversation-management-routes.ts +0 -36
  235. package/src/runtime/routes/conversation-query-routes.ts +106 -2
  236. package/src/runtime/routes/conversation-routes.ts +4 -43
  237. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  238. package/src/runtime/routes/identity-routes.ts +18 -29
  239. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  240. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  241. package/src/runtime/routes/integrations/vercel.ts +89 -0
  242. package/src/runtime/routes/log-export-routes.ts +5 -0
  243. package/src/runtime/routes/memory-item-routes.test.ts +221 -3
  244. package/src/runtime/routes/memory-item-routes.ts +144 -4
  245. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  246. package/src/runtime/routes/migration-routes.ts +17 -1
  247. package/src/runtime/routes/notification-routes.ts +58 -0
  248. package/src/runtime/routes/schedule-routes.ts +65 -0
  249. package/src/runtime/routes/settings-routes.ts +41 -1
  250. package/src/runtime/routes/tts-routes.ts +86 -0
  251. package/src/runtime/routes/upgrade-broadcast-routes.ts +175 -0
  252. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  253. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  254. package/src/runtime/routes/workspace-routes.ts +1 -1
  255. package/src/runtime/routes/workspace-utils.ts +86 -2
  256. package/src/schedule/schedule-store.ts +0 -21
  257. package/src/security/ces-credential-client.ts +59 -22
  258. package/src/security/ces-rpc-credential-backend.ts +85 -0
  259. package/src/security/credential-backend.ts +12 -88
  260. package/src/security/keychain-broker-client.ts +10 -2
  261. package/src/security/secure-keys.ts +94 -113
  262. package/src/skills/catalog-install.ts +13 -7
  263. package/src/skills/inline-command-render.ts +5 -1
  264. package/src/skills/inline-command-runner.ts +30 -2
  265. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  266. package/src/tools/calls/call-start.ts +1 -0
  267. package/src/tools/executor.ts +0 -4
  268. package/src/tools/memory/handlers.ts +1 -129
  269. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  270. package/src/tools/network/web-fetch.ts +3 -1
  271. package/src/tools/permission-checker.ts +18 -0
  272. package/src/tools/skills/execute.ts +1 -1
  273. package/src/tools/skills/load.ts +9 -2
  274. package/src/tools/types.ts +0 -8
  275. package/src/util/errors.ts +0 -12
  276. package/src/util/platform.ts +8 -55
  277. package/src/util/xml.ts +8 -0
  278. package/src/workspace/git-service.ts +5 -2
  279. package/src/workspace/heartbeat-service.ts +5 -24
  280. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  281. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  282. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  283. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  284. package/src/workspace/migrations/006-services-config.ts +49 -0
  285. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  286. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  287. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  288. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  289. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  290. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  291. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  292. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  293. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  294. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  295. package/src/workspace/migrations/017-seed-persona-dirs.ts +95 -0
  296. package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
  297. package/src/workspace/migrations/registry.ts +8 -0
  298. package/src/workspace/migrations/runner.ts +106 -2
  299. package/src/workspace/migrations/types.ts +4 -0
  300. package/src/__tests__/archive-recall.test.ts +0 -560
  301. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  302. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  303. package/src/__tests__/conversation-memory-dirty-tail.test.ts +0 -150
  304. package/src/__tests__/conversation-switch-memory-reduction.test.ts +0 -474
  305. package/src/__tests__/db-memory-archive-migration.test.ts +0 -372
  306. package/src/__tests__/db-memory-brief-state-migration.test.ts +0 -213
  307. package/src/__tests__/db-memory-reducer-checkpoints.test.ts +0 -273
  308. package/src/__tests__/diagnostics-export.test.ts +0 -288
  309. package/src/__tests__/local-gateway-health.test.ts +0 -209
  310. package/src/__tests__/memory-brief-open-loops.test.ts +0 -530
  311. package/src/__tests__/memory-brief-time.test.ts +0 -285
  312. package/src/__tests__/memory-brief-wrapper.test.ts +0 -311
  313. package/src/__tests__/memory-chunk-archive.test.ts +0 -400
  314. package/src/__tests__/memory-chunk-dual-write.test.ts +0 -453
  315. package/src/__tests__/memory-episode-archive.test.ts +0 -370
  316. package/src/__tests__/memory-episode-dual-write.test.ts +0 -626
  317. package/src/__tests__/memory-observation-archive.test.ts +0 -375
  318. package/src/__tests__/memory-observation-dual-write.test.ts +0 -318
  319. package/src/__tests__/memory-reducer-job.test.ts +0 -538
  320. package/src/__tests__/memory-reducer-scheduling.test.ts +0 -473
  321. package/src/__tests__/memory-reducer-store.test.ts +0 -728
  322. package/src/__tests__/memory-reducer-types.test.ts +0 -707
  323. package/src/__tests__/memory-reducer.test.ts +0 -704
  324. package/src/__tests__/memory-simplified-config.test.ts +0 -281
  325. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  326. package/src/__tests__/simplified-memory-e2e.test.ts +0 -666
  327. package/src/__tests__/simplified-memory-runtime.test.ts +0 -616
  328. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  329. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  330. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  331. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  332. package/src/__tests__/swarm-recursion.test.ts +0 -197
  333. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  334. package/src/__tests__/swarm-tool.test.ts +0 -185
  335. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  336. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  337. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  338. package/src/commands/cc-command-registry.ts +0 -248
  339. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  340. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  341. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  342. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  343. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  344. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  345. package/src/config/schemas/memory-simplified.ts +0 -101
  346. package/src/config/schemas/swarm.ts +0 -82
  347. package/src/logfire.ts +0 -135
  348. package/src/memory/archive-recall.ts +0 -516
  349. package/src/memory/archive-store.ts +0 -400
  350. package/src/memory/brief-formatting.ts +0 -33
  351. package/src/memory/brief-open-loops.ts +0 -266
  352. package/src/memory/brief-time.ts +0 -162
  353. package/src/memory/brief.ts +0 -75
  354. package/src/memory/job-handlers/backfill-simplified-memory.ts +0 -462
  355. package/src/memory/job-handlers/reduce-conversation-memory.ts +0 -229
  356. package/src/memory/migrations/185-memory-brief-state.ts +0 -52
  357. package/src/memory/migrations/186-memory-archive.ts +0 -109
  358. package/src/memory/migrations/187-memory-reducer-checkpoints.ts +0 -19
  359. package/src/memory/reducer-scheduler.ts +0 -242
  360. package/src/memory/reducer-store.ts +0 -271
  361. package/src/memory/reducer-types.ts +0 -106
  362. package/src/memory/reducer.ts +0 -467
  363. package/src/memory/schema/memory-archive.ts +0 -121
  364. package/src/memory/schema/memory-brief.ts +0 -55
  365. package/src/runtime/local-gateway-health.ts +0 -275
  366. package/src/security/secret-ingress.ts +0 -68
  367. package/src/swarm/backend-claude-code.ts +0 -225
  368. package/src/swarm/checkpoint.ts +0 -137
  369. package/src/swarm/graph-utils.ts +0 -53
  370. package/src/swarm/index.ts +0 -55
  371. package/src/swarm/limits.ts +0 -66
  372. package/src/swarm/orchestrator.ts +0 -424
  373. package/src/swarm/plan-validator.ts +0 -117
  374. package/src/swarm/router-planner.ts +0 -162
  375. package/src/swarm/router-prompts.ts +0 -39
  376. package/src/swarm/synthesizer.ts +0 -81
  377. package/src/swarm/types.ts +0 -72
  378. package/src/swarm/worker-backend.ts +0 -131
  379. package/src/swarm/worker-prompts.ts +0 -80
  380. package/src/swarm/worker-runner.ts +0 -170
  381. package/src/tools/claude-code/claude-code.ts +0 -610
  382. package/src/tools/swarm/delegate.ts +0 -205
@@ -33,7 +33,9 @@ export function recoverCrashedMigrations(database: DrizzleDb): string[] {
33
33
  return [];
34
34
  }
35
35
 
36
- const crashed = rows.filter((r) => r.value === "started").map((r) => r.key);
36
+ const crashed = rows
37
+ .filter((r) => r.value === "started" || r.value === "rolling_back")
38
+ .map((r) => r.key);
37
39
  if (crashed.length === 0) return [];
38
40
 
39
41
  log.error(
@@ -83,7 +85,12 @@ export function withCrashRecovery(
83
85
  const existing = raw
84
86
  .query(`SELECT value FROM memory_checkpoints WHERE key = ?`)
85
87
  .get(checkpointKey) as { value: string } | null;
86
- if (existing && existing.value !== "started") return;
88
+ if (
89
+ existing &&
90
+ existing.value !== "started" &&
91
+ existing.value !== "rolling_back"
92
+ )
93
+ return;
87
94
 
88
95
  raw
89
96
  .query(
@@ -126,12 +133,14 @@ export function validateMigrationState(
126
133
  .all() as Array<{ key: string; value: string }>;
127
134
  } catch {
128
135
  // memory_checkpoints may not exist on a very old database; skip.
129
- return { crashed: [], dependencyViolations: [] };
136
+ return { crashed: [], dependencyViolations: [], unknownCheckpoints: [] };
130
137
  }
131
138
 
132
- // Any remaining 'started' checkpoints after recovery + migration execution
133
- // indicate a migration that was retried but failed again.
134
- const crashed = rows.filter((r) => r.value === "started").map((r) => r.key);
139
+ // Any remaining 'started' or 'rolling_back' checkpoints after recovery +
140
+ // migration execution indicate a migration that was retried but failed again.
141
+ const crashed = rows
142
+ .filter((r) => r.value === "started" || r.value === "rolling_back")
143
+ .map((r) => r.key);
135
144
  if (crashed.length > 0) {
136
145
  log.error(
137
146
  { crashed },
@@ -149,11 +158,14 @@ export function validateMigrationState(
149
158
  );
150
159
  }
151
160
 
152
- // Only rows whose value is NOT 'started' represent truly completed migrations.
153
- // In-progress/crashed checkpoints (value = 'started') must not count as applied
154
- // dependencies — the migration never finished, so its postconditions are unmet.
161
+ // Only rows whose value is NOT 'started' or 'rolling_back' represent truly
162
+ // completed migrations. In-progress/crashed checkpoints must not count as
163
+ // applied dependencies — the migration never finished, so its postconditions
164
+ // are unmet.
155
165
  const completed = new Set(
156
- rows.filter((r) => r.value !== "started").map((r) => r.key),
166
+ rows
167
+ .filter((r) => r.value !== "started" && r.value !== "rolling_back")
168
+ .map((r) => r.key),
157
169
  );
158
170
 
159
171
  const dependencyViolations: Array<{
@@ -191,5 +203,119 @@ export function validateMigrationState(
191
203
  );
192
204
  }
193
205
 
194
- return { crashed, dependencyViolations };
206
+ // Detect checkpoints that exist in the database but have no corresponding
207
+ // registry entry — these are from a newer version of the daemon.
208
+ //
209
+ // The memory_checkpoints table is a general-purpose key-value store also
210
+ // used by non-migration subsystems (e.g., "identity:intro:text",
211
+ // "conversation_starters:item_count_at_last_gen"). Filter to only keys
212
+ // that follow migration naming conventions before comparing against the
213
+ // registry to avoid false-positive warnings.
214
+ const registryKeys = new Set(MIGRATION_REGISTRY.map((e) => e.key));
215
+ const isMigrationKey = (k: string): boolean =>
216
+ k.startsWith("migration_") ||
217
+ k.startsWith("backfill_") ||
218
+ k.startsWith("drop_");
219
+ const unknownCheckpoints = [...completed].filter(
220
+ (k) => isMigrationKey(k) && !registryKeys.has(k),
221
+ );
222
+
223
+ if (unknownCheckpoints.length > 0) {
224
+ log.warn(
225
+ { unknownCheckpoints },
226
+ `Database contains ${unknownCheckpoints.length} migration checkpoint(s) from a newer version. Data may be incompatible.`,
227
+ );
228
+ }
229
+
230
+ return { crashed, dependencyViolations, unknownCheckpoints };
231
+ }
232
+
233
+ /**
234
+ * Roll back all completed memory (database) migrations with version > targetVersion.
235
+ *
236
+ * Iterates eligible migrations in reverse version order. For each:
237
+ * 1. Marks the checkpoint as `"rolling_back"` for crash recovery.
238
+ * 2. Calls `entry.down(database)` — each down() manages its own transactions.
239
+ * (`down` is required on `MigrationRegistryEntry` at the type level.)
240
+ * 3. Deletes the checkpoint from `memory_checkpoints`.
241
+ *
242
+ * **Usage**: Pass the target version number you want to roll back *to*. All
243
+ * migrations with a higher version number that have been applied will be
244
+ * reversed. For example, `rollbackMemoryMigration(db, 5)` rolls back all
245
+ * applied migrations with version > 5.
246
+ *
247
+ * **Checkpoint state**: Each rolled-back migration's checkpoint is deleted
248
+ * from `memory_checkpoints`. If the process crashes mid-rollback, the
249
+ * `"rolling_back"` marker is detected and cleared by
250
+ * `recoverCrashedMigrations` on the next startup.
251
+ *
252
+ * **Warning — data loss**: Some down() migrations may not fully restore the
253
+ * original state (e.g., DROP TABLE migrations recreate the table but cannot
254
+ * recover the original data). Review each migration's down() implementation
255
+ * before calling this function programmatically.
256
+ *
257
+ * **Important**: Stop the assistant before running rollbacks. Rolling back
258
+ * migrations while the assistant is running may cause schema mismatches,
259
+ * query failures, or data corruption.
260
+ *
261
+ * @param database The Drizzle database instance.
262
+ * @param targetVersion Roll back to this version (exclusive — all migrations
263
+ * with version > targetVersion are reversed).
264
+ * @returns The list of rolled-back migration keys.
265
+ */
266
+ export function rollbackMemoryMigration(
267
+ database: DrizzleDb,
268
+ targetVersion: number,
269
+ ): string[] {
270
+ const raw = getSqliteFrom(database);
271
+
272
+ // Read completed checkpoints to determine which migrations have been applied.
273
+ let rows: Array<{ key: string; value: string }>;
274
+ try {
275
+ rows = raw
276
+ .query(`SELECT key, value FROM memory_checkpoints`)
277
+ .all() as Array<{ key: string; value: string }>;
278
+ } catch {
279
+ return [];
280
+ }
281
+
282
+ const completedKeys = new Set(
283
+ rows
284
+ .filter((r) => r.value !== "started" && r.value !== "rolling_back")
285
+ .map((r) => r.key),
286
+ );
287
+
288
+ // Find registry entries with version > targetVersion that have completed checkpoints.
289
+ const toRollback = MIGRATION_REGISTRY.filter(
290
+ (entry) => entry.version > targetVersion && completedKeys.has(entry.key),
291
+ ).sort((a, b) => b.version - a.version); // reverse version order
292
+
293
+ const rolledBack: string[] = [];
294
+
295
+ for (const entry of toRollback) {
296
+ // Mark as rolling_back for crash recovery — if the process crashes here,
297
+ // recoverCrashedMigrations will clear this checkpoint on next startup.
298
+ raw
299
+ .query(
300
+ `UPDATE memory_checkpoints SET value = 'rolling_back', updated_at = ? WHERE key = ?`,
301
+ )
302
+ .run(Date.now(), entry.key);
303
+
304
+ // Execute the down migration — let it manage its own transaction lifecycle.
305
+ // Many down() functions call BEGIN/COMMIT internally or use PRAGMA statements
306
+ // that are no-ops inside a transaction.
307
+ entry.down(database);
308
+
309
+ // Delete the checkpoint after down() succeeds — outside any transaction
310
+ // so it's not affected by down()'s internal transaction management.
311
+ raw.query(`DELETE FROM memory_checkpoints WHERE key = ?`).run(entry.key);
312
+
313
+ log.info(
314
+ { key: entry.key, version: entry.version },
315
+ `Rolled back migration "${entry.key}" (version ${entry.version})`,
316
+ );
317
+ rolledBack.push(entry.key);
318
+ }
319
+
320
+ return rolledBack;
195
321
  }
@@ -101,6 +101,15 @@ export function isQdrantBreakerOpen(): boolean {
101
101
  return breakerState !== "closed";
102
102
  }
103
103
 
104
+ /**
105
+ * Returns true when the breaker is open and the cooldown has elapsed,
106
+ * meaning the next call to `withQdrantBreaker` will transition to half-open.
107
+ * Use this to allow a single probe job through when embed jobs are otherwise skipped.
108
+ */
109
+ export function shouldAllowQdrantProbe(): boolean {
110
+ return breakerState === "open" && Date.now() - openedAt >= COOLDOWN_MS;
111
+ }
112
+
104
113
  /** @internal Test-only: reset circuit breaker state */
105
114
  export function _resetQdrantBreaker(): void {
106
115
  breakerState = "closed";
@@ -20,7 +20,7 @@ export interface QdrantClientConfig {
20
20
  }
21
21
 
22
22
  export interface QdrantPointPayload {
23
- target_type: "segment" | "item" | "summary" | "observation" | "chunk" | "episode" | "media";
23
+ target_type: "segment" | "item" | "summary" | "media";
24
24
  target_id: string;
25
25
  text: string;
26
26
  kind?: string;
@@ -230,7 +230,7 @@ export class VellumQdrantClient {
230
230
  }
231
231
 
232
232
  async upsert(
233
- targetType: "segment" | "item" | "summary" | "observation" | "chunk" | "episode" | "media",
233
+ targetType: "segment" | "item" | "summary" | "media",
234
234
  targetId: string,
235
235
  vector: number[],
236
236
  payload: Omit<QdrantPointPayload, "target_type" | "target_id">,
@@ -324,9 +324,7 @@ export class VellumQdrantClient {
324
324
  async searchWithFilter(
325
325
  vector: number[],
326
326
  limit: number,
327
- targetTypes: Array<
328
- "segment" | "item" | "summary" | "media" | "chunk" | "episode"
329
- >,
327
+ targetTypes: Array<"segment" | "item" | "summary" | "media">,
330
328
  excludeMessageIds?: string[],
331
329
  scopeIds?: string[],
332
330
  ): Promise<QdrantSearchResult[]> {
@@ -349,7 +347,7 @@ export class VellumQdrantClient {
349
347
  },
350
348
  {
351
349
  key: "target_type",
352
- match: { any: ["segment", "summary", "media", "chunk"] },
350
+ match: { any: ["segment", "summary", "media"] },
353
351
  },
354
352
  ],
355
353
  });
@@ -4,6 +4,7 @@ import {
4
4
  existsSync,
5
5
  mkdirSync,
6
6
  readFileSync,
7
+ symlinkSync,
7
8
  unlinkSync,
8
9
  writeFileSync,
9
10
  } from "node:fs";
@@ -12,7 +13,7 @@ import { dirname, join } from "node:path";
12
13
 
13
14
  import type { Subprocess } from "bun";
14
15
 
15
- import { getQdrantUrlEnv } from "../config/env.js";
16
+ import { getQdrantReadyzTimeoutMs, getQdrantUrlEnv } from "../config/env.js";
16
17
  import { getLogger } from "../util/logger.js";
17
18
  import { getDataDir } from "../util/platform.js";
18
19
 
@@ -47,6 +48,8 @@ export interface QdrantManagerConfig {
47
48
  */
48
49
  export class QdrantManager {
49
50
  private process: Subprocess | null = null;
51
+ private stderrBuffer = "";
52
+ private stderrDrained: Promise<void> = Promise.resolve();
50
53
  private readonly url: string;
51
54
  private readonly host: string;
52
55
  private readonly port: number;
@@ -67,7 +70,8 @@ export class QdrantManager {
67
70
 
68
71
  this.readyzPollIntervalMs =
69
72
  config.readyzPollIntervalMs ?? READYZ_POLL_INTERVAL_MS;
70
- this.readyzTimeoutMs = config.readyzTimeoutMs ?? READYZ_TIMEOUT_MS;
73
+ this.readyzTimeoutMs =
74
+ config.readyzTimeoutMs ?? getQdrantReadyzTimeoutMs() ?? READYZ_TIMEOUT_MS;
71
75
  this.shutdownGraceMs = config.shutdownGraceMs ?? SHUTDOWN_GRACE_MS;
72
76
 
73
77
  // External mode only if QDRANT_URL is explicitly set
@@ -92,13 +96,15 @@ export class QdrantManager {
92
96
  await this.installBinary(binaryPath);
93
97
  }
94
98
 
99
+ const spawnPath = this.ensureVellumSymlink(binaryPath);
100
+
95
101
  log.info(
96
- { binaryPath, storagePath: this.storagePath, port: this.port },
102
+ { binaryPath: spawnPath, storagePath: this.storagePath, port: this.port },
97
103
  "Starting Qdrant",
98
104
  );
99
105
 
100
- this.process = Bun.spawn({
101
- cmd: [binaryPath],
106
+ const proc = Bun.spawn({
107
+ cmd: [spawnPath],
102
108
  env: {
103
109
  ...process.env,
104
110
  QDRANT__SERVICE__HOST: this.host,
@@ -109,8 +115,10 @@ export class QdrantManager {
109
115
  QDRANT__LOG_LEVEL: "WARN",
110
116
  },
111
117
  stdout: "ignore",
112
- stderr: "ignore",
118
+ stderr: "pipe",
113
119
  });
120
+ this.process = proc;
121
+ this.drainStderrFrom(proc.stderr);
114
122
 
115
123
  if (this.process.pid) {
116
124
  this.writePid(this.process.pid);
@@ -150,6 +158,7 @@ export class QdrantManager {
150
158
  }
151
159
 
152
160
  this.process = null;
161
+ this.stderrBuffer = "";
153
162
  this.cleanupPid();
154
163
  log.info("Qdrant stopped");
155
164
  }
@@ -259,6 +268,15 @@ export class QdrantManager {
259
268
  private async waitForReady(): Promise<void> {
260
269
  const start = Date.now();
261
270
  while (Date.now() - start < this.readyzTimeoutMs) {
271
+ // Fail fast if the managed process exited before becoming ready
272
+ if (this.process != null && this.process.exitCode != null) {
273
+ await this.stderrDrained;
274
+ const stderr = this.stderrBuffer.trim();
275
+ throw new Error(
276
+ `Qdrant process exited with code ${this.process.exitCode} before becoming ready` +
277
+ (stderr ? `\nstderr:\n${stderr}` : ""),
278
+ );
279
+ }
262
280
  try {
263
281
  const res = await fetch(`${this.url}/readyz`);
264
282
  if (res.ok) return;
@@ -267,11 +285,32 @@ export class QdrantManager {
267
285
  }
268
286
  await Bun.sleep(this.readyzPollIntervalMs);
269
287
  }
288
+ const stderr = this.stderrBuffer.trim();
270
289
  throw new Error(
271
- `Qdrant did not become ready within ${this.readyzTimeoutMs}ms at ${this.url}`,
290
+ `Qdrant did not become ready within ${this.readyzTimeoutMs}ms at ${this.url}` +
291
+ (stderr ? `\nstderr:\n${stderr}` : ""),
272
292
  );
273
293
  }
274
294
 
295
+ private drainStderrFrom(stream: ReadableStream<Uint8Array>): void {
296
+ const reader = stream.getReader();
297
+ const decoder = new TextDecoder();
298
+ this.stderrDrained = (async () => {
299
+ try {
300
+ for (;;) {
301
+ const { done, value } = await reader.read();
302
+ if (done) break;
303
+ this.stderrBuffer += decoder.decode(value, { stream: true });
304
+ if (this.stderrBuffer.length > 4096) {
305
+ this.stderrBuffer = this.stderrBuffer.slice(-4096);
306
+ }
307
+ }
308
+ } catch {
309
+ // Stream closed or error — expected during shutdown
310
+ }
311
+ })();
312
+ }
313
+
275
314
  private getBinaryPath(): string {
276
315
  return join(getDataDir(), "qdrant", "bin", "qdrant");
277
316
  }
@@ -314,4 +353,22 @@ export class QdrantManager {
314
353
  }
315
354
  }
316
355
  }
356
+
357
+ /**
358
+ * Ensures a `vellum-qdrant` symlink exists next to the real binary so that
359
+ * `lsof` reports "vellum-qdrant" in the COMMAND column, making the process
360
+ * discoverable by tools that scan for "vellum" in process names.
361
+ */
362
+ private ensureVellumSymlink(binaryPath: string): string {
363
+ const symlinkPath = join(dirname(binaryPath), "vellum-qdrant");
364
+ if (!existsSync(symlinkPath)) {
365
+ try {
366
+ symlinkSync(binaryPath, symlinkPath);
367
+ } catch {
368
+ // Fall back to the real binary if symlink creation fails
369
+ return binaryPath;
370
+ }
371
+ }
372
+ return symlinkPath;
373
+ }
317
374
  }
@@ -27,6 +27,7 @@ export const callSessions = sqliteTable(
27
27
  inviteGuardianName: text("invite_guardian_name"),
28
28
  callerIdentityMode: text("caller_identity_mode"),
29
29
  callerIdentitySource: text("caller_identity_source"),
30
+ skipDisclosure: integer("skip_disclosure").notNull().default(0),
30
31
  initiatedFromConversationId: text("initiated_from_conversation_id"),
31
32
  startedAt: integer("started_at"),
32
33
  endedAt: integer("ended_at"),
@@ -10,6 +10,7 @@ export const contacts = sqliteTable("contacts", {
10
10
  updatedAt: integer("updated_at").notNull(),
11
11
  role: text("role").notNull().default("contact"), // 'guardian' | 'contact'
12
12
  principalId: text("principal_id"), // internal auth principal (nullable)
13
+ userFile: text("user_file"), // workspace-relative path to per-user persona file
13
14
  contactType: text("contact_type").notNull().default("human"), // 'human' | 'assistant'
14
15
  });
15
16
 
@@ -30,9 +30,6 @@ export const conversations = sqliteTable(
30
30
  forkParentMessageId: text("fork_parent_message_id"),
31
31
  isAutoTitle: integer("is_auto_title").notNull().default(1),
32
32
  scheduleJobId: text("schedule_job_id"),
33
- memoryReducedThroughMessageId: text("memory_reduced_through_message_id"),
34
- memoryDirtyTailSinceMessageId: text("memory_dirty_tail_since_message_id"),
35
- memoryLastReducedAt: integer("memory_last_reduced_at"),
36
33
  },
37
34
  (table) => [
38
35
  index("idx_conversations_updated_at").on(table.updatedAt),
@@ -3,8 +3,6 @@ export * from "./contacts.js";
3
3
  export * from "./conversations.js";
4
4
  export * from "./guardian.js";
5
5
  export * from "./infrastructure.js";
6
- export * from "./memory-archive.js";
7
- export * from "./memory-brief.js";
8
6
  export * from "./memory-core.js";
9
7
  export * from "./notifications.js";
10
8
  export * from "./oauth.js";
@@ -10,7 +10,7 @@ import { readdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
10
10
  import { join } from "node:path";
11
11
 
12
12
  import { ensureDir, pathExists } from "../util/fs.js";
13
- import { getRootDir } from "../util/platform.js";
13
+ import { getWorkspaceDir } from "../util/platform.js";
14
14
 
15
15
  export interface Draft {
16
16
  id: string;
@@ -25,7 +25,7 @@ export interface Draft {
25
25
  }
26
26
 
27
27
  function getDraftsDir(platform: string): string {
28
- const dir = join(getRootDir(), "workspace", "data", "drafts", platform);
28
+ const dir = join(getWorkspaceDir(), "data", "drafts", platform);
29
29
  ensureDir(dir);
30
30
  return dir;
31
31
  }
@@ -13,6 +13,7 @@ import { v4 as uuid } from "uuid";
13
13
 
14
14
  import { getDeliverableChannels } from "../channels/config.js";
15
15
  import { getConfig } from "../config/loader.js";
16
+ import { resolveGuardianPersona } from "../prompts/persona-resolver.js";
16
17
  import { buildCoreIdentityContext } from "../prompts/system-prompt.js";
17
18
  import {
18
19
  createTimeout,
@@ -800,7 +801,9 @@ async function classifyWithLLM(
800
801
  const candidateContext = candidateSet
801
802
  ? (serializeCandidatesForPrompt(candidateSet) ?? undefined)
802
803
  : undefined;
803
- const rawIdentityContext = buildCoreIdentityContext();
804
+ const rawIdentityContext = buildCoreIdentityContext({
805
+ userPersona: resolveGuardianPersona(),
806
+ });
804
807
  const identityContext = rawIdentityContext
805
808
  ? truncate(rawIdentityContext, MAX_IDENTITY_CONTEXT_CHARS, "\n…[truncated]")
806
809
  : undefined;
@@ -156,10 +156,12 @@ async function resolvePlatformConnectionId(
156
156
  );
157
157
  }
158
158
 
159
- const body = (await response.json()) as {
160
- results?: Array<{ id: string; account_label?: string }>;
161
- };
162
- const connections = body.results ?? [];
159
+ const body = (await response.json()) as unknown;
160
+ const connections = (
161
+ Array.isArray(body)
162
+ ? body
163
+ : ((body as Record<string, unknown>).results ?? [])
164
+ ) as Array<{ id: string; account_label?: string }>;
163
165
 
164
166
  if (connections.length === 0) {
165
167
  throw new Error(
@@ -147,7 +147,6 @@ const LOW_RISK_PROGRAMS = new Set([
147
147
  "du",
148
148
  "df",
149
149
  "assistant",
150
- "vellum",
151
150
  ]);
152
151
 
153
152
  // High-risk shell programs / patterns
@@ -201,32 +200,6 @@ const LOW_RISK_GIT_SUBCOMMANDS = new Set([
201
200
  "reflog",
202
201
  ]);
203
202
 
204
- // Mutating assistant/vellum CLI subcommands that should be escalated to Medium
205
- // risk. Most assistant/vellum subcommands are read-only and stay Low risk.
206
- // This mirrors the git subcommand pattern — only known mutating operations
207
- // get escalated.
208
- const MEDIUM_RISK_CLI_SUBCOMMANDS = new Set([
209
- "credentials",
210
- "config",
211
- "bash",
212
- "trust",
213
- "autonomy",
214
- "contacts",
215
- "mcp",
216
- "keys",
217
- "wake",
218
- "sleep",
219
- "hatch",
220
- "retire",
221
- "clean",
222
- "setup",
223
- "upgrade",
224
- "recover",
225
- "login",
226
- "use",
227
- "pair",
228
- ]);
229
-
230
203
  // Commands that wrap another program — the real program appears as the first
231
204
  // non-flag argument. When one of these is the segment program we look through
232
205
  // its args to find the effective program (e.g. `env curl …` → curl).
@@ -771,17 +744,6 @@ async function classifyRiskUncached(
771
744
  continue;
772
745
  }
773
746
 
774
- if (prog === "vellum" || prog === "assistant") {
775
- const subcommand = firstPositionalArg(seg.args);
776
- if (subcommand && MEDIUM_RISK_CLI_SUBCOMMANDS.has(subcommand)) {
777
- // Known mutating subcommands are medium
778
- maxRisk = RiskLevel.Medium;
779
- continue;
780
- }
781
- // Read-only / unknown subcommands stay at current risk
782
- continue;
783
- }
784
-
785
747
  if (!LOW_RISK_PROGRAMS.has(prog)) {
786
748
  // Unknown program → medium
787
749
  if (maxRisk === RiskLevel.Low) {
@@ -2,7 +2,7 @@ import { join } from "node:path";
2
2
 
3
3
  import { getConfig } from "../config/loader.js";
4
4
  import { getBundledSkillsDir } from "../config/skills.js";
5
- import { getRootDir } from "../util/platform.js";
5
+ import { getWorkspaceDir } from "../util/platform.js";
6
6
 
7
7
  export interface DefaultRuleTemplate {
8
8
  id: string;
@@ -116,7 +116,7 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
116
116
  // Workspace prompt files — the agent should always be able to read, edit,
117
117
  // and write these without prompting. Also allow `rm BOOTSTRAP.md` so the
118
118
  // agent can delete it at the end of the onboarding ritual.
119
- const workspaceDir = join(getRootDir(), "workspace").replaceAll("\\", "/");
119
+ const workspaceDir = getWorkspaceDir().replaceAll("\\", "/");
120
120
  const WORKSPACE_PROMPT_FILES = [
121
121
  "IDENTITY.md",
122
122
  "USER.md",
@@ -163,7 +163,7 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
163
163
  // Skill source directories — writing or editing skill source files should
164
164
  // require explicit user approval so a compromised agent loop cannot silently
165
165
  // modify skill code to escalate privileges.
166
- const managedSkillsDir = join(getRootDir(), "workspace", "skills").replaceAll(
166
+ const managedSkillsDir = join(getWorkspaceDir(), "skills").replaceAll(
167
167
  "\\",
168
168
  "/",
169
169
  );