@vellumai/assistant 0.12.1-staging.1 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/AGENTS.md +0 -4
  2. package/ARCHITECTURE.md +12 -11
  3. package/docs/architecture/turn-actor.md +8 -15
  4. package/openapi.yaml +1 -291
  5. package/package.json +1 -1
  6. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  7. package/src/__tests__/app-compiler.test.ts +0 -6
  8. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  9. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  10. package/src/__tests__/app-source-watcher.test.ts +218 -0
  11. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  12. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  13. package/src/__tests__/computer-use-tools.test.ts +5 -17
  14. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  15. package/src/__tests__/config-schema.test.ts +29 -28
  16. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  17. package/src/__tests__/config-watcher.test.ts +8 -23
  18. package/src/__tests__/connection-model-compat.test.ts +2 -2
  19. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  20. package/src/__tests__/conversation-pairing.test.ts +0 -26
  21. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  22. package/src/__tests__/conversation-queue.test.ts +207 -48
  23. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  24. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  25. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  26. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  27. package/src/__tests__/conversation-title-service.test.ts +10 -14
  28. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  29. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  30. package/src/__tests__/credential-record-retire.test.ts +1 -171
  31. package/src/__tests__/credential-routes.test.ts +3 -212
  32. package/src/__tests__/credential-security-invariants.test.ts +1 -2
  33. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  34. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  35. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  36. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  37. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  38. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  39. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  40. package/src/__tests__/host-file-proxy.test.ts +23 -11
  41. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  42. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  43. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  44. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  45. package/src/__tests__/mcp-health-check.test.ts +11 -8
  46. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  47. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  48. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  49. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  51. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  52. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  53. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  54. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  55. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  56. package/src/__tests__/model-intents.test.ts +0 -3
  57. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  58. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  59. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  60. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  61. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  62. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  63. package/src/__tests__/speaker-identification.test.ts +56 -0
  64. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  65. package/src/__tests__/subagent-tools.test.ts +2 -3
  66. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  67. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  68. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  69. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  70. package/src/__tests__/workspace-git-service.test.ts +0 -26
  71. package/src/acp/__tests__/agent-process.test.ts +4 -258
  72. package/src/acp/__tests__/auth-required.test.ts +0 -96
  73. package/src/acp/__tests__/client-handler.test.ts +2 -90
  74. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  75. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  76. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  77. package/src/acp/__tests__/session-manager.test.ts +4 -895
  78. package/src/acp/agent-process.test.ts +1 -4
  79. package/src/acp/agent-process.ts +9 -94
  80. package/src/acp/auth-required.ts +1 -50
  81. package/src/acp/auto-install.test.ts +7 -9
  82. package/src/acp/client-handler.ts +3 -16
  83. package/src/acp/resolve-agent.test.ts +6 -220
  84. package/src/acp/resolve-agent.ts +23 -88
  85. package/src/acp/session-manager.test.ts +3 -196
  86. package/src/acp/session-manager.ts +18 -441
  87. package/src/acp/types.ts +5 -50
  88. package/src/api/events/app-files-changed.ts +3 -4
  89. package/src/api/index.ts +0 -6
  90. package/src/apps/app-store.ts +1 -1
  91. package/src/bundler/app-compiler.ts +0 -15
  92. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  93. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  94. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  95. package/src/calls/call-constants.ts +4 -24
  96. package/src/calls/call-controller.ts +199 -499
  97. package/src/calls/call-transport.ts +0 -16
  98. package/src/calls/media-stream-output.ts +0 -32
  99. package/src/calls/media-stream-server.ts +30 -82
  100. package/src/calls/media-stream-stt-session.ts +0 -15
  101. package/src/calls/resolve-call-tts-provider.ts +2 -33
  102. package/src/calls/speaker-identification.ts +233 -0
  103. package/src/calls/tts-call-strategy.ts +5 -9
  104. package/src/calls/types.ts +0 -2
  105. package/src/calls/voice-control-protocol.ts +21 -53
  106. package/src/calls/voice-session-bridge.ts +46 -59
  107. package/src/calls/voice-triage-escalate.ts +56 -175
  108. package/src/cli/commands/apps.help.ts +13 -67
  109. package/src/cli/commands/apps.ts +0 -183
  110. package/src/cli/commands/channels/index.help.ts +2 -70
  111. package/src/cli/commands/channels/index.ts +3 -16
  112. package/src/cli/commands/credentials.help.ts +2 -6
  113. package/src/cli/commands/credentials.ts +2 -2
  114. package/src/cli/commands/mcp.help.ts +8 -8
  115. package/src/cli/commands/mcp.ts +1 -1
  116. package/src/cli/commands/roadmap.help.ts +1 -5
  117. package/src/cli/commands/roadmap.ts +1 -1
  118. package/src/cli/lib/bundled-marketplace.json +90 -103
  119. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  120. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  121. package/src/config/__tests__/platform-rehydration.test.ts +0 -93
  122. package/src/config/acp-defaults.test.ts +3 -13
  123. package/src/config/acp-defaults.ts +6 -23
  124. package/src/config/acp-schema.ts +2 -30
  125. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  126. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  127. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  128. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  129. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  130. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  131. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  132. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  133. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  134. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  135. package/src/config/default-profile-catalog.ts +1 -1
  136. package/src/config/env.ts +2 -2
  137. package/src/config/feature-flag-registry.json +12 -8
  138. package/src/config/memory-v3-gate.test.ts +0 -31
  139. package/src/config/memory-v3-gate.ts +16 -20
  140. package/src/config/platform-rehydration.ts +21 -75
  141. package/src/config/schema.ts +2 -2
  142. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  143. package/src/config/schemas/calls.ts +28 -1
  144. package/src/config/schemas/live-voice.ts +173 -1
  145. package/src/config/schemas/mcp.ts +1 -1
  146. package/src/config/schemas/memory-retrospective.ts +0 -10
  147. package/src/config/schemas/skills.ts +14 -0
  148. package/src/credential-execution/process-manager.test.ts +19 -18
  149. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  150. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  151. package/src/daemon/app-source-watcher.ts +218 -0
  152. package/src/daemon/config-watcher.ts +194 -13
  153. package/src/daemon/conversation-process.ts +64 -35
  154. package/src/daemon/conversation-skill-tools.ts +31 -13
  155. package/src/daemon/conversation-store.ts +1 -1
  156. package/src/daemon/conversation-surfaces.ts +8 -10
  157. package/src/daemon/conversation-tool-setup.ts +43 -37
  158. package/src/daemon/conversation.ts +3 -0
  159. package/src/daemon/host-bash-proxy.ts +12 -8
  160. package/src/daemon/host-browser-proxy.ts +1 -15
  161. package/src/daemon/host-file-proxy.ts +10 -8
  162. package/src/daemon/host-transfer-proxy.ts +18 -14
  163. package/src/daemon/lifecycle.ts +5 -0
  164. package/src/daemon/mcp-reload-service.ts +5 -5
  165. package/src/daemon/message-types/sync.ts +0 -1
  166. package/src/daemon/providers-setup.ts +1 -1
  167. package/src/daemon/shutdown-handlers.ts +9 -1
  168. package/src/daemon/skill-memory-refresh.ts +0 -64
  169. package/src/daemon/tool-side-effects.ts +18 -7
  170. package/src/hooks/types.ts +0 -33
  171. package/src/inbound/platform-callback-registration.ts +5 -4
  172. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  173. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  174. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  175. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  176. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  177. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  178. package/src/live-voice/live-voice-session.ts +693 -213
  179. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  180. package/src/live-voice/protocol.ts +2 -0
  181. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  182. package/src/mcp/effective-config.ts +3 -3
  183. package/src/mcp/mcp-header-store.ts +45 -29
  184. package/src/mcp/startup.ts +4 -8
  185. package/src/messaging/provider.ts +3 -10
  186. package/src/messaging/providers/callback-routing.ts +0 -18
  187. package/src/messaging/providers/channel-transport.ts +0 -56
  188. package/src/messaging/providers/discord/transport.ts +0 -17
  189. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  190. package/src/messaging/providers/slack/adapter.ts +44 -7
  191. package/src/messaging/providers/slack/transport.ts +0 -16
  192. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  193. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  194. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  195. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  196. package/src/messaging/providers/whatsapp/client.ts +29 -0
  197. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  198. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  199. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  200. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  201. package/src/notifications/assistant-reply-producer.ts +3 -8
  202. package/src/notifications/conversation-pairing.ts +16 -36
  203. package/src/notifications/delivered-post-record.ts +1 -11
  204. package/src/notifications/home-feed-side-effect.ts +7 -55
  205. package/src/outbound-proxy/certs.ts +5 -3
  206. package/src/permissions/checker.test.ts +6 -11
  207. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  208. package/src/persistence/conversation-crud.ts +63 -71
  209. package/src/persistence/conversation-lineage.ts +4 -12
  210. package/src/persistence/conversation-title-service.ts +26 -9
  211. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  212. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  213. package/src/persistence/message-reads.ts +0 -30
  214. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  215. package/src/persistence/schema/memory-core.ts +0 -5
  216. package/src/platform/client.test.ts +0 -2
  217. package/src/platform/client.ts +10 -2
  218. package/src/plugin-api/constants.ts +0 -2
  219. package/src/plugin-api/index.ts +0 -1
  220. package/src/plugin-api/types.ts +0 -2
  221. package/src/plugins/defaults/index.ts +0 -2
  222. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  223. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  224. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  225. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  226. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  227. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  228. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  229. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  230. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  231. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  232. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  233. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  234. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  235. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  236. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  237. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  238. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  239. package/src/plugins/defaults/memory/startup.ts +1 -6
  240. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  241. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  242. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  243. package/src/plugins/defaults/memory/worker.ts +0 -6
  244. package/src/plugins/mcp-servers.ts +75 -15
  245. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  246. package/src/providers/gemini/client.ts +23 -9
  247. package/src/providers/model-catalog.ts +0 -34
  248. package/src/providers/model-intents.ts +5 -10
  249. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  250. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  251. package/src/providers/openai/chat-completions-provider.ts +78 -192
  252. package/src/providers/openai/codex-models.ts +4 -0
  253. package/src/runtime/AGENTS.md +0 -2
  254. package/src/runtime/auth/same-actor.ts +3 -38
  255. package/src/runtime/http-server.ts +151 -160
  256. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  257. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  258. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  259. package/src/runtime/routes/acp-routes.test.ts +0 -15
  260. package/src/runtime/routes/acp-routes.ts +9 -72
  261. package/src/runtime/routes/app-management-routes.ts +0 -73
  262. package/src/runtime/routes/app-routes.ts +1 -1
  263. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  264. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  265. package/src/runtime/routes/credential-routes.ts +10 -19
  266. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  267. package/src/runtime/routes/index.ts +0 -4
  268. package/src/runtime/routes/log-export-routes.ts +0 -2
  269. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  270. package/src/runtime/routes/migration-routes.ts +21 -8
  271. package/src/runtime/routes/platform-routes.ts +15 -18
  272. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  273. package/src/runtime/services/conversation-serializer.ts +3 -16
  274. package/src/runtime/sync/resource-sync-events.ts +1 -2
  275. package/src/schedule/worker.ts +1 -1
  276. package/src/security/ces-rpc-record-backend.ts +0 -7
  277. package/src/subagent/consult-context.ts +25 -12
  278. package/src/tools/acp/list-agents.test.ts +1 -3
  279. package/src/tools/acp/spawn.test.ts +11 -146
  280. package/src/tools/acp/spawn.ts +3 -21
  281. package/src/tools/acp/status.ts +3 -40
  282. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  283. package/src/tools/capability-offer.test.ts +2 -22
  284. package/src/tools/capability-offer.ts +1 -16
  285. package/src/tools/computer-use/definitions.ts +2 -4
  286. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  287. package/src/tools/credentials/metadata-store.ts +0 -100
  288. package/src/tools/host-filesystem/edit.test.ts +1 -2
  289. package/src/tools/host-filesystem/edit.ts +2 -2
  290. package/src/tools/host-filesystem/read.test.ts +1 -2
  291. package/src/tools/host-filesystem/read.ts +2 -2
  292. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  293. package/src/tools/host-filesystem/transfer.ts +2 -2
  294. package/src/tools/host-filesystem/write.test.ts +1 -2
  295. package/src/tools/host-filesystem/write.ts +2 -2
  296. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  297. package/src/tools/host-terminal/host-shell.ts +20 -4
  298. package/src/tools/policy-context.ts +7 -6
  299. package/src/tools/subagent/spawn.ts +8 -5
  300. package/src/tools/watch/watch-retro-report.ts +8 -0
  301. package/src/util/__tests__/language-subtag.test.ts +1 -23
  302. package/src/util/fs-watcher-error.ts +36 -0
  303. package/src/util/language-subtag.ts +0 -16
  304. package/src/util/platform.ts +0 -8
  305. package/src/workspace/git-service.ts +54 -5
  306. package/src/workspace/migrations/registry.ts +0 -6
  307. package/scripts/smoke-desktop-window-theme.ts +0 -186
  308. package/src/__tests__/git-porcelain.test.ts +0 -47
  309. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  310. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  311. package/src/__tests__/resolve-app.test.ts +0 -135
  312. package/src/__tests__/source-fingerprint.test.ts +0 -184
  313. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  314. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  315. package/src/acp/model-config.test.ts +0 -166
  316. package/src/acp/model-config.ts +0 -138
  317. package/src/api/events/acp-session-model-update.test.ts +0 -88
  318. package/src/api/events/acp-session-model-update.ts +0 -46
  319. package/src/apps/resolve-app.ts +0 -81
  320. package/src/apps/source-fingerprint.ts +0 -266
  321. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  322. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  323. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  324. package/src/calls/barge-in-guard.ts +0 -118
  325. package/src/calls/voice-leg-coordinator.ts +0 -189
  326. package/src/calls/voice-progress-cadence.ts +0 -423
  327. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  328. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  329. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  330. package/src/cli/commands/channels/send.ts +0 -128
  331. package/src/config/__tests__/platform-identity.test.ts +0 -117
  332. package/src/config/acp-agent-write.ts +0 -43
  333. package/src/config/acp-schema.test.ts +0 -81
  334. package/src/config/platform-identity.ts +0 -144
  335. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  336. package/src/config/schemas/voice.ts +0 -150
  337. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  338. package/src/daemon/app-change-notify.ts +0 -45
  339. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  340. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  341. package/src/desktop/desktop-chrome-policy.ts +0 -42
  342. package/src/desktop/desktop-dependencies.test.ts +0 -102
  343. package/src/desktop/desktop-dependencies.ts +0 -306
  344. package/src/desktop/desktop-feature.test.ts +0 -18
  345. package/src/desktop/desktop-feature.ts +0 -19
  346. package/src/desktop/desktop-panel-config.test.ts +0 -135
  347. package/src/desktop/desktop-panel-config.ts +0 -149
  348. package/src/desktop/desktop-session-manager.test.ts +0 -627
  349. package/src/desktop/desktop-session-manager.ts +0 -814
  350. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  351. package/src/desktop/desktop-stream-bridge.ts +0 -214
  352. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  353. package/src/desktop/desktop-wallpaper.ts +0 -113
  354. package/src/desktop/desktop-window-theme.ts +0 -170
  355. package/src/i18n/AGENTS.md +0 -22
  356. package/src/i18n/__tests__/i18n.test.ts +0 -108
  357. package/src/i18n/index.ts +0 -16
  358. package/src/i18n/locales.ts +0 -93
  359. package/src/i18n/messages.ts +0 -61
  360. package/src/i18n/title.ts +0 -25
  361. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  362. package/src/mcp/spec-schema.ts +0 -111
  363. package/src/mcp/workspace-mcp-config.ts +0 -188
  364. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  365. package/src/persistence/conversation-title-placeholders.ts +0 -23
  366. package/src/persistence/message-cursor.ts +0 -78
  367. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  368. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  369. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  370. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  371. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  372. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  373. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  374. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  375. package/src/providers/gemini-thought-signature.test.ts +0 -63
  376. package/src/providers/gemini-thought-signature.ts +0 -44
  377. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  378. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  379. package/src/providers/openai/google-thought-signature.ts +0 -320
  380. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  381. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  382. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  383. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  384. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  385. package/src/runtime/channel-send.ts +0 -316
  386. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  387. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  388. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  389. package/src/runtime/routes/channel-send-routes.ts +0 -85
  390. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  391. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  392. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  393. package/src/security/ces-http-record-backend.ts +0 -120
  394. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  395. package/src/skills/workspace-skill-md-signature.ts +0 -50
  396. package/src/tools/acp/status.test.ts +0 -94
  397. package/src/util/ca-bundle.ts +0 -13
  398. package/src/workspace/git-porcelain.ts +0 -66
  399. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  400. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  401. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  402. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  403. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  404. /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
