@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
@@ -5,11 +5,7 @@
5
5
  // Two pointers move independently:
6
6
  // - `lastProcessedMessageId` advances ONLY when a retrospective run
7
7
  // completes successfully (correctness invariant — failures must
8
- // re-process the same messages on the next attempt). Its companion
9
- // `lastProcessedCreatedAt` is that row's `createdAt` at write time, so the
10
- // `(createdAt, id)` cursor stays reconstructible after the row itself is
11
- // deleted: a regenerated reply discards the latest assistant message,
12
- // which is exactly where the cursor tends to sit.
8
+ // re-process the same messages on the next attempt).
13
9
  // - `lastRunAt` advances at the end of every job that actually attempted a
14
10
  // run (success or failure). Drives the per-conversation cooldown gate in
15
11
  // the trigger-check helper so failing jobs can't loop in tight retries
@@ -29,39 +25,20 @@
29
25
  // that connection is unavailable. The memory database has no `conversations`
30
26
  // table, so there is no FK cascade — the `conversation-deleted` hook purges the
31
27
  // row explicitly instead.
32
- //
33
- // `last_processed_created_at` is added to the table by
34
- // `ensureRetrospectiveCursorColumn`: an idempotent, fail-open ALTER run lazily
35
- // on first use in each process (daemon, memory worker, CLI) rather than by the
36
- // global migration chain, which must not gate DB readiness on the memory
37
- // database. The probe is memoized per memory connection, so a connection
38
- // replaced by `resetDb()` (restores, imports) is probed again before its
39
- // first read. When the column cannot be added, reads and writes fall back to
40
- // the id-only cursor shape and the probe is retried after a short backoff.
41
28
 
42
29
  import { desc, eq } from "drizzle-orm";
43
30
 
44
31
  import type { DrizzleDb } from "../../../persistence/db-connection.js";
45
- import { messageCreatedAtByIds } from "../../../persistence/message-reads.js";
46
32
  import { memoryRetrospectiveState } from "../../../persistence/schema/index.js";
47
33
  import { withSqliteRetry } from "./host-utils.js";
48
34
  import { getLogger } from "./logging.js";
49
- import { memoryDbOrNull, memorySqliteOrNull } from "./memory-db.js";
35
+ import { memoryDbOrNull } from "./memory-db.js";
50
36
 
51
37
  const log = getLogger("memory-retrospective-state");
52
38
 
