@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2

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 (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -9,17 +9,23 @@
9
9
  */
10
10
  import { z } from "zod";
11
11
 
12
+ import type { ChannelId } from "../../channels/types.js";
12
13
  import { isHttpAuthDisabled } from "../../config/env.js";
13
- import type { TrustContext } from "../../daemon/trust-context.js";
14
+ import { findGuardianForChannel } from "../../contacts/contact-store.js";
14
15
  import { getLogger } from "../../util/logger.js";
16
+ import type { TrustClass } from "../actor-trust-resolver.js";
17
+ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
15
18
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
16
19
  import { processGuardianDecision } from "../guardian-action-service.js";
17
- import { reResolveTrustOnResetDrift } from "../guardian-vellum-migration.js";
20
+ import { healGuardianBindingDrift } from "../guardian-vellum-migration.js";
18
21
  import {
19
- findLocalGuardianPrincipalId,
20
22
  resolveActorPrincipalIdForLocalGuardian,
23
+ resolveLocalTrustContext,
21
24
  } from "../local-actor-identity.js";
22
- import { resolveLocalPrincipalTrustContext } from "../local-principal-trust.js";
25
+ import {
26
+ resolveTrustContext,
27
+ withSourceChannel,
28
+ } from "../trust-context-resolver.js";
23
29
  import { parseCallbackData } from "./channel-route-shared.js";
24
30
  import {
25
31
  BadRequestError,
@@ -37,51 +43,58 @@ const log = getLogger("surface-action-routes");
37
43
  // ---------------------------------------------------------------------------
38
44
 
39
45
  /**
40
- * Resolve trust context for the actor principal from the gateway guardian
41
- * binding and set it on the conversation. A vellum principal is the guardian or
42
- * nobody, so the mapper yields guardian or unknown.
46
+ * Resolve trust context from the actor principal ID and set it on the
47
+ * conversation, following the same pattern as POST /v1/messages. This ensures
48
+ * surface actions inherit the correct trust class (guardian vs trusted_contact)
49
+ * rather than defaulting to unknown.
43
50
  */
44
- async function applyTrustContext(
51
+ function applyTrustContext(
45
52
  conversation: {
46
- setTrustContext?(ctx: TrustContext): void;
53
+ setTrustContext?(ctx: {
54
+ trustClass: TrustClass;
55
+ sourceChannel: ChannelId;
56
+ }): void;
47
57
  },
48
58
  actorPrincipalId: string | undefined,
49
- ): Promise<void> {
59
+ ): void {
50
60
  if (!conversation.setTrustContext) return;
51
61
 
52
62
  const sourceChannel = "vellum";
53
63
 
54
- if (!actorPrincipalId) {
55
- conversation.setTrustContext({ trustClass: "guardian", sourceChannel });
56
- return;
57
- }
58
-
59
- // Dev-bypass injects a synthetic principal that won't match the real
60
- // guardian binding, so resolve the actual guardian principalId (gateway
61
- // first, local store fallback) before mapping trust.
62
- let principalId = actorPrincipalId;
63
- if (isHttpAuthDisabled() && actorPrincipalId === "dev-bypass") {
64
- principalId = (await findLocalGuardianPrincipalId()) ?? actorPrincipalId;
65
- }
66
-
67
- let trustCtx = await resolveLocalPrincipalTrustContext({
68
- actorPrincipalId: principalId,
69
- sourceChannel,
70
- conversationExternalId: "local",
71
- });
72
- if (trustCtx.trustClass === "unknown") {
73
- const healed = await reResolveTrustOnResetDrift(principalId, sourceChannel);
74
- if (healed) {
75
- trustCtx = healed;
76
- if (healed.trustClass !== "unknown") {
77
- log.info(
78
- { actorPrincipalId: principalId, trustClass: trustCtx.trustClass },
79
- "Trust re-resolved from local mirror after gateway reset drift (surface action)",
80
- );
64
+ if (actorPrincipalId) {
65
+ if (isHttpAuthDisabled() && actorPrincipalId === "dev-bypass") {
66
+ conversation.setTrustContext(resolveLocalTrustContext(sourceChannel));
67
+ } else {
68
+ const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
69
+ let trustCtx = resolveTrustContext({
70
+ assistantId,
71
+ sourceChannel,
72
+ conversationExternalId: "local",
73
+ actorExternalId: actorPrincipalId,
74
+ });
75
+ if (trustCtx.trustClass === "unknown") {
76
+ const healed = healGuardianBindingDrift(actorPrincipalId);
77
+ if (healed) {
78
+ trustCtx = resolveTrustContext({
79
+ assistantId,
80
+ sourceChannel,
81
+ conversationExternalId: "local",
82
+ actorExternalId: actorPrincipalId,
83
+ });
84
+ log.info(
85
+ {
86
+ actorPrincipalId,
87
+ trustClass: trustCtx.trustClass,
88
+ },
89
+ "Trust re-resolved after guardian binding drift heal (surface action)",
90
+ );
91
+ }
81
92
  }
93
+ conversation.setTrustContext(withSourceChannel(sourceChannel, trustCtx));
82
94
  }
95
+ } else {
96
+ conversation.setTrustContext({ trustClass: "guardian", sourceChannel });
83
97
  }
84
- conversation.setTrustContext(trustCtx);
85
98
  }
86
99
 
87
100
  // ---------------------------------------------------------------------------
@@ -119,15 +132,16 @@ async function handleSurfaceAction({
119
132
  const aprDecision = parseCallbackData(actionId, "vellum");
120
133
  if (aprDecision) {
121
134
  // Resolve the actor's guardian principal ID. In dev mode the synthetic
122
- // "dev-bypass" principal won't match the real guardian binding, so resolve
123
- // the local guardian principal — mirrors guardian-action-routes.ts.
135
+ // "dev-bypass" principal won't match the real guardian binding, so fall
136
+ // back to the local guardian binding — mirrors guardian-action-routes.ts.
124
137
  let guardianPrincipalId: string | undefined =
125
138
  headers?.["x-vellum-actor-principal-id"] ?? undefined;
126
139
  if (
127
140
  isHttpAuthDisabled() &&
128
141
  headers?.["x-vellum-actor-principal-id"] === "dev-bypass"
129
142
  ) {
130
- guardianPrincipalId = (await findLocalGuardianPrincipalId()) ?? undefined;
143
+ const binding = findGuardianForChannel("vellum");
144
+ guardianPrincipalId = binding?.contact.principalId ?? undefined;
131
145
  }
132
146
 
133
147
  const result = await processGuardianDecision({
@@ -175,7 +189,7 @@ async function handleSurfaceAction({
175
189
  }
176
190
 
177
191
  const actorPrincipalId = headers?.["x-vellum-actor-principal-id"];
178
- await applyTrustContext(conversation, actorPrincipalId);
192
+ applyTrustContext(conversation, actorPrincipalId);
179
193
 
180
194
  // Translate dev-bypass → real guardian so the surface turn's principal matches
181
195
  // the SSE host-proxy client's registered principal; otherwise CU/app-control
@@ -48,7 +48,6 @@ function makeConversationRow(
48
48
  inferenceProfileSessionId: null,
49
49
  inferenceProfileExpiresAt: null,
50
50
  lastNotifiedInferenceProfile: null,
51
- processingStartedAt: null,
52
51
  ...overrides,
53
52
  };
54
53
  }
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { parseChannelId } from "../../channels/types.js";
11
11
  import { getConfig } from "../../config/loader.js";
12
+ import { findConversation } from "../../daemon/conversation-registry.js";
12
13
  import { normalizeConversationType } from "../../daemon/message-types/shared.js";
13
14
  import {
14
15
  type AttentionState,
@@ -20,7 +21,6 @@ import {
20
21
  type ConversationRow,
21
22
  getConversation,
22
23
  getDisplayMetaForConversations,
23
- isConversationProcessing,
24
24
  } from "../../memory/conversation-crud.js";
25
25
  import type { ExternalConversationBinding } from "../../memory/external-conversation-store.js";
26
26
  import { getBindingsForConversations } from "../../memory/external-conversation-store.js";
@@ -196,9 +196,9 @@ export function serializeConversationSummary(params: {
196
196
  parentCache: Map<string, ConversationRow | null>;
197
197
  /**
198
198
  * Whether the agent loop is currently mid-turn for this conversation.
199
- * Resolved by `isConversationProcessing(id)`, which checks the in-memory
200
- * daemon flag first and falls back to the persisted
201
- * `processing_started_at` column for cold conversations. Plumbed in
199
+ * Sourced from the in-memory daemon `Conversation.isProcessing()` flag
200
+ * callers resolve via `findConversation(id)?.isProcessing() ?? false`
201
+ * so cold (evicted / never-loaded) rows report `false`. Plumbed in
202
202
  * rather than read here so the serializer stays a pure shape mapper
203
203
  * with no daemon-store coupling.
204
204
  */
@@ -286,9 +286,11 @@ export function buildConversationDetailResponse(
286
286
  attentionState: attentionStates.get(conversation.id),
287
287
  displayMeta: displayMeta.get(conversation.id),
288
288
  parentCache,
289
- // Checks in-memory flag first (hot path), falls back to the
290
- // persisted `processing_started_at` column for cold conversations.
291
- isProcessing: isConversationProcessing(conversation.id),
289
+ // Cold (evicted / never-loaded) rows aren't in the in-memory
290
+ // store, so `findConversation` returns `undefined` and they
291
+ // report `isProcessing: false` — by definition they aren't
292
+ // mid-turn since the agent loop only runs on resident convs.
293
+ isProcessing: findConversation(conversation.id)?.isProcessing() ?? false,
292
294
  }),
293
295
  };
294
296
  }
@@ -59,9 +59,9 @@ export type ToolGrantRequestResult =
59
59
  * Returns a result indicating whether a new request was created, an existing
60
60
  * one was deduped, or the escalation failed (no binding, missing identity).
61
61
  */
62
- export async function createOrReuseToolGrantRequest(
62
+ export function createOrReuseToolGrantRequest(
63
63
  params: ToolGrantRequestParams,
64
- ): Promise<ToolGrantRequestResult> {
64
+ ): ToolGrantRequestResult {
65
65
  const {
66
66
  assistantId,
67
67
  sourceChannel,
@@ -78,7 +78,7 @@ export async function createOrReuseToolGrantRequest(
78
78
  return { failed: true, reason: "missing_identity" };
79
79
  }
80
80
 
81
- const binding = await getGuardianBinding(assistantId, sourceChannel);
81
+ const binding = getGuardianBinding(assistantId, sourceChannel);
82
82
  if (!binding) {
83
83
  log.debug(
84
84
  { sourceChannel, assistantId },
@@ -33,17 +33,16 @@ export interface TrustVerdictTransport {
33
33
  }
34
34
 
35
35
  /**
36
- * Reassemble an {@link ActorTrustContext} from a gateway verdict + transport
37
- * identity (mirroring `resolveActorTrust`), without any local DB/IPC reads.
36
+ * Build a {@link TrustContext} from a gateway verdict + transport identity.
38
37
  *
39
- * Pure: the voice path consumes this directly for routing on
40
- * `actorTrust.trustClass`; {@link trustContextFromVerdict} routes it through
41
- * {@link toTrustContext}.
38
+ * Reassembles an {@link ActorTrustContext} (mirroring `resolveActorTrust`) and
39
+ * routes it through {@link toTrustContext}, so the output is byte-identical to
40
+ * the local resolution path.
42
41
  */
43
- export function actorTrustContextFromVerdict(
42
+ export function trustContextFromVerdict(
44
43
  verdict: TrustVerdict,
45
44
  input: TrustVerdictTransport,
46
- ): ActorTrustContext {
45
+ ): TrustContext {
47
46
  const canonicalSenderId = verdict.canonicalSenderId;
48
47
  const memberDisplayName = verdict.memberDisplayName;
49
48
  const senderDisplayName = input.actorDisplayName;
@@ -52,7 +51,7 @@ export function actorTrustContextFromVerdict(
52
51
  ? `@${username}`
53
52
  : (canonicalSenderId ?? undefined);
54
53
 
55
- return {
54
+ const actorTrustContext: ActorTrustContext = {
56
55
  canonicalSenderId,
57
56
  guardianBindingMatch: verdict.guardianExternalUserId
58
57
  ? {
@@ -61,12 +60,7 @@ export function actorTrustContextFromVerdict(
61
60
  }
62
61
  : null,
63
62
  guardianPrincipalId: verdict.guardianPrincipalId,
64
- // Populate from the verdict so the voice path's ACL gates (which read
65
- // actorTrust.memberRecord.channel status/policy) enforce blocked/revoked/
66
- // deny/escalate. Null for memberless verdicts. Text path is unaffected:
67
- // toTrustContext derives the same member fields trustContextFromVerdict
68
- // already stamps.
69
- memberRecord: resolvedMemberFromVerdict(verdict),
63
+ memberRecord: null,
70
64
  trustClass: verdict.trustClass,
71
65
  actorMetadata: {
72
66
  identifier,
@@ -78,21 +72,9 @@ export function actorTrustContextFromVerdict(
78
72
  trustStatus: verdict.trustClass,
79
73
  },
80
74
  };
81
- }
82
75
 
83
- /**
84
- * Build a {@link TrustContext} from a gateway verdict + transport identity.
85
- *
86
- * Reassembles an {@link ActorTrustContext} (mirroring `resolveActorTrust`) and
87
- * routes it through {@link toTrustContext}, so the output is byte-identical to
88
- * the local resolution path.
89
- */
90
- export function trustContextFromVerdict(
91
- verdict: TrustVerdict,
92
- input: TrustVerdictTransport,
93
- ): TrustContext {
94
76
  const context = toTrustContext(
95
- actorTrustContextFromVerdict(verdict, input),
77
+ actorTrustContext,
96
78
  input.conversationExternalId,
97
79
  );
98
80
 
@@ -109,26 +91,6 @@ export function trustContextFromVerdict(
109
91
  return context;
110
92
  }
111
93
 
112
- /**
113
- * True when the verdict carries a member identity (contactId or channelId),
114
- * regardless of whether that member resolves to a usable {@link ResolvedMember}.
115
- */
116
- export function verdictHasMemberIdentity(verdict: TrustVerdict): boolean {
117
- return !!(verdict.contactId || verdict.channelId);
118
- }
119
-
120
- /**
121
- * True when the verdict claims a member identity but that member can't be
122
- * synthesized (partial/mixed-version verdict). Such a verdict is unusable —
123
- * callers fall back to local resolution.
124
- */
125
- export function verdictMemberUnresolvable(verdict: TrustVerdict): boolean {
126
- return (
127
- verdictHasMemberIdentity(verdict) &&
128
- resolvedMemberFromVerdict(verdict) === null
129
- );
130
- }
131
-
132
94
  // Allowed ACL enum values, kept in sync with the ContactChannel union types.
133
95
  const CHANNEL_STATUS_VALUES: readonly ChannelStatus[] = [
134
96
  "active",
@@ -151,44 +113,6 @@ function isChannelPolicy(value: string): value is ChannelPolicy {
151
113
  return (CHANNEL_POLICY_VALUES as readonly string[]).includes(value);
152
114
  }
153
115
 
154
- /**
155
- * The ACL fields a gateway verdict carries for a resolved member, decoupled
156
- * from the schema-derived {@link ContactChannel}.
157
- */
158
- export interface VerdictMember {
159
- contactId: string;
160
- channelId: string;
161
- status: ChannelStatus;
162
- policy: ChannelPolicy;
163
- verifiedAt: number | null;
164
- displayName: string | null;
165
- }
166
-
167
- /**
168
- * Extract the narrow {@link VerdictMember} ACL view from a gateway verdict.
169
- *
170
- * Mirrors {@link resolvedMemberFromVerdict}'s guards (contactId/channelId
171
- * present + known status/policy enums), failing closed to null otherwise.
172
- */
173
- export function verdictMemberFromVerdict(
174
- verdict: TrustVerdict,
175
- ): VerdictMember | null {
176
- if (!verdict.contactId || !verdict.channelId) return null;
177
- if (!verdict.status || !verdict.policy) return null;
178
- if (!isChannelStatus(verdict.status) || !isChannelPolicy(verdict.policy)) {
179
- return null;
180
- }
181
-
182
- return {
183
- contactId: verdict.contactId,
184
- channelId: verdict.channelId,
185
- status: verdict.status,
186
- policy: verdict.policy,
187
- verifiedAt: verdict.verifiedAt ?? null,
188
- displayName: verdict.memberDisplayName ?? null,
189
- };
190
- }
191
-
192
116
  /**
193
117
  * Build a synthetic {@link ResolvedMember} from a gateway verdict.
194
118
  *
@@ -21,7 +21,7 @@ import {
21
21
  countRecentSendsToDestination,
22
22
  createOutboundSession,
23
23
  findActiveSession,
24
- isGuardianBoundForChannel,
24
+ getGuardianBinding,
25
25
  updateSessionDelivery,
26
26
  updateSessionStatus,
27
27
  } from "./channel-verification-service.js";
@@ -224,7 +224,7 @@ export async function startOutbound(
224
224
  originConversationId,
225
225
  );
226
226
  } else if (channel === "phone") {
227
- return await startOutboundVoice(
227
+ return startOutboundVoice(
228
228
  params.destination,
229
229
  assistantId,
230
230
  channel,
@@ -232,7 +232,7 @@ export async function startOutbound(
232
232
  originConversationId,
233
233
  );
234
234
  } else if (channel === "slack") {
235
- return await startOutboundSlack(
235
+ return startOutboundSlack(
236
236
  params.destination,
237
237
  assistantId,
238
238
  channel,
@@ -240,7 +240,7 @@ export async function startOutbound(
240
240
  originConversationId,
241
241
  );
242
242
  } else if (channel === "email") {
243
- return await startOutboundEmail(
243
+ return startOutboundEmail(
244
244
  params.destination,
245
245
  assistantId,
246
246
  channel,
@@ -274,8 +274,8 @@ async function startOutboundTelegram(
274
274
  };
275
275
  }
276
276
 
277
- const alreadyBound = await isGuardianBoundForChannel(channel);
278
- if (alreadyBound && !rebind) {
277
+ const existingBinding = getGuardianBinding(assistantId, channel);
278
+ if (existingBinding && !rebind) {
279
279
  return {
280
280
  success: false,
281
281
  error: "already_bound",
@@ -394,13 +394,13 @@ async function startOutboundTelegram(
394
394
  };
395
395
  }
396
396
 
397
- async function startOutboundVoice(
397
+ function startOutboundVoice(
398
398
  rawDestination: string | undefined,
399
399
  assistantId: string,
400
400
  channel: ChannelId,
401
401
  rebind?: boolean,
402
402
  originConversationId?: string,
403
- ): Promise<OutboundActionResult> {
403
+ ): OutboundActionResult {
404
404
  if (!rawDestination) {
405
405
  return {
406
406
  success: false,
@@ -422,8 +422,8 @@ async function startOutboundVoice(
422
422
  };
423
423
  }
424
424
 
425
- const alreadyBound = await isGuardianBoundForChannel(channel);
426
- if (alreadyBound && !rebind) {
425
+ const existingBinding = getGuardianBinding(assistantId, channel);
426
+ if (existingBinding && !rebind) {
427
427
  return {
428
428
  success: false,
429
429
  error: "already_bound",
@@ -591,13 +591,13 @@ export function deliverVerificationEmail(
591
591
  })();
592
592
  }
593
593
 
594
- async function startOutboundSlack(
594
+ function startOutboundSlack(
595
595
  destination: string | undefined,
596
596
  assistantId: string,
597
597
  channel: ChannelId,
598
598
  rebind?: boolean,
599
599
  originConversationId?: string,
600
- ): Promise<OutboundActionResult> {
600
+ ): OutboundActionResult {
601
601
  if (!destination) {
602
602
  return {
603
603
  success: false,
@@ -607,8 +607,8 @@ async function startOutboundSlack(
607
607
  };
608
608
  }
609
609
 
610
- const alreadyBound = await isGuardianBoundForChannel(channel);
611
- if (alreadyBound && !rebind) {
610
+ const existingBinding = getGuardianBinding(assistantId, channel);
611
+ if (existingBinding && !rebind) {
612
612
  return {
613
613
  success: false,
614
614
  error: "already_bound",
@@ -669,13 +669,13 @@ async function startOutboundSlack(
669
669
  };
670
670
  }
671
671
 
672
- async function startOutboundEmail(
672
+ function startOutboundEmail(
673
673
  destination: string | undefined,
674
674
  assistantId: string,
675
675
  channel: ChannelId,
676
676
  rebind?: boolean,
677
677
  originConversationId?: string,
678
- ): Promise<OutboundActionResult> {
678
+ ): OutboundActionResult {
679
679
  if (!destination) {
680
680
  return {
681
681
  success: false,
@@ -688,8 +688,8 @@ async function startOutboundEmail(
688
688
 
689
689
  const normalizedEmail = destination.trim().toLowerCase();
690
690
 
691
- const alreadyBound = await isGuardianBoundForChannel(channel);
692
- if (alreadyBound && !rebind) {
691
+ const existingBinding = getGuardianBinding(assistantId, channel);
692
+ if (existingBinding && !rebind) {
693
693
  return {
694
694
  success: false,
695
695
  error: "already_bound",
@@ -15,7 +15,6 @@ import { readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
15
15
  import { join } from "node:path";
16
16
 
17
17
  import { getOrCreateConversation } from "../daemon/conversation-store.js";
18
- import { supersedePendingInteractionsOnEnqueue } from "../daemon/handlers/conversations.js";
19
18
  import type { UserMessageAttachment } from "../daemon/message-types/shared.js";
20
19
  import {
21
20
  processMessageInBackground,
@@ -132,21 +131,6 @@ async function dispatchUserMessage(params: {
132
131
  assistantMessageInterface: resolvedInterface,
133
132
  },
134
133
  });
135
- if (!result.rejected) {
136
- // Mirror the HTTP send path: a follow-up enqueued while the turn is busy
137
- // auto-denies pending confirmations and supersedes a parked ask_question
138
- // so it isn't stranded behind the prompt until the response backstop.
139
- // Best-effort — the message is already queued, so a cleanup failure must
140
- // not surface as an error that makes the CLI retry and enqueue a duplicate.
141
- try {
142
- supersedePendingInteractionsOnEnqueue(conversationId, requestId);
143
- } catch (err) {
144
- log.warn(
145
- { err, conversationId },
146
- "Post-enqueue supersession failed — queued message unaffected",
147
- );
148
- }
149
- }
150
134
  return { accepted: !result.rejected };
151
135
  }
152
136
 
@@ -553,15 +553,6 @@ export class SubagentManager {
553
553
  ),
554
554
  );
555
555
  managed.state.completedAt = Date.now();
556
- // Capture the conversation's latest usage before emitting the terminal
557
- // status. `subagent_status_changed` ships `state.usage`, and the abort path
558
- // (unlike the completion/failure paths, which sync at agent-loop exit) would
559
- // otherwise send the {0,0,0} init usage — zeroing the client's token counts
560
- // even though those tokens were already spent. `usageStats` accrues per LLM
561
- // turn (see conversation-usage.ts), so this is the most recent total.
562
- if (managed.conversation) {
563
- managed.state.usage = { ...managed.conversation.usageStats };
564
- }
565
556
  if (parentSendToClient) {
566
557
  // Route the status update through the stored parent sender so the
567
558
  // owning conversation's UI chip updates, even when the abort comes from a
@@ -180,7 +180,7 @@ export const SUBAGENT_ROLE_REGISTRY: Record<SubagentRole, SubagentRoleConfig> =
180
180
  },
181
181
  investigator: {
182
182
  allowedTools: [
183
- "code_search",
183
+ "bash",
184
184
  "file_read",
185
185
  "file_list",
186
186
  "web_search",
@@ -191,8 +191,8 @@ export const SUBAGENT_ROLE_REGISTRY: Record<SubagentRole, SubagentRoleConfig> =
191
191
  skillIds: [],
192
192
  systemPromptPreamble: [
193
193
  "You are an investigation-focused subagent for root-cause analysis: debugging, log forensics, and tracing behavior across code.",
194
- "You have read-only investigation tools only — there is no shell. Use code_search to search file contents across directories, file_list to enumerate paths, and file_read to read whole files and logs. You cannot modify files or system state.",
195
- "Working method: read whole files instead of many small line-range slices; prefer broad code_search queries across a directory over one-symbol-at-a-time queries.",
194
+ "Your shell access is for read-only investigation (grep, find, reading files and logs) do not modify files or system state.",
195
+ "Working method: read whole files instead of many small line-range slices; prefer broad searches (e.g. grep -rn across a directory) over one-symbol-at-a-time queries.",
196
196
  "Send notify_parent (urgency 'important') as soon as each finding is confirmed, so progress survives interruption.",
197
197
  "Your final message must be a compact root-cause report with these sections: Symptom, Root cause, Evidence (file:line references), Suggested fix, Open questions.",
198
198
  "If you approach context limits, stop investigating and produce the report from what you have — a partial report delivered is worth more than a complete investigation lost.",
@@ -391,38 +391,6 @@ export interface SkillLoadedTelemetryEvent extends ModelTelemetryEventBase {
391
391
  conversation_id: string | null;
392
392
  }
393
393
 
394
- /**
395
- * Watchdog health event — one per watchdog check firing. The daemon's
396
- * watchdog observes liveness/health signals (event-loop block, stream-idle
397
- * stalls, restarts, ...) and emits one event per check firing.
398
- *
399
- * Deliberately minimal and forward-compatible, mirroring the platform
400
- * `WatchdogTelemetryEventSerializer`:
401
- *
402
- * - `check_name` — which watchdog check fired. Open string set (not a
403
- * closed enum) so the daemon can introduce a new check without a
404
- * coordinated serializer release; it is the primary group-by dimension
405
- * downstream. The infrastructure admin chart filters this to
406
- * `event_loop_blocked`.
407
- * - `value` — the single measured magnitude for the check (block ms, idle
408
- * ms, ...). Nullable: not every check carries a scalar. The platform
409
- * coerces ints to float, so the daemon need not distinguish.
410
- * - `detail` — open JSON bag for any extra fields the daemon attaches
411
- * (reason codes, secondary numbers, a human message) without a
412
- * platform-coordinated schema change. Null when the daemon attaches
413
- * nothing. Bounded server-side (4096 bytes serialized); an oversize bag
414
- * rejects only the single event, never the batch.
415
- *
416
- * Metadata only — no conversation content. Dedupe downstream on
417
- * `daemon_event_id` (the daemon retries a batch on transient POST failure).
418
- */
419
- export interface WatchdogTelemetryEvent extends TelemetryEventBase {
420
- type: "watchdog";
421
- check_name: string;
422
- value: number | null;
423
- detail: Record<string, unknown> | null;
424
- }
425
-
426
394
  /** Discriminated union of all telemetry event types. */
427
395
  export type TelemetryEvent =
428
396
  | LlmUsageTelemetryEvent
@@ -431,5 +399,4 @@ export type TelemetryEvent =
431
399
  | OnboardingTelemetryEvent
432
400
  | AuthFallbackTelemetryEvent
433
401
  | ToolExecutedTelemetryEvent
434
- | SkillLoadedTelemetryEvent
435
- | WatchdogTelemetryEvent;
402
+ | SkillLoadedTelemetryEvent;
@@ -1547,11 +1547,11 @@ describe("UsageTelemetryReporter", () => {
1547
1547
  // No HTTP call should have been made
1548
1548
  expect(mockFetch).not.toHaveBeenCalled();
1549
1549
 
1550
- // All 8 timestamp watermarks should have been advanced, and all 8 ID
1550
+ // All 7 timestamp watermarks should have been advanced, and all 7 ID
1551
1551
  // watermarks pinned to the high-sorting sentinel (a truthy value keeps
1552
1552
  // the compound-cursor branch active while closing its same-millisecond
1553
1553
  // arm against opt-out rows).
1554
- expect(mockSetMemoryCheckpoint).toHaveBeenCalledTimes(16);
1554
+ expect(mockSetMemoryCheckpoint).toHaveBeenCalledTimes(14);
1555
1555
 
1556
1556
  const calls = mockSetMemoryCheckpoint.mock.calls;
1557
1557
  const keys = calls.map((c) => c[0]);
@@ -1563,7 +1563,6 @@ describe("UsageTelemetryReporter", () => {
1563
1563
  "auth_fallback",
1564
1564
  "tool_executed",
1565
1565
  "skill_loaded",
1566
- "watchdog",
1567
1566
  ];
1568
1567
  for (const eventType of eventTypes) {
1569
1568
  expect(keys).toContain(`telemetry:${eventType}:last_reported_at`);