@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-staging.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 (439) 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/docs/guardian-request-flow.md +0 -16
  5. package/openapi.yaml +49 -291
  6. package/package.json +1 -1
  7. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  8. package/src/__tests__/app-compiler.test.ts +0 -6
  9. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  10. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  11. package/src/__tests__/app-source-watcher.test.ts +218 -0
  12. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  13. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  14. package/src/__tests__/computer-use-tools.test.ts +5 -17
  15. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  16. package/src/__tests__/config-schema.test.ts +29 -28
  17. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  18. package/src/__tests__/config-watcher.test.ts +8 -23
  19. package/src/__tests__/connection-model-compat.test.ts +2 -2
  20. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  21. package/src/__tests__/conversation-pairing.test.ts +0 -26
  22. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  23. package/src/__tests__/conversation-queue.test.ts +207 -48
  24. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  25. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  26. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  27. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  28. package/src/__tests__/conversation-title-service.test.ts +10 -14
  29. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  30. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  31. package/src/__tests__/credential-record-retire.test.ts +1 -171
  32. package/src/__tests__/credential-routes.test.ts +3 -212
  33. package/src/__tests__/credential-security-invariants.test.ts +2 -4
  34. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  35. package/src/__tests__/document-sync-tags.test.ts +0 -25
  36. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  37. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  38. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  39. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  40. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  41. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  42. package/src/__tests__/host-file-proxy.test.ts +23 -11
  43. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  44. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  45. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  46. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  47. package/src/__tests__/mcp-health-check.test.ts +11 -8
  48. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  49. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  51. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  52. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  53. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  54. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  55. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  56. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  57. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  58. package/src/__tests__/model-intents.test.ts +0 -3
  59. package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
  60. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  61. package/src/__tests__/platform-callback-registration.test.ts +16 -8
  62. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  63. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  64. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  66. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  67. package/src/__tests__/speaker-identification.test.ts +56 -0
  68. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  69. package/src/__tests__/subagent-tools.test.ts +2 -3
  70. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  71. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  72. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  73. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  74. package/src/__tests__/workspace-git-service.test.ts +0 -26
  75. package/src/acp/__tests__/agent-process.test.ts +4 -258
  76. package/src/acp/__tests__/auth-required.test.ts +0 -96
  77. package/src/acp/__tests__/client-handler.test.ts +2 -90
  78. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  79. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  80. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  81. package/src/acp/__tests__/session-manager.test.ts +4 -895
  82. package/src/acp/agent-process.test.ts +1 -4
  83. package/src/acp/agent-process.ts +9 -94
  84. package/src/acp/auth-required.ts +1 -50
  85. package/src/acp/auto-install.test.ts +7 -9
  86. package/src/acp/client-handler.ts +3 -16
  87. package/src/acp/resolve-agent.test.ts +6 -220
  88. package/src/acp/resolve-agent.ts +23 -88
  89. package/src/acp/session-manager.test.ts +3 -196
  90. package/src/acp/session-manager.ts +18 -441
  91. package/src/acp/types.ts +5 -50
  92. package/src/api/events/app-files-changed.ts +3 -4
  93. package/src/api/events/notification-intent.ts +0 -2
  94. package/src/api/index.ts +0 -6
  95. package/src/apps/app-store.ts +1 -1
  96. package/src/bundler/app-compiler.ts +0 -15
  97. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  98. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  99. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  100. package/src/calls/call-constants.ts +4 -24
  101. package/src/calls/call-controller.ts +199 -499
  102. package/src/calls/call-transport.ts +0 -16
  103. package/src/calls/media-stream-output.ts +0 -32
  104. package/src/calls/media-stream-server.ts +30 -82
  105. package/src/calls/media-stream-stt-session.ts +0 -15
  106. package/src/calls/resolve-call-tts-provider.ts +2 -33
  107. package/src/calls/speaker-identification.ts +233 -0
  108. package/src/calls/tts-call-strategy.ts +5 -9
  109. package/src/calls/types.ts +0 -2
  110. package/src/calls/voice-control-protocol.ts +21 -53
  111. package/src/calls/voice-session-bridge.ts +46 -59
  112. package/src/calls/voice-triage-escalate.ts +56 -175
  113. package/src/cli/commands/apps.help.ts +13 -67
  114. package/src/cli/commands/apps.ts +0 -183
  115. package/src/cli/commands/bash.help.ts +13 -8
  116. package/src/cli/commands/bash.ts +25 -7
  117. package/src/cli/commands/channels/index.help.ts +2 -70
  118. package/src/cli/commands/channels/index.ts +3 -16
  119. package/src/cli/commands/credentials.help.ts +2 -6
  120. package/src/cli/commands/credentials.ts +2 -2
  121. package/src/cli/commands/mcp.help.ts +8 -8
  122. package/src/cli/commands/mcp.ts +1 -1
  123. package/src/cli/commands/roadmap.help.ts +1 -5
  124. package/src/cli/commands/roadmap.ts +1 -1
  125. package/src/cli/lib/bundled-marketplace.json +90 -103
  126. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  127. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  128. package/src/config/__tests__/platform-rehydration.test.ts +9 -99
  129. package/src/config/acp-defaults.test.ts +3 -13
  130. package/src/config/acp-defaults.ts +6 -23
  131. package/src/config/acp-schema.ts +2 -30
  132. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  133. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  134. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  135. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  136. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  137. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  138. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  139. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  140. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  141. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  142. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  143. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  144. package/src/config/default-profile-catalog.ts +1 -1
  145. package/src/config/env.ts +2 -2
  146. package/src/config/feature-flag-registry.json +12 -24
  147. package/src/config/loader.ts +0 -1
  148. package/src/config/memory-v3-gate.test.ts +0 -31
  149. package/src/config/memory-v3-gate.ts +16 -20
  150. package/src/config/platform-rehydration.ts +27 -11
  151. package/src/config/schema.ts +2 -2
  152. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  153. package/src/config/schemas/calls.ts +28 -1
  154. package/src/config/schemas/live-voice.ts +173 -1
  155. package/src/config/schemas/mcp.ts +1 -1
  156. package/src/config/schemas/memory-retrospective.ts +0 -10
  157. package/src/config/schemas/services.ts +0 -8
  158. package/src/config/schemas/skills.ts +14 -0
  159. package/src/credential-execution/process-manager.test.ts +19 -18
  160. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  161. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  162. package/src/daemon/app-source-watcher.ts +218 -0
  163. package/src/daemon/config-watcher.ts +194 -13
  164. package/src/daemon/conversation-process.ts +64 -35
  165. package/src/daemon/conversation-skill-tools.ts +31 -13
  166. package/src/daemon/conversation-store.ts +1 -1
  167. package/src/daemon/conversation-surfaces.ts +8 -10
  168. package/src/daemon/conversation-tool-setup.ts +43 -37
  169. package/src/daemon/conversation.ts +3 -0
  170. package/src/daemon/host-bash-proxy.ts +12 -8
  171. package/src/daemon/host-browser-proxy.ts +1 -15
  172. package/src/daemon/host-file-proxy.ts +10 -8
  173. package/src/daemon/host-transfer-proxy.ts +18 -14
  174. package/src/daemon/lifecycle.ts +5 -0
  175. package/src/daemon/mcp-reload-service.ts +5 -5
  176. package/src/daemon/message-types/sync.ts +0 -1
  177. package/src/daemon/orphan-reaper.ts +1 -1
  178. package/src/daemon/providers-setup.ts +1 -1
  179. package/src/daemon/shutdown-handlers.ts +9 -1
  180. package/src/daemon/skill-memory-refresh.ts +0 -64
  181. package/src/daemon/tool-side-effects.ts +18 -7
  182. package/src/home/__tests__/feed-writer.test.ts +0 -22
  183. package/src/home/feed-writer.ts +2 -11
  184. package/src/hooks/types.ts +0 -33
  185. package/src/inbound/platform-callback-registration.ts +5 -4
  186. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  187. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  188. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  189. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  190. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  191. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  192. package/src/live-voice/live-voice-session.ts +693 -213
  193. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  194. package/src/live-voice/protocol.ts +2 -0
  195. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  196. package/src/mcp/effective-config.ts +3 -3
  197. package/src/mcp/mcp-header-store.ts +45 -29
  198. package/src/mcp/startup.ts +4 -8
  199. package/src/messaging/provider.ts +3 -10
  200. package/src/messaging/providers/callback-routing.ts +0 -18
  201. package/src/messaging/providers/channel-transport.ts +0 -56
  202. package/src/messaging/providers/discord/transport.ts +0 -17
  203. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  204. package/src/messaging/providers/slack/adapter.ts +44 -7
  205. package/src/messaging/providers/slack/transport.ts +0 -16
  206. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  207. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  208. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  209. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  210. package/src/messaging/providers/whatsapp/client.ts +29 -0
  211. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  212. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  213. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  214. package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
  215. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  216. package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
  217. package/src/notifications/adapters/macos.ts +0 -3
  218. package/src/notifications/assistant-reply-producer.ts +3 -8
  219. package/src/notifications/conversation-pairing.ts +16 -36
  220. package/src/notifications/delivered-post-record.ts +1 -11
  221. package/src/notifications/guardian-feed-projection.ts +5 -125
  222. package/src/notifications/home-feed-side-effect.ts +7 -55
  223. package/src/notifications/schedule-result-producer.ts +22 -66
  224. package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
  225. package/src/oauth/byo-connection.test.ts +0 -45
  226. package/src/oauth/byo-connection.ts +6 -36
  227. package/src/oauth/connection-resolver.test.ts +0 -73
  228. package/src/oauth/connection-resolver.ts +2 -95
  229. package/src/oauth/seed-providers.ts +0 -165
  230. package/src/outbound-proxy/certs.ts +5 -3
  231. package/src/permissions/checker.test.ts +6 -11
  232. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  233. package/src/persistence/conversation-crud.ts +63 -71
  234. package/src/persistence/conversation-lineage.ts +4 -12
  235. package/src/persistence/conversation-title-service.ts +26 -9
  236. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  237. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  238. package/src/persistence/message-reads.ts +0 -30
  239. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  240. package/src/persistence/schema/memory-core.ts +0 -5
  241. package/src/platform/client.test.ts +2 -4
  242. package/src/platform/client.ts +10 -2
  243. package/src/plugin-api/constants.ts +0 -2
  244. package/src/plugin-api/index.ts +0 -1
  245. package/src/plugin-api/types.ts +0 -2
  246. package/src/plugins/defaults/index.ts +0 -2
  247. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  248. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  249. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  250. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  251. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  252. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  253. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  254. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  255. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  256. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  257. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  258. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  259. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  260. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  261. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  262. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  263. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  264. package/src/plugins/defaults/memory/startup.ts +1 -6
  265. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  266. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  267. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  268. package/src/plugins/defaults/memory/worker.ts +0 -6
  269. package/src/plugins/mcp-servers.ts +75 -15
  270. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  271. package/src/providers/gemini/client.ts +23 -9
  272. package/src/providers/inference/auth.ts +3 -2
  273. package/src/providers/inference/connection-availability.ts +8 -27
  274. package/src/providers/inference/resolve-auth.ts +4 -22
  275. package/src/providers/model-catalog.ts +0 -34
  276. package/src/providers/model-intents.ts +5 -10
  277. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  278. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  279. package/src/providers/openai/chat-completions-provider.ts +78 -192
  280. package/src/providers/openai/codex-models.ts +4 -0
  281. package/src/runtime/AGENTS.md +0 -2
  282. package/src/runtime/auth/same-actor.ts +3 -38
  283. package/src/runtime/http-server.ts +151 -160
  284. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  286. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  287. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  288. package/src/runtime/routes/acp-routes.test.ts +0 -15
  289. package/src/runtime/routes/acp-routes.ts +9 -72
  290. package/src/runtime/routes/app-management-routes.ts +0 -73
  291. package/src/runtime/routes/app-routes.ts +1 -1
  292. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  293. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  294. package/src/runtime/routes/credential-routes.ts +10 -19
  295. package/src/runtime/routes/debug-bash-routes.ts +173 -0
  296. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  297. package/src/runtime/routes/index.ts +2 -4
  298. package/src/runtime/routes/log-export-routes.ts +0 -2
  299. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  300. package/src/runtime/routes/migration-routes.ts +20 -6
  301. package/src/runtime/routes/platform-routes.ts +15 -18
  302. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  303. package/src/runtime/services/conversation-serializer.ts +3 -16
  304. package/src/runtime/sync/resource-sync-events.ts +1 -2
  305. package/src/schedule/worker.ts +1 -1
  306. package/src/security/ces-rpc-record-backend.ts +0 -7
  307. package/src/subagent/consult-context.ts +25 -12
  308. package/src/tools/acp/list-agents.test.ts +1 -3
  309. package/src/tools/acp/spawn.test.ts +11 -146
  310. package/src/tools/acp/spawn.ts +3 -21
  311. package/src/tools/acp/status.ts +3 -40
  312. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  313. package/src/tools/capability-offer.test.ts +2 -22
  314. package/src/tools/capability-offer.ts +1 -16
  315. package/src/tools/computer-use/definitions.ts +2 -4
  316. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  317. package/src/tools/credentials/metadata-store.ts +0 -100
  318. package/src/tools/host-filesystem/edit.test.ts +1 -2
  319. package/src/tools/host-filesystem/edit.ts +2 -2
  320. package/src/tools/host-filesystem/read.test.ts +1 -2
  321. package/src/tools/host-filesystem/read.ts +2 -2
  322. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  323. package/src/tools/host-filesystem/transfer.ts +2 -2
  324. package/src/tools/host-filesystem/write.test.ts +1 -2
  325. package/src/tools/host-filesystem/write.ts +2 -2
  326. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  327. package/src/tools/host-terminal/host-shell.ts +20 -4
  328. package/src/tools/policy-context.ts +7 -6
  329. package/src/tools/subagent/spawn.ts +8 -5
  330. package/src/tools/watch/watch-retro-report.ts +8 -0
  331. package/src/util/__tests__/language-subtag.test.ts +1 -23
  332. package/src/util/fs-watcher-error.ts +36 -0
  333. package/src/util/language-subtag.ts +0 -16
  334. package/src/util/platform.ts +0 -8
  335. package/src/workspace/git-service.ts +54 -5
  336. package/src/workspace/migrations/registry.ts +0 -6
  337. package/scripts/smoke-desktop-window-theme.ts +0 -186
  338. package/src/__tests__/git-porcelain.test.ts +0 -47
  339. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  340. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  341. package/src/__tests__/resolve-app.test.ts +0 -135
  342. package/src/__tests__/service-account-token.test.ts +0 -247
  343. package/src/__tests__/source-fingerprint.test.ts +0 -184
  344. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  345. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  346. package/src/acp/model-config.test.ts +0 -166
  347. package/src/acp/model-config.ts +0 -138
  348. package/src/api/events/acp-session-model-update.test.ts +0 -88
  349. package/src/api/events/acp-session-model-update.ts +0 -46
  350. package/src/apps/resolve-app.ts +0 -81
  351. package/src/apps/source-fingerprint.ts +0 -266
  352. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  353. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  354. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  355. package/src/calls/barge-in-guard.ts +0 -118
  356. package/src/calls/voice-leg-coordinator.ts +0 -189
  357. package/src/calls/voice-progress-cadence.ts +0 -423
  358. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  359. package/src/cli/commands/__tests__/bash.test.ts +0 -53
  360. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  361. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  362. package/src/cli/commands/channels/send.ts +0 -128
  363. package/src/config/__tests__/platform-identity.test.ts +0 -255
  364. package/src/config/acp-agent-write.ts +0 -43
  365. package/src/config/acp-schema.test.ts +0 -81
  366. package/src/config/platform-identity.ts +0 -201
  367. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  368. package/src/config/schemas/voice.ts +0 -150
  369. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  370. package/src/daemon/app-change-notify.ts +0 -45
  371. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  372. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  373. package/src/desktop/desktop-chrome-policy.ts +0 -42
  374. package/src/desktop/desktop-dependencies.test.ts +0 -102
  375. package/src/desktop/desktop-dependencies.ts +0 -306
  376. package/src/desktop/desktop-feature.test.ts +0 -18
  377. package/src/desktop/desktop-feature.ts +0 -19
  378. package/src/desktop/desktop-panel-config.test.ts +0 -135
  379. package/src/desktop/desktop-panel-config.ts +0 -149
  380. package/src/desktop/desktop-session-manager.test.ts +0 -627
  381. package/src/desktop/desktop-session-manager.ts +0 -814
  382. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  383. package/src/desktop/desktop-stream-bridge.ts +0 -214
  384. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  385. package/src/desktop/desktop-wallpaper.ts +0 -113
  386. package/src/desktop/desktop-window-theme.ts +0 -170
  387. package/src/i18n/AGENTS.md +0 -22
  388. package/src/i18n/__tests__/i18n.test.ts +0 -108
  389. package/src/i18n/index.ts +0 -16
  390. package/src/i18n/locales.ts +0 -93
  391. package/src/i18n/messages.ts +0 -61
  392. package/src/i18n/title.ts +0 -25
  393. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  394. package/src/mcp/spec-schema.ts +0 -111
  395. package/src/mcp/workspace-mcp-config.ts +0 -188
  396. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  397. package/src/persistence/conversation-title-placeholders.ts +0 -23
  398. package/src/persistence/message-cursor.ts +0 -78
  399. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  400. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  401. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  402. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  403. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  404. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  405. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  406. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  407. package/src/providers/gemini-thought-signature.test.ts +0 -63
  408. package/src/providers/gemini-thought-signature.ts +0 -44
  409. package/src/providers/inference/service-account-token.ts +0 -248
  410. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  411. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  412. package/src/providers/openai/google-thought-signature.ts +0 -320
  413. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  414. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  415. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  416. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  417. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  418. package/src/runtime/channel-send.ts +0 -316
  419. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  420. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  421. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  422. package/src/runtime/routes/channel-send-routes.ts +0 -85
  423. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  424. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  425. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  426. package/src/security/ces-http-record-backend.ts +0 -120
  427. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  428. package/src/skills/workspace-skill-md-signature.ts +0 -50
  429. package/src/tools/acp/status.test.ts +0 -94
  430. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
  431. package/src/tools/terminal/sanitized-bash.ts +0 -105
  432. package/src/util/ca-bundle.ts +0 -13
  433. package/src/workspace/git-porcelain.ts +0 -66
  434. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  435. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  436. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  437. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  438. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  439. /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