@@ -28,9 +28,6 @@ describe("model intents", () => {
28
28
  expect(resolveModelIntent("openai", "latency-optimized")).toBe(
29
29
  "gpt-5.6-luna",
30
30
  );
31
- expect(resolveModelIntent("gemini", "cost-optimized")).toBe(
32
- "gemini-3.1-flash-lite",
33
- );
34
31
  expect(resolveModelIntent("gemini", "latency-optimized")).toBe(
35
32
  "gemini-3.1-flash-lite",
36
33
  );
@@ -429,7 +429,7 @@ describe("Outlook messaging provider", () => {
429
429
  describe("sendMessage", () => {
430
430
  test("sends a new message with correct recipient, subject, and body", async () => {
431
431
  const conn = createMockConnection();
432
- const result = await outlookMessagingProvider.sendMessage!(
432
+ const result = await outlookMessagingProvider.sendMessage(
433
433
  conn,
434
434
  "recipient@example.com",
435
435
  "Hello!",
@@ -452,7 +452,7 @@ describe("Outlook messaging provider", () => {
452
452
 
453
453
  test("uses empty string for subject when not provided", async () => {
454
454
  const conn = createMockConnection();
455
- await outlookMessagingProvider.sendMessage!(
455
+ await outlookMessagingProvider.sendMessage(
456
456
  conn,
457
457
  "recipient@example.com",
458
458
  "Hello!",
@@ -471,7 +471,7 @@ describe("Outlook messaging provider", () => {
471
471
 
472
472
  test("calls replyToMessage when inReplyTo is provided", async () => {
473
473
  const conn = createMockConnection();
474
- const result = await outlookMessagingProvider.sendMessage!(
474
+ const result = await outlookMessagingProvider.sendMessage(
475
475
  conn,
476
476
  "conv-id",
477
477
  "Reply text",
@@ -493,7 +493,7 @@ describe("Outlook messaging provider", () => {
493
493
 
494
494
  test("attaches files to a new message as Graph file attachments", async () => {
495
495
  const conn = createMockConnection();
496
- await outlookMessagingProvider.sendMessage!(
496
+ await outlookMessagingProvider.sendMessage(
497
497
  conn,
498
498
  "recipient@example.com",
499
499
  "See attached",
@@ -530,7 +530,7 @@ describe("Outlook messaging provider", () => {
530
530
 
531
531
  test("forwards attachments to replyToMessage when replying", async () => {
532
532
  const conn = createMockConnection();
533
- await outlookMessagingProvider.sendMessage!(
533
+ await outlookMessagingProvider.sendMessage(
534
534
  conn,
535
535
  "conv-id",
536
536
  "Reply body",
@@ -563,7 +563,7 @@ describe("Outlook messaging provider", () => {
563
563
 
564
564
  test("throws when connection is undefined", async () => {
565
565
  await expect(
566
- outlookMessagingProvider.sendMessage!(
566
+ outlookMessagingProvider.sendMessage(
567
567
  undefined,
568
568
  "recipient@example.com",
569
569
  "Hello!",
@@ -19,9 +19,7 @@ mock.module("../providers/platform-proxy/context.js", () => ({
19
19
  }),
20
20
  }));
21
21
 
22
- const actualEnv = await import("../config/env.js");
23
22
  mock.module("../config/env.js", () => ({
24
- ...actualEnv,
25
23
  getPlatformAssistantId: () => platformAssistantId,
26
24
  }));
27
25
 
@@ -129,9 +129,6 @@ const BASELINE: Record<string, readonly string[]> = {
129
129
  "../../../../daemon/embedding-reconcile.js",
130
130
  "../../../../daemon/trust-context.js",
131
131
  "../../../../daemon/turn-latency-sub-spans.js",
132
- // mcp-setup capability cards list configured server names from the
133
- // workspace mcp.json document. No plugin-api equivalent.
134
- "../../../../mcp/workspace-mcp-config.js",
135
132
  "../../../../notifications/background-failure-signal.js",
136
133
  "../../../../persistence/checkpoints.js",
137
134
  "../../../../persistence/conversation-types.js",
@@ -213,16 +210,6 @@ const BASELINE: Record<string, readonly string[]> = {
213
210
  "../../../persistence/job-handlers/message-lexical.js",
214
211
  "../../../persistence/job-utils.js",
215
212
  "../../../persistence/jobs-store.js",
216
- // The retrospective cursor is a `(createdAt, id)` bound that must keep
217
- // working after its message row is deleted. The resolver lives beside
218
- // the persistence after-reads it also drives, so the plugin's
219
- // accounting imports it rather than re-deriving the bound. No
220
- // plugin-api equivalent.
221
- "../../../persistence/message-cursor.js",
222
- // Named any-state `createdAt` lookup the cursor bookkeeping uses for
223
- // forks and the timestamp backfill; the messages-read boundary guard
224
- // requires the read to live in persistence. No plugin-api equivalent.
225
- "../../../persistence/message-reads.js",
226
213
  "../../../persistence/raw-query.js",
227
214
  "../../../persistence/schema/index.js",
228
215
  "../../../prompts/persona-resolver.js",
@@ -8,7 +8,6 @@ import {
8
8
  getCAPath,
9
9
  issueLeafCert,
10
10
  } from "../outbound-proxy/index.js";
11
- import { writeCombinedCABundle } from "../util/ca-bundle.js";
12
11
 
13
12
  let dataDir: string;
14
13
 
@@ -20,40 +19,6 @@ afterAll(async () => {
20
19
  await rm(dataDir, { recursive: true, force: true });
21
20
  });
22
21
 
23
- test("combined trust verifies certificates from both CA sources", async () => {
24
- const roots = [join(dataDir, "system"), join(dataDir, "extra")];
25
- const leaves: string[] = [];
26
- for (const root of roots) {
27
- await ensureLocalCA(root);
28
- const caDir = join(root, "proxy-ca");
29
- await issueLeafCert(caDir, "example.com");
30
- leaves.push(join(caDir, "issued", "example.com.pem"));
31
- }
32
- const bundle = join(dataDir, "combined.pem");
33
- await writeCombinedCABundle(
34
- getCAPath(roots[0]!),
35
- getCAPath(roots[1]!),
36
- bundle,
37
- );
38
- const verify = Bun.spawn(
39
- ["openssl", "verify", "-CAfile", bundle, ...leaves],
40
- {
41
- stdout: "pipe",
42
- stderr: "pipe",
43
- windowsHide: true,
44
- },
45
- );
46
- const [code, output, error] = await Promise.all([
47
- verify.exited,
48
- new Response(verify.stdout).text(),
49
- new Response(verify.stderr).text(),
50
- ]);
51
- expect({ code, error }).toEqual({ code: 0, error: "" });
52
- for (const leaf of leaves) {
53
- expect(output).toContain(`${leaf}: OK`);
54
- }
55
- });
56
-
57
22
  describe("ensureLocalCA", () => {
58
23
  test("creates CA cert and key with correct permissions", async () => {
59
24
  await ensureLocalCA(dataDir);
@@ -60,7 +60,7 @@ function makeConfig(overrides: Partial<AssistantConfig> = {}): AssistantConfig {
60
60
  return {
61
61
  skills: {
62
62
  entries: {},
63
- load: { extraDirs: [] },
63
+ load: { extraDirs: [], watch: true, watchDebounceMs: 250 },
64
64
  install: { nodeManager: "npm" },
65
65
  allowBundled: null,
66
66
  remoteProviders: {
@@ -28,7 +28,7 @@ function makeConfig(overrides: Partial<AssistantConfig> = {}): AssistantConfig {
28
28
  return {
29
29
  skills: {
30
30
  entries: {},
31
- load: { extraDirs: [] },
31
+ load: { extraDirs: [], watch: true, watchDebounceMs: 250 },
32
32
  install: { nodeManager: "npm" },
33
33
  allowBundled: null,
34
34
  remoteProviders: {
@@ -233,7 +233,7 @@ describe("resolveSkillStates with feature flags", () => {
233
233
  const config = makeConfig({
234
234
  skills: {
235
235
  entries: { [DECLARED_SKILL_ID]: { enabled: true } },
236
- load: { extraDirs: [] },
236
+ load: { extraDirs: [], watch: true, watchDebounceMs: 250 },
237
237
  install: { nodeManager: "npm" },
238
238
  allowBundled: null,
239
239
  remoteProviders: {
@@ -0,0 +1,56 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ extractPromptSpeakerMetadata,
5
+ SpeakerIdentityTracker,
6
+ } from "../calls/speaker-identification.js";
7
+
8
+ describe("speaker-identification", () => {
9
+ test("extractPromptSpeakerMetadata: reads top-level and nested fields", () => {
10
+ const metadata = extractPromptSpeakerMetadata({
11
+ speaker_id: "spk-7",
12
+ speaker_label: "Conference room mic",
13
+ speaker_confidence: "0.88",
14
+ metadata: {
15
+ participantId: "participant-22",
16
+ },
17
+ });
18
+
19
+ expect(metadata.speakerId).toBe("spk-7");
20
+ expect(metadata.speakerLabel).toBe("Conference room mic");
21
+ expect(metadata.speakerConfidence).toBe(0.88);
22
+ expect(metadata.participantId).toBe("participant-22");
23
+ });
24
+
25
+ test("SpeakerIdentityTracker: keeps stable identity for provider speaker id", () => {
26
+ const tracker = new SpeakerIdentityTracker();
27
+
28
+ const first = tracker.identifySpeaker({
29
+ speakerId: "speaker-a",
30
+ speakerName: "Aaron",
31
+ speakerConfidence: 0.93,
32
+ });
33
+ const second = tracker.identifySpeaker({
34
+ speakerId: "speaker-a",
35
+ speakerName: "Aaron",
36
+ speakerConfidence: 0.81,
37
+ });
38
+
39
+ expect(first.speakerId).toBe("speaker-a");
40
+ expect(first.speakerLabel).toBe("Aaron");
41
+ expect(first.source).toBe("provider");
42
+ expect(second.speakerId).toBe("speaker-a");
43
+ expect(second.speakerLabel).toBe("Aaron");
44
+ expect(second.speakerConfidence).toBe(0.81);
45
+ expect(tracker.listProfiles()).toHaveLength(1);
46
+ });
47
+
48
+ test("SpeakerIdentityTracker: falls back to inferred primary speaker without provider ids", () => {
49
+ const tracker = new SpeakerIdentityTracker();
50
+ const speaker = tracker.identifySpeaker({});
51
+
52
+ expect(speaker.speakerId).toBe("primary-speaker");
53
+ expect(speaker.speakerLabel).toBe("Speaker 1");
54
+ expect(speaker.source).toBe("inferred");
55
+ });
56
+ });
@@ -249,23 +249,14 @@ describe("createResolveToolsCallback — toolContextPin", () => {
249
249
  });
250
250
  }
251
251
 
252
- test("control: without a pin, a clientless fork drops client-gated tools but keeps host and UI tools", () => {
252
+ test("control: without a pin, a clientless fork drops every client-gated tool from the wire", () => {
253
253
  projectedSkillToolNames = [];
254
254
  const resolve = createResolveToolsCallback(
255
255
  CLIENT_GATED_DEFS,
256
256
  clientlessExecutionCtx(),
257
257
  )!;
258
258
 
259
- // Host tool definitions stay on the wire for background turns, and
260
- // ui_show stays because background UI surfaces persist and return. The
261
- // executor rejects host tools on explicitly non-interactive turns before
262
- // dispatch; ask_question and request_system_permission remain
263
- // client-gated at resolution.
264
- expect(resolve(EMPTY_HISTORY).map((t) => t.name)).toEqual([
265
- "remember",
266
- "host_bash",
267
- "ui_show",
268
- ]);
259
+ expect(resolve(EMPTY_HISTORY).map((t) => t.name)).toEqual(["remember"]);
269
260
  });
270
261
 
271
262
  test("a desktop-source pin restores the host/UI/client tool defs on the wire", () => {
@@ -300,14 +291,7 @@ describe("createResolveToolsCallback — toolContextPin", () => {
300
291
  }),
301
292
  )!;
302
293
 
303
- // Host tool definitions stay on the wire for background turns, and
304
- // ui_show survives the clientless pin: it persists and returns. The
305
- // executor rejects host tools on explicitly non-interactive turns.
306
- expect(resolve(EMPTY_HISTORY).map((t) => t.name)).toEqual([
307
- "remember",
308
- "host_bash",
309
- "ui_show",
310
- ]);
294
+ expect(resolve(EMPTY_HISTORY).map((t) => t.name)).toEqual(["remember"]);
311
295
  });
312
296
 
313
297
  test("invariant: a pinned-in tool is on the wire but can never execute", async () => {
@@ -3447,9 +3447,8 @@ describe("Subagent advisor-role consult", () => {
3447
3447
  });
3448
3448
 
3449
3449
  test("advisor consults still run when the parent conversation is gone", async () => {
3450
- // Advisor consults do not look up the parent conversation for a skill
3451
- // catalog snapshot. An evicted parent still gets a consult; the context
3452
- // pack loads the catalog from disk independently.
3450
+ // The parent is looked up only for its warm skill catalog, so an evicted
3451
+ // conversation costs a section of the context pack, not the consult.
3453
3452
  mockFindConversation = () => undefined;
3454
3453
  const { captured, restore } = stubSpawn();
3455
3454
  try {
@@ -455,11 +455,10 @@ describe("resolveCallTtsProvider with requiresPcmAudio", () => {
455
455
  expect(result.provider?.id).toBe("elevenlabs");
456
456
  });
457
457
 
458
- test("without requiresPcmAudio the configured provider is not swapped for playability", async () => {
458
+ test("without requiresPcmAudio the configured provider is not swapped", async () => {
459
459
  testConfig.services.tts.provider = "deepgram";
460
- storedKeys["deepgram"] = "dg-key";
461
- // The CR transport path does not consult the media-stream playability
462
- // capability.
460
+ // No credentials at all — the CR transport path does not consult the
461
+ // media-stream playability capability.
463
462
  registerStubProvider("deepgram", async () => {
464
463
  return { audio: Buffer.from("x"), contentType: "audio/mpeg" };
465
464
  });
@@ -469,37 +468,6 @@ describe("resolveCallTtsProvider with requiresPcmAudio", () => {
469
468
  expect(result.useSynthesizedPath).toBe(true);
470
469
  expect(result.audioFormat).toBe("mp3");
471
470
  });
472
-
473
- test("managed speech stands in for a configured provider whose credential is missing", async () => {
474
- testConfig.services.tts.provider = "deepgram";
475
- // No deepgram key, managed speech available: the phone speaks through
476
- // managed speech, the same substitution live voice makes.
477
- registerStubProvider("deepgram", async () => {
478
- throw new Error("should not be used");
479
- });
480
- registerStubProvider("vellum", async () => {
481
- return { audio: Buffer.from("x"), contentType: "audio/mpeg" };
482
- });
483
-
484
- const result = await resolveCallTtsProvider();
485
- expect(result.provider?.id).toBe("vellum");
486
- expect(result.useSynthesizedPath).toBe(true);
487
- });
488
-
489
- test("without managed speech a credential-less configured provider is kept", async () => {
490
- mockManagedSpeechAvailable = false;
491
- try {
492
- testConfig.services.tts.provider = "deepgram";
493
- registerStubProvider("deepgram", async () => {
494
- return { audio: Buffer.from("x"), contentType: "audio/mpeg" };
495
- });
496
-
497
- const result = await resolveCallTtsProvider();
498
- expect(result.provider?.id).toBe("deepgram");
499
- } finally {
500
- mockManagedSpeechAvailable = true;
501
- }
502
- });
503
471
  });
504
472
 
505
473
  // ---------------------------------------------------------------------------
@@ -616,7 +584,6 @@ describe("speakSystemPrompt mid-stream failure after audio started", () => {
616
584
  test("non-PCM transport: skips the native text fallback — no full-prompt re-speak", async () => {
617
585
  testConfig.services.tts.provider = "fish-audio";
618
586
  testConfig.services.tts.providers["fish-audio"].referenceId = "ref-123";
619
- storedKeys["fish-audio"] = "fa-key";
620
587
 
621
588
  const fishStream = jest.fn(failAfterFirstChunk());
622
589
  registerStreamingStubProvider("fish-audio", fishStream);
@@ -690,7 +657,6 @@ describe("speakSystemPrompt aborted synthesis", () => {
690
657
  test("non-PCM transport with native-fallback provider: abort skips the text fallback and end-of-turn", async () => {
691
658
  testConfig.services.tts.provider = "fish-audio";
692
659
  testConfig.services.tts.providers["fish-audio"].referenceId = "ref-123";
693
- storedKeys["fish-audio"] = "fa-key";
694
660
 
695
661
  const controller = new AbortController();
696
662
  controller.abort();
@@ -776,7 +742,6 @@ describe("speakSystemPrompt aborted synthesis", () => {
776
742
  test("provider AbortError without any signal is a failure — non-PCM native fallback still runs", async () => {
777
743
  testConfig.services.tts.provider = "fish-audio";
778
744
  testConfig.services.tts.providers["fish-audio"].referenceId = "ref-123";
779
- storedKeys["fish-audio"] = "fa-key";
780
745
 
781
746
  const fishSynthesize = jest.fn(async () => {
782
747
  throw new DOMException("socket torn down", "AbortError");
@@ -136,10 +136,6 @@ describe("vellum-self-knowledge skill", () => {
136
136
  const result = await executeSkillLoad({ skill: "vellum-self-knowledge" });
137
137
  expect(result.content).toContain("## Critical Rule");
138
138
  expect(result.content).toContain("Never answer from memory");
139
- expect(result.content).toContain("distinct, legacy Vellum product");
140
- expect(result.content).toContain(
141
- "Never use it to answer questions about this Vellum",
142
- );
143
139
  });
144
140
 
145
141
  // ── Resolution order ─────────────────────────────────────────────────
@@ -1,21 +1,13 @@
1
- /**
2
- * Tests for `startVoiceTurn`'s turn flow against real persistence: delta and
3
- * error forwarding, abort handling, persisted channel metadata, the auto-built
4
- * phone control prompt, and the approval-policy split between guardian and
5
- * non-guardian callers. The sibling `voice-session-bridge.test.ts` covers the
6
- * routing legs, transcript hygiene, tool-event forwarding, and the lock and
7
- * teardown races against scripted doubles.
8
- */
9
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
10
2
 
11
- import { setConfig } from "../../__tests__/helpers/set-config.js";
12
- import type { AssistantEvent } from "../../api/index.js";
3
+ import type { AssistantEvent } from "../api/index.js";
13
4
  import type {
14
5
  TurnChannelContext,
15
6
  TurnInterfaceContext,
16
- } from "../../channels/types.js";
17
- import type { Conversation } from "../../daemon/conversation.js";
18
- import { persistUserMessage as persistUserMessageImpl } from "../../daemon/conversation-messaging.js";
7
+ } from "../channels/types.js";
8
+ import type { Conversation } from "../daemon/conversation.js";
9
+ import { persistUserMessage as persistUserMessageImpl } from "../daemon/conversation-messaging.js";
10
+ import { setConfig } from "./helpers/set-config.js";
19
11
 
20
12
  /** Seed the config the voice bridge reads: disclosure copy, plus disabled
21
13
  * secret detection and memory so the real persist path stays inert. */
@@ -27,7 +19,7 @@ function seedVoiceConfig(disclosure: { enabled: boolean; text: string }): void {
27
19
 
28
20
  let voiceConversationFactory: (() => Conversation) | null = null;
29
21
 
30
- mock.module("../../daemon/conversation-store.js", () => ({
22
+ mock.module("../daemon/conversation-store.js", () => ({
31
23
  getOrCreateConversation: async () => {
32
24
  if (!voiceConversationFactory) {
33
25
  throw new Error("voiceConversationFactory not set for test");
@@ -36,18 +28,18 @@ mock.module("../../daemon/conversation-store.js", () => ({
36
28
  },
37
29
  }));
38
30
 
31
+ import { CALL_OPENING_MARKER } from "../calls/voice-control-protocol.js";
32
+ import { startVoiceTurn } from "../calls/voice-session-bridge.js";
39
33
  import {
40
34
  createConversation,
41
35
  getMessages,
42
- } from "../../persistence/conversation-crud.js";
43
- import { getDb } from "../../persistence/db-connection.js";
44
- import { initializeDb } from "../../persistence/db-init.js";
36
+ } from "../persistence/conversation-crud.js";
37
+ import { getDb } from "../persistence/db-connection.js";
38
+ import { initializeDb } from "../persistence/db-init.js";
45
39
  import {
46
40
  assistantEventHub,
47
41
  broadcastMessage,
48
- } from "../../runtime/assistant-event-hub.js";
49
- import { CALL_OPENING_MARKER } from "../voice-control-protocol.js";
50
- import { startVoiceTurn } from "../voice-session-bridge.js";
42
+ } from "../runtime/assistant-event-hub.js";
51
43
 
52
44
  await initializeDb();
53
45
 
@@ -1,10 +1,13 @@
1
1
  /**
2
2
  * The gate that decides whether a watch retrospective can report at all.
3
3
  *
4
- * A retrospective runs as a `clientless` wake, but its report continues to
5
- * use the post-turn renderer so the report lands after its tool call has been
6
- * persisted. The core UI tools remain available on that turn for other
7
- * background work, so this file pins both contracts against the real registry.
4
+ * A retrospective runs as a `clientless` wake, which pins the turn
5
+ * non-interactive. `conversation-tool-setup` gates the whole `ui_surface`
6
+ * family on a client being present, so in that turn `ui_show` is not denied,
7
+ * it is absent: a retrospective told to call it can only tell the user it
8
+ * cannot. Nothing about the card's schema, its renderer, or the prompt's
9
+ * wording reveals that, which is why it is asserted here against the real
10
+ * registry rather than assumed anywhere else.
8
11
  */
9
12
 
10
13
  import { afterAll, describe, expect, test } from "bun:test";
@@ -51,14 +54,20 @@ describe("watch retrospective tool availability", () => {
51
54
  ).toBe(true);
52
55
  });
53
56
 
54
- test("core UI tools stay available on a clientless turn", async () => {
57
+ test("ui_show is absent from a clientless turn", async () => {
55
58
  await initializeTools();
56
59
  const ctx = clientlessContext();
57
60
 
58
- for (const name of ["ui_show", "ui_update", "ui_dismiss"]) {
59
- expect(isToolActiveForContext(name, ctx)).toBe(true);
60
- }
61
+ // The reason the report does not go through `ui_show`. If this ever flips
62
+ // to true, the extra tool above can be reconsidered; while it is false,
63
+ // routing the retrospective's card through `ui_show` produces a turn that
64
+ // cannot report at all.
65
+ expect(isToolActiveForContext("ui_show", ctx)).toBe(false);
66
+ expect(isToolActiveForContext("ui_update", ctx)).toBe(false);
67
+ expect(isToolActiveForContext("ui_dismiss", ctx)).toBe(false);
61
68
 
69
+ // And the gate really is about the client, not about the tools being
70
+ // unregistered: with one attached, the same names are active.
62
71
  const withClient = clientfulContext();
63
72
  expect(isToolActiveForContext("ui_show", withClient)).toBe(true);
64
73
  });
@@ -4,7 +4,6 @@ import {
4
4
  existsSync,
5
5
  mkdirSync,
6
6
  readFileSync,
7
- renameSync,
8
7
  rmSync,
9
8
  statSync,
10
9
  symlinkSync,
@@ -524,31 +523,6 @@ describe("WorkspaceGitService", () => {
524
523
  expect(trackedFiles()).not.toContain("gone-b.txt");
525
524
  expect(trackedFiles()).not.toContain("gone-c.txt");
526
525
  });
527
-
528
- test("batched rename stages origin and destination even when they split", async () => {
529
- const service = new WorkspaceGitService(testDir);
530
- await service.ensureInitialized();
531
-
532
- writeFileSync(join(testDir, "old-name.txt"), "moved");
533
- await service.commitChanges("Seed rename source");
534
-
535
- renameSync(join(testDir, "old-name.txt"), join(testDir, "new-name.txt"));
536
- for (const name of ["x0.txt", "x1.txt", "x2.txt", "x3.txt"]) {
537
- writeFileSync(join(testDir, name), name);
538
- }
539
-
540
- await withStageBatchSize(2, async () => {
541
- await service.commitChanges("Rename across batches");
542
- });
543
-
544
- expect(trackedFiles()).toContain("new-name.txt");
545
- expect(trackedFiles()).not.toContain("old-name.txt");
546
- const status = execFileSync("git", ["status", "--porcelain"], {
547
- cwd: testDir,
548
- encoding: "utf-8",
549
- }).trim();
550
- expect(status).toBe("");
551
- });
552
526
  });
553
527
 
554
528
  describe("getStatus", () => {