@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
@@ -272,6 +272,7 @@ describe("WhatsApp channel ingress attachment resolution", () => {
272
272
  const trustVerdict = resolveLocalTrustVerdict({
273
273
  channelType: "whatsapp",
274
274
  actorExternalId: WHATSAPP_USER_ID,
275
+ externalChatId: "whatsapp-chat-1",
275
276
  });
276
277
  return {
277
278
  sourceChannel: "whatsapp",
@@ -96,8 +96,6 @@ const addMessageMock = mock(
96
96
  );
97
97
 
98
98
  mock.module("../memory/conversation-crud.js", () => ({
99
- setConversationProcessingStartedAt: () => {},
100
- isConversationProcessing: () => false,
101
99
  addMessage: (
102
100
  conversationId: string,
103
101
  role: string,
@@ -129,18 +127,6 @@ mock.module("../runtime/trust-context-resolver.js", () => ({
129
127
  }),
130
128
  }));
131
129
 
132
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
133
- getGuardianDelivery: async () => [
134
- {
135
- channelType: "vellum",
136
- contactId: "guardian-contact",
137
- principalId: "test-user",
138
- address: "test-user",
139
- status: "active",
140
- },
141
- ],
142
- }));
143
-
144
130
  mock.module("../runtime/guardian-reply-router.js", () => ({
145
131
  routeGuardianReply: async () => ({
146
132
  consumed: false,
@@ -109,38 +109,17 @@ mock.module("../daemon/approval-generators.js", () => ({
109
109
  createApprovalConversationGenerator: () => _approvalGenerator,
110
110
  }));
111
111
 
112
- // Dev-bypass resolves the real guardian principal, then runs the real
113
- // local-principal trust mapper against the gateway delivery read.
112
+ // Mock local-actor-identity to return a stable guardian context that uses
113
+ // the same principal as the canonical requests created in tests.
114
114
  mock.module("../runtime/local-actor-identity.js", () => ({
115
- findLocalGuardianPrincipalId: async () => "test-principal-id",
116
- }));
117
-
118
- // Mock the IPC transport rather than local-principal-trust.js so the sibling
119
- // resolver unit test (which mocks guardian-delivery-reader, not ipcCall) isn't
120
- // shadowed when both files run in one Bun process. resolve_guardian_delivery
121
- // returns a single active vellum guardian whose principal matches the
122
- // dev-bypass-resolved id; any other method throws so unexpected IPC surfaces.
123
- mock.module("../ipc/gateway-client.js", () => ({
124
- ipcCall: async (method: string) => {
125
- if (method === "resolve_guardian_delivery") {
126
- return {
127
- guardians: [
128
- {
129
- channelType: "vellum",
130
- contactId: "test-contact-id",
131
- principalId: "test-principal-id",
132
- address: "test-principal-id",
133
- externalChatId: "test-principal-id",
134
- status: "active",
135
- },
136
- ],
137
- };
138
- }
139
- throw new Error(`Unexpected ipcCall in test: ${method}`);
140
- },
115
+ resolveLocalTrustContext: () => ({
116
+ sourceChannel: "vellum",
117
+ trustClass: "guardian",
118
+ guardianPrincipalId: "test-principal-id",
119
+ guardianExternalUserId: "test-principal-id",
120
+ }),
141
121
  }));
142
122
 
143
- import { __resetGuardianDeliveryCacheForTest } from "../contacts/guardian-delivery-reader.js";
144
123
  import { getDb } from "../memory/db-connection.js";
145
124
  import { initializeDb } from "../memory/db-init.js";
146
125
  import type { AssistantEvent } from "../runtime/assistant-event.js";
@@ -364,7 +343,6 @@ describe("POST /v1/messages — queue-if-busy and hub publishing", () => {
364
343
  db.run("DELETE FROM contact_channels");
365
344
  db.run("DELETE FROM contacts");
366
345
  pendingInteractions.clear();
367
- __resetGuardianDeliveryCacheForTest();
368
346
 
369
347
  createGuardianBinding({
370
348
  channel: "vellum",
@@ -351,50 +351,6 @@ describe("plugin-resident skills", () => {
351
351
  expect(skill).toBeUndefined();
352
352
  });
353
353
 
354
- test("warns when a plugin directory is missing package.json", () => {
355
- const warnings: unknown[][] = [];
356
- const originalWarn = noopLogger.warn;
357
- noopLogger.warn = (...args: unknown[]) => {
358
- warnings.push(args);
359
- };
360
- try {
361
- writePluginSkill(
362
- "the-force",
363
- "software-engineering",
364
- "Software Engineering",
365
- "Engineering workflow",
366
- "body",
367
- { withPackageJson: false },
368
- );
369
-
370
- const skill = loadSkillCatalog().find(
371
- (s) => s.id === "software-engineering",
372
- );
373
- expect(skill).toBeUndefined();
374
-
375
- const warnedForDir = warnings.some(
376
- (args) =>
377
- typeof args[0] === "object" &&
378
- args[0] !== null &&
379
- "pluginDir" in args[0] &&
380
- (args[0] as { pluginDir: string }).pluginDir.endsWith("the-force") &&
381
- typeof args[1] === "string" &&
382
- args[1].includes("missing package.json"),
383
- );
384
- expect(warnedForDir).toBe(true);
385
- } finally {
386
- noopLogger.warn = originalWarn;
387
- }
388
- });
389
-
390
- test("does not load resident skills from a plugin disabled via .disabled", () => {
391
- writePluginSkill("caveman", "caveman", "Caveman", "Terse mode");
392
- writeFileSync(join(pluginsDir, "caveman", ".disabled"), "");
393
-
394
- const skill = loadSkillCatalog().find((s) => s.id === "caveman");
395
- expect(skill).toBeUndefined();
396
- });
397
-
398
354
  test("workspace skill overrides a plugin-resident skill with the same id", () => {
399
355
  const WORKSPACE_DIR = join(
400
356
  tmpdir(),
@@ -55,35 +55,6 @@ mock.module("../runtime/gateway-client.js", () => ({
55
55
  },
56
56
  }));
57
57
 
58
- // Guardian identity resolves via the gateway delivery reader, not the local
59
- // contacts DB. Seed it to mirror the createGuardianBinding calls below.
60
- interface GatewayGuardian {
61
- channelType: string;
62
- contactId: string;
63
- principalId?: string | null;
64
- displayName?: string | null;
65
- address: string;
66
- externalChatId?: string | null;
67
- status: string;
68
- verifiedAt?: number | null;
69
- }
70
- let gatewayGuardians: GatewayGuardian[] = [];
71
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
72
- getGuardianDelivery: async () => gatewayGuardians,
73
- guardianForChannel: (list: GatewayGuardian[], channelType: string) =>
74
- list.find((g) => g.channelType === channelType && g.status === "active"),
75
- }));
76
-
77
- function seedGatewayGuardian(
78
- g: Partial<GatewayGuardian> & { channelType: string; address: string },
79
- ): void {
80
- gatewayGuardians.push({
81
- contactId: `c-${g.channelType}`,
82
- status: "active",
83
- ...g,
84
- });
85
- }
86
-
87
58
  import { getDb } from "../memory/db-connection.js";
88
59
  import { initializeDb } from "../memory/db-init.js";
89
60
  import { findActiveSession } from "../runtime/channel-verification-service.js";
@@ -109,16 +80,7 @@ function resetState(): void {
109
80
  db.run("DELETE FROM canonical_guardian_deliveries");
110
81
  db.run("DELETE FROM contact_channels");
111
82
  db.run("DELETE FROM contacts");
112
- gatewayGuardians = [];
113
- // Seed the vellum guardian binding (gateway does this at startup in
114
- // production). The gateway list is the source of truth for guardian
115
- // resolution; the DB write mirrors it for any local INFO reads.
116
- seedGatewayGuardian({
117
- channelType: "vellum",
118
- address: "guardian-principal",
119
- principalId: "guardian-principal",
120
- displayName: "guardian-principal",
121
- });
83
+ // Seed the vellum guardian binding (gateway does this at startup in production)
122
84
  createGuardianBinding({
123
85
  channel: "vellum",
124
86
  guardianExternalUserId: "guardian-principal",
@@ -200,14 +162,7 @@ describe("Slack inbound trusted contact verification", () => {
200
162
  });
201
163
 
202
164
  test("guardian is notified of the access attempt alongside verification", async () => {
203
- // Set up a guardian binding so the notification can target it. The gateway
204
- // list resolves guardian identity; the DB write mirrors it.
205
- seedGatewayGuardian({
206
- channelType: "slack",
207
- address: "U_GUARDIAN",
208
- externalChatId: "D_GUARDIAN_DM",
209
- principalId: "guardian-principal",
210
- });
165
+ // Set up a guardian binding so the notification can target it
211
166
  createGuardianBinding({
212
167
  channel: "slack",
213
168
  guardianExternalUserId: "U_GUARDIAN",
@@ -13,15 +13,6 @@ let mockRecentContacts: ContactWithChannels[] = [];
13
13
  let mockFindContactByAddressThrows = false;
14
14
  let mockListContactsThrows = false;
15
15
 
16
- // Guardian deliveries returned by the mocked gateway reader. resolveGuardianName
17
- // is mocked to echo mockGuardianName, so the displayName here is captured below.
18
- let mockGuardianDelivery: Array<{
19
- channelType: string;
20
- status: string;
21
- displayName: string | null;
22
- }> | null = null;
23
- let lastGuardianDisplayNameSeen: string | null | undefined;
24
-
25
16
  const logWarnFn = mock(() => {});
26
17
 
27
18
  // ---------------------------------------------------------------------------
@@ -34,10 +25,7 @@ mock.module("../daemon/identity-helpers.js", () => ({
34
25
 
35
26
  mock.module("../prompts/user-reference.js", () => ({
36
27
  DEFAULT_USER_REFERENCE: "my human",
37
- resolveGuardianName: (displayName?: string | null) => {
38
- lastGuardianDisplayNameSeen = displayName;
39
- return mockGuardianName;
40
- },
28
+ resolveGuardianName: () => mockGuardianName,
41
29
  }));
42
30
 
43
31
  mock.module("../contacts/contact-store.js", () => ({
@@ -47,6 +35,8 @@ mock.module("../contacts/contact-store.js", () => ({
47
35
  }
48
36
  return mockTargetContact;
49
37
  },
38
+ findGuardianForChannel: () => null,
39
+ listGuardianChannels: () => null,
50
40
  listContacts: (_limit?: number) => {
51
41
  if (mockListContactsThrows) {
52
42
  throw new Error("DB error: listContacts");
@@ -55,15 +45,6 @@ mock.module("../contacts/contact-store.js", () => ({
55
45
  },
56
46
  }));
57
47
 
58
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
59
- getGuardianDelivery: async () => mockGuardianDelivery,
60
- guardianForChannel: (
61
- list: Array<{ channelType: string; status: string }>,
62
- channelType: string,
63
- ) => list.find((g) => g.channelType === channelType && g.status === "active"),
64
- anyGuardian: (list: unknown[]) => list[0],
65
- }));
66
-
67
48
  // Bun's mock.module for "../util/logger.js" doesn't intercept the transitive
68
49
  // import in stt-hints.ts due to a Bun limitation. Mocking pino at the package
69
50
  // level works because getLogger uses a Proxy that lazily creates a pino child
@@ -338,22 +319,10 @@ describe("resolveCallHints", () => {
338
319
  mockRecentContacts = [];
339
320
  mockFindContactByAddressThrows = false;
340
321
  mockListContactsThrows = false;
341
- mockGuardianDelivery = null;
342
- lastGuardianDisplayNameSeen = undefined;
343
322
  logWarnFn.mockClear();
344
323
  });
345
324
 
346
- test("guardian displayName for hints comes from the gateway binding", async () => {
347
- mockGuardianDelivery = [
348
- { channelType: "phone", status: "active", displayName: "GatewayGuardian" },
349
- ];
350
-
351
- await resolveCallHints(null, []);
352
-
353
- expect(lastGuardianDisplayNameSeen).toBe("GatewayGuardian");
354
- });
355
-
356
- test("happy path wires all sources correctly", async () => {
325
+ test("happy path wires all sources correctly", () => {
357
326
  mockTargetContact = makeContact("Alice");
358
327
  mockRecentContacts = [makeContact("Bob"), makeContact("Charlie")];
359
328
 
@@ -366,7 +335,7 @@ describe("resolveCallHints", () => {
366
335
  inviteGuardianName: "Eve",
367
336
  };
368
337
 
369
- const result = await resolveCallHints(session, ["StaticHint"]);
338
+ const result = resolveCallHints(session, ["StaticHint"]);
370
339
  const parts = result.split(",");
371
340
 
372
341
  expect(parts).toContain("StaticHint");
@@ -382,7 +351,7 @@ describe("resolveCallHints", () => {
382
351
  expect(logWarnFn).not.toHaveBeenCalled();
383
352
  });
384
353
 
385
- test("findContactByAddress failure is caught and logged without throwing", async () => {
354
+ test("findContactByAddress failure is caught and logged without throwing", () => {
386
355
  mockFindContactByAddressThrows = true;
387
356
  mockRecentContacts = [makeContact("Bob")];
388
357
 
@@ -396,7 +365,7 @@ describe("resolveCallHints", () => {
396
365
  };
397
366
 
398
367
  // Should not throw
399
- const result = await resolveCallHints(session, []);
368
+ const result = resolveCallHints(session, []);
400
369
  const parts = result.split(",");
401
370
 
402
371
  // Target contact should be absent (lookup failed)
@@ -407,7 +376,7 @@ describe("resolveCallHints", () => {
407
376
  expect(logWarnFn).toHaveBeenCalled();
408
377
  });
409
378
 
410
- test("listContacts failure is caught and logged without throwing", async () => {
379
+ test("listContacts failure is caught and logged without throwing", () => {
411
380
  mockListContactsThrows = true;
412
381
  mockTargetContact = makeContact("Alice");
413
382
 
@@ -421,7 +390,7 @@ describe("resolveCallHints", () => {
421
390
  };
422
391
 
423
392
  // Should not throw
424
- const result = await resolveCallHints(session, []);
393
+ const result = resolveCallHints(session, []);
425
394
  const parts = result.split(",");
426
395
 
427
396
  // Recent contacts should be absent (listing failed)
@@ -432,7 +401,7 @@ describe("resolveCallHints", () => {
432
401
  expect(logWarnFn).toHaveBeenCalled();
433
402
  });
434
403
 
435
- test("inbound call resolves caller contact from fromNumber", async () => {
404
+ test("inbound call resolves caller contact from fromNumber", () => {
436
405
  mockTargetContact = makeContact("Alice");
437
406
  mockRecentContacts = [makeContact("Bob")];
438
407
 
@@ -445,7 +414,7 @@ describe("resolveCallHints", () => {
445
414
  inviteGuardianName: null,
446
415
  };
447
416
 
448
- const result = await resolveCallHints(session, []);
417
+ const result = resolveCallHints(session, []);
449
418
  const parts = result.split(",");
450
419
 
451
420
  // For inbound, the contact found via fromNumber should appear as caller, not target
@@ -456,10 +425,10 @@ describe("resolveCallHints", () => {
456
425
  expect(logWarnFn).not.toHaveBeenCalled();
457
426
  });
458
427
 
459
- test("null session produces hints from assistant name, guardian name, and recent contacts", async () => {
428
+ test("null session produces hints from assistant name, guardian name, and recent contacts", () => {
460
429
  mockRecentContacts = [makeContact("RecentOne"), makeContact("RecentTwo")];
461
430
 
462
- const result = await resolveCallHints(null, ["Static"]);
431
+ const result = resolveCallHints(null, ["Static"]);
463
432
  const parts = result.split(",");
464
433
 
465
434
  expect(parts).toContain("Static");
@@ -130,33 +130,6 @@ describe("parseSubagentMessages", () => {
130
130
  expect(result.objective).toBe("Research vampire lore");
131
131
  });
132
132
 
133
- test("emits toolUseId and raw input on tool_use, toolUseId on tool_result", () => {
134
- const messages = [
135
- msg("user", [{ type: "text", text: "Do something" }]),
136
- msg("assistant", [
137
- {
138
- type: "tool_use",
139
- id: "t-abc",
140
- name: "bash",
141
- input: { command: "ls -la" },
142
- },
143
- ]),
144
- msg("user", [
145
- { type: "tool_result", tool_use_id: "t-abc", content: "total 0" },
146
- ]),
147
- ];
148
-
149
- const result = parseSubagentMessages("sub-1", messages);
150
- const toolUse = result.events.find((e) => e.type === "tool_use");
151
- expect(toolUse).toBeDefined();
152
- expect(toolUse!.toolUseId).toBe("t-abc");
153
- expect(toolUse!.input).toEqual({ command: "ls -la" });
154
-
155
- const toolResult = result.events.find((e) => e.type === "tool_result");
156
- expect(toolResult).toBeDefined();
157
- expect(toolResult!.toolUseId).toBe("t-abc");
158
- });
159
-
160
133
  test("includes messageId on text events from assistant messages", () => {
161
134
  const messages = [
162
135
  msg("user", [{ type: "text", text: "Do something" }]),
@@ -326,68 +326,3 @@ describe("SubagentManager terminal disposal", () => {
326
326
  asInternals(manager).stopSweep();
327
327
  });
328
328
  });
329
-
330
- describe("SubagentManager.abort usage", () => {
331
- test("emits the conversation's latest usage on abort, not zeros", () => {
332
- const manager = new SubagentManager();
333
- const sent: ServerMessage[] = [];
334
- const sender = (msg: ServerMessage) => sent.push(msg);
335
-
336
- const subagentId = "sa-abort-usage";
337
- // state.usage starts at {0,0,0}; the live (fake) conversation has accrued
338
- // usage (makeFakeConversation → {100, 50, 0.005}). Wire `sender` as the
339
- // stored parent sender so `setStatus` routes the terminal event through it.
340
- injectFakeSubagent(manager, subagentId, makeState(subagentId), sender);
341
-
342
- const aborted = manager.abort(subagentId, sender, undefined, {
343
- suppressNotification: true,
344
- });
345
- expect(aborted).toBe(true);
346
-
347
- const statusMsg = sent.find(
348
- (m): m is Extract<ServerMessage, { type: "subagent_status_changed" }> =>
349
- m.type === "subagent_status_changed",
350
- );
351
- expect(statusMsg).toBeDefined();
352
- expect(statusMsg!.status).toBe("aborted");
353
- // The emitted usage is the conversation's accrued total — NOT the {0,0,0}
354
- // init — so the client doesn't flush the token panel to zero on stop.
355
- expect(statusMsg!.usage).toEqual({
356
- inputTokens: 100,
357
- outputTokens: 50,
358
- estimatedCost: 0.005,
359
- });
360
-
361
- asInternals(manager).stopSweep();
362
- });
363
-
364
- test("keeps the last-known state.usage when the conversation was already released", () => {
365
- const manager = new SubagentManager();
366
- const sent: ServerMessage[] = [];
367
- const sender = (msg: ServerMessage) => sent.push(msg);
368
-
369
- const subagentId = "sa-abort-no-conv";
370
- // No live conversation (released), but state carries a last-known usage —
371
- // the abort must surface that, not overwrite it.
372
- const state = makeState(subagentId, {
373
- usage: { inputTokens: 320, outputTokens: 80, estimatedCost: 0.004 },
374
- });
375
- injectFakeSubagent(manager, subagentId, state, sender, null);
376
-
377
- manager.abort(subagentId, sender, undefined, {
378
- suppressNotification: true,
379
- });
380
-
381
- const statusMsg = sent.find(
382
- (m): m is Extract<ServerMessage, { type: "subagent_status_changed" }> =>
383
- m.type === "subagent_status_changed",
384
- );
385
- expect(statusMsg!.usage).toEqual({
386
- inputTokens: 320,
387
- outputTokens: 80,
388
- estimatedCost: 0.004,
389
- });
390
-
391
- asInternals(manager).stopSweep();
392
- });
393
- });
@@ -4,8 +4,6 @@ import { describe, expect, mock, test } from "bun:test";
4
4
 
5
5
  // Mock conversation-crud before importing tool executors that depend on it.
6
6
  mock.module("../memory/conversation-crud.js", () => ({
7
- setConversationProcessingStartedAt: () => {},
8
- isConversationProcessing: () => false,
9
7
  setConversationOriginChannelIfUnset: () => {},
10
8
  updateConversationContextWindow: () => {},
11
9
  deleteMessageById: () => {},
@@ -70,11 +70,8 @@ describe("SUBAGENT_ROLE_REGISTRY", () => {
70
70
  expect(SUBAGENT_ROLE_REGISTRY.planner.allowedTools!).toContain("recall");
71
71
  });
72
72
 
73
- test("investigator is shell-free and uses code_search for code/log investigation", () => {
74
- const tools = SUBAGENT_ROLE_REGISTRY.investigator.allowedTools!;
75
- expect(tools).not.toContain("bash");
76
- expect(tools).not.toContain("host_bash");
77
- expect(tools).toContain("code_search");
73
+ test('investigator includes "bash" for grep/find-based code and log investigation', () => {
74
+ expect(SUBAGENT_ROLE_REGISTRY.investigator.allowedTools!).toContain("bash");
78
75
  });
79
76
 
80
77
  test("investigator excludes file write tools (read-only investigation)", () => {
@@ -88,8 +85,6 @@ describe("SUBAGENT_ROLE_REGISTRY", () => {
88
85
  expect(preamble).toContain("Root cause");
89
86
  expect(preamble).toContain("Evidence");
90
87
  expect(preamble).toContain("notify_parent");
91
- expect(preamble).not.toContain("shell access");
92
- expect(preamble).toContain("code_search");
93
88
  });
94
89
 
95
90
  test("no role references the old memory_recall tool name", () => {
@@ -3,8 +3,6 @@ import { mock } from "bun:test";
3
3
 
4
4
  // Mock conversation-crud before importing tool executors that depend on it.
5
5
  mock.module("../memory/conversation-crud.js", () => ({
6
- setConversationProcessingStartedAt: () => {},
7
- isConversationProcessing: () => false,
8
6
  setConversationOriginChannelIfUnset: () => {},
9
7
  updateConversationContextWindow: () => {},
10
8
  deleteMessageById: () => {},
@@ -29,8 +29,6 @@ mock.module("../config/loader.js", () => ({
29
29
  }),
30
30
  }));
31
31
  mock.module("../memory/conversation-crud.js", () => ({
32
- setConversationProcessingStartedAt: () => {},
33
- isConversationProcessing: () => false,
34
32
  setConversationOriginChannelIfUnset: () => {},
35
33
  updateConversationContextWindow: () => {},
36
34
  deleteMessageById: () => {},
@@ -50,8 +50,6 @@ const mockGetMessages = mock((_conversationId: string) => [
50
50
  ]);
51
51
 
52
52
  mock.module("../memory/conversation-crud.js", () => ({
53
- setConversationProcessingStartedAt: () => {},
54
- isConversationProcessing: () => false,
55
53
  getMessages: mockGetMessages,
56
54
  getConversation: (_id: string) => null,
57
55
  reserveMessage: mock(async () => ({ id: "msg-reserve" })),
@@ -64,8 +64,6 @@ const mockGetConversation = mock(
64
64
  },
65
65
  );
66
66
  mock.module("../memory/conversation-crud.js", () => ({
67
- setConversationProcessingStartedAt: () => {},
68
- isConversationProcessing: () => false,
69
67
  getConversation: mockGetConversation,
70
68
  }));
71
69
 
@@ -78,8 +78,6 @@ mock.module("../permissions/checker.js", () => ({
78
78
  }));
79
79
 
80
80
  mock.module("../memory/conversation-crud.js", () => ({
81
- setConversationProcessingStartedAt: () => {},
82
- isConversationProcessing: () => false,
83
81
  createConversation: (title: string) => ({ id: "conversation-1", title }),
84
82
  reserveMessage: mock(async () => ({ id: "msg-reserve" })),
85
83
  }));
@@ -17,7 +17,6 @@ const mockConfig = {
17
17
  shellDefaultTimeoutSec: 120,
18
18
  shellMaxTimeoutSec: 600,
19
19
  permissionTimeoutSec: 300,
20
- questionResponseTimeoutSec: 1800,
21
20
  },
22
21
  sandbox: {
23
22
  enabled: false,
@@ -1301,31 +1300,27 @@ describe("ToolExecutionResult includes risk metadata from classifier assessment"
1301
1300
 
1302
1301
  describe("computePerToolTimeoutMs ask_question budget", () => {
1303
1302
  // Regression guard: ask_question blocks on user input inside execute() via
1304
- // QuestionPrompter, which waits up to questionResponseTimeoutSec. The
1305
- // executor's generic toolExecutionTimeoutSec wrapper must give ask_question a
1306
- // budget strictly larger than that prompt timeout — otherwise the wrapper
1307
- // fires first and orphans the still-pending prompt behind the confusing "may
1303
+ // QuestionPrompter, which waits up to permissionTimeoutSec. The executor's
1304
+ // generic toolExecutionTimeoutSec wrapper must give ask_question a budget
1305
+ // strictly larger than that prompt timeout — otherwise the wrapper fires
1306
+ // first and orphans the still-pending prompt behind the confusing "may
1308
1307
  // still be running in the background" error. These assertions fail if the
1309
- // special case is removed and ask_question falls back to the generic budget,
1310
- // or if the executor budget and the prompter timeout drift onto different
1311
- // config knobs.
1312
- test("execution-timeout budget exceeds the prompt's own questionResponseTimeoutSec", () => {
1313
- const { questionResponseTimeoutSec } = mockConfig.timeouts;
1308
+ // special case is removed and ask_question falls back to the generic budget.
1309
+ test("execution-timeout budget exceeds the prompt's own permissionTimeoutSec", () => {
1310
+ const { permissionTimeoutSec } = mockConfig.timeouts;
1314
1311
  const askQuestionBudgetMs = computePerToolTimeoutMs("ask_question", {});
1315
1312
 
1316
- expect(askQuestionBudgetMs).toBeGreaterThan(
1317
- questionResponseTimeoutSec * 1000,
1318
- );
1319
- expect(askQuestionBudgetMs).toBe((questionResponseTimeoutSec + 5) * 1000);
1313
+ expect(askQuestionBudgetMs).toBeGreaterThan(permissionTimeoutSec * 1000);
1314
+ expect(askQuestionBudgetMs).toBe((permissionTimeoutSec + 5) * 1000);
1320
1315
  });
1321
1316
 
1322
1317
  test("the generic budget that would otherwise apply is shorter than the prompt timeout", () => {
1323
- const { questionResponseTimeoutSec } = mockConfig.timeouts;
1318
+ const { permissionTimeoutSec } = mockConfig.timeouts;
1324
1319
  const genericBudgetMs = computePerToolTimeoutMs("some_other_tool", {});
1325
1320
 
1326
1321
  // This is the collision the ask_question special case fixes: the generic
1327
1322
  // execution-timeout budget is shorter than the prompter's own wait, so
1328
1323
  // without the special case the wrapper trips first.
1329
- expect(genericBudgetMs).toBeLessThan(questionResponseTimeoutSec * 1000);
1324
+ expect(genericBudgetMs).toBeLessThan(permissionTimeoutSec * 1000);
1330
1325
  });
1331
1326
  });
@@ -60,8 +60,6 @@ const reserveMessageMock = mock(
60
60
  const updateMessageContentMock = mock((_id: string, _content: string) => {});
61
61
 
62
62
  mock.module("../memory/conversation-crud.js", () => ({
63
- setConversationProcessingStartedAt: () => {},
64
- isConversationProcessing: () => false,
65
63
  getConversation: () => null,
66
64
  getMessageById: () => null,
67
65
  updateMessageContent: updateMessageContentMock,
@@ -40,8 +40,6 @@ mock.module("../config/loader.js", () => ({
40
40
  }));
41
41
 
42
42
  mock.module("../memory/conversation-crud.js", () => ({
43
- setConversationProcessingStartedAt: () => {},
44
- isConversationProcessing: () => false,
45
43
  addMessage: () => ({ id: "mock-msg-id" }),
46
44
  getMessageById: () => null,
47
45
  updateMessageContent: () => {},
@@ -43,8 +43,6 @@ let mockedRowContent = "";
43
43
  const updates: Array<{ id: string; content: string }> = [];
44
44
 
45
45
  mock.module("../memory/conversation-crud.js", () => ({
46
- setConversationProcessingStartedAt: () => {},
47
- isConversationProcessing: () => false,
48
46
  addMessage: () => ({ id: "mock-msg-id" }),
49
47
  getMessageById: (id: string) =>
50
48
  mockedRowContent ? { id, content: mockedRowContent } : null,