@@ -190,36 +190,6 @@ export function existingMessageIds(
190
190
  );
191
191
  }
192
192
 
193
- /**
194
- * `createdAt` of each of `messageIds` that exists as a row, keyed by id, in
195
- * any state.
196
- *
197
- * Any-state deliberately: a row's `createdAt` is fixed at insert, so its
198
- * completeness does not change the answer, and the callers (retrospective
199
- * cursor bookkeeping) hold ids taken from rows they have already reviewed.
200
- * An empty input returns an empty map without querying.
201
- */
202
- export function messageCreatedAtByIds(
203
- messageIds: readonly string[],
204
- opts?: { db?: MessageReadHandle },
205
- ): Map<string, number> {
206
- const db = opts?.db ?? getDb();
207
- const result = new Map<string, number>();
208
- // Chunked so a whole-conversation id list stays under SQLite's bound
209
- // parameter limit.
210
- for (let offset = 0; offset < messageIds.length; offset += 500) {
211
- const rows = db
212
- .select({ id: messages.id, createdAt: messages.createdAt })
213
- .from(messages)
214
- .where(inArray(messages.id, messageIds.slice(offset, offset + 500)))
215
- .all();
216
- for (const row of rows) {
217
- result.set(row.id, row.createdAt);
218
- }
219
- }
220
- return result;
221
- }
222
-
223
193
  /**
224
194
  * The conversation that owns `messageId`, in any state, or null when the
225
195
  * message does not exist.
@@ -1,5 +1,4 @@
1
1
  import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
- import { tableExists } from "./schema-introspection.js";
3
2
 
4
3
  /**
5
4
  * Add a required contact_id column to assistant_ingress_invites.
@@ -11,16 +10,8 @@ import { tableExists } from "./schema-introspection.js";
11
10
  * 1. Add the column as nullable.
12
11
  * 2. Delete legacy rows that have no contact binding (NULL).
13
12
  * 3. Rebuild the table to enforce NOT NULL (SQLite cannot ALTER COLUMN).
14
- *
15
- * The rebuild copies whichever session-id column is live:
16
- * `source_conversation_id` (after migrateRenameCreatedBySessionIdColumns)
17
- * or `created_by_session_id`.
18
13
  */