53
- const TABLE = "memory_retrospective_state";
54
- const CURSOR_CREATED_AT_COLUMN = "last_processed_created_at";
55
-
56
39
  export interface MemoryRetrospectiveState {
57
40
  conversationId: string;
58
41
  lastProcessedMessageId: string;
59
- /**
60
- * `createdAt` of the `lastProcessedMessageId` row when the pointer was
61
- * written, or null when unknown: rows written before the column existed,
62
- * and the `""` sentinel. Lets the cursor bound a read after its row is gone.
63
- */
64
- lastProcessedCreatedAt: number | null;
65
42
  lastRunAt: number;
66
43
  /**
67
44
  * Cumulative `remember` contents from prior retrospective passes, oldest
@@ -122,124 +99,6 @@ function serializeRememberedLog(log: string[]): string | null {
122
99
  return log.length === 0 ? null : JSON.stringify(log);
123
100
  }
124
101
 
125
- // ---------------------------------------------------------------------------
126
- // Cursor timestamp column
127
- // ---------------------------------------------------------------------------
128
-
129
- type MemorySqlite = NonNullable<ReturnType<typeof memorySqliteOrNull>>;
130
-
131
- /** The memory connection the column was confirmed on; any other re-probes. */
132
- let cursorColumnEnsuredOn: MemorySqlite | null = null;
133
- /**
134
- * The connection the last probe failed on and when. The backoff applies to
135
- * that connection only: a replaced connection is probed at once, so a
136
- * restore right after a failure still gets the column before its first read.
137
- */
138
- let cursorColumnFailedOn: MemorySqlite | null = null;
139
- let lastCursorColumnFailureAt = 0;
140
- /** Backoff before re-probing the same connection after a failed ALTER. */
141
- const CURSOR_COLUMN_RETRY_MS = 60_000;
142
-
143
- function isDuplicateColumnError(err: unknown): boolean {
144
- return err instanceof Error && /duplicate column name/i.test(err.message);
145
- }
146
-
147
- /**
148
- * Add `last_processed_created_at` to the state table when it is missing.
149
- * Idempotent; memoized per memory connection, so a connection replaced by
150
- * `resetDb()` is probed again and an imported database that lacks the column
151
- * gets it before its first read. Fail-open: when the ALTER cannot run, the
152
- * failure is logged, every read and write falls back to the id-only shape,
153
- * and that connection is probed again after {@link CURSOR_COLUMN_RETRY_MS}.
154
- * A table the migration chain has not created yet is neither memoized nor a
155
- * failure.
156
- */
157
- export function ensureRetrospectiveCursorColumn(context: string): boolean {
158
- const raw = memorySqliteOrNull(context);
159
- if (!raw) {
160
- return false;
161
- }
162
- if (cursorColumnEnsuredOn === raw) {
163
- return true;
164
- }
165
- if (
166
- cursorColumnFailedOn === raw &&
167
- Date.now() - lastCursorColumnFailureAt < CURSOR_COLUMN_RETRY_MS
168
- ) {
169
- return false;
170
- }
171
- try {
172
- const columns = raw.query(`PRAGMA table_info(${TABLE})`).all() as Array<{
173
- name: string;
174
- }>;
175
- if (columns.length === 0) {
176
- return false;
177
- }
178
- if (!columns.some((column) => column.name === CURSOR_CREATED_AT_COLUMN)) {
179
- raw.exec(
180
- `ALTER TABLE ${TABLE} ADD COLUMN ${CURSOR_CREATED_AT_COLUMN} INTEGER`,
181
- );
182
- }
183
- } catch (err) {
184
- if (!isDuplicateColumnError(err)) {
185
- cursorColumnFailedOn = raw;
186
- lastCursorColumnFailureAt = Date.now();
187
- log.warn(
188
- { err, context },
189
- "could not add the retrospective cursor timestamp column; cursors fall back to id-only until the next probe",
190
- );
191
- return false;
192
- }
193
- }
194
- cursorColumnEnsuredOn = raw;
195
- cursorColumnFailedOn = null;
196
- return true;
197
- }
198
-
199
- /**
200
- * Forget the memoized column probe so the next call re-runs it. Intended
201
- * ONLY for tests that recreate the memory database mid-process.
202
- */
203
- export function _resetRetrospectiveCursorColumnForTests(): void {
204
- cursorColumnEnsuredOn = null;
205
- cursorColumnFailedOn = null;
206
- lastCursorColumnFailureAt = 0;
207
- }
208
-
209
- // ---------------------------------------------------------------------------
210
- // Reads
211
- // ---------------------------------------------------------------------------
212
-
213
- const BASE_COLUMNS = {
214
- conversationId: memoryRetrospectiveState.conversationId,
215
- lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
216
- lastRunAt: memoryRetrospectiveState.lastRunAt,
217
- rememberedLog: memoryRetrospectiveState.rememberedLog,
218
- };
219
-
220
- const CURSOR_COLUMNS = {
221
- ...BASE_COLUMNS,
222
- lastProcessedCreatedAt: memoryRetrospectiveState.lastProcessedCreatedAt,
223
- };
224
-
225
- interface StateRow {
226
- conversationId: string;
227
- lastProcessedMessageId: string;
228
- lastRunAt: number;
229
- rememberedLog: string | null;
230
- lastProcessedCreatedAt?: number | null;
231
- }
232
-
233
- function toState(row: StateRow): MemoryRetrospectiveState {
234
- return {
235
- conversationId: row.conversationId,
236
- lastProcessedMessageId: row.lastProcessedMessageId,
237
- lastProcessedCreatedAt: row.lastProcessedCreatedAt ?? null,
238
- lastRunAt: row.lastRunAt,
239
- rememberedLog: parseRememberedLog(row.rememberedLog),
240
- };
241
- }
242
-
243
102
  /**
244
103
  * Return the `limit` most-recently-run retrospective state rows, newest first.
245
104
  */
@@ -250,22 +109,23 @@ export function listRetrospectiveStates(
250
109
  if (!mdb) {
251
110
  return [];
252
111
  }
253
- const rows: StateRow[] = ensureRetrospectiveCursorColumn(
254
- "listRetrospectiveStates",
255
- )
256
- ? mdb
257
- .select(CURSOR_COLUMNS)
258
- .from(memoryRetrospectiveState)
259
- .orderBy(desc(memoryRetrospectiveState.lastRunAt))
260
- .limit(limit)
261
- .all()
262
- : mdb
263
- .select(BASE_COLUMNS)
264
- .from(memoryRetrospectiveState)
265
- .orderBy(desc(memoryRetrospectiveState.lastRunAt))
266
- .limit(limit)
267
- .all();
268
- return rows.map(toState);
112
+ const rows = mdb
113
+ .select({
114
+ conversationId: memoryRetrospectiveState.conversationId,
115
+ lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
116
+ lastRunAt: memoryRetrospectiveState.lastRunAt,
117
+ rememberedLog: memoryRetrospectiveState.rememberedLog,
118
+ })
119
+ .from(memoryRetrospectiveState)
120
+ .orderBy(desc(memoryRetrospectiveState.lastRunAt))
121
+ .limit(limit)
122
+ .all();
123
+ return rows.map((row) => ({
124
+ conversationId: row.conversationId,
125
+ lastProcessedMessageId: row.lastProcessedMessageId,
126
+ lastRunAt: row.lastRunAt,
127
+ rememberedLog: parseRememberedLog(row.rememberedLog),
128
+ }));
269
129
  }
270
130
 
271
131
  /**
@@ -278,45 +138,37 @@ export function getRetrospectiveState(
278
138
  if (!mdb) {
279
139
  return null;
280
140
  }
281
- const where = eq(memoryRetrospectiveState.conversationId, conversationId);
282
- const row: StateRow | undefined = ensureRetrospectiveCursorColumn(
283
- "getRetrospectiveState",
284
- )
285
- ? mdb
286
- .select(CURSOR_COLUMNS)
287
- .from(memoryRetrospectiveState)
288
- .where(where)
289
- .get()
290
- : mdb
291
- .select(BASE_COLUMNS)
292
- .from(memoryRetrospectiveState)
293
- .where(where)
294
- .get();
295
- return row ? toState(row) : null;
141
+ const row = mdb
142
+ .select({
143
+ conversationId: memoryRetrospectiveState.conversationId,
144
+ lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
145
+ lastRunAt: memoryRetrospectiveState.lastRunAt,
146
+ rememberedLog: memoryRetrospectiveState.rememberedLog,
147
+ })
148
+ .from(memoryRetrospectiveState)
149
+ .where(eq(memoryRetrospectiveState.conversationId, conversationId))
150
+ .get();
151
+ if (!row) {
152
+ return null;
153
+ }
154
+ return {
155
+ conversationId: row.conversationId,
156
+ lastProcessedMessageId: row.lastProcessedMessageId,
157
+ lastRunAt: row.lastRunAt,
158
+ rememberedLog: parseRememberedLog(row.rememberedLog),
159
+ };
296
160
  }
297
161
 
298
- // ---------------------------------------------------------------------------
299
- // Writes
300
- // ---------------------------------------------------------------------------
301
-
302
162
  /**
303
163
  * Upsert both pointers atomically. Used on successful retrospective runs.
304
164
  *
305
- * `lastProcessedCreatedAt` is the id's companion and is rewritten with every
306
- * pointer write: an omitted value records "unknown" for the new id rather
307
- * than keeping the previous row's timestamp.
308
- *
309
165
  * `rememberedLog`, when provided, is written in the same statement so the
310
166
  * cumulative dedup log can never drift from the pointer it was computed
311
167
  * against. When omitted, the stored log is left untouched (and seeded NULL on
312
168
  * first insert).
313
169
  */
314
170
  export async function upsertRetrospectiveState(
315
- args: Omit<
316
- MemoryRetrospectiveState,
317
- "rememberedLog" | "lastProcessedCreatedAt"
318
- > & {
319
- lastProcessedCreatedAt?: number | null;
171
+ args: Omit<MemoryRetrospectiveState, "rememberedLog"> & {
320
172
  rememberedLog?: string[];
321
173
  },
322
174
  ): Promise<void> {
@@ -324,9 +176,6 @@ export async function upsertRetrospectiveState(
324
176
  if (!mdb) {
325
177
  return;
326
178
  }
327
- const withCursor = ensureRetrospectiveCursorColumn(
328
- "upsertRetrospectiveState",
329
- );
330
179
  const serializedLog =
331
180
  args.rememberedLog === undefined
332
181
  ? undefined
@@ -336,16 +185,12 @@ export async function upsertRetrospectiveState(
336
185
  // on first insert).
337
186
  const set: {
338
187
  lastProcessedMessageId: string;
339
- lastProcessedCreatedAt?: number | null;
340
188
  lastRunAt: number;
341
189
  rememberedLog?: string | null;
342
190
  } = {
343
191
  lastProcessedMessageId: args.lastProcessedMessageId,
344
192
  lastRunAt: args.lastRunAt,
345
193
  };
346
- if (withCursor) {
347
- set.lastProcessedCreatedAt = args.lastProcessedCreatedAt ?? null;
348
- }
349
194
  if (serializedLog !== undefined) {
350
195
  set.rememberedLog = serializedLog;
351
196
  }
@@ -358,9 +203,6 @@ export async function upsertRetrospectiveState(
358
203
  lastProcessedMessageId: args.lastProcessedMessageId,
359
204
  lastRunAt: args.lastRunAt,
360
205
  rememberedLog: serializedLog ?? null,
361
- ...(withCursor
362
- ? { lastProcessedCreatedAt: args.lastProcessedCreatedAt ?? null }
363
- : {}),
364
206
  })
365
207
  .onConflictDoUpdate({
366
208
  target: memoryRetrospectiveState.conversationId,
@@ -374,46 +216,6 @@ export async function upsertRetrospectiveState(
374
216
  );
375
217
  }
376
218
 
377
- /**
378
- * The copied source row that sits latest at or before `bound` in
379
- * `(createdAt, id)` order, as its forked id and `createdAt`, or null when
380
- * every copied row lies after the bound. Reads the source rows through the
381
- * fork transaction's handle.
382
- */
383
- function latestCopiedRowAtOrBefore(
384
- database: DrizzleDb,
385
- forkedMessageIds: Map<string, string>,
386
- bound: { createdAt: number; id: string },
387
- ): { forkedId: string; createdAt: number } | null {
388
- const createdAtBySourceId = messageCreatedAtByIds(
389
- [...forkedMessageIds.keys()],
390
- { db: database },
391
- );
392
- let best: { sourceId: string; createdAt: number } | null = null;
393
- for (const [sourceId, createdAt] of createdAtBySourceId) {
394
- const atOrBefore =
395
- createdAt < bound.createdAt ||
396
- (createdAt === bound.createdAt && sourceId <= bound.id);
397
- if (!atOrBefore) {
398
- continue;
399
- }
400
- const later =
401
- best === null ||
402
- createdAt > best.createdAt ||
403
- (createdAt === best.createdAt && sourceId > best.sourceId);
404
- if (later) {
405
- best = { sourceId, createdAt };
406
- }
407
- }
408
- if (best === null) {
409
- return null;
410
- }
411
- const forkedId = forkedMessageIds.get(best.sourceId);
412
- return forkedId === undefined
413
- ? null
414
- : { forkedId, createdAt: best.createdAt };
415
- }
416
-
417
219
  /**
418
220
  * Carry the source conversation's retrospective state into a forked child so
419
221
  * the fork doesn't re-process content the parent already covered. Synchronous
@@ -427,23 +229,18 @@ function latestCopiedRowAtOrBefore(
427
229
  * succeeded) → child pointer is also `""`.
428
230
  * - source pointer is within the copied range (`forkedMessageIds` has it) →
429
231
  * child pointer is the mapped forked message ID.
430
- * - source pointer is not in `forkedMessageIds` (its row was deleted, or it
431
- * lies past the copied range) and carries a stored `createdAt` → child
432
- * pointer is the latest copied row at or before the source's
433
- * `(createdAt, id)` bound; copied rows after the bound stay unprocessed.
434
- * - source pointer is not in `forkedMessageIds` and has no stored
435
- * `createdAt` → child pointer is the last copied message's mapped ID, on
436
- * the assumption it lies past the fork boundary.
232
+ * - source pointer is past the fork boundary (not in `forkedMessageIds`) →
233
+ * child pointer is the last copied message's mapped ID. All copied
234
+ * messages have already been retro'd by the source, so the child should
235
+ * wait for new post-fork messages before its first retro fires.
437
236
  *
438
- * `lastProcessedCreatedAt` is read from the forked pointer's row through
439
- * `database`, the fork transaction's main-DB handle, which is the only handle
440
- * the freshly copied rows are visible through.
441
237
  * `lastRunAt` is copied verbatim — the cooldown gate inherits from source.
442
238
  * `rememberedLog` is copied verbatim — the parent's saves remain the child's
443
239
  * dedup baseline.
444
240
  *
445
- * The state row itself is written on the memory connection; an unavailable
446
- * memory database is a best-effort no-op.
241
+ * The row lives on the memory connection, so this reads/writes there rather
242
+ * than on the main fork transaction's handle — the `database` arg is unused
243
+ * now, and an unavailable memory database is a best-effort no-op.
447
244
  */
448
245
  export function forkRetrospectiveState(args: {
449
246
  database: DrizzleDb;
@@ -453,7 +250,6 @@ export function forkRetrospectiveState(args: {
453
250
  lastCopiedSourceMessageId: string | null;
454
251
  }): void {
455
252
  const {
456
- database,
457
253
  sourceConversationId,
458
254
  forkedConversationId,
459
255
  forkedMessageIds,
@@ -466,84 +262,47 @@ export function forkRetrospectiveState(args: {
466
262
  return;
467
263
  }
468
264
 
469
- const withCursor = ensureRetrospectiveCursorColumn(
470
- "forkRetrospectiveState",
471
- );
472
- const sourceRow: StateRow | undefined = withCursor
473
- ? mdb
474
- .select(CURSOR_COLUMNS)
475
- .from(memoryRetrospectiveState)
476
- .where(
477
- eq(memoryRetrospectiveState.conversationId, sourceConversationId),
478
- )
479
- .get()
480
- : mdb
481
- .select(BASE_COLUMNS)
482
- .from(memoryRetrospectiveState)
483
- .where(
484
- eq(memoryRetrospectiveState.conversationId, sourceConversationId),
485
- )
486
- .get();
265
+ const sourceRow = mdb
266
+ .select({
267
+ lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
268
+ lastRunAt: memoryRetrospectiveState.lastRunAt,
269
+ rememberedLog: memoryRetrospectiveState.rememberedLog,
270
+ })
271
+ .from(memoryRetrospectiveState)
272
+ .where(eq(memoryRetrospectiveState.conversationId, sourceConversationId))
273
+ .get();
487
274
  if (!sourceRow) {
488
275
  return;
489
276
  }
490
277
 
491
- const sourcePointer = sourceRow.lastProcessedMessageId;
492
- const sourceCreatedAt = sourceRow.lastProcessedCreatedAt ?? null;
493
278
  let forkedPointer = "";
494
- let forkedCreatedAt: number | null = null;
495
- if (sourcePointer !== "") {
496
- const mapped = forkedMessageIds.get(sourcePointer);
279
+ if (sourceRow.lastProcessedMessageId !== "") {
280
+ const mapped = forkedMessageIds.get(sourceRow.lastProcessedMessageId);
497
281
  if (mapped !== undefined) {
498
282
  forkedPointer = mapped;
499
- forkedCreatedAt =
500
- messageCreatedAtByIds([forkedPointer], { db: database }).get(
501
- forkedPointer,
502
- ) ?? null;
503
- } else if (sourceCreatedAt !== null) {
504
- // The source pointer is not among the copied rows: either its row
505
- // was deleted (a regenerated reply) or it lies past the copied range.
506
- // Its stored `(createdAt, id)` bound still says where it sat, so the
507
- // child takes the latest copied row at or before that bound. Copied
508
- // rows after it (a replacement reply, later turns) stay unprocessed;
509
- // a bound before every copied row leaves the child at "nothing
510
- // processed yet".
511
- const placed = latestCopiedRowAtOrBefore(database, forkedMessageIds, {
512
- createdAt: sourceCreatedAt,
513
- id: sourcePointer,
514
- });
515
- if (placed) {
516
- forkedPointer = placed.forkedId;
517
- forkedCreatedAt = placed.createdAt;
518
- }
519
283
  } else if (lastCopiedSourceMessageId !== null) {
520
- // No stored bound to place a missing pointer by (a row written before
521
- // timestamps were kept): treat it as past the fork boundary and clamp
522
- // to the last copied message so the fork waits for new post-fork
523
- // messages.
284
+ // Source pointer is past the fork boundary — everything copied has
285
+ // already been processed by the source, so clamp to the last copied
286
+ // message so the fork waits for new post-fork messages.
524
287
  forkedPointer = forkedMessageIds.get(lastCopiedSourceMessageId) ?? "";
525
- forkedCreatedAt =
526
- forkedPointer === ""
527
- ? null
528
- : (messageCreatedAtByIds([forkedPointer], { db: database }).get(
529
- forkedPointer,
530
- ) ?? null);
531
288
  }
532
289
  }
533
290
 
534
- const values = {
535
- lastProcessedMessageId: forkedPointer,
536
- lastRunAt: sourceRow.lastRunAt,
537
- rememberedLog: sourceRow.rememberedLog,
538
- ...(withCursor ? { lastProcessedCreatedAt: forkedCreatedAt } : {}),
539
- };
540
-
541
291
  mdb
542
292
  .insert(memoryRetrospectiveState)
543
- .values({ conversationId: forkedConversationId, ...values })
293
+ .values({
294
+ conversationId: forkedConversationId,
295
+ lastProcessedMessageId: forkedPointer,
296
+ lastRunAt: sourceRow.lastRunAt,
297
+ rememberedLog: sourceRow.rememberedLog,
298
+ })
544
299
  .onConflictDoUpdate({
545
300
  target: memoryRetrospectiveState.conversationId,
546
- set: values,
301
+ set: {
302
+ lastProcessedMessageId: forkedPointer,
303
+ lastRunAt: sourceRow.lastRunAt,
304
+ rememberedLog: sourceRow.rememberedLog,
305
+ },
547
306
  })
548
307
  .run();
549
308
  } catch (err) {
@@ -78,7 +78,6 @@ import { conversations } from "../../../persistence/schema/index.js";
78
78
  import { getLogger } from "./logging.js";
79
79
  import { countRetrospectiveMessagesAfter } from "./memory-retrospective-accounting.js";
80
80
  import { MEMORY_RETROSPECTIVE_SOURCES } from "./memory-retrospective-constants.js";
81
- import { retrospectiveCursor } from "./memory-retrospective-cursor.js";
82
81
  import { enqueueMemoryRetrospectiveIfEnabled } from "./memory-retrospective-enqueue.js";
83
82
  import { getRetrospectiveState } from "./memory-retrospective-state.js";
84
83
 
@@ -274,7 +273,7 @@ export async function runRetrospectiveSweep(
274
273
 
275
274
  const unprocessed = countRetrospectiveMessagesAfter(
276
275
  conversationId,
277
- retrospectiveCursor(state),
276
+ state?.lastProcessedMessageId ?? null,
278
277
  );
279
278
  if (unprocessed === 0) {
280
279
  continue;
@@ -9,9 +9,8 @@
9
9
  // (success or failure). Prevents tight retry loops across trigger
10
10
  // types.
11
11
  // 2. Interval threshold: time since last attempt >= `timeThresholdMs`.
12
- // 3. Message count threshold: new messages since the persisted cursor
13
- // (`lastProcessedMessageId` with its `createdAt`, so the count survives
14
- // the cursor's row being deleted) >= `messageThreshold`.
12
+ // 3. Message count threshold: new messages since `lastProcessedMessageId`
13
+ // >= `messageThreshold`.
15
14
  //
16
15
  // First-run case (no state row) skips the cooldown — `lastRunAt = 0` so the
17
16
  // gap is effectively `Infinity`. The interval threshold trips immediately;
@@ -25,7 +24,6 @@
25
24
  import type { AssistantConfig } from "../../../config/types.js";
26
25
  import { getLogger } from "./logging.js";
27
26
  import { countRetrospectiveMessagesAfter } from "./memory-retrospective-accounting.js";
28
- import { retrospectiveCursor } from "./memory-retrospective-cursor.js";
29
27
  import { enqueueMemoryRetrospectiveIfEnabled } from "./memory-retrospective-enqueue.js";
30
28
  import { getRetrospectiveState } from "./memory-retrospective-state.js";
31
29
 
@@ -85,7 +83,7 @@ export function maybeEnqueueRetrospective(
85
83
  const state = getRetrospectiveState(conversationId);
86
84
  const newMessageCount = countRetrospectiveMessagesAfter(
87
85
  conversationId,
88
- retrospectiveCursor(state),
86
+ state?.lastProcessedMessageId ?? null,
89
87
  );
90
88
  if (newMessageCount === 0) {
91
89
  return;
@@ -28,10 +28,7 @@ import { join } from "node:path";
28
28
  import { usesConceptPageMemory } from "../../../config/memory-v3-gate.js";
29
29
  import type { AssistantConfig } from "../../../config/schema.js";
30
30
  import { reconcileEmbeddingIdentity } from "../../../daemon/embedding-reconcile.js";
31
- import {
32
- refreshSkillCapabilityMemories,
33
- startWorkspaceSkillMdMtimePoll,
34
- } from "../../../daemon/skill-memory-refresh.js";
31
+ import { refreshSkillCapabilityMemories } from "../../../daemon/skill-memory-refresh.js";
35
32
  import { selectEmbeddingBackend } from "../../../persistence/embeddings/embedding-backend.js";
36
33
  import {
37
34
  initMessagesLexicalIndex,
@@ -266,8 +263,6 @@ export async function runMemoryStartup(config: AssistantConfig): Promise<void> {
266
263
  log.warn({ err }, "Graph capability seeding failed — continuing");
267
264
  }
268
265
 
269
- startWorkspaceSkillMdMtimePoll();
270
-
271
266
  // ---- v1 (legacy engine) — delete with v1 ----
272
267
  // Auto-bootstrap: if the graph has no non-procedural nodes but historical
273
268
  // segments exist, enqueue a one-time graph_bootstrap job to populate the
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { describe, expect, test } from "bun:test";
6
6
 
7
- import { setWorkspaceMcp } from "../../../../../__tests__/helpers/set-workspace-mcp.js";
7
+ import { setConfig } from "../../../../../__tests__/helpers/set-config.js";
8
8
  import type { SkillCapabilityInput } from "../skill-content.js";
9
9
 
10
10
  describe("buildSkillContent", () => {
@@ -90,12 +90,14 @@ describe("augmentMcpSetupDescription", () => {
90
90
  });
91
91
 
92
92
  test("appends 'Configured: <names>' for mcp-setup with configured servers", async () => {
93
- setWorkspaceMcp({
94
- "example-server": {
95
- transport: { type: "stdio", command: "example-cmd", args: [] },
96
- },
97
- "another-server": {
98
- transport: { type: "stdio", command: "another-cmd", args: [] },
93
+ setConfig("mcp", {
94
+ servers: {
95
+ "example-server": {
96
+ transport: { type: "stdio", command: "example-cmd" },
97
+ },
98
+ "another-server": {
99
+ transport: { type: "stdio", command: "another-cmd" },
100
+ },
99
101
  },
100
102
  });
101
103
  const { augmentMcpSetupDescription } = await import("../skill-content.js");
@@ -1,4 +1,4 @@
1
- import { loadWorkspaceMcpConfig } from "../../../../mcp/workspace-mcp-config.js";
1
+ import { getConfig } from "../../../../config/loader.js";
2
2
 
3
3
  /**
4
4
  * Generic input for building capability statements: the capability fields of
@@ -92,7 +92,7 @@ export function augmentMcpSetupDescription(
92
92
  if (input.id !== "mcp-setup") {
93
93
  return input;
94
94
  }
95
- const servers = loadWorkspaceMcpConfig().servers;
95
+ const servers = getConfig().mcp?.servers;
96
96
  if (!servers) {
97
97
  return input;
98
98
  }