@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -1,11 +1,7 @@
1
1
  // Smoke command (run all security test files together):
2
2
  // bun test src/__tests__/checker.test.ts src/__tests__/conversation-skill-tools.test.ts src/__tests__/skill-script-runner-host.test.ts
3
3
 
4
- import {
5
- mkdirSync,
6
- rmSync,
7
- writeFileSync,
8
- } from "node:fs";
4
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
9
5
  import { homedir } from "node:os";
10
6
  import { join } from "node:path";
11
7
  import {
@@ -20,7 +16,6 @@ import {
20
16
  test,
21
17
  } from "bun:test";
22
18
 
23
-
24
19
  const checkerTestDir = process.env.VELLUM_WORKSPACE_DIR!;
25
20
 
26
21
  // Point the file-based trust backend at the test temp dir.
@@ -376,7 +371,6 @@ describe("Permission Checker", () => {
376
371
  );
377
372
  expect(result.decision).toBe("prompt");
378
373
  });
379
-
380
374
  });
381
375
 
382
376
  // ── skill-origin tool default-ask policy ─────────────────────
@@ -421,7 +415,6 @@ describe("Permission Checker", () => {
421
415
  expect(result.decision).toBe("allow");
422
416
  expect(result.reason).toContain("Low risk");
423
417
  });
424
-
425
418
  });
426
419
 
427
420
  // ── workspace files are auto-allowed (low risk) ──────────────
@@ -489,7 +482,6 @@ describe("Permission Checker", () => {
489
482
  const result = await check("file_write", { path: guardianPath }, "/tmp");
490
483
  expect(result.decision).toBe("allow");
491
484
  });
492
-
493
485
  });
494
486
 
495
487
  // ── generateAllowlistOptions ───────────────────────────────────
@@ -905,7 +897,6 @@ describe("Permission Checker", () => {
905
897
  const result = await check("file_write", { path: hookPath }, "/tmp");
906
898
  expect(result.decision).toBe("prompt");
907
899
  });
908
-
909
900
  });
910
901
 
911
902
  describe("PolicyContext type (PR 3)", () => {
@@ -977,7 +968,6 @@ describe("Permission Checker", () => {
977
968
  expect(result.decision).toBe("prompt");
978
969
  expect(result.reason).toContain("above auto-approve threshold");
979
970
  });
980
-
981
971
  });
982
972
 
983
973
  // ── sandbox auto-approve ──
@@ -1226,7 +1216,6 @@ describe("Permission Checker", () => {
1226
1216
  expect(result.decision).toBe("prompt");
1227
1217
  expect(result.reason).toContain("above auto-approve threshold");
1228
1218
  });
1229
-
1230
1219
  });
1231
1220
 
1232
1221
  // ── skill mutation approval regression tests (PR 30) ──────────
