@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
@@ -82,12 +82,76 @@ describe("deriveShellActionKeys", () => {
82
82
  ]);
83
83
  });
84
84
 
85
- test("pipelines are marked non-simple", async () => {
85
+ test("pipelines are marked non-simple but produce action keys", async () => {
86
86
  const analysis = await analyzeShellCommand("git log | grep fix");
87
87
  const result = deriveShellActionKeys(analysis);
88
88
 
89
89
  expect(result.isSimpleAction).toBe(false);
90
- expect(result.keys).toHaveLength(0);
90
+ expect(result.keys).toEqual([
91
+ { key: "action:git log", depth: 2 },
92
+ { key: "action:git", depth: 1 },
93
+ ]);
94
+ });
95
+
96
+ test("pipeline extracts action keys from first segment", async () => {
97
+ const analysis = await analyzeShellCommand(
98
+ "pdftotext file.pdf | head -100",
99
+ );
100
+ const result = deriveShellActionKeys(analysis);
101
+
102
+ expect(result.isSimpleAction).toBe(false);
103
+ // file.pdf is treated as a subcommand token (doesn't start with . or contain /)
104
+ expect(result.keys).toEqual([
105
+ { key: "action:pdftotext file.pdf", depth: 2 },
106
+ { key: "action:pdftotext", depth: 1 },
107
+ ]);
108
+ });
109
+
110
+ test("setup-prefix + pipeline extracts action keys", async () => {
111
+ const analysis = await analyzeShellCommand(
112
+ "cd /tmp && pdftotext file.pdf | grep oil",
113
+ );
114
+ const result = deriveShellActionKeys(analysis);
115
+
116
+ expect(result.isSimpleAction).toBe(false);
117
+ expect(result.keys).toEqual([
118
+ { key: "action:pdftotext file.pdf", depth: 2 },
119
+ { key: "action:pdftotext", depth: 1 },
120
+ ]);
121
+ });
122
+
123
+ test("pipeline with subcommand extracts deeper keys", async () => {
124
+ const analysis = await analyzeShellCommand("cd repo && gh pr list | head");
125
+ const result = deriveShellActionKeys(analysis);
126
+
127
+ expect(result.isSimpleAction).toBe(false);
128
+ expect(result.keys).toEqual([
129
+ { key: "action:gh pr list", depth: 3 },
130
+ { key: "action:gh pr", depth: 2 },
131
+ { key: "action:gh", depth: 1 },
132
+ ]);
133
+ });
134
+
135
+ test("multi-pipe pipeline extracts first segment only", async () => {
136
+ const analysis = await analyzeShellCommand("cat file | grep error | wc -l");
137
+ const result = deriveShellActionKeys(analysis);
138
+
139
+ expect(result.isSimpleAction).toBe(false);
140
+ expect(result.keys).toEqual([
141
+ { key: "action:cat file", depth: 2 },
142
+ { key: "action:cat", depth: 1 },
143
+ ]);
144
+ });
145
+
146
+ test("dangerous pipe_to_shell still extracts keys", async () => {
147
+ const analysis = await analyzeShellCommand("curl url | bash");
148
+ const result = deriveShellActionKeys(analysis);
149
+
150
+ expect(result.isSimpleAction).toBe(false);
151
+ expect(result.keys).toEqual([
152
+ { key: "action:curl url", depth: 2 },
153
+ { key: "action:curl", depth: 1 },
154
+ ]);
91
155
  });
92
156
 
93
157
  test("complex chains with multiple actions are non-simple", async () => {
@@ -198,9 +262,19 @@ describe("buildShellCommandCandidates", () => {
198
262
  expect(candidates).toEqual(['git add . && git commit -m "fix"']);
199
263
  });
200
264
 
201
- test("pipeline returns raw-only", async () => {
265
+ test("pipeline returns raw and action key candidates", async () => {
202
266
  const candidates = await buildShellCommandCandidates("git log | grep fix");
203
- expect(candidates).toEqual(["git log | grep fix"]);
267
+ expect(candidates[0]).toBe("git log | grep fix");
268
+ expect(candidates).toContain("action:git log");
269
+ expect(candidates).toContain("action:git");
270
+ });
271
+
272
+ test("pipeline with setup prefix includes action candidates", async () => {
273
+ const candidates = await buildShellCommandCandidates(
274
+ "cd /tmp && pdftotext file.pdf | wc -c",
275
+ );
276
+ expect(candidates[0]).toBe("cd /tmp && pdftotext file.pdf | wc -c");
277
+ expect(candidates).toContain("action:pdftotext");
204
278
  });
205
279
 
206
280
  test("candidate order is stable", async () => {
@@ -241,13 +315,29 @@ describe("buildShellAllowlistOptions — complex command restrictions", () => {
241
315
  expect(options[0].description).toContain("compound");
242
316
  });
243
317
 
244
- test("pipeline offers exact only", async () => {
318
+ test("pipeline offers exact and action-key options", async () => {
245
319
  const options = await buildShellAllowlistOptions(
246
320
  "cat file.txt | grep error | wc -l",
247
321
  );
248
- expect(options).toHaveLength(1);
322
+ expect(options.length).toBeGreaterThanOrEqual(2);
249
323
  expect(options[0].pattern).toBe("cat file.txt | grep error | wc -l");
250
324
  expect(options[0].description).toContain("compound");
325
+ expect(options.some((o) => o.pattern.startsWith("action:"))).toBe(true);
326
+ });
327
+
328
+ test("pipeline offers action-key options from first segment", async () => {
329
+ const options = await buildShellAllowlistOptions(
330
+ "pdftotext file.pdf | head -100",
331
+ );
332
+ expect(options.length).toBeGreaterThanOrEqual(2);
333
+ expect(options[0].pattern).toBe("pdftotext file.pdf | head -100");
334
+ expect(
335
+ options.some(
336
+ (o) =>
337
+ o.pattern === "action:pdftotext" &&
338
+ o.description.includes('Any "pdftotext" command'),
339
+ ),
340
+ ).toBe(true);
251
341
  });
252
342
 
253
343
  test("semicolon chain offers exact only", async () => {
@@ -5,9 +5,20 @@
5
5
  * parses it via the real frontmatter parser, and verifies that `skillFlagKey()`
6
6
  * returns the correct key and `resolveSkillStates()` correctly gates the skill.
7
7
  */
8
- import { describe, expect, test } from "bun:test";
8
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
9
9
 
10
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
10
+ import {
11
+ _setOverridesForTesting,
12
+ isAssistantFeatureFlagEnabled,
13
+ } from "../config/assistant-feature-flags.js";
14
+
15
+ beforeEach(() => {
16
+ _setOverridesForTesting({});
17
+ });
18
+
19
+ afterEach(() => {
20
+ _setOverridesForTesting({});
21
+ });
11
22
  import type { AssistantConfig } from "../config/schema.js";
12
23
  import { resolveSkillStates, skillFlagKey } from "../config/skill-state.js";
13
24
  import type { SkillSummary } from "../config/skills.js";
@@ -150,12 +161,11 @@ describe("frontmatter feature-flag integration", () => {
150
161
  });
151
162
 
152
163
  test("resolveSkillStates includes skill with featureFlag when flag is ON", () => {
153
- const skill = buildSkillSummary("contacts", SKILL_MD_WITH_FLAG)!;
154
- const config = makeConfig({
155
- assistantFeatureFlagValues: {
156
- "feature_flags.contacts.enabled": true,
157
- },
164
+ _setOverridesForTesting({
165
+ "feature_flags.contacts.enabled": true,
158
166
  });
167
+ const skill = buildSkillSummary("contacts", SKILL_MD_WITH_FLAG)!;
168
+ const config = makeConfig();
159
169
 
160
170
  const resolved = resolveSkillStates([skill], config);
161
171
  expect(resolved.length).toBe(1);
@@ -165,11 +175,10 @@ describe("frontmatter feature-flag integration", () => {
165
175
  test("resolveSkillStates never gates skill without featureFlag", () => {
166
176
  const skill = buildSkillSummary("plain-skill", SKILL_MD_WITHOUT_FLAG)!;
167
177
  // Even with an explicit false override for this skill ID, it should pass through
168
- const config = makeConfig({
169
- assistantFeatureFlagValues: {
170
- "feature_flags.plain-skill.enabled": false,
171
- },
178
+ _setOverridesForTesting({
179
+ "feature_flags.plain-skill.enabled": false,
172
180
  });
181
+ const config = makeConfig();
173
182
 
174
183
  const resolved = resolveSkillStates([skill], config);
175
184
  expect(resolved.length).toBe(1);
@@ -203,9 +212,8 @@ describe("frontmatter feature-flag integration", () => {
203
212
  expect(resolvedDefault[0].summary.id).toBe("contacts");
204
213
 
205
214
  // Step 6: With override disabled, skill is filtered out
206
- const configOff = makeConfig({
207
- assistantFeatureFlagValues: { [key!]: false },
208
- });
215
+ _setOverridesForTesting({ [key!]: false });
216
+ const configOff = makeConfig();
209
217
  expect(isAssistantFeatureFlagEnabled(key!, configOff)).toBe(false);
210
218
 
211
219
  const resolvedOff = resolveSkillStates([skill], configOff);
@@ -1,10 +1,21 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
2
 
3
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
3
+ import {
4
+ _setOverridesForTesting,
5
+ isAssistantFeatureFlagEnabled,
6
+ } from "../config/assistant-feature-flags.js";
4
7
  import type { AssistantConfig } from "../config/schema.js";
5
8
  import { resolveSkillStates, skillFlagKey } from "../config/skill-state.js";
6
9
  import type { SkillSummary } from "../config/skills.js";
7
10
 
11
+ beforeEach(() => {
12
+ _setOverridesForTesting({});
13
+ });
14
+
15
+ afterEach(() => {
16
+ _setOverridesForTesting({});
17
+ });
18
+
8
19
  const DECLARED_FLAG_ID = "contacts";
9
20
  const DECLARED_FLAG_KEY = `feature_flags.${DECLARED_FLAG_ID}.enabled`;
10
21
  const DECLARED_SKILL_ID = "contacts";
@@ -92,9 +103,8 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
92
103
  });
93
104
 
94
105
  test("returns true when skill key is explicitly true", () => {
95
- const config = makeConfig({
96
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: true },
97
- });
106
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
107
+ const config = makeConfig();
98
108
  expect(
99
109
  isAssistantFeatureFlagEnabled(
100
110
  skillFlagKey({ featureFlag: DECLARED_FLAG_ID })!,
@@ -104,9 +114,8 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
104
114
  });
105
115
 
106
116
  test("returns false when skill key is explicitly false", () => {
107
- const config = makeConfig({
108
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: false },
109
- });
117
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
118
+ const config = makeConfig();
110
119
  expect(
111
120
  isAssistantFeatureFlagEnabled(
112
121
  skillFlagKey({ featureFlag: DECLARED_FLAG_ID })!,
@@ -128,11 +137,9 @@ describe("isAssistantFeatureFlagEnabled", () => {
128
137
  ).toBe(true);
129
138
  });
130
139
 
131
- test("assistantFeatureFlagValues overrides registry default", () => {
132
- const config = {
133
- ...makeConfig(),
134
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: false },
135
- } as AssistantConfig;
140
+ test("file-based override overrides registry default", () => {
141
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
142
+ const config = makeConfig();
136
143
  expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
137
144
  false,
138
145
  );
@@ -145,9 +152,8 @@ describe("isAssistantFeatureFlagEnabled", () => {
145
152
  });
146
153
 
147
154
  test("respects persisted overrides for undeclared keys", () => {
148
- const config = makeConfig({
149
- assistantFeatureFlagValues: { "feature_flags.browser.enabled": false },
150
- });
155
+ _setOverridesForTesting({ "feature_flags.browser.enabled": false });
156
+ const config = makeConfig();
151
157
  expect(
152
158
  isAssistantFeatureFlagEnabled("feature_flags.browser.enabled", config),
153
159
  ).toBe(false);
@@ -168,16 +174,15 @@ describe("isAssistantFeatureFlagEnabled", () => {
168
174
 
169
175
  describe("resolveSkillStates with feature flags", () => {
170
176
  test("flag OFF skill does not appear in resolved list", () => {
177
+ _setOverridesForTesting({
178
+ [DECLARED_FLAG_KEY]: false,
179
+ "feature_flags.browser.enabled": true,
180
+ });
171
181
  const catalog = [
172
182
  makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID),
173
183
  makeSkill("browser", "bundled", "browser"),
174
184
  ];
175
- const config = makeConfig({
176
- assistantFeatureFlagValues: {
177
- [DECLARED_FLAG_KEY]: false,
178
- "feature_flags.browser.enabled": true,
179
- },
180
- });
185
+ const config = makeConfig();
181
186
 
182
187
  const resolved = resolveSkillStates(catalog, config);
183
188
  const ids = resolved.map((r) => r.summary.id);
@@ -187,16 +192,15 @@ describe("resolveSkillStates with feature flags", () => {
187
192
  });
188
193
 
189
194
  test("flag ON skill appears normally", () => {
195
+ _setOverridesForTesting({
196
+ [DECLARED_FLAG_KEY]: true,
197
+ "feature_flags.browser.enabled": true,
198
+ });
190
199
  const catalog = [
191
200
  makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID),
192
201
  makeSkill("browser", "bundled", "browser"),
193
202
  ];
194
- const config = makeConfig({
195
- assistantFeatureFlagValues: {
196
- [DECLARED_FLAG_KEY]: true,
197
- "feature_flags.browser.enabled": true,
198
- },
199
- });
203
+ const config = makeConfig();
200
204
 
201
205
  const resolved = resolveSkillStates(catalog, config);
202
206
  const ids = resolved.map((r) => r.summary.id);
@@ -227,9 +231,9 @@ describe("resolveSkillStates with feature flags", () => {
227
231
  });
228
232
 
229
233
  test("feature flag OFF takes precedence over user-enabled config entry", () => {
234
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
230
235
  const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
231
236
  const config = makeConfig({
232
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: false },
233
237
  skills: {
234
238
  entries: { [DECLARED_SKILL_ID]: { enabled: true } },
235
239
  load: { extraDirs: [], watch: true, watchDebounceMs: 250 },
@@ -253,18 +257,17 @@ describe("resolveSkillStates with feature flags", () => {
253
257
  });
254
258
 
255
259
  test("multiple skills with mixed flags — persisted overrides respected", () => {
260
+ _setOverridesForTesting({
261
+ [DECLARED_FLAG_KEY]: false,
262
+ "feature_flags.browser.enabled": true,
263
+ "feature_flags.deploy.enabled": false,
264
+ });
256
265
  const catalog = [
257
266
  makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID),
258
267
  makeSkill("browser", "bundled", "browser"),
259
268
  makeSkill("deploy", "bundled", "deploy"),
260
269
  ];
261
- const config = makeConfig({
262
- assistantFeatureFlagValues: {
263
- [DECLARED_FLAG_KEY]: false,
264
- "feature_flags.browser.enabled": true,
265
- "feature_flags.deploy.enabled": false,
266
- },
267
- });
270
+ const config = makeConfig();
268
271
 
269
272
  const resolved = resolveSkillStates(catalog, config);
270
273
  const ids = resolved.map((r) => r.summary.id);
@@ -290,11 +293,10 @@ describe("resolveSkillStates with frontmatter featureFlag", () => {
290
293
  expect(resolved[0].summary.id).toBe(DECLARED_SKILL_ID);
291
294
  });
292
295
 
293
- test("skill with featureFlag is included when config override enables it", () => {
296
+ test("skill with featureFlag is included when override enables it", () => {
297
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
294
298
  const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
295
- const config = makeConfig({
296
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: true },
297
- });
299
+ const config = makeConfig();
298
300
 
299
301
  const resolved = resolveSkillStates(catalog, config);
300
302
  const ids = resolved.map((r) => r.summary.id);
@@ -316,12 +318,11 @@ describe("resolveSkillStates with frontmatter featureFlag", () => {
316
318
  // This proves the implicit skillId→flag mapping is gone:
317
319
  // setting feature_flags.my-skill.enabled = false has no effect
318
320
  // when the skill itself does not declare a featureFlag.
319
- const catalog = [makeSkill("my-skill")];
320
- const config = makeConfig({
321
- assistantFeatureFlagValues: {
322
- "feature_flags.my-skill.enabled": false,
323
- },
321
+ _setOverridesForTesting({
322
+ "feature_flags.my-skill.enabled": false,
324
323
  });
324
+ const catalog = [makeSkill("my-skill")];
325
+ const config = makeConfig();
325
326
 
326
327
  const resolved = resolveSkillStates(catalog, config);
327
328
  const ids = resolved.map((r) => r.summary.id);
@@ -7,6 +7,8 @@ import { tmpdir } from "node:os";
7
7
  import { join } from "node:path";
8
8
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
9
9
 
10
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
11
+
10
12
  const TEST_DIR = join(
11
13
  tmpdir(),
12
14
  `vellum-skill-load-flag-test-${crypto.randomUUID()}`,
@@ -75,7 +77,6 @@ mock.module("../config/loader.js", () => ({
75
77
  invalidateConfigCache: () => {},
76
78
  getNestedValue: () => undefined,
77
79
  setNestedValue: () => {},
78
- syncConfigToLockfile: () => {},
79
80
  }));
80
81
 
81
82
  await import("../tools/skills/load.js");
@@ -113,9 +114,11 @@ describe("skill_load feature flag enforcement", () => {
113
114
  beforeEach(() => {
114
115
  mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
115
116
  currentConfig = {};
117
+ _setOverridesForTesting({});
116
118
  });
117
119
 
118
120
  afterEach(() => {
121
+ _setOverridesForTesting({});
119
122
  if (existsSync(TEST_DIR)) {
120
123
  rmSync(TEST_DIR, { recursive: true, force: true });
121
124
  }
@@ -133,9 +136,7 @@ describe("skill_load feature flag enforcement", () => {
133
136
  `- ${DECLARED_SKILL_ID}\n`,
134
137
  );
135
138
 
136
- currentConfig = {
137
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: false },
138
- };
139
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
139
140
 
140
141
  const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
141
142
 
@@ -156,9 +157,7 @@ describe("skill_load feature flag enforcement", () => {
156
157
  `- ${DECLARED_SKILL_ID}\n`,
157
158
  );
158
159
 
159
- currentConfig = {
160
- assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: true },
161
- };
160
+ _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
162
161
 
163
162
  const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
164
163
 
@@ -178,9 +177,7 @@ describe("skill_load feature flag enforcement", () => {
178
177
  `- ${DECLARED_SKILL_ID}\n`,
179
178
  );
180
179
 
181
- currentConfig = {
182
- assistantFeatureFlagValues: {},
183
- };
180
+ // No overrides — uses registry defaults
184
181
 
185
182
  const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
186
183
 
@@ -21,6 +21,8 @@ import { tmpdir } from "node:os";
21
21
  import { join } from "node:path";
22
22
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
23
23
 
24
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
25
+
24
26
  // ── Test directory ────────────────────────────────────────────────────────────
25
27
 
26
28
  const TEST_DIR = mkdtempSync(
@@ -50,9 +52,7 @@ const platformOverrides: Record<string, (...args: unknown[]) => unknown> = {
50
52
  getSessionTokenPath: () => join(TEST_DIR, "session-token"),
51
53
  readSessionToken: () => null,
52
54
  getClipboardCommand: () => null,
53
- readLockfile: () => null,
54
55
  normalizeAssistantId: (id: unknown) => String(id),
55
- writeLockfile: () => {},
56
56
  getEmbeddingModelsDir: () => join(TEST_DIR, "embedding-models"),
57
57
  getTCPPort: () => 8765,
58
58
  isTCPEnabled: () => false,
@@ -127,7 +127,6 @@ interface TestConfig {
127
127
  permissions: { mode: "strict" | "workspace" };
128
128
  skills: { load: { extraDirs: string[] } };
129
129
  sandbox: { enabled: boolean };
130
- assistantFeatureFlagValues?: Record<string, boolean>;
131
130
  [key: string]: unknown;
132
131
  }
133
132
 
@@ -135,9 +134,6 @@ const testConfig: TestConfig = {
135
134
  permissions: { mode: "workspace" },
136
135
  skills: { load: { extraDirs: [] } },
137
136
  sandbox: { enabled: true },
138
- assistantFeatureFlagValues: {
139
- "feature_flags.inline-skill-commands.enabled": true,
140
- },
141
137
  };
142
138
 
143
139
  mock.module("../config/loader.js", () => ({
@@ -215,9 +211,9 @@ describe("skill_load inline command expansion", () => {
215
211
  }));
216
212
 
217
213
  // Enable the feature flag
218
- testConfig.assistantFeatureFlagValues = {
214
+ _setOverridesForTesting({
219
215
  "feature_flags.inline-skill-commands.enabled": true,
220
- };
216
+ });
221
217
  testConfig.skills = { load: { extraDirs: [] } };
222
218
  });
223
219
 
@@ -316,9 +312,9 @@ describe("skill_load inline command expansion", () => {
316
312
 
317
313
  describe("feature flag disabled", () => {
318
314
  test("returns error when flag is off and skill has inline commands", async () => {
319
- testConfig.assistantFeatureFlagValues = {
315
+ _setOverridesForTesting({
320
316
  "feature_flags.inline-skill-commands.enabled": false,
321
- };
317
+ });
322
318
 
323
319
  writeSkill(
324
320
  "flagged-off-skill",
@@ -337,9 +333,9 @@ describe("skill_load inline command expansion", () => {
337
333
  });
338
334
 
339
335
  test("plain skill still loads when flag is off", async () => {
340
- testConfig.assistantFeatureFlagValues = {
336
+ _setOverridesForTesting({
341
337
  "feature_flags.inline-skill-commands.enabled": false,
342
- };
338
+ });
343
339
 
344
340
  writeSkill(
345
341
  "plain-flag-off",
@@ -23,6 +23,8 @@ import { tmpdir } from "node:os";
23
23
  import { join } from "node:path";
24
24
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
25
25
 
26
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
27
+
26
28
  // ── Test directory ────────────────────────────────────────────────────────────
27
29
 
28
30
  const TEST_DIR = mkdtempSync(
@@ -52,9 +54,7 @@ const platformOverrides: Record<string, (...args: unknown[]) => unknown> = {
52
54
  getSessionTokenPath: () => join(TEST_DIR, "session-token"),
53
55
  readSessionToken: () => null,
54
56
  getClipboardCommand: () => null,
55
- readLockfile: () => null,
56
57
  normalizeAssistantId: (id: unknown) => String(id),
57
- writeLockfile: () => {},
58
58
  getEmbeddingModelsDir: () => join(TEST_DIR, "embedding-models"),
59
59
  getTCPPort: () => 8765,
60
60
  isTCPEnabled: () => false,
@@ -129,7 +129,6 @@ interface TestConfig {
129
129
  permissions: { mode: "strict" | "workspace" };
130
130
  skills: { load: { extraDirs: string[] } };
131
131
  sandbox: { enabled: boolean };
132
- assistantFeatureFlagValues?: Record<string, boolean>;
133
132
  [key: string]: unknown;
134
133
  }
135
134
 
@@ -137,9 +136,6 @@ const testConfig: TestConfig = {
137
136
  permissions: { mode: "workspace" },
138
137
  skills: { load: { extraDirs: [] } },
139
138
  sandbox: { enabled: true },
140
- assistantFeatureFlagValues: {
141
- "feature_flags.inline-skill-commands.enabled": true,
142
- },
143
139
  };
144
140
 
145
141
  mock.module("../config/loader.js", () => ({
@@ -225,9 +221,9 @@ describe("skill_load inline command expansion for included skills", () => {
225
221
  }));
226
222
 
227
223
  // Enable the feature flag
228
- testConfig.assistantFeatureFlagValues = {
224
+ _setOverridesForTesting({
229
225
  "feature_flags.inline-skill-commands.enabled": true,
230
- };
226
+ });
231
227
  testConfig.skills = { load: { extraDirs: [] } };
232
228
  });
233
229
 
@@ -575,9 +571,9 @@ describe("skill_load inline command expansion for included skills", () => {
575
571
 
576
572
  describe("feature flag disabled for included skills", () => {
577
573
  test("skill_load returns error when child has inline commands and flag is off", async () => {
578
- testConfig.assistantFeatureFlagValues = {
574
+ _setOverridesForTesting({
579
575
  "feature_flags.inline-skill-commands.enabled": false,
580
- };
576
+ });
581
577
 
582
578
  writeSkill(
583
579
  "child-flag-off",
@@ -38,9 +38,7 @@ const platformOverrides: Record<string, (...args: unknown[]) => unknown> = {
38
38
  getSessionTokenPath: () => join(TEST_DIR, "session-token"),
39
39
  readSessionToken: () => null,
40
40
  getClipboardCommand: () => null,
41
- readLockfile: () => null,
42
41
  normalizeAssistantId: (id: unknown) => String(id),
43
- writeLockfile: () => {},
44
42
  getEmbeddingModelsDir: () => join(TEST_DIR, "embedding-models"),
45
43
  getTCPPort: () => 8765,
46
44
  isTCPEnabled: () => false,