19
14
  export function migrateInviteContactId(database: DrizzleDb): void {
20
- if (!tableExists(database, "assistant_ingress_invites")) {
21
- return;
22
- }
23
-
24
15
  const raw = getSqliteFrom(database);
25
16
 
26
17
  const cols = (
@@ -29,28 +20,25 @@ export function migrateInviteContactId(database: DrizzleDb): void {
29
20
  notnull: number;
30
21
  }>
31
22
  ).map((c) => ({ name: c.name, notnull: c.notnull }));
32
- const colNames = new Set(cols.map((c) => c.name));
33
23
 
34
24
  const col = cols.find((c) => c.name === "contact_id");
35
25
 
26
+ // Step 1: Add the column as nullable
36
27
  if (!col) {
37
28
  raw.exec(
38
29
  /*sql*/ `ALTER TABLE assistant_ingress_invites ADD COLUMN contact_id TEXT`,
39
30
  );
40
31
  }
41
32
 
33
+ // Step 2: Delete legacy rows with no contact binding
42
34
  raw.exec(
43
35
  /*sql*/ `DELETE FROM assistant_ingress_invites WHERE contact_id IS NULL OR contact_id = ''`,
44
36
  );
45
37
 
38
+ // Step 3: Rebuild the table with NOT NULL on contact_id
46
39
  if (col && col.notnull === 1) {
47
40
  return;
48
- }
49
-
50
- const sessionCol = colNames.has("source_conversation_id")
51
- ? "source_conversation_id"
52
- : "created_by_session_id";
53
- const sessionSelect = colNames.has(sessionCol) ? sessionCol : "NULL";
41
+ } // already NOT NULL
54
42
 
55
43
  raw.exec("PRAGMA foreign_keys = OFF");
56
44
  try {
@@ -61,7 +49,7 @@ export function migrateInviteContactId(database: DrizzleDb): void {
61
49
  id TEXT PRIMARY KEY,
62
50
  source_channel TEXT NOT NULL,
63
51
  token_hash TEXT NOT NULL,
64
- ${sessionCol} TEXT,
52
+ created_by_session_id TEXT,
65
53
  note TEXT,
66
54
  max_uses INTEGER NOT NULL DEFAULT 1 CHECK (max_uses > 0),
67
55
  use_count INTEGER NOT NULL DEFAULT 0 CHECK (use_count >= 0),
@@ -82,7 +70,7 @@ export function migrateInviteContactId(database: DrizzleDb): void {
82
70
  );
83
71
 
84
72
  INSERT INTO assistant_ingress_invites_new
85
- SELECT id, source_channel, token_hash, ${sessionSelect}, note,
73
+ SELECT id, source_channel, token_hash, created_by_session_id, note,
86
74
  max_uses, use_count, expires_at, status,
87
75
  redeemed_by_external_user_id, redeemed_by_external_chat_id,
88
76
  redeemed_at, expected_external_user_id, voice_code_hash,
@@ -104,11 +104,6 @@ export const memoryRetrospectiveState = sqliteTable(
104
104
  conversationId: text("conversation_id").primaryKey(),
105
105
  lastProcessedMessageId: text("last_processed_message_id").notNull(),
106
106
  lastRunAt: integer("last_run_at").notNull(),
107
- // `createdAt` of the `last_processed_message_id` row when the pointer was
108
- // written, so the cursor still bounds reads after that row is deleted.
109
- // NULL when unknown. Added lazily by `ensureRetrospectiveCursorColumn`
110
- // (memory-retrospective-state.ts), not by the migration chain.
111
- lastProcessedCreatedAt: integer("last_processed_created_at"),
112
107
  // JSON array of strings — cumulative `remember` contents from prior
113
108
  // retrospective passes (capped; see memory-retrospective-state.ts).
114
109
  // NULL for rows that predate migration 281 or have no saves yet.
@@ -24,9 +24,7 @@ mock.module("../providers/platform-proxy/context.js", () => ({
24
24
  resolveManagedProxyContext: () => mockResolveManagedProxyContext(),
25
25
  }));
26
26
 
27
- const actualEnv = await import("../config/env.js");
28
27
  mock.module("../config/env.js", () => ({
29
- ...actualEnv,
30
28
  getPlatformAssistantId: () => mockAssistantId,
31
29
  }));
32
30
 
@@ -115,11 +113,11 @@ describe("VellumPlatformClient", () => {
115
113
  platformBaseUrl: "",
116
114
  assistantApiKey: "",
117
115
  };
118
- mockAssistantId = "stored-assistant-id";
116
+ mockAssistantId = "";
119
117
  mockSecureKeys = {
120
118
  "vellum:platform_base_url": "https://stored-platform.example.com/",
121
119
  "vellum:assistant_api_key": "stored-api-key",
122
- "vellum:platform_assistant_id": " vault-assistant-id ",
120
+ "vellum:platform_assistant_id": " stored-assistant-id ",
123
121
  };
124
122
 
125
123
  const client = await VellumPlatformClient.create();
@@ -7,7 +7,7 @@
7
7
 
8
8
  import type { PlatformCredentialVerificationStatus } from "@vellumai/service-contracts/platform-credential";
9
9
 
10
- import { resolvePlatformAssistantId } from "../config/platform-identity.js";
10
+ import { getPlatformAssistantId } from "../config/env.js";
11
11
  import { resolveManagedProxyContext } from "../providers/platform-proxy/context.js";
12
12
  import { credentialKey } from "../security/credential-key.js";
13
13
  import { getSecureKeyAsync } from "../security/secure-keys.js";
@@ -63,7 +63,7 @@ async function resolvePlatformClientConfig(): Promise<PlatformClientConfig | nul
63
63
 
64
64
  let baseUrl = ctx.enabled ? ctx.platformBaseUrl : "";
65
65
  let apiKey = ctx.enabled ? ctx.assistantApiKey : "";
66
- const assistantId = await resolvePlatformAssistantId();
66
+ let assistantId = getPlatformAssistantId();
67
67
 
68
68
  // Fall back to credential store for values not yet rehydrated (standalone CLI).
69
69
  if (!baseUrl) {
@@ -76,6 +76,14 @@ async function resolvePlatformClientConfig(): Promise<PlatformClientConfig | nul
76
76
  (await getSecureKeyAsync(credentialKey("vellum", "assistant_api_key"))) ??
77
77
  "";
78
78
  }
79
+ if (!assistantId) {
80
+ assistantId =
81
+ (
82
+ await getSecureKeyAsync(
83
+ credentialKey("vellum", "platform_assistant_id"),
84
+ )
85
+ )?.trim() ?? "";
86
+ }
79
87
 
80
88
  if (!baseUrl || !apiKey) {
81
89
  const level = _missingPrereqsWarned ? "debug" : "warn";
@@ -34,8 +34,6 @@ export const HOOKS = {
34
34
  CONVERSATION_DELETED: "conversation-deleted",
35
35
  /** Fires once when every conversation is wiped at once (the clear-all reset), after the main tables are cleared. Carries no `conversationId`; cleanup hooks wipe their own per-conversation state wholesale. */
36
36
  CONVERSATIONS_CLEARED: "conversations-cleared",
37
- /** Fires once per deleted message row, after the row is removed, carrying the row's `(createdAt, id)` so a hook can settle state that pointed at it. Fire-and-forget cleanup signal, like `conversation-deleted`; whole-conversation deletes dispatch that hook instead. */
38
- MESSAGE_DELETED: "message-deleted",
39
37
  } as const;
40
38
 
41
39
  /** Union of every hook name declared in {@link HOOKS}. */
@@ -110,7 +110,6 @@ export type {
110
110
  HookBroadcast,
111
111
  HookFunction,
112
112
  InitContext,
113
- MessageDeletedContext,
114
113
  ModelProfileInfo,
115
114
  PluginLogger,
116
115
  PostCompactContext,
@@ -16,7 +16,6 @@ export type {
16
16
  ConversationDeletedContext,
17
17
  ConversationsClearedContext,
18
18
  HookBroadcast,
19
- MessageDeletedContext,
20
19
  PluginLogger,
21
20
  PostCompactContext,
22
21
  PostModelCallContext,
@@ -61,7 +60,6 @@ export type {
61
60
  * - `post-model-call` — {@link PostModelCallContext}
62
61
  * - `conversation-deleted` — {@link ConversationDeletedContext}
63
62
  * - `conversations-cleared` — {@link ConversationsClearedContext}
64
- * - `message-deleted`: {@link MessageDeletedContext}
65
63
  */
66
64
  export type HookFunction<TCtx = unknown> = (
67
65
  ctx: TCtx,
@@ -65,7 +65,6 @@ import maxTokensContinuePkg from "./max-tokens-continue/package.json" with { typ
65
65
  import memoryConversationDeleted from "./memory/hooks/conversation-deleted.js";
66
66
  import memoryConversationsCleared from "./memory/hooks/conversations-cleared.js";
67
67
  import memoryInit from "./memory/hooks/init.js";
68
- import memoryMessageDeleted from "./memory/hooks/message-deleted.js";
69
68
  import memoryPostCompact from "./memory/hooks/post-compact.js";
70
69
  import memoryShutdown from "./memory/hooks/shutdown.js";
71
70
  import memoryUserPromptSubmit from "./memory/hooks/user-prompt-submit.js";
@@ -200,7 +199,6 @@ export const defaultMemoryPlugin: Plugin = {
200
199
  "post-compact": memoryPostCompact,
201
200
  "conversation-deleted": memoryConversationDeleted,
202
201
  "conversations-cleared": memoryConversationsCleared,
203
- "message-deleted": memoryMessageDeleted,
204
202
  },
205
203
  injectors: memoryInjectors,
206
204
  };
@@ -434,49 +434,3 @@ describe("ambient camera frames are not retrospective work", () => {
434
434
  expect(hasQualifyingUserMessageAfter(CONV, null)).toBe(true);
435
435
  });
436
436
  });
437
-
438
- describe("retrospective accounting: a cursor survives its row's deletion", () => {
439
- beforeEach(() => {
440
- const db = getDb();
441
- db.run(`DELETE FROM messages`);
442
- db.run(`DELETE FROM conversations`);
443
- createConversation({ id: CONV });
444
- });
445
-
446
- test("a deleted cursor row with a stored timestamp still bounds the count, the slice, and the user-activity probe", () => {
447
- insertRaw({ role: "user", content: TEXT, createdAt: 1_000 });
448
- const reply = insertRaw({
449
- role: "assistant",
450
- content: TEXT,
451
- createdAt: 2_000,
452
- });
453
- // Regenerate: the reply the cursor sits on is discarded and replaced.
454
- getDb().delete(messages).where(eq(messages.id, reply)).run();
455
- const regenerated = insertRaw({
456
- role: "assistant",
457
- content: TEXT,
458
- createdAt: 3_000,
459
- });
460
- const followUp = insertRaw({
461
- role: "user",
462
- content: TEXT,
463
- createdAt: 4_000,
464
- });
465
-
466
- const cursor = { id: reply, createdAt: 2_000 };
467
- expect(countRetrospectiveMessagesAfter(CONV, cursor)).toBe(2);
468
- expect(
469
- getRetrospectiveMessagesAfter(CONV, cursor).map((r) => r.id),
470
- ).toEqual([regenerated, followUp]);
471
- expect(hasQualifyingUserMessageAfter(CONV, cursor)).toBe(true);
472
- });
473
-
474
- test("a deleted cursor row without a timestamp still reads as no new work", () => {
475
- insertRaw({ role: "user", content: TEXT, createdAt: 1_000 });
476
-
477
- const cursor = { id: "gone", createdAt: null };
478
- expect(countRetrospectiveMessagesAfter(CONV, cursor)).toBe(0);
479
- expect(getRetrospectiveMessagesAfter(CONV, cursor)).toEqual([]);
480
- expect(hasQualifyingUserMessageAfter(CONV, cursor)).toBe(false);
481
- });
482
- });
@@ -1,7 +1,5 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
- import type { MessagesAfterRef } from "../../../../persistence/message-cursor.js";
4
-
5
3
  // ---------------------------------------------------------------------------
6
4
  // Mock state — reset between tests.
7
5
  // ---------------------------------------------------------------------------
@@ -19,7 +17,6 @@ let cfgThrows = false;
19
17
  let mockStateRow: {
20
18
  conversationId: string;
21
19
  lastProcessedMessageId: string;
22
- lastProcessedCreatedAt: number | null;
23
20
  lastRunAt: number;
24
21
  rememberedLog: string[];
25
22
  } | null = null;
@@ -27,7 +24,7 @@ let tailQualifies = true;
27
24
  let gateProbeThrows = false;
28
25
  let gateProbeCalls: Array<{
29
26
  conversationId: string;
30
- after: MessagesAfterRef;
27
+ afterMessageId: string | null;
31
28
  }> = [];
32
29
 
33
30
  mock.module("../../../../persistence/conversation-crud.js", () => ({
@@ -71,9 +68,9 @@ mock.module("../memory-retrospective-state.js", () => ({
71
68
  mock.module("../memory-retrospective-accounting.js", () => ({
72
69
  hasQualifyingUserMessageAfter: (
73
70
  conversationId: string,
74
- after: MessagesAfterRef,
71
+ afterMessageId: string | null,
75
72
  ) => {
76
- gateProbeCalls.push({ conversationId, after });
73
+ gateProbeCalls.push({ conversationId, afterMessageId });
77
74
  if (gateProbeThrows) {
78
75
  throw new Error("messages table unavailable");
79
76
  }
@@ -173,11 +170,10 @@ describe("enqueueMemoryRetrospectiveIfEnabled", () => {
173
170
  expect(gateProbeCalls).toHaveLength(0);
174
171
  });
175
172
 
176
- test("gate probes the tail from the state row's cursor, timestamp included", () => {
173
+ test("gate probes the tail from the state row's cursor", () => {
177
174
  mockStateRow = {
178
175
  conversationId: "c1",
179
176
  lastProcessedMessageId: "m9",
180
- lastProcessedCreatedAt: 9_000,
181
177
  lastRunAt: 1,
182
178
  rememberedLog: [],
183
179
  };
@@ -187,7 +183,7 @@ describe("enqueueMemoryRetrospectiveIfEnabled", () => {
187
183
  });
188
184
 
189
185
  expect(gateProbeCalls).toEqual([
190
- { conversationId: "c1", after: { id: "m9", createdAt: 9_000 } },
186
+ { conversationId: "c1", afterMessageId: "m9" },
191
187
  ]);
192
188
  });
193
189
 
@@ -20,7 +20,6 @@ let mockState: StateRow = null;
20
20
  let stateUpserts: Array<{
21
21
  conversationId: string;
22
22
  lastProcessedMessageId: string;
23
- lastProcessedCreatedAt?: number | null;
24
23
  lastRunAt: number;
25
24
  rememberedLog?: string[];
26
25
  }> = [];
@@ -150,7 +149,6 @@ mock.module("../memory-retrospective-state.js", () => ({
150
149
  upsertRetrospectiveState: (args: {
151
150
  conversationId: string;
152
151
  lastProcessedMessageId: string;
153
- lastProcessedCreatedAt?: number | null;
154
152
  lastRunAt: number;
155
153
  rememberedLog?: string[];
156
154
  }) => {
@@ -334,16 +332,15 @@ mock.module("../../../../persistence/jobs-store.js", () => ({
334
332
  },
335
333
  }));
336
334
 
337
- // Retrospective skill improvement is distinct from the v3 tier. Keep v3 live
338
- // while flipping the authoring gate so these tests prove the job reads the
339
- // dedicated predicate rather than using the broader tier predicate.
340
- let mockV3TierActive = true;
341
- let mockSkillImprovementActive = false;
335
+ // The v3-tier gate. Drives both `buildForkInstruction`'s skill-authoring
336
+ // section (proc-to-skills) and the wake's origin pin behavior. Default inactive
337
+ // (remember-only), matching a stock install; tests flip it on to assert the
338
+ // authoring section.
339
+ let mockV3TierActive = false;
342
340
  mock.module("../../../../config/memory-v3-gate.js", () => ({
343
341
  isMemoryEnabled: (config?: { memory?: { enabled?: boolean } }) =>
344
342
  config?.memory?.enabled !== false,
345
343
  isV3TierActive: () => mockV3TierActive,
346
- isSkillImprovementActive: () => mockSkillImprovementActive,
347
344
  isMemoryV3Live: () => mockV3TierActive,
348
345
  usesConceptPageMemory: (memory?: {
349
346
  enabled?: boolean;
@@ -507,8 +504,7 @@ describe("memoryRetrospectiveJob", () => {
507
504
  processingStartedAtById = {};
508
505
  mockResolvedUserSlug = "alice";
509
506
  resolveUserSlugCalls = [];
510
- mockV3TierActive = true;
511
- mockSkillImprovementActive = false;
507
+ mockV3TierActive = false;
512
508
  });
513
509
 
514
510
  test("first-run happy path: no state row, no prior retrospective, both pointer fields set on success", async () => {
@@ -522,11 +518,6 @@ describe("memoryRetrospectiveJob", () => {
522
518
  }
523
519
  expect(stateUpserts).toHaveLength(1);
524
520
  expect(stateUpserts[0]!.lastProcessedMessageId).toBe("m3");
525
- // The cutoff's `createdAt` rides along so the cursor keeps bounding reads
526
- // after a regenerate deletes m3.
527
- expect(stateUpserts[0]!.lastProcessedCreatedAt).toBe(
528
- Date.parse("2026-05-11T10:10:00Z"),
529
- );
530
521
  expect(lastRunAtBumps).toHaveLength(0);
531
522
  expect(wakeCalls).toHaveLength(1);
532
523
  // Forks off the source so future runs can find it via
@@ -1317,7 +1308,7 @@ describe("memoryRetrospectiveJob", () => {
1317
1308
  });
1318
1309
 
1319
1310
  test("wake allows memory saves + skill authoring and suppresses the internal wake surface", async () => {
1320
- mockSkillImprovementActive = true;
1311
+ mockV3TierActive = true;
1321
1312
  await memoryRetrospectiveJob(makeJob(), stubConfig);
1322
1313
 
1323
1314
  expect(forkCalls).toHaveLength(1);
@@ -1340,9 +1331,8 @@ describe("memoryRetrospectiveJob", () => {
1340
1331
  expect(opts.hintRole).toBe("user");
1341
1332
  });
1342
1333
 
1343
- test("wake is remember-only when skill improvement is disabled on a live v3 tier", async () => {
1344
- mockV3TierActive = true;
1345
- mockSkillImprovementActive = false;
1334
+ test("wake is remember-only when proc-to-skills is inactive", async () => {
1335
+ mockV3TierActive = false;
1346
1336
  await memoryRetrospectiveJob(makeJob(), stubConfig);
1347
1337
 
1348
1338
  expect(wakeCalls).toHaveLength(1);
@@ -2548,7 +2538,7 @@ describe("memoryRetrospectiveJob", () => {
2548
2538
  });
2549
2539
 
2550
2540
  test("proc-to-skills active: instruction carries the pre-check + dedup + companion-file directives", async () => {
2551
- mockSkillImprovementActive = true;
2541
+ mockV3TierActive = true;
2552
2542
 
2553
2543
  await memoryRetrospectiveJob(makeJob(), stubConfig);
2554
2544
 
@@ -6,22 +6,16 @@ import { setConfig } from "../../../../__tests__/helpers/set-config.js";
6
6
  // pipeline (both flags default true under the real loader).
7
7
  setConfig("memory", { enabled: false, v2: { enabled: false } });
8
8
 
9
- import { createConversation } from "../../../../persistence/conversation-crud.js";
10
9
  import {
11
10
  getDb,
12
11
  getMemorySqlite,
13
- resetDb,
14
12
  } from "../../../../persistence/db-connection.js";
15
13
  import { initializeDb } from "../../../../persistence/db-init.js";
16
- import { messages } from "../../../../persistence/schema/index.js";
17
14
  import {
18
- _resetRetrospectiveCursorColumnForTests,
19
15
  appendToRememberedLog,
20
16
  bumpRetrospectiveLastRunAt,
21
- ensureRetrospectiveCursorColumn,
22
17
  forkRetrospectiveState,
23
18
  getRetrospectiveState,
24
- listRetrospectiveStates,
25
19
  REMEMBERED_LOG_MAX_BYTES,
26
20
  REMEMBERED_LOG_MAX_ENTRIES,
27
21
  upsertRetrospectiveState,
@@ -182,219 +176,6 @@ describe("memory-retrospective-state remembered log persistence", () => {
182
176
  });
183
177
  });
184
178
 
185
- describe("memory-retrospective-state cursor timestamp", () => {
186
- beforeEach(() => {
187
- resetTables();
188
- });
189
-
190
- test("upsert persists lastProcessedCreatedAt and both reads return it", async () => {
191
- await upsertRetrospectiveState({
192
- conversationId: "conv-ts",
193
- lastProcessedMessageId: "m1",
194
- lastProcessedCreatedAt: 1_234,
195
- lastRunAt: 1000,
196
- });
197
-
198
- expect(getRetrospectiveState("conv-ts")?.lastProcessedCreatedAt).toBe(
199
- 1_234,
200
- );
201
- expect(
202
- listRetrospectiveStates(10).find((s) => s.conversationId === "conv-ts")
203
- ?.lastProcessedCreatedAt,
204
- ).toBe(1_234);
205
- });
206
-
207
- test("an upsert that omits the timestamp records unknown for the new pointer", async () => {
208
- await upsertRetrospectiveState({
209
- conversationId: "conv-ts",
210
- lastProcessedMessageId: "m1",
211
- lastProcessedCreatedAt: 1_234,
212
- lastRunAt: 1000,
213
- });
214
- await upsertRetrospectiveState({
215
- conversationId: "conv-ts",
216
- lastProcessedMessageId: "m2",
217
- lastRunAt: 2000,
218
- });
219
-
220
- const state = getRetrospectiveState("conv-ts");
221
- expect(state?.lastProcessedMessageId).toBe("m2");
222
- expect(state?.lastProcessedCreatedAt).toBeNull();
223
- });
224
-
225
- test("bumpRetrospectiveLastRunAt leaves the timestamp untouched", async () => {
226
- await upsertRetrospectiveState({
227
- conversationId: "conv-ts",
228
- lastProcessedMessageId: "m1",
229
- lastProcessedCreatedAt: 1_234,
230
- lastRunAt: 1000,
231
- });
232
- await bumpRetrospectiveLastRunAt("conv-ts", 5000);
233
-
234
- const state = getRetrospectiveState("conv-ts");
235
- expect(state?.lastRunAt).toBe(5000);
236
- expect(state?.lastProcessedCreatedAt).toBe(1_234);
237
- });
238
-
239
- test("forking carries the forked pointer's createdAt, read through the main handle", async () => {
240
- const db = getDb();
241
- createConversation({ id: "conv-fork-ts-src" });
242
- createConversation({ id: "conv-fork-ts-dst" });
243
- for (const [id, conversationId] of [
244
- ["src-m1", "conv-fork-ts-src"],
245
- ["dst-m1", "conv-fork-ts-dst"],
246
- ] as const) {
247
- db.insert(messages)
248
- .values({
249
- id,
250
- conversationId,
251
- role: "user",
252
- content: "[]",
253
- createdAt: 4_000,
254
- metadata: null,
255
- })
256
- .run();
257
- }
258
- await upsertRetrospectiveState({
259
- conversationId: "conv-fork-ts-src",
260
- lastProcessedMessageId: "src-m1",
261
- lastProcessedCreatedAt: 4_000,
262
- lastRunAt: 1,
263
- });
264
-
265
- forkRetrospectiveState({
266
- database: db,
267
- sourceConversationId: "conv-fork-ts-src",
268
- forkedConversationId: "conv-fork-ts-dst",
269
- forkedMessageIds: new Map([["src-m1", "dst-m1"]]),
270
- lastCopiedSourceMessageId: "src-m1",
271
- });
272
-
273
- const child = getRetrospectiveState("conv-fork-ts-dst");
274
- expect(child?.lastProcessedMessageId).toBe("dst-m1");
275
- expect(child?.lastProcessedCreatedAt).toBe(4_000);
276
-
277
- db.run(`DELETE FROM messages`);
278
- db.run(`DELETE FROM conversations`);
279
- });
280
-
281
- test("a source cursor whose row was regenerated away is placed by its stored bound, not clamped past the copies", async () => {
282
- const db = getDb();
283
- createConversation({ id: "conv-fork-bound-src" });
284
- createConversation({ id: "conv-fork-bound-dst" });
285
- // src-m2 (createdAt 2_000) was the cursor; a regenerate deleted it and
286
- // src-m3 replaced it. The fork copies src-m1 and src-m3.
287
- for (const [id, conversationId, createdAt] of [
288
- ["src-m1", "conv-fork-bound-src", 1_000],
289
- ["src-m3", "conv-fork-bound-src", 3_000],
290
- ["dst-m1", "conv-fork-bound-dst", 1_000],
291
- ["dst-m3", "conv-fork-bound-dst", 3_000],
292
- ] as const) {
293
- db.insert(messages)
294
- .values({
295
- id,
296
- conversationId,
297
- role: "user",
298
- content: "[]",
299
- createdAt,
300
- metadata: null,
301
- })
302
- .run();
303
- }
304
- await upsertRetrospectiveState({
305
- conversationId: "conv-fork-bound-src",
306
- lastProcessedMessageId: "src-m2",
307
- lastProcessedCreatedAt: 2_000,
308
- lastRunAt: 1,
309
- });
310
-
311
- forkRetrospectiveState({
312
- database: db,
313
- sourceConversationId: "conv-fork-bound-src",
314
- forkedConversationId: "conv-fork-bound-dst",
315
- forkedMessageIds: new Map([
316
- ["src-m1", "dst-m1"],
317
- ["src-m3", "dst-m3"],
318
- ]),
319
- lastCopiedSourceMessageId: "src-m3",
320
- });
321
-
322
- const child = getRetrospectiveState("conv-fork-bound-dst");
323
- expect(child?.lastProcessedMessageId).toBe("dst-m1");
324
- expect(child?.lastProcessedCreatedAt).toBe(1_000);
325
-
326
- // A bound before every copied row leaves the child with nothing processed.
327
- await upsertRetrospectiveState({
328
- conversationId: "conv-fork-bound-src",
329
- lastProcessedMessageId: "src-m0",
330
- lastProcessedCreatedAt: 500,
331
- lastRunAt: 1,
332
- });
333
- forkRetrospectiveState({
334
- database: db,
335
- sourceConversationId: "conv-fork-bound-src",
336
- forkedConversationId: "conv-fork-bound-dst",
337
- forkedMessageIds: new Map([
338
- ["src-m1", "dst-m1"],
339
- ["src-m3", "dst-m3"],
340
- ]),
341
- lastCopiedSourceMessageId: "src-m3",
342
- });
343
- expect(
344
- getRetrospectiveState("conv-fork-bound-dst")?.lastProcessedMessageId,
345
- ).toBe("");
346
-
347
- db.run(`DELETE FROM messages`);
348
- db.run(`DELETE FROM conversations`);
349
- });
350
-
351
- test("ensureRetrospectiveCursorColumn adds the column to a legacy table once and is a no-op after", () => {
352
- const raw = getMemorySqlite()!;
353
- raw.exec("DROP TABLE memory_retrospective_state");
354
- raw.exec(`
355
- CREATE TABLE memory_retrospective_state (
356
- conversation_id TEXT PRIMARY KEY,
357
- last_processed_message_id TEXT NOT NULL,
358
- last_run_at INTEGER NOT NULL,
359
- remembered_log TEXT
360
- )
361
- `);
362
- _resetRetrospectiveCursorColumnForTests();
363
-
364
- expect(ensureRetrospectiveCursorColumn("test")).toBe(true);
365
- expect(ensureRetrospectiveCursorColumn("test")).toBe(true);
366
-
367
- const columns = raw
368
- .query("PRAGMA table_info(memory_retrospective_state)")
369
- .all() as Array<{ name: string }>;
370
- expect(
371
- columns.filter((c) => c.name === "last_processed_created_at"),
372
- ).toHaveLength(1);
373
- });
374
-
375
- test("a replaced memory connection is probed again, so a restored database without the column gets it", () => {
376
- expect(ensureRetrospectiveCursorColumn("test")).toBe(true);
377
-
378
- // What a restore or import does: the stored connections are dropped and
379
- // reopened. Strip the column on the reopened file to stand in for an
380
- // older database.
381
- resetDb();
382
- const reopened = getMemorySqlite()!;
383
- reopened.exec(
384
- "ALTER TABLE memory_retrospective_state DROP COLUMN last_processed_created_at",
385
- );
386
-
387
- expect(getRetrospectiveState("conv-none")).toBeNull();
388
- expect(ensureRetrospectiveCursorColumn("test")).toBe(true);
389
- const columns = reopened
390
- .query("PRAGMA table_info(memory_retrospective_state)")
391
- .all() as Array<{ name: string }>;
392
- expect(columns.some((c) => c.name === "last_processed_created_at")).toBe(
393
- true,
394
- );
395
- });
396
- });
397
-
398
179
  describe("fail-soft when the underlying statement fails", () => {
399
180
  // The memory connection is present, but the relocated table is gone (a
400
181
  // corrupt/dropped table, SQLITE_FULL, I/O error, or SQLITE_BUSY after