@@ -1243,7 +1232,7 @@ describe("Permission Checker", () => {
1243
1232
  describe("strict mode: skill source writes prompt with high risk", () => {
1244
1233
  test("strict mode: file_write to skill source prompts (no implicit allow)", async () => {
1245
1234
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1246
- _clearGlobalCacheForTesting();
1235
+ _clearGlobalCacheForTesting();
1247
1236
  ensureSkillsDir();
1248
1237
  const skillPath = join(
1249
1238
  checkerTestDir,
@@ -1259,7 +1248,7 @@ describe("Permission Checker", () => {
1259
1248
  test("strict mode: file_edit of skill source prompts (no implicit allow)", async () => {
1260
1249
  mockRisk("high");
1261
1250
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1262
- _clearGlobalCacheForTesting();
1251
+ _clearGlobalCacheForTesting();
1263
1252
  ensureSkillsDir();
1264
1253
  const skillPath = join(
1265
1254
  checkerTestDir,
@@ -1273,7 +1262,7 @@ describe("Permission Checker", () => {
1273
1262
 
1274
1263
  test("strict mode: file_write to non-skill path prompts as Strict mode", async () => {
1275
1264
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1276
- _clearGlobalCacheForTesting();
1265
+ _clearGlobalCacheForTesting();
1277
1266
  const normalPath = "/tmp/some-file.txt";
1278
1267
  const result = await check("file_write", { path: normalPath }, "/tmp");
1279
1268
  expect(result.decision).toBe("prompt");
@@ -1296,7 +1285,7 @@ describe("Permission Checker", () => {
1296
1285
 
1297
1286
  test("strict mode: host_file_write to skill source prompts (high risk overrides host ask)", async () => {
1298
1287
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1299
- _clearGlobalCacheForTesting();
1288
+ _clearGlobalCacheForTesting();
1300
1289
  ensureSkillsDir();
1301
1290
  const skillPath = join(
1302
1291
  checkerTestDir,
@@ -1314,7 +1303,7 @@ describe("Permission Checker", () => {
1314
1303
 
1315
1304
  test("strict mode: host_file_edit of skill source prompts", async () => {
1316
1305
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1317
- _clearGlobalCacheForTesting();
1306
+ _clearGlobalCacheForTesting();
1318
1307
  ensureSkillsDir();
1319
1308
  const skillPath = join(
1320
1309
  checkerTestDir,
@@ -1398,7 +1387,6 @@ describe("Permission Checker", () => {
1398
1387
  expect(options).toHaveLength(1);
1399
1388
  expect(options[0].pattern).toBe("skill_load:*");
1400
1389
  });
1401
-
1402
1390
  });
1403
1391
 
1404
1392
  // ── strict mode: skill_load behavior ──
@@ -1416,7 +1404,6 @@ describe("Permission Checker", () => {
1416
1404
  const result = await check("skill_load", { skill: "any-skill" }, "/tmp");
1417
1405
  expect(result.decision).toBe("allow");
1418
1406
  });
1419
-
1420
1407
  });
1421
1408
 
1422
1409
  // ══════════════════════════════════════════════════════════════════
@@ -1433,7 +1420,7 @@ describe("Permission Checker", () => {
1433
1420
  describe("Invariant 1: strict mode requires explicit matching rule for every tool", () => {
1434
1421
  test("bash prompts in strict mode (no default allow rule outside container)", async () => {
1435
1422
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1436
- _clearGlobalCacheForTesting();
1423
+ _clearGlobalCacheForTesting();
1437
1424
  const result = await check("bash", { command: "echo hello" }, "/tmp");
1438
1425
  expect(result.decision).toBe("prompt");
1439
1426
  expect(result.reason).toContain("above auto-approve threshold");
@@ -1441,7 +1428,7 @@ describe("Permission Checker", () => {
1441
1428
 
1442
1429
  test("low-risk host_bash prompts in strict mode (no matching rule)", async () => {
1443
1430
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1444
- _clearGlobalCacheForTesting();
1431
+ _clearGlobalCacheForTesting();
1445
1432
  const result = await check(
1446
1433
  "host_bash",
1447
1434
  { command: "echo hello" },
@@ -1453,7 +1440,7 @@ describe("Permission Checker", () => {
1453
1440
 
1454
1441
  test("low-risk file_read with no rule prompts in strict mode", async () => {
1455
1442
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1456
- _clearGlobalCacheForTesting();
1443
+ _clearGlobalCacheForTesting();
1457
1444
  const result = await check(
1458
1445
  "file_read",
1459
1446
  { path: "/tmp/test.txt" },
@@ -1465,7 +1452,7 @@ describe("Permission Checker", () => {
1465
1452
 
1466
1453
  test("low-risk skill_load prompts in strict mode without an explicit rule", async () => {
1467
1454
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1468
- _clearGlobalCacheForTesting();
1455
+ _clearGlobalCacheForTesting();
1469
1456
  const result = await check(
1470
1457
  "skill_load",
1471
1458
  { skill: "any-skill" },
@@ -1477,7 +1464,7 @@ describe("Permission Checker", () => {
1477
1464
 
1478
1465
  test("low-risk file_write with no rule prompts in strict mode", async () => {
1479
1466
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1480
- _clearGlobalCacheForTesting();
1467
+ _clearGlobalCacheForTesting();
1481
1468
  const result = await check(
1482
1469
  "file_write",
1483
1470
  { path: "/tmp/file.txt" },
@@ -1490,7 +1477,7 @@ describe("Permission Checker", () => {
1490
1477
  test("high-risk bash prompts in strict mode (no default allow rule outside container)", async () => {
1491
1478
  mockRisk("high");
1492
1479
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1493
- _clearGlobalCacheForTesting();
1480
+ _clearGlobalCacheForTesting();
1494
1481
  const result = await check(
1495
1482
  "bash",
1496
1483
  { command: "sudo apt update" },
@@ -1501,7 +1488,7 @@ describe("Permission Checker", () => {
1501
1488
 
1502
1489
  test("high-risk host_bash command with no user rule prompts in strict mode", async () => {
1503
1490
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1504
- _clearGlobalCacheForTesting();
1491
+ _clearGlobalCacheForTesting();
1505
1492
  const result = await check(
1506
1493
  "host_bash",
1507
1494
  { command: "sudo apt update" },
@@ -1512,19 +1499,18 @@ describe("Permission Checker", () => {
1512
1499
 
1513
1500
  test("skill-origin tool with no rule prompts in strict mode", async () => {
1514
1501
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1515
- _clearGlobalCacheForTesting();
1502
+ _clearGlobalCacheForTesting();
1516
1503
  const result = await check("skill_test_tool", {}, "/tmp");
1517
1504
  expect(result.decision).toBe("prompt");
1518
1505
  });
1519
1506
 
1520
1507
  test("bundled skill-origin tool with no rule prompts in strict mode", async () => {
1521
1508
  mockIpcResponse("get_global_thresholds", STRICT_GATEWAY_THRESHOLDS);
1522
- _clearGlobalCacheForTesting();
1509
+ _clearGlobalCacheForTesting();
1523
1510
  const result = await check("skill_bundled_test_tool", {}, "/tmp");
1524
1511
  expect(result.decision).toBe("prompt");
1525
1512
  expect(result.reason).toContain("above auto-approve threshold");
1526
1513
  });
1527
-
1528
1514
  });
1529
1515
 
1530
1516
  // ── Invariant 4: Host execution approvals — high risk prompts ──
@@ -1532,7 +1518,11 @@ describe("Permission Checker", () => {
1532
1518
  describe("Invariant 4: high-risk host execution always prompts", () => {
1533
1519
  test("host_bash high risk prompts", async () => {
1534
1520
  mockRisk("high");
1535
- const result = await check("host_bash", { command: "sudo rm -rf /" }, "/tmp");
1521
+ const result = await check(
1522
+ "host_bash",
1523
+ { command: "sudo rm -rf /" },
1524
+ "/tmp",
1525
+ );
1536
1526
  expect(result.decision).toBe("prompt");
1537
1527
  });
1538
1528
 
@@ -1555,7 +1545,6 @@ describe("Permission Checker", () => {
1555
1545
  );
1556
1546
  expect(result.decision).toBe("prompt");
1557
1547
  });
1558
-
1559
1548
  });
1560
1549
  });
1561
1550
  });
@@ -1607,7 +1596,6 @@ describe("bash network_mode=proxied — risk capped at medium", () => {
1607
1596
  );
1608
1597
  expect(result.decision).toBe("allow");
1609
1598
  });
1610
-
1611
1599
  });
1612
1600
 
1613
1601
  describe("workspace mode — auto-allow workspace-scoped operations", () => {
@@ -1755,7 +1743,6 @@ describe("workspace mode — auto-allow workspace-scoped operations", () => {
1755
1743
  expect(result.decision).toBe("prompt");
1756
1744
  expect(result.reason).toContain("risk");
1757
1745
  });
1758
-
1759
1746
  });
1760
1747
 
1761
1748
  describe("integration regressions (PR 11)", () => {
@@ -1814,5 +1801,4 @@ describe("integration regressions (PR 11)", () => {
1814
1801
  nonHostScopes.map((s) => s.scope),
1815
1802
  );
1816
1803
  });
1817
-
1818
1804
  });
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Guard test: every `assistant_text_delta` emission in the `/compact` and
3
+ * other slash-command completion paths must carry `conversationId` on the
4
+ * message body.
5
+ *
6
+ * Without this, a long-running compaction can finish after the user has
7
+ * switched conversations, and the macOS client's `belongsToConversation(nil)`
8
+ * check (which accepts nil ids as system events) renders the completion text
9
+ * into whichever VM is currently active — leaking the message into the
10
+ * wrong conversation.
11
+ */
12
+ import { readFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { describe, expect, test } from "bun:test";
15
+
16
+ const SCANNED_FILES = [
17
+ "runtime/routes/conversation-routes.ts",
18
+ "daemon/conversation-process.ts",
19
+ ];
20
+
21
+ describe("compact slash-command emits conversationId on assistant_text_delta", () => {
22
+ for (const relativePath of SCANNED_FILES) {
23
+ test(`${relativePath} tags every assistant_text_delta with conversationId`, () => {
24
+ const fullPath = join(__dirname, "..", relativePath);
25
+ const source = readFileSync(fullPath, "utf-8");
26
+
27
+ // Find every `type: "assistant_text_delta"` literal and inspect the
28
+ // surrounding object literal for a `conversationId` key. Looking at a
29
+ // ~200-char window forward covers multi-line object literals while
30
+ // staying tight enough to avoid matching unrelated nearby code.
31
+ const TYPE_LITERAL = /type:\s*"assistant_text_delta"/g;
32
+ const offsets: number[] = [];
33
+ let match: RegExpExecArray | null;
34
+ while ((match = TYPE_LITERAL.exec(source)) !== null) {
35
+ offsets.push(match.index);
36
+ }
37
+ expect(offsets.length).toBeGreaterThan(0);
38
+
39
+ const violations: string[] = [];
40
+ for (const offset of offsets) {
41
+ const window = source.slice(offset, offset + 200);
42
+ if (!/conversationId/.test(window)) {
43
+ const lineNumber = source.slice(0, offset).split("\n").length;
44
+ violations.push(`${relativePath}:${lineNumber}`);
45
+ }
46
+ }
47
+ expect(violations).toEqual([]);
48
+ });
49
+ }
50
+ });
@@ -87,6 +87,8 @@ mock.module("../config/loader.js", () => ({
87
87
  pricingOverrides: [],
88
88
  },
89
89
  rateLimit: { maxRequestsPerMinute: 0 },
90
+ memory: { v2: { enabled: false } },
91
+ conversations: { skipAutoRetitling: false },
90
92
  timeouts: { permissionTimeoutSec: 1 },
91
93
  skills: { entries: {}, allowBundled: true },
92
94
  permissions: { mode: "workspace" },
@@ -57,10 +57,12 @@ import { invalidateConfigCache, loadConfig } from "../config/loader.js";
57
57
  import {
58
58
  AssistantConfigSchema,
59
59
  DEFAULT_ELEVENLABS_VOICE_ID,
60
- SttServiceSchema,
61
- TtsServiceSchema,
62
- VALID_TTS_SERVICE_PROVIDERS,
63
60
  } from "../config/schema.js";
61
+ import { SttServiceSchema } from "../config/schemas/stt.js";
62
+ import {
63
+ TtsServiceSchema,
64
+ VALID_TTS_PROVIDERS as VALID_TTS_SERVICE_PROVIDERS,
65
+ } from "../config/schemas/tts.js";
64
66
  import type { AssistantConfig } from "../config/types.js";
65
67
  import { _setStorePath } from "../security/encrypted-store.js";
66
68
  import { listCatalogProviderIds } from "../tts/provider-catalog.js";
@@ -126,9 +128,7 @@ describe("AssistantConfigSchema", () => {
126
128
  });
127
129
  expect(result.secretDetection).toEqual({
128
130
  enabled: true,
129
- action: "redact",
130
131
  blockIngress: true,
131
- entropyThreshold: 4.0,
132
132
  allowOneTimeSend: false,
133
133
  });
134
134
  expect(result.auditLog).toEqual({ retentionDays: 0 });
@@ -151,9 +151,7 @@ describe("AssistantConfigSchema", () => {
151
151
  rateLimit: { maxRequestsPerMinute: 10 },
152
152
  secretDetection: {
153
153
  enabled: false,
154
- action: "block" as const,
155
154
  blockIngress: false,
156
- entropyThreshold: 5.5,
157
155
  },
158
156
  auditLog: { retentionDays: 30 },
159
157
  };
@@ -162,7 +160,7 @@ describe("AssistantConfigSchema", () => {
162
160
  expect(result.llm.default.model).toBe("gpt-4");
163
161
  expect(result.llm.default.maxTokens).toBe(4096);
164
162
  expect(result.llm.default.thinking.enabled).toBe(true);
165
- expect(result.secretDetection.action).toBe("block");
163
+ expect(result.secretDetection.enabled).toBe(false);
166
164
  });
167
165
 
168
166
  test("applies llm defaults when llm key is omitted", () => {
@@ -577,24 +575,6 @@ describe("AssistantConfigSchema", () => {
577
575
  }
578
576
  });
579
577
 
580
- test("rejects invalid secretDetection.action", () => {
581
- const result = AssistantConfigSchema.safeParse({
582
- secretDetection: { action: "explode" },
583
- });
584
- expect(result.success).toBe(false);
585
- if (!result.success) {
586
- const msgs = result.error.issues.map((i) => i.message);
587
- expect(msgs.some((m) => m.includes("secretDetection.action"))).toBe(true);
588
- }
589
- });
590
-
591
- test("rejects negative secretDetection.entropyThreshold", () => {
592
- const result = AssistantConfigSchema.safeParse({
593
- secretDetection: { entropyThreshold: -1 },
594
- });
595
- expect(result.success).toBe(false);
596
- });
597
-
598
578
  test("rejects negative rateLimit values", () => {
599
579
  const result = AssistantConfigSchema.safeParse({
600
580
  rateLimit: { maxRequestsPerMinute: -1 },
@@ -641,19 +621,9 @@ describe("AssistantConfigSchema", () => {
641
621
  }
642
622
  });
643
623
 
644
- test("accepts all valid secretDetection.action values", () => {
645
- for (const action of ["redact", "warn", "block"] as const) {
646
- const result = AssistantConfigSchema.safeParse({
647
- secretDetection: { action },
648
- });
649
- expect(result.success).toBe(true);
650
- }
651
- });
652
-
653
624
  test("provides helpful error messages", () => {
654
625
  const result = AssistantConfigSchema.safeParse({
655
626
  llm: { default: { maxTokens: -1 } },
656
- secretDetection: { action: "explode" },
657
627
  });
658
628
  expect(result.success).toBe(false);
659
629
  if (!result.success) {
@@ -665,12 +635,6 @@ describe("AssistantConfigSchema", () => {
665
635
  (m) => m.includes("positive") || /expected number to be >0/i.test(m),
666
636
  ),
667
637
  ).toBe(true);
668
- expect(
669
- messages.some(
670
- (m) =>
671
- m.includes("redact") && m.includes("warn") && m.includes("block"),
672
- ),
673
- ).toBe(true);
674
638
  }
675
639
  });
676
640
 
@@ -2179,12 +2143,6 @@ describe("loadConfig with schema validation", () => {
2179
2143
  expect(config.timeouts.permissionTimeoutSec).toBe(300);
2180
2144
  });
2181
2145
 
2182
- test("falls back for invalid secretDetection.action", () => {
2183
- writeConfig({ secretDetection: { action: "explode" } });
2184
- const config = loadConfig();
2185
- expect(config.secretDetection.action).toBe("redact");
2186
- });
2187
-
2188
2146
  test("falls back for invalid contextWindow relationship", () => {
2189
2147
  writeConfig({
2190
2148
  llm: {
@@ -73,6 +73,7 @@ mock.module("../config/loader.js", () => ({
73
73
  getConfig: () => ({
74
74
  ui: {},
75
75
  }),
76
+ loadConfig: () => ({ ui: {} }),
76
77
  invalidateConfigCache: () => {},
77
78
  }));
78
79
 
@@ -85,6 +86,9 @@ mock.module("../permissions/trust-store.js", () => ({
85
86
  }));
86
87
 
87
88
  mock.module("../providers/registry.js", () => ({
89
+ getProvider: () => undefined,
90
+ listProviders: () => [],
91
+ getProviderRoutingSource: () => undefined,
88
92
  initializeProviders: () => {},
89
93
  }));
90
94
 
@@ -96,6 +100,14 @@ mock.module("../signals/conversation-undo.js", () => ({
96
100
  handleConversationUndoSignal: () => {},
97
101
  }));
98
102
 
103
+ mock.module("../signals/user-message.js", () => ({
104
+ handleUserMessageSignal: async () => {},
105
+ }));
106
+
107
+ mock.module("../signals/cancel.js", () => ({
108
+ handleCancelSignal: () => {},
109
+ }));
110
+
99
111
  // Import after mocks are set up
100
112
  const { ConfigWatcher } = await import("../daemon/config-watcher.js");
101
113
 
@@ -1,57 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
- import {
4
- hasNoAuthOverride,
5
- shouldAutoStartDaemon,
6
- } from "../daemon/connection-policy.js";
7
-
8
- describe("hasNoAuthOverride", () => {
9
- test("returns false when VELLUM_DAEMON_NOAUTH is not set", () => {
10
- expect(hasNoAuthOverride({})).toBe(false);
11
- });
12
-
13
- test("returns false when VELLUM_DAEMON_NOAUTH is empty", () => {
14
- expect(hasNoAuthOverride({ VELLUM_DAEMON_NOAUTH: "" })).toBe(false);
15
- });
16
-
17
- test("returns false when VELLUM_DAEMON_NOAUTH is whitespace", () => {
18
- expect(hasNoAuthOverride({ VELLUM_DAEMON_NOAUTH: " " })).toBe(false);
19
- });
20
-
21
- test("returns false when VELLUM_DAEMON_NOAUTH is 0", () => {
22
- expect(hasNoAuthOverride({ VELLUM_DAEMON_NOAUTH: "0" })).toBe(false);
23
- });
24
-
25
- test("returns false when VELLUM_DAEMON_NOAUTH is false", () => {
26
- expect(hasNoAuthOverride({ VELLUM_DAEMON_NOAUTH: "false" })).toBe(false);
27
- });
28
-
29
- test("returns true when VELLUM_DAEMON_NOAUTH is 1 with safety gate", () => {
30
- expect(
31
- hasNoAuthOverride({
32
- VELLUM_DAEMON_NOAUTH: "1",
33
- VELLUM_UNSAFE_AUTH_BYPASS: "1",
34
- }),
35
- ).toBe(true);
36
- });
37
-
38
- test("returns false when VELLUM_DAEMON_NOAUTH is 1 without safety gate", () => {
39
- expect(hasNoAuthOverride({ VELLUM_DAEMON_NOAUTH: "1" })).toBe(false);
40
- });
41
-
42
- test("returns true when VELLUM_DAEMON_NOAUTH is true with safety gate", () => {
43
- expect(
44
- hasNoAuthOverride({
45
- VELLUM_DAEMON_NOAUTH: "true",
46
- VELLUM_UNSAFE_AUTH_BYPASS: "1",
47
- }),
48
- ).toBe(true);
49
- });
50
-
51
- test("returns false when VELLUM_DAEMON_NOAUTH is true without safety gate", () => {
52
- expect(hasNoAuthOverride({ VELLUM_DAEMON_NOAUTH: "true" })).toBe(false);
53
- });
54
- });
3
+ import { shouldAutoStartDaemon } from "../daemon/connection-policy.js";
55
4
 
56
5
  describe("shouldAutoStartDaemon", () => {
57
6
  test("returns true by default (no env vars set)", () => {
@@ -8,7 +8,7 @@
8
8
  * writes land under that temp dir and are cleaned up automatically.
9
9
  */
10
10
 
11
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
11
+ import { existsSync } from "node:fs";
12
12
  import { join } from "node:path";
13
13
  import { beforeEach, describe, expect, mock, test } from "bun:test";
14
14
 
@@ -19,10 +19,7 @@ mock.module("../util/logger.js", () => ({
19
19
  }),
20
20
  }));
21
21
 
22
- import {
23
- createGuardianBinding,
24
- upsertContactChannel,
25
- } from "../contacts/contacts-write.js";
22
+ import { upsertContactChannel } from "../contacts/contacts-write.js";
26
23
  import { getSqlite } from "../memory/db-connection.js";
27
24
  import { initializeDb } from "../memory/db-init.js";
28
25
  initializeDb();
@@ -47,65 +44,6 @@ function userFilePath(slug: string): string {
47
44
  return join(workspaceDir(), "users", slug);
48
45
  }
49
46
 
50
- describe("createGuardianBinding seeds users/<slug>.md", () => {
51
- beforeEach(() => {
52
- resetContactTables();
53
- });
54
-
55
- test("writes the persona template scaffold on first creation", () => {
56
- createGuardianBinding({
57
- channel: "telegram",
58
- guardianExternalUserId: "Chris",
59
- guardianDeliveryChatId: "chat-chris",
60
- guardianPrincipalId: "principal-chris",
61
- verifiedVia: "challenge",
62
- });
63
-
64
- const expectedPath = userFilePath("chris.md");
65
- expect(existsSync(expectedPath)).toBe(true);
66
-
67
- const content = readFileSync(expectedPath, "utf-8");
68
- expect(content).toContain("# User Profile");
69
- expect(content).toContain("Preferred name/reference:");
70
- expect(content).toContain("Daily tools:");
71
- // Template comment-line prefix survives verbatim.
72
- expect(content.startsWith("_ Lines starting with _ are comments")).toBe(
73
- true,
74
- );
75
- });
76
-
77
- test("does not clobber a pre-existing customized users/<slug>.md", () => {
78
- // First creation seeds the scaffold.
79
- createGuardianBinding({
80
- channel: "telegram",
81
- guardianExternalUserId: "Alice",
82
- guardianDeliveryChatId: "chat-alice",
83
- guardianPrincipalId: "principal-alice",
84
- verifiedVia: "challenge",
85
- });
86
-
87
- const expectedPath = userFilePath("alice.md");
88
- expect(existsSync(expectedPath)).toBe(true);
89
-
90
- // User customizes the file manually.
91
- const customContent = "# Alice's Profile\n\n- Loves kayaking\n";
92
- writeFileSync(expectedPath, customContent, "utf-8");
93
-
94
- // Re-running createGuardianBinding (idempotent re-verification) must
95
- // not overwrite the user's edits.
96
- createGuardianBinding({
97
- channel: "telegram",
98
- guardianExternalUserId: "Alice",
99
- guardianDeliveryChatId: "chat-alice",
100
- guardianPrincipalId: "principal-alice",
101
- verifiedVia: "challenge",
102
- });
103
-
104
- const afterContent = readFileSync(expectedPath, "utf-8");
105
- expect(afterContent).toBe(customContent);
106
- });
107
- });
108
-
109
47
  // Invariant: `upsertContactChannel` must not seed `users/<slug>.md`. Seeding
110
48
  // there fires the users/ directory watcher on every inbound message
111
49
  // from a new contact and evicts live conversations. Seeding is
@@ -321,7 +321,7 @@ describe("parseImageDimensions", () => {
321
321
  const pngPath = join(
322
322
  import.meta.dir,
323
323
  "../../..",
324
- "clients/chrome-extension/icons/icon16.png",
324
+ "clients/chrome-extension/icons/production/icon16.png",
325
325
  );
326
326
  const pngData = readFileSync(pngPath);
327
327
  const base64 = pngData.toString("